From 3a2e0859d43a806436f283a55653dca247ef6aed Mon Sep 17 00:00:00 2001 From: Tim Oelkers Date: Wed, 25 Feb 2026 13:04:36 +0100 Subject: [PATCH 1/3] feat: require-data-selector uses consistent rules with assignments --- lib/rules/require-data-selectors.js | 16 ++++------------ tests/lib/rules/require-data-selectors.js | 8 ++++++-- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/lib/rules/require-data-selectors.js b/lib/rules/require-data-selectors.js index 18ab403e..887e7d6a 100644 --- a/lib/rules/require-data-selectors.js +++ b/lib/rules/require-data-selectors.js @@ -19,18 +19,7 @@ module.exports = { return { VariableDeclarator(node) { if (node.init && node.id && node.id.type === 'Identifier') { - let selectorValue = null - - if (node.init.type === 'Literal' && typeof node.init.value === 'string') { - selectorValue = node.init.value - } - else if (node.init.type === 'TemplateLiteral' - && node.init.expressions.length === 0 - && node.init.quasis.length === 1) { - selectorValue = node.init.quasis[0].value.cooked - } - - if (selectorValue && isAliasOrDataSelector(selectorValue)) { + if (isDataNode(node.init, variablesSet)) { variablesSet.add(node.id.name) } } @@ -57,7 +46,10 @@ function isDataArgument(node, dataVariables) { if (node.arguments.length === 0) return false const firstArg = node.arguments[0] + return isDataNode(firstArg, dataVariables) +} +function isDataNode(firstArg, dataVariables) { if (firstArg.type === 'Literal') { return isAliasOrDataSelector(String(firstArg.value)) } diff --git a/tests/lib/rules/require-data-selectors.js b/tests/lib/rules/require-data-selectors.js index 9fb0a45d..599ed055 100644 --- a/tests/lib/rules/require-data-selectors.js +++ b/tests/lib/rules/require-data-selectors.js @@ -14,11 +14,13 @@ ruleTester.run('require-data-selectors', rule, { { code: 'cy.clock(5000)' }, { code: 'cy.scrollTo(0, 10)' }, { code: 'cy.tick(500)' }, - { code: 'cy.get(\`[data-cy=${1}]\`)' }, // eslint-disable-line no-useless-escape + { code: 'cy.get(`[data-cy=${1}]`)' }, { code: 'cy.get("@my-alias")' }, { code: 'cy.get(`@my-alias`)' }, { code: 'const ASSESSMENT_SUBMIT = "[data-cy=assessment-submit]"; cy.get(ASSESSMENT_SUBMIT)' }, { code: 'const ALIAS_TEMPLATE = `@my-alias`; cy.get(ALIAS_TEMPLATE)' }, + { code: 'const TEMPLATE = `[data-cy=${1}]`; cy.get(TEMPLATE)' }, + { code: 'const ALIAS_TEMPLATE = `@my-alias`; const REASSIGNED = ALIAS_TEMPLATE; cy.get(REASSIGNED)' }, ], invalid: [ @@ -27,8 +29,10 @@ ruleTester.run('require-data-selectors', rule, { { code: 'cy.get(".btn-large").click()', errors }, { code: 'cy.get(".btn-.large").click()', errors }, { code: 'cy.get(".a")', errors }, - { code: 'cy.get(\`[daedta-cy=${1}]\`)', errors }, // eslint-disable-line no-useless-escape + { code: 'cy.get(`[daedta-cy=${1}]`)', errors }, { code: 'const BAD_SELECTOR = ".my-class"; cy.get(BAD_SELECTOR)', errors }, { code: 'const GOOD = "[data-cy=good]"; const BAD = ".bad"; cy.get(GOOD); cy.get(BAD)', errors }, + { code: 'const TEMPLATE = `[daedta-cy=${1}]`; cy.get(TEMPLATE)', errors }, + { code: 'const BAD = ".bad"; const REASSIGNED = BAD; cy.get(REASSIGNED)', errors }, ], }) From 35c6f6e586b95163065333eaf54e3aff7199e042 Mon Sep 17 00:00:00 2001 From: Tim Oelkers Date: Thu, 26 Feb 2026 12:45:04 +0100 Subject: [PATCH 2/3] feat: add more examples to documentation --- docs/rules/require-data-selectors.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/rules/require-data-selectors.md b/docs/rules/require-data-selectors.md index e094551b..20119c6f 100644 --- a/docs/rules/require-data-selectors.md +++ b/docs/rules/require-data-selectors.md @@ -21,6 +21,13 @@ cy.get('.btn-.large').click() const CLASS_SELECTOR = ".my-class"; cy.get(CLASS_SELECTOR) + +const TYPE = 'submit' +const SUBMIT_TEMPLATE = `.${submit}]` +cy.get(SUBMIT_TEMPLATE) + +const MY_SUBMIT_TEMPLATE = SUBMIT_TEMPLATE; +cy.get(MY_SUBMIT_TEMPLATE) ``` Examples of **correct** code for this rule: @@ -34,6 +41,13 @@ cy.get(`[data-QA=submit]`) ```js const ASSESSMENT_SUBMIT = "[data-cy=assessment-submit]" cy.get(ASSESSMENT_SUBMIT).click() + +const TYPE = 'submit' +const SUBMIT_TEMPLATE = `[data-QA=${submit}]` +cy.get(SUBMIT_TEMPLATE) + +const MY_SUBMIT_TEMPLATE = SUBMIT_TEMPLATE; +cy.get(MY_SUBMIT_TEMPLATE) ``` ## Further Reading From db3c15c639ef83a101ca0b698d6d901dd5a077fe Mon Sep 17 00:00:00 2001 From: MgmClientGuy0 Date: Mon, 2 Mar 2026 08:36:56 +0100 Subject: [PATCH 3/3] feat: cleanup documentation Co-authored-by: Mike McCready <66998419+MikeMcC399@users.noreply.github.com> --- docs/rules/require-data-selectors.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/rules/require-data-selectors.md b/docs/rules/require-data-selectors.md index 20119c6f..a868b6ed 100644 --- a/docs/rules/require-data-selectors.md +++ b/docs/rules/require-data-selectors.md @@ -23,7 +23,7 @@ const CLASS_SELECTOR = ".my-class"; cy.get(CLASS_SELECTOR) const TYPE = 'submit' -const SUBMIT_TEMPLATE = `.${submit}]` +const SUBMIT_TEMPLATE = `.${TYPE}` cy.get(SUBMIT_TEMPLATE) const MY_SUBMIT_TEMPLATE = SUBMIT_TEMPLATE; @@ -36,14 +36,12 @@ Examples of **correct** code for this rule: cy.get('[data-cy=submit]').click() cy.get('[data-QA=submit]') cy.get(`[data-QA=submit]`) -``` -```js const ASSESSMENT_SUBMIT = "[data-cy=assessment-submit]" cy.get(ASSESSMENT_SUBMIT).click() const TYPE = 'submit' -const SUBMIT_TEMPLATE = `[data-QA=${submit}]` +const SUBMIT_TEMPLATE = `[data-QA=${TYPE}]` cy.get(SUBMIT_TEMPLATE) const MY_SUBMIT_TEMPLATE = SUBMIT_TEMPLATE;