-
Notifications
You must be signed in to change notification settings - Fork 63
chore: refactor cypress tests #1060
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughAdds Cursor rule configs; updates .gitignore entries; modifies Cypress test suite (adds features and permissions tests, removes admin and roles tests), updates support commands and utils; bumps Cypress and scripts; adjusts playground config and scripts; capitalizes a content-type displayName; and replaces playground register with an async bootstrap that seeds an admin user. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Process as Node.js Process
participant Strapi as Strapi (bootstrap)
participant AdminSvc as admin::user service
participant RoleSvc as Role service
Process->>Strapi: start()
Strapi->>Strapi: bootstrap({ strapi }) — seed admin
Strapi->>AdminSvc: findOne({ email })
alt admin not found
Strapi->>RoleSvc: find \"strapi-super-admin\" role
Strapi->>AdminSvc: create({ email, password, roles:[super-admin] })
AdminSvc-->>Strapi: created user
else admin exists
Strapi->>AdminSvc: if password === 'password' -> update(userId, { password })
AdminSvc-->>Strapi: updated (optional)
end
Strapi-->>Process: bootstrap complete (log success/failure)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
🔇 Additional comments (1)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
🧹 Nitpick comments (9)
cypress/support/commands.js (1)
38-38
: Consider the impact of removing the timeout option.The timeout option was removed from
cy.get('form')
. While the current implementation usesshould('be.visible')
which has its own timeout, ensure this change doesn't affect tests running against slower environments.cypress/e2e/permissions.cy.js (4)
105-113
: Scope selection with find; avoid nested getget(...) resets the subject to document. Use find to scope to the nav and streamline the click flow.
- cy.get('nav') - .get('a[aria-label="Meilisearch"]', { timeout: 10000 }) - .should('be.visible') - cy.get('nav') - .get('a[aria-label="Meilisearch"]', { timeout: 10000 }) - .click() + cy.get('nav') + .find('a[aria-label="Meilisearch"]', { timeout: 10000 }) + .should('be.visible') + .click()
156-161
: Prefer cy.contains/find over jQuery :contains inside cy.getSelectors like tr:contains("user") inside get are brittle. Use cy.contains to locate the row, then scope with find.
- cy.get('tr:contains("user") button[role="checkbox"]').first().click() + cy.contains('tr', 'user').find('button[role="checkbox"]').first().click() @@ - cy.get('tr:contains("user")').contains('Yes').should('be.visible') - cy.get('tr:contains("user")').contains('1 / 1').should('be.visible') - cy.get('tr:contains("user")').contains('Hooked').should('be.visible') + cy.contains('tr', 'user').should('contain.text', 'Yes') + cy.contains('tr', 'user').should('contain.text', '1 / 1') + cy.contains('tr', 'user').should('contain.text', 'Hooked') @@ - cy.get('tr:contains(user)').first().contains('Yes').should('be.visible') - cy.get('tr:contains(user)') - .first() - .contains('Hooked') - .should('be.visible') - cy.get('tr:contains(user)').first().contains('button', 'Update').click() + cy.contains('tr', 'user').should('contain.text', 'Yes') + cy.contains('tr', 'user').should('contain.text', 'Hooked') + cy.contains('tr', 'user').contains('button', 'Update').click() @@ - cy.get('tr:contains(user)').first().contains('Yes').should('be.visible') - cy.get('tr:contains(user)') - .first() - .contains('Hooked') - .should('be.visible') - cy.get('tr:contains(user)') - .first() - .get('button[role="checkbox"]') - .first() - .click() + cy.contains('tr', 'user').should('contain.text', 'Yes') + cy.contains('tr', 'user').should('contain.text', 'Hooked') + cy.contains('tr', 'user').find('button[role="checkbox"]').first().click() @@ - cy.get('tr:contains(user)') - .first() - .contains('Reload needed') - .should('be.visible') + cy.contains('tr', 'user').contains('Reload needed').should('be.visible')Also applies to: 166-177, 223-232, 271-287
186-187
: Standardize negative assertions for buttonsReplace "root().should('not.contain', 'button:contains(...)')" with direct non-existence checks.
- cy.root().should('not.contain', 'button:contains("Update")') + cy.contains('button', 'Update').should('not.exist') @@ - cy.root().should('not.contain', 'button:contains("Save")') + cy.contains('button', 'Save').should('not.exist')Apply similarly at the other cited locations.
Also applies to: 192-193, 236-237, 265-266, 335-336, 340-341
35-43
: Extract helpers to Cypress commandsloginUser and visitPluginPage are duplicated across suites. Move them into cypress/support/commands.js (or a shared util) for reuse and stability.
I can provide a commands.js snippet if helpful.
Also applies to: 46-50
cypress/e2e/features.cy.js (3)
69-70
: Use cy.contains for text instead of jQuery :contains inside getPrefer cy.contains('button', 'Settings') over cy.get('button:contains("Settings")') for clarity and reliability.
- cy.get('button:contains("Settings")').click() + cy.contains('button', 'Settings').click() @@ - cy.get('button:contains("Settings")').click() + cy.contains('button', 'Settings').click()Apply similarly at the other cited locations.
Also applies to: 86-87, 94-98, 111-118, 135-140
35-44
: Use forEach for side-effects (avoid map)map is unused; forEach is clearer for iterative assertions.
- const checkCollectionContent = ({ rowNb, contains }) => { + const checkCollectionContent = ({ rowNb, contains }) => { const row = `table[role='grid'] tbody tr:nth-child(${rowNb})` - contains.map(value => + contains.forEach(value => cy .get(row, { timeout: 10000, }) .contains(value, { timeout: 10000 }), - ) + ) }
46-64
: Avoid static waits in cy.session validateRely on content-based waits only. Drop cy.wait(1000) to reduce flakiness.
- cy.wait(1000) cy.contains('Hello User who can manage Meilisearch').should( 'be.visible', )
playground/package.json (1)
7-7
: Ensure target dir exists and overwrite deterministicallyPlain cp will fail if .tmp is missing. Create the directory and overwrite.
- "setup": "cp pre-seeded-database.db .tmp/data.db", + "setup": "mkdir -p .tmp && cp -f pre-seeded-database.db .tmp/data.db",If Windows support is required, consider using shx: "setup": "shx mkdir -p .tmp && shx cp -f pre-seeded-database.db .tmp/data.db".
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (5)
playground/.tmp/data.db
is excluded by!**/*.db
playground/pre-seeded-database.db
is excluded by!**/*.db
playground/types/generated/contentTypes.d.ts
is excluded by!**/generated/**
playground/yarn.lock
is excluded by!**/yarn.lock
,!**/*.lock
yarn.lock
is excluded by!**/yarn.lock
,!**/*.lock
📒 Files selected for processing (15)
.cursor/rules/cypress.mdc
(1 hunks).cursor/rules/general.mdc
(1 hunks).gitignore
(2 hunks)cypress/e2e/admin.cy.js
(0 hunks)cypress/e2e/features.cy.js
(1 hunks)cypress/e2e/permissions.cy.js
(1 hunks)cypress/e2e/roles.cy.js
(0 hunks)cypress/e2e/utils.js
(1 hunks)cypress/support/commands.js
(1 hunks)package.json
(2 hunks)playground/.gitignore
(1 hunks)playground/config/admin.js
(1 hunks)playground/package.json
(1 hunks)playground/src/api/restaurant/content-types/restaurant/schema.json
(1 hunks)playground/src/index.js
(1 hunks)
💤 Files with no reviewable changes (2)
- cypress/e2e/admin.cy.js
- cypress/e2e/roles.cy.js
🧰 Additional context used
🪛 Biome (2.1.2)
cypress/e2e/utils.js
[error] 1-6: Illegal use of an export declaration outside of a module
not allowed inside scripts
(parse)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: cypress-run
🔇 Additional comments (11)
.cursor/rules/cypress.mdc (1)
1-6
: LGTM!The Cursor rule configuration is well-structured and provides helpful context for developers working with Cypress tests.
package.json (1)
10-11
: Good separation of setup and dev scripts.The new
playground:setup
script and the simplifiedplayground:dev
script improve the workflow clarity and align with the seeding strategy refactor..cursor/rules/general.mdc (1)
1-7
: LGTM!The general rule configuration appropriately documents the project's package manager conventions.
playground/src/api/restaurant/content-types/restaurant/schema.json (1)
7-7
: LGTM!The capitalization of the display name improves the UI presentation and follows proper naming conventions.
.gitignore (2)
75-75
: LGTM!Enabling the
.tmp
directory ignore follows standard practices for temporary files.
136-139
: LGTM!The addition of
dist
to the ignore list and the exception forplayground/.tmp/data.db
properly support the new seeding strategy. The exception ensures the pre-seeded database remains tracked for the playground setup workflow.playground/.gitignore (1)
134-134
: LGTM!The trailing newline ensures proper file formatting.
cypress/support/commands.js (1)
33-51
: Nocy.login(
calls found. Manually verify any login invocations pass the requiredshouldContain
argument.cypress/e2e/features.cy.js (1)
141-165
: Sync after toggles: rely on intercepted aliases for each rowGood use of intercepts. Minor: ensure waits pair to each click to avoid race across loop iterations.
Consider moving waits inside the click branch (already done) and adding a short assertion per row after @fetchCollections completes, as you did below. LGTM otherwise.
playground/config/admin.js (1)
2-2
: autoOpen: false is appropriate for CI/test runsPrevents auto-opening the admin UI during setup. LGTM.
Confirm this property is supported in your Strapi version (5.9.0). If needed, we can quickly check docs.
playground/src/index.js (1)
7-17
: Use Strapi v5 APIs for queries and updates
- Replace
strapi.query('admin::user').findOne
withstrapi.db.query('admin::user').findOne
- Replace
adminUserService.updateById(adminUser.id, {...})
with the v5 update signature, e.g.:await strapi.db.query('admin::user').update({ where: { id: adminUser.id }, data: { password: 'password' }, });
cy.get('div[role="status').contains('success').should('be.visible') | ||
cy.get('div[role="status') | ||
.contains('Credentials successfully updated') | ||
.should('be.visible') | ||
cy.removeNotifications() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Invalid attribute selector; fix bracket/quote
Selector 'div[role="status' is malformed; tests will fail to locate the status element.
- cy.get('div[role="status').contains('success').should('be.visible')
- cy.get('div[role="status')
+ cy.get('div[role="status"]').contains('success').should('be.visible')
+ cy.get('div[role="status"]')
.contains('Credentials successfully updated')
.should('be.visible')
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
cy.get('div[role="status').contains('success').should('be.visible') | |
cy.get('div[role="status') | |
.contains('Credentials successfully updated') | |
.should('be.visible') | |
cy.removeNotifications() | |
cy.get('div[role="status"]').contains('success').should('be.visible') | |
cy.get('div[role="status"]') | |
.contains('Credentials successfully updated') | |
.should('be.visible') | |
cy.removeNotifications() |
🤖 Prompt for AI Agents
In cypress/e2e/features.cy.js around lines 77 to 81 the attribute selector is
malformed ('div[role="status' missing the closing quote and bracket), causing
the test to fail to find the status element; update both selectors to use the
correct syntax div[role="status"] (e.g.,
cy.get('div[role="status"]').contains('success').should('be.visible') and
cy.get('div[role="status"]').contains('Credentials successfully
updated').should('be.visible') so the attribute selector is properly closed.
cy.get('input[name="title').type('The slimy snail') | ||
cy.get('form').contains('button', 'Save').click() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix selector for title input
Missing closing bracket in attribute selector.
- cy.get('input[name="title').type('The slimy snail')
+ cy.get('input[name="title"]').type('The slimy snail')
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
cy.get('input[name="title').type('The slimy snail') | |
cy.get('form').contains('button', 'Save').click() | |
cy.get('input[name="title"]').type('The slimy snail') | |
cy.get('form').contains('button', 'Save').click() |
🤖 Prompt for AI Agents
In cypress/e2e/features.cy.js around lines 265 to 267 the attribute selector for
the title input is missing a closing quote/bracket: update the selector to
correctly target the input element (e.g., input[name="title"] ), then run the
test to ensure the .type('The slimy snail') call targets the field before
clicking the Save button.
it('cannot see the plugin in the sidepanel', () => { | ||
cy.visit(`${adminUrl}`) | ||
cy.get('nav').should('not.contain', 'a[aria-label="Meilisearch"]') | ||
}) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix negative existence assertion in sidepanel check
Using "not.contain" with a selector string checks text, not element presence. Assert element non-existence instead.
Apply this diff:
- cy.visit(`${adminUrl}`)
- cy.get('nav').should('not.contain', 'a[aria-label="Meilisearch"]')
+ cy.visit(`${adminUrl}`)
+ cy.get('nav').find('a[aria-label="Meilisearch"]').should('not.exist')
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
it('cannot see the plugin in the sidepanel', () => { | |
cy.visit(`${adminUrl}`) | |
cy.get('nav').should('not.contain', 'a[aria-label="Meilisearch"]') | |
}) | |
it('cannot see the plugin in the sidepanel', () => { | |
cy.visit(`${adminUrl}`) | |
cy.get('nav').find('a[aria-label="Meilisearch"]').should('not.exist') | |
}) |
🤖 Prompt for AI Agents
In cypress/e2e/permissions.cy.js around lines 71 to 75, the test uses
cy.get('nav').should('not.contain', 'a[aria-label="Meilisearch"]'), which checks
text content rather than element presence; change it to assert element
non-existence by querying the link selector inside the nav and asserting it does
not exist (for example, use nav.find('a[aria-label="Meilisearch"]') and assert
.should('not.exist') or use cy.get('nav').within(...) and assert the selector
does not exist).
it('cannot create an index', () => { | ||
visitPluginPage() | ||
// There are checkboxes in front of each collection | ||
cy.root().should('not.contain', 'button[role="checkbox"]') | ||
}) | ||
|
||
it('cannot change settings', () => { | ||
visitPluginPage() | ||
cy.root().should('not.contain', 'button:contains("Save")') | ||
}) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use existence checks, not text-based "not.contain"
For "cannot create index" and "cannot change settings", assert element absence directly.
- // There are checkboxes in front of each collection
- cy.root().should('not.contain', 'button[role="checkbox"]')
+ // There are checkboxes in front of each collection
+ cy.get('button[role="checkbox"]').should('not.exist')
@@
- cy.root().should('not.contain', 'button:contains("Save")')
+ cy.contains('button', 'Save').should('not.exist')
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
it('cannot create an index', () => { | |
visitPluginPage() | |
// There are checkboxes in front of each collection | |
cy.root().should('not.contain', 'button[role="checkbox"]') | |
}) | |
it('cannot change settings', () => { | |
visitPluginPage() | |
cy.root().should('not.contain', 'button:contains("Save")') | |
}) | |
}) | |
it('cannot create an index', () => { | |
visitPluginPage() | |
// There are checkboxes in front of each collection | |
cy.get('button[role="checkbox"]').should('not.exist') | |
}) | |
it('cannot change settings', () => { | |
visitPluginPage() | |
cy.contains('button', 'Save').should('not.exist') | |
}) | |
}) |
🤖 Prompt for AI Agents
In cypress/e2e/permissions.cy.js around lines 115 to 125, the tests use
text-based "not.contain" assertions to check absence; replace them with direct
DOM existence checks: for the "cannot create an index" test assert that the
checkbox button selector (button[role="checkbox"]) does not exist, and for the
"cannot change settings" test assert that the Save button (use a selector such
as a button containing the text "Save" or a specific save button selector) does
not exist; use Cypress existence assertions (e.g., .should('not.exist')) to
perform these checks.
cy.get('button[role="checkbox"]').first().should('not.be.checked') | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"be.checked" is invalid for button role checkboxes
The element is a button, not an input. Assert ARIA/data-state instead.
- cy.get('button[role="checkbox"]').first().should('not.be.checked')
+ cy.get('button[role="checkbox"]')
+ .first()
+ .should($btn => {
+ const state = $btn.attr('aria-checked') || $btn.attr('data-state')
+ expect(state).to.not.eq('true')
+ expect(state).to.not.eq('checked')
+ })
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
cy.get('button[role="checkbox"]').first().should('not.be.checked') | |
}) | |
cy.get('button[role="checkbox"]') | |
.first() | |
.should($btn => { | |
const state = $btn.attr('aria-checked') || $btn.attr('data-state') | |
expect(state).to.not.eq('true') | |
expect(state).to.not.eq('checked') | |
}) | |
}) |
🤖 Prompt for AI Agents
In cypress/e2e/permissions.cy.js around lines 304-305, the test uses
.should('not.be.checked') on a button with role="checkbox" which is invalid for
non-input elements; replace that assertion with an ARIA/data-state check — e.g.,
assert the element's aria-checked attribute equals "false"
(cy.get(...).first().should('have.attr', 'aria-checked', 'false')) or, if your
implementation uses data-state, assert the appropriate data-state value (e.g.,
'unchecked').
export const STRAPI_ADMIN_ROLES = { | ||
SUPER_ADMIN: 1, | ||
ADMIN: 2, | ||
EDITOR: 3, | ||
AUTHOR: 4, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Centralized role constants are good, but verify ES module configuration.
The STRAPI_ADMIN_ROLES
constant provides a clean centralized reference for role IDs across tests.
However, the static analysis error suggests this file may not be properly configured as an ES module. Ensure Cypress is configured to support ES modules (typically via cypress.config.js
with specPattern
and proper module settings).
🏁 Script executed:
#!/bin/bash
# Verify Cypress configuration supports ES modules
cat cypress.config.js 2>/dev/null || cat cypress.config.ts 2>/dev/null || echo "Cypress config not found"
Length of output: 836
Use CommonJS exports in cypress/e2e/utils.js
Cypress is configured as CommonJS, so replace the ES module export with:
-export const STRAPI_ADMIN_ROLES = {
+module.exports.STRAPI_ADMIN_ROLES = {
SUPER_ADMIN: 1,
ADMIN: 2,
EDITOR: 3,
AUTHOR: 4,
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
export const STRAPI_ADMIN_ROLES = { | |
SUPER_ADMIN: 1, | |
ADMIN: 2, | |
EDITOR: 3, | |
AUTHOR: 4, | |
} | |
module.exports.STRAPI_ADMIN_ROLES = { | |
SUPER_ADMIN: 1, | |
ADMIN: 2, | |
EDITOR: 3, | |
AUTHOR: 4, | |
} |
🧰 Tools
🪛 Biome (2.1.2)
[error] 1-6: Illegal use of an export declaration outside of a module
not allowed inside scripts
(parse)
🤖 Prompt for AI Agents
In cypress/e2e/utils.js lines 1-6, the file currently uses an ES module export;
change it to CommonJS by declaring the constant and exporting it with
module.exports. Replace the "export const STRAPI_ADMIN_ROLES = { ... }" syntax
with a plain const declaration and add "module.exports = { STRAPI_ADMIN_ROLES }"
so Cypress can require the value under CommonJS.
* @param {string} password | ||
*/ | ||
const login = ({ adminUrl, email, password }) => { | ||
const login = ({ adminUrl, email, password, shouldContain }) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a default value or validation for the shouldContain
parameter.
The new shouldContain
parameter is not optional but lacks a default value. If callers don't provide this parameter, Line 47 will fail with undefined being passed to cy.contains()
.
Apply this diff to provide a sensible default:
-const login = ({ adminUrl, email, password, shouldContain }) => {
+const login = ({ adminUrl, email, password, shouldContain = 'Welcome' }) => {
Or add validation:
const login = ({ adminUrl, email, password, shouldContain }) => {
+ if (!shouldContain) {
+ throw new Error('shouldContain parameter is required for login validation')
+ }
cy.session(
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const login = ({ adminUrl, email, password, shouldContain }) => { | |
const login = ({ adminUrl, email, password, shouldContain = 'Welcome' }) => { |
🤖 Prompt for AI Agents
In cypress/support/commands.js around line 33, the login function signature
currently declares shouldContain without a default which can pass undefined into
cy.contains(); update the function to either give shouldContain a safe default
(e.g. shouldContain = undefined) and only call cy.contains(shouldContain) when
it's not undefined, or add an explicit validation at the start of the function
that checks if shouldContain is provided before invoking cy.contains; ensure
callers behavior is unchanged when shouldContain is supplied.
"babel-jest": "^29.7.0", | ||
"concurrently": "^8.2.2", | ||
"cypress": "^14.0.1", | ||
"cypress": "^15.3.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
🧩 Analysis chain
Verify Cypress v15 compatibility.
The major version bump from Cypress ^14.0.1 to ^15.3.0 may introduce breaking changes. Ensure all existing tests remain compatible with Cypress v15.
🌐 Web query:
What are the breaking changes in Cypress v15 compared to v14?
💡 Result:
Short list of breaking changes introduced in Cypress v15 (changes you must address when moving from v14 → v15):
- Node.js support: Node 18 and 23 are no longer supported; supported installers require Node 20, 22, 24+. [1][2]
- Linux/glibc: Binaries no longer support Linux distributions with glibc older than 2.31. [1][2]
- Firefox automation: Chrome DevTools Protocol support for Firefox removed. [1]
- cy.exec result property rename: the returned property code → exitCode (update any .its('code') usages). [2]
- cy.stub signature: removed support for the deprecated three-argument signature of cy.stub. [1]
- API rename: Cypress.SelectorPlayground renamed to Cypress.ElementSelector (update any references). [3]
For migration details and examples see the official v15 changelog and migration guide. [1][2]
Sources: Cypress v15 changelog, v15 migration guide, Cypress blog post. [1][2][3]
Update tests for Cypress v15 breaking changes
- Ensure CI runs on Node 20/22/24+ (Node 18 & 23 unsupported)
- Verify Linux images use glibc ≥2.31
- Remove Firefox CDP automation usage
- Replace all
cy.exec().its('code')
→.its('exitCode')
- Remove any 3-argument
cy.stub()
calls - Rename
Cypress.SelectorPlayground
→Cypress.ElementSelector
// Update the password if it's not hashed (for existing users) | ||
if (adminUser.password === 'password') { | ||
const adminUserService = strapi.service('admin::user'); | ||
await adminUserService.updateById(adminUser.id, { | ||
password: 'password' | ||
}); | ||
console.log('✅ Admin user password updated with proper hash'); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Plaintext password comparison is ineffective
adminUser.password is hashed; comparing to 'password' will never be true. Either always set a known password during seeding (if desired) or skip resetting existing users.
- // Update the password if it's not hashed (for existing users)
- if (adminUser.password === 'password') {
- const adminUserService = strapi.service('admin::user');
- await adminUserService.updateById(adminUser.id, {
- password: 'password'
- });
- console.log('✅ Admin user password updated with proper hash');
- }
+ // Keep existing admin user as-is to avoid overriding credentials
+ // If you need to reset the password for tests, do it explicitly and unconditionally.
+ // Example (optional):
+ // const adminUserService = strapi.service('admin::user');
+ // await adminUserService.updateById(adminUser.id, { password: 'password' });
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
// Update the password if it's not hashed (for existing users) | |
if (adminUser.password === 'password') { | |
const adminUserService = strapi.service('admin::user'); | |
await adminUserService.updateById(adminUser.id, { | |
password: 'password' | |
}); | |
console.log('✅ Admin user password updated with proper hash'); | |
} | |
// Keep existing admin user as-is to avoid overriding credentials | |
// If you need to reset the password for tests, do it explicitly and unconditionally. | |
// Example (optional): | |
// const adminUserService = strapi.service('admin::user'); | |
// await adminUserService.updateById(adminUser.id, { password: 'password' }); |
what
Refactor Cypress tests to:
how
Summary by CodeRabbit
New Features
Tests
Chores
CI