diff --git a/CHANGELOG.md b/CHANGELOG.md index 4148966..ee48b2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - [#40](https://github.com/green-code-initiative/creedengo-javascript/pull/40) Add rule `@creedengo/avoid-autoplay` (GCI36) +- [#45](https://github.com/green-code-initiative/creedengo-javascript/pull/45) Add rule `@creedengo/avoid-keep-awake` (GCI505) - [#46](https://github.com/green-code-initiative/creedengo-javascript/pull/46) Add rule `@creedengo/prefer-lighter-formats-for-image-files` (GCI31) ## [2.0.0] - 2025-01-22 diff --git a/eslint-plugin/README.md b/eslint-plugin/README.md index 35086e1..0504ba6 100644 --- a/eslint-plugin/README.md +++ b/eslint-plugin/README.md @@ -80,6 +80,7 @@ Add `@creedengo` to the `plugins` section of your `.eslintrc`, followed by rules | [avoid-brightness-override](docs/rules/avoid-brightness-override.md) | Should avoid to override brightness | ✅ | | [avoid-css-animations](docs/rules/avoid-css-animations.md) | Avoid usage of CSS animations | ✅ | | [avoid-high-accuracy-geolocation](docs/rules/avoid-high-accuracy-geolocation.md) | Avoid using high accuracy geolocation in web applications | ✅ | +| [avoid-keep-awake](docs/rules/avoid-keep-awake.md) | Avoid screen keep awake | ✅ | | [limit-db-query-results](docs/rules/limit-db-query-results.md) | Should limit the number of returns for a SQL query | ✅ | | [no-empty-image-src-attribute](docs/rules/no-empty-image-src-attribute.md) | Disallow usage of image with empty source attribute | ✅ | | [no-import-all-from-library](docs/rules/no-import-all-from-library.md) | Should not import all from library | ✅ | diff --git a/eslint-plugin/docs/rules/avoid-keep-awake.md b/eslint-plugin/docs/rules/avoid-keep-awake.md new file mode 100644 index 0000000..056ccf2 --- /dev/null +++ b/eslint-plugin/docs/rules/avoid-keep-awake.md @@ -0,0 +1,40 @@ +# Avoid screen keep awake (`@creedengo/avoid-keep-awake`) + +⚠️ This rule _warns_ in the ✅ `recommended` config. + + + +## Why is this an issue? + +To avoid draining the battery, an Android device that is left idle quickly falls asleep. +Hence, keeping the screen on should be avoided, unless it is absolutely necessary. + +> **Note**: This rule currently only supports detecting `expo-keep-awake` package usage. Support for other keep-awake packages may be added in future versions. + +```js +import { useKeepAwake } from "expo-keep-awake"; + +export default function KeepAwakeExample() { + useKeepAwake(); // Non compliant + return ( + + This screen will never sleep! + + ); +} +``` + +```js +import { activateKeepAwake } from "expo-keep-awake"; + +_activate = () => { + activateKeepAwake(); // Non-compliant + alert("Activated!"); +}; +``` + +## Resources + +### Documentation + +- [Expo Docs](https://docs.expo.dev/versions/latest/sdk/keep-awake/) - Expo KeepAwake diff --git a/eslint-plugin/lib/rules/avoid-keep-awake.js b/eslint-plugin/lib/rules/avoid-keep-awake.js new file mode 100644 index 0000000..06f3737 --- /dev/null +++ b/eslint-plugin/lib/rules/avoid-keep-awake.js @@ -0,0 +1,65 @@ +/* + * creedengo JavaScript plugin - Provides rules to reduce the environmental footprint of your JavaScript programs + * Copyright © 2023 Green Code Initiative (https://green-code-initiative.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +"use strict"; + +const keepAwakeLibrariesMethods = { + "expo-keep-awake": ["activateKeepAwake", "useKeepAwake"], +}; + +/** @type {import("eslint").Rule.RuleModule} */ +module.exports = { + meta: { + type: "suggestion", + docs: { + description: "Avoid screen keep awake", + category: "eco-design", + recommended: "warn", + }, + messages: { + AvoidKeepAwake: "Avoid screen keep awake", + }, + schema: [], + }, + create: function (context) { + const librariesFoundInImports = []; + + return { + ImportDeclaration(node) { + const currentLibrary = node.source.value; + + if (keepAwakeLibrariesMethods[currentLibrary]) { + librariesFoundInImports.push(currentLibrary); + } + }, + CallExpression(node) { + if (librariesFoundInImports.length === 0) { + return; + } + + if ( + librariesFoundInImports.some((library) => + keepAwakeLibrariesMethods[library].includes(node.callee.name), + ) + ) { + context.report({ node, messageId: "AvoidKeepAwake" }); + } + }, + }; + }, +}; diff --git a/eslint-plugin/tests/lib/rules/avoid-keep-awake.js b/eslint-plugin/tests/lib/rules/avoid-keep-awake.js new file mode 100644 index 0000000..6bea138 --- /dev/null +++ b/eslint-plugin/tests/lib/rules/avoid-keep-awake.js @@ -0,0 +1,127 @@ +/* + * creedengo JavaScript plugin - Provides rules to reduce the environmental footprint of your JavaScript programs + * Copyright © 2023 Green Code Initiative (https://green-code-initiative.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/avoid-keep-awake"); +const RuleTester = require("eslint").RuleTester; + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester({ + parserOptions: { + ecmaVersion: 2022, + sourceType: "module", + ecmaFeatures: { + jsx: true, + }, + }, +}); + +const expectedErrorHook = { + messageId: "AvoidKeepAwake", + type: "CallExpression", +}; + +const expectedErrorFunction = { + messageId: "AvoidKeepAwake", + type: "CallExpression", +}; + +ruleTester.run("avoid-keep-awake", rule, { + valid: [ + { + code: ` + import React from 'react'; + import { Text, View } from 'react-native'; + + export default function ValidExample() { + return ( + + This screen will sleep! + + ); + } + `, + }, + { + code: ` + import React from 'react'; + import { useKeepAwake } from 'other-library'; + import { Button, View } from 'react-native'; + + export default class ValidExample extends React.Component { + render() { + useKeepAwake(); + return ( + + + ); + } + } + `, + }, + ], + invalid: [ + { + code: ` + import { useKeepAwake } from 'expo-keep-awake'; + import React from 'react'; + import { Text, View } from 'react-native'; + + export default function KeepAwakeExample() { + useKeepAwake(); + return ( + + This screen will never sleep! + + ); + } + `, + errors: [expectedErrorHook], + }, + { + code: ` + import { activateKeepAwake } from 'expo-keep-awake'; + import React from 'react'; + import { Button, View } from 'react-native'; + + export default class KeepAwakeExample extends React.Component { + render() { + return ( + +