@nextsparkjs/theme-default 0.1.0-beta.20 → 0.1.0-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/tests/cypress/e2e/_devtools/access.bdd.md +262 -0
- package/tests/cypress/e2e/_devtools/access.cy.ts +171 -0
- package/tests/cypress/e2e/_devtools/navigation.bdd.md +261 -0
- package/tests/cypress/e2e/_devtools/navigation.cy.ts +157 -0
- package/tests/cypress/e2e/_devtools/pages.bdd.md +303 -0
- package/tests/cypress/e2e/_devtools/pages.cy.ts +184 -0
- package/tests/cypress/e2e/_docs/README.md +215 -0
- package/tests/cypress/e2e/_docs/tutorials/sector7-superadmin-teams.narration.json +155 -0
- package/tests/cypress/e2e/_docs/tutorials/sector7-superadmin.cy.ts +390 -0
- package/tests/cypress/e2e/_docs/tutorials/teams-system.doc.cy.ts +349 -0
- package/tests/cypress/e2e/_docs/tutorials/teams-system.narration.json +165 -0
- package/tests/cypress/e2e/_selectors/auth.cy.ts +306 -0
- package/tests/cypress/e2e/_selectors/billing.cy.ts +89 -0
- package/tests/cypress/e2e/_selectors/dashboard-mobile.cy.ts +113 -0
- package/tests/cypress/e2e/_selectors/dashboard-navigation.cy.ts +89 -0
- package/tests/cypress/e2e/_selectors/dashboard-sidebar.cy.ts +60 -0
- package/tests/cypress/e2e/_selectors/dashboard-topnav.cy.ts +146 -0
- package/tests/cypress/e2e/_selectors/devtools.cy.ts +210 -0
- package/tests/cypress/e2e/_selectors/global-search.cy.ts +88 -0
- package/tests/cypress/e2e/_selectors/pages-editor.cy.ts +179 -0
- package/tests/cypress/e2e/_selectors/posts-editor.cy.ts +282 -0
- package/tests/cypress/e2e/_selectors/public.cy.ts +112 -0
- package/tests/cypress/e2e/_selectors/settings-api-keys.cy.ts +228 -0
- package/tests/cypress/e2e/_selectors/settings-billing.cy.ts +105 -0
- package/tests/cypress/e2e/_selectors/settings-layout.cy.ts +119 -0
- package/tests/cypress/e2e/_selectors/settings-password.cy.ts +71 -0
- package/tests/cypress/e2e/_selectors/settings-profile.cy.ts +82 -0
- package/tests/cypress/e2e/_selectors/settings-teams.cy.ts +68 -0
- package/tests/cypress/e2e/_selectors/superadmin.cy.ts +185 -0
- package/tests/cypress/e2e/_selectors/tasks.cy.ts +242 -0
- package/tests/cypress/e2e/_selectors/taxonomies.cy.ts +126 -0
- package/tests/cypress/e2e/_selectors/teams.cy.ts +142 -0
- package/tests/cypress/e2e/_superadmin/all-teams.bdd.md +261 -0
- package/tests/cypress/e2e/_superadmin/all-teams.cy.ts +177 -0
- package/tests/cypress/e2e/_superadmin/all-users.bdd.md +406 -0
- package/tests/cypress/e2e/_superadmin/all-users.cy.ts +294 -0
- package/tests/cypress/e2e/_superadmin/dashboard.bdd.md +235 -0
- package/tests/cypress/e2e/_superadmin/dashboard.cy.ts +149 -0
- package/tests/cypress/e2e/_superadmin/subscriptions-overview.bdd.md +290 -0
- package/tests/cypress/e2e/_superadmin/subscriptions-overview.cy.ts +194 -0
- package/tests/cypress/e2e/ai/ai-usage.cy.ts +209 -0
- package/tests/cypress/e2e/ai/chat-api.cy.ts +107 -0
- package/tests/cypress/e2e/ai/guardrails.cy.ts +332 -0
- package/tests/cypress/e2e/api/billing/BillingAPIController.js +319 -0
- package/tests/cypress/e2e/api/billing/check-action.cy.ts +326 -0
- package/tests/cypress/e2e/api/billing/checkout.cy.ts +358 -0
- package/tests/cypress/e2e/api/billing/lifecycle.cy.ts +423 -0
- package/tests/cypress/e2e/api/billing/plans/README.md +345 -0
- package/tests/cypress/e2e/api/billing/plans/business.cy.ts +412 -0
- package/tests/cypress/e2e/api/billing/plans/downgrade.cy.ts +510 -0
- package/tests/cypress/e2e/api/billing/plans/fixtures/billing-plans.json +163 -0
- package/tests/cypress/e2e/api/billing/plans/free.cy.ts +500 -0
- package/tests/cypress/e2e/api/billing/plans/pro.cy.ts +497 -0
- package/tests/cypress/e2e/api/billing/plans/starter.cy.ts +342 -0
- package/tests/cypress/e2e/api/billing/portal.cy.ts +313 -0
- package/tests/cypress/e2e/api/devtools/registries.bdd.md +300 -0
- package/tests/cypress/e2e/api/devtools/registries.cy.ts +368 -0
- package/tests/cypress/e2e/api/entities/blocks-scope.cy.ts +396 -0
- package/tests/cypress/e2e/api/entities/customers-crud.cy.ts +648 -0
- package/tests/cypress/e2e/api/entities/customers-metas.cy.ts +839 -0
- package/tests/cypress/e2e/api/entities/pages-crud.cy.ts +425 -0
- package/tests/cypress/e2e/api/entities/pages-status.cy.ts +335 -0
- package/tests/cypress/e2e/api/entities/post-categories-crud.cy.ts +610 -0
- package/tests/cypress/e2e/api/entities/posts-crud.cy.ts +709 -0
- package/tests/cypress/e2e/api/entities/posts-status.cy.ts +396 -0
- package/tests/cypress/e2e/api/entities/tasks-crud.cy.ts +602 -0
- package/tests/cypress/e2e/api/entities/tasks-metas.cy.ts +878 -0
- package/tests/cypress/e2e/api/entities/users-crud.cy.ts +469 -0
- package/tests/cypress/e2e/api/entities/users-metas.cy.ts +913 -0
- package/tests/cypress/e2e/api/entities/users-security.cy.ts +375 -0
- package/tests/cypress/e2e/api/scheduled-actions/cron-endpoint.bdd.md +375 -0
- package/tests/cypress/e2e/api/scheduled-actions/cron-endpoint.cy.ts +346 -0
- package/tests/cypress/e2e/api/scheduled-actions/devtools-endpoint.bdd.md +451 -0
- package/tests/cypress/e2e/api/scheduled-actions/devtools-endpoint.cy.ts +447 -0
- package/tests/cypress/e2e/api/scheduled-actions/scheduling.bdd.md +649 -0
- package/tests/cypress/e2e/api/scheduled-actions/scheduling.cy.ts +333 -0
- package/tests/cypress/e2e/api/settings/api-keys.crud.cy.ts +923 -0
- package/tests/cypress/e2e/uat/auth/app-roles/developer-login.bdd.md +231 -0
- package/tests/cypress/e2e/uat/auth/app-roles/developer-login.cy.ts +144 -0
- package/tests/cypress/e2e/uat/auth/app-roles/superadmin-login.bdd.md +118 -0
- package/tests/cypress/e2e/uat/auth/app-roles/superadmin-login.cy.ts +84 -0
- package/tests/cypress/e2e/uat/auth/custom-roles/editor-login.bdd.md +288 -0
- package/tests/cypress/e2e/uat/auth/custom-roles/editor-login.cy.ts +188 -0
- package/tests/cypress/e2e/uat/auth/login-logout.bdd.md +160 -0
- package/tests/cypress/e2e/uat/auth/login-logout.cy.ts +116 -0
- package/tests/cypress/e2e/uat/auth/password-reset.bdd.md +289 -0
- package/tests/cypress/e2e/uat/auth/password-reset.cy.ts +200 -0
- package/tests/cypress/e2e/uat/auth/team-roles/admin-login.bdd.md +225 -0
- package/tests/cypress/e2e/uat/auth/team-roles/admin-login.cy.ts +148 -0
- package/tests/cypress/e2e/uat/auth/team-roles/member-login.bdd.md +251 -0
- package/tests/cypress/e2e/uat/auth/team-roles/member-login.cy.ts +163 -0
- package/tests/cypress/e2e/uat/auth/team-roles/owner-login.bdd.md +231 -0
- package/tests/cypress/e2e/uat/auth/team-roles/owner-login.cy.ts +141 -0
- package/tests/cypress/e2e/uat/billing/extended.bdd.md +273 -0
- package/tests/cypress/e2e/uat/billing/extended.cy.ts +209 -0
- package/tests/cypress/e2e/uat/billing/feature-gates.bdd.md +407 -0
- package/tests/cypress/e2e/uat/billing/feature-gates.cy.ts +307 -0
- package/tests/cypress/e2e/uat/billing/page.bdd.md +329 -0
- package/tests/cypress/e2e/uat/billing/page.cy.ts +250 -0
- package/tests/cypress/e2e/uat/billing/status.bdd.md +190 -0
- package/tests/cypress/e2e/uat/billing/status.cy.ts +145 -0
- package/tests/cypress/e2e/uat/billing/team-switch.bdd.md +156 -0
- package/tests/cypress/e2e/uat/billing/team-switch.cy.ts +122 -0
- package/tests/cypress/e2e/uat/billing/usage.bdd.md +218 -0
- package/tests/cypress/e2e/uat/billing/usage.cy.ts +176 -0
- package/tests/cypress/e2e/uat/blocks/hero.bdd.md +124 -0
- package/tests/cypress/e2e/uat/blocks/hero.cy.ts +56 -0
- package/tests/cypress/e2e/uat/devtools/api-tester.cy.ts +390 -0
- package/tests/cypress/e2e/uat/entities/customers/member.bdd.md +275 -0
- package/tests/cypress/e2e/uat/entities/customers/member.cy.ts +122 -0
- package/tests/cypress/e2e/uat/entities/customers/owner.bdd.md +243 -0
- package/tests/cypress/e2e/uat/entities/customers/owner.cy.ts +165 -0
- package/tests/cypress/e2e/uat/entities/pages/block-crud.bdd.md +476 -0
- package/tests/cypress/e2e/uat/entities/pages/block-crud.cy.ts +486 -0
- package/tests/cypress/e2e/uat/entities/pages/block-editor.bdd.md +460 -0
- package/tests/cypress/e2e/uat/entities/pages/block-editor.cy.ts +301 -0
- package/tests/cypress/e2e/uat/entities/pages/list.bdd.md +432 -0
- package/tests/cypress/e2e/uat/entities/pages/list.cy.ts +273 -0
- package/tests/cypress/e2e/uat/entities/pages/public-rendering.bdd.md +696 -0
- package/tests/cypress/e2e/uat/entities/pages/public-rendering.cy.ts +340 -0
- package/tests/cypress/e2e/uat/entities/posts/categories-api-aware.bdd.md +161 -0
- package/tests/cypress/e2e/uat/entities/posts/categories-api-aware.cy.ts +104 -0
- package/tests/cypress/e2e/uat/entities/posts/categories.bdd.md +375 -0
- package/tests/cypress/e2e/uat/entities/posts/categories.cy.ts +241 -0
- package/tests/cypress/e2e/uat/entities/posts/editor.bdd.md +429 -0
- package/tests/cypress/e2e/uat/entities/posts/editor.cy.ts +257 -0
- package/tests/cypress/e2e/uat/entities/posts/list.bdd.md +340 -0
- package/tests/cypress/e2e/uat/entities/posts/list.cy.ts +177 -0
- package/tests/cypress/e2e/uat/entities/posts/public.bdd.md +614 -0
- package/tests/cypress/e2e/uat/entities/posts/public.cy.ts +249 -0
- package/tests/cypress/e2e/uat/entities/tasks/member.bdd.md +222 -0
- package/tests/cypress/e2e/uat/entities/tasks/member.cy.ts +165 -0
- package/tests/cypress/e2e/uat/entities/tasks/owner.bdd.md +419 -0
- package/tests/cypress/e2e/uat/entities/tasks/owner.cy.ts +191 -0
- package/tests/cypress/e2e/uat/roles/editor-role.bdd.md +552 -0
- package/tests/cypress/e2e/uat/roles/editor-role.cy.ts +210 -0
- package/tests/cypress/e2e/uat/roles/member-restrictions.bdd.md +450 -0
- package/tests/cypress/e2e/uat/roles/member-restrictions.cy.ts +189 -0
- package/tests/cypress/e2e/uat/roles/owner-full-crud.bdd.md +530 -0
- package/tests/cypress/e2e/uat/roles/owner-full-crud.cy.ts +247 -0
- package/tests/cypress/e2e/uat/scheduled-actions/devtools-ui.bdd.md +736 -0
- package/tests/cypress/e2e/uat/scheduled-actions/devtools-ui.cy.ts +740 -0
- package/tests/cypress/e2e/uat/teams/roles-matrix.bdd.md +553 -0
- package/tests/cypress/e2e/uat/teams/roles-matrix.cy.ts +185 -0
- package/tests/cypress/e2e/uat/teams/switcher.bdd.md +1151 -0
- package/tests/cypress/e2e/uat/teams/switcher.cy.ts +497 -0
- package/tests/cypress/e2e/uat/teams/team-switcher.md +198 -0
- package/tests/cypress/fixtures/blocks.json +218 -0
- package/tests/cypress/fixtures/entities.json +78 -0
- package/tests/cypress/fixtures/page-builder.json +21 -0
- package/tests/cypress/src/components/CategoriesPOM.ts +382 -0
- package/tests/cypress/src/components/CustomersPOM.ts +439 -0
- package/tests/cypress/src/components/DevKeyringPOM.ts +160 -0
- package/tests/cypress/src/components/EntityForm.ts +375 -0
- package/tests/cypress/src/components/EntityList.ts +389 -0
- package/tests/cypress/src/components/PageBuilderPOM.ts +710 -0
- package/tests/cypress/src/components/PostEditorPOM.ts +370 -0
- package/tests/cypress/src/components/PostsListPOM.ts +223 -0
- package/tests/cypress/src/components/PublicPagePOM.ts +447 -0
- package/tests/cypress/src/components/PublicPostPOM.ts +146 -0
- package/tests/cypress/src/components/TasksPOM.ts +272 -0
- package/tests/cypress/src/components/TeamSwitcherPOM.ts +450 -0
- package/tests/cypress/src/components/index.ts +21 -0
- package/tests/cypress/src/controllers/ApiKeysAPIController.js +178 -0
- package/tests/cypress/src/controllers/BaseAPIController.js +317 -0
- package/tests/cypress/src/controllers/CustomerAPIController.js +251 -0
- package/tests/cypress/src/controllers/PagesAPIController.js +226 -0
- package/tests/cypress/src/controllers/PostsAPIController.js +250 -0
- package/tests/cypress/src/controllers/TaskAPIController.js +240 -0
- package/tests/cypress/src/controllers/UsersAPIController.js +242 -0
- package/tests/cypress/src/controllers/index.js +25 -0
- package/tests/cypress/src/core/AuthPOM.ts +450 -0
- package/tests/cypress/src/core/BasePOM.ts +86 -0
- package/tests/cypress/src/core/BlockEditorBasePOM.ts +576 -0
- package/tests/cypress/src/core/DashboardEntityPOM.ts +692 -0
- package/tests/cypress/src/core/index.ts +14 -0
- package/tests/cypress/src/entities/CustomersPOM.ts +172 -0
- package/tests/cypress/src/entities/PagesPOM.ts +137 -0
- package/tests/cypress/src/entities/PostsPOM.ts +137 -0
- package/tests/cypress/src/entities/TasksPOM.ts +176 -0
- package/tests/cypress/src/entities/index.ts +14 -0
- package/tests/cypress/src/features/BillingPOM.ts +385 -0
- package/tests/cypress/src/features/DashboardPOM.ts +245 -0
- package/tests/cypress/src/features/DevtoolsPOM.ts +739 -0
- package/tests/cypress/src/features/PageBuilderPOM.ts +263 -0
- package/tests/cypress/src/features/PostEditorPOM.ts +313 -0
- package/tests/cypress/src/features/ScheduledActionsPOM.ts +463 -0
- package/tests/cypress/src/features/SettingsPOM.ts +362 -0
- package/tests/cypress/src/features/SuperadminPOM.ts +331 -0
- package/tests/cypress/src/features/SuperadminTeamRolesPOM.ts +285 -0
- package/tests/cypress/src/features/index.ts +28 -0
- package/tests/cypress/src/helpers/ApiInterceptor.ts +177 -0
- package/tests/cypress/src/index.ts +101 -0
- package/tests/cypress/src/pages/dashboard/Dashboard.js +677 -0
- package/tests/cypress/src/pages/dashboard/DashboardPage.js +43 -0
- package/tests/cypress/src/pages/dashboard/DashboardStats.js +546 -0
- package/tests/cypress/src/pages/dashboard/index.js +6 -0
- package/tests/cypress/src/pages/index.js +5 -0
- package/tests/cypress/src/pages/public/FeaturesPage.js +28 -0
- package/tests/cypress/src/pages/public/LandingPage.js +69 -0
- package/tests/cypress/src/pages/public/PricingPage.js +33 -0
- package/tests/cypress/src/pages/public/index.js +6 -0
- package/tests/cypress/src/selectors.ts +46 -0
- package/tests/cypress/src/session-helpers.ts +500 -0
- package/tests/cypress/support/doc-commands.ts +260 -0
- package/tests/cypress.config.ts +150 -0
- package/tests/jest/components/post-header.test.tsx +377 -0
- package/tests/jest/config/role-config.test.ts +529 -0
- package/tests/jest/jest.config.ts +81 -0
- package/tests/jest/langchain/COVERAGE.md +372 -0
- package/tests/jest/langchain/guardrails.test.ts +465 -0
- package/tests/jest/langchain/streaming.test.ts +367 -0
- package/tests/jest/langchain/token-tracker.test.ts +455 -0
- package/tests/jest/langchain/tracer-callbacks.test.ts +881 -0
- package/tests/jest/langchain/tracer.test.ts +823 -0
- package/tests/jest/user-roles/role-helpers.test.ts +432 -0
- package/tests/jest/validation/categories.test.ts +429 -0
- package/tests/jest/validation/posts.test.ts +546 -0
- package/tests/tsconfig.json +15 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
import * as allure from 'allure-cypress'
|
|
4
|
+
|
|
5
|
+
import { DevKeyringPOM } from '../../../src/components/DevKeyringPOM'
|
|
6
|
+
import { DEFAULT_THEME_USERS } from '../../../src/session-helpers'
|
|
7
|
+
|
|
8
|
+
describe('Authentication - DevKeyring Flow', {
|
|
9
|
+
tags: ['@uat', '@feat-auth', '@smoke', '@regression']
|
|
10
|
+
}, () => {
|
|
11
|
+
const devKeyring = DevKeyringPOM.create()
|
|
12
|
+
const users = DEFAULT_THEME_USERS
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
allure.epic('UAT')
|
|
16
|
+
allure.feature('Authentication')
|
|
17
|
+
allure.story('DevKeyring Login')
|
|
18
|
+
// Clear cookies and localStorage to ensure fresh state
|
|
19
|
+
cy.clearCookies()
|
|
20
|
+
cy.clearLocalStorage()
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
describe('LOGIN_001: Owner Login via DevKeyring', { tags: '@smoke' }, () => {
|
|
24
|
+
it('should login as Owner and access dashboard', { tags: '@smoke' }, () => {
|
|
25
|
+
allure.severity('critical')
|
|
26
|
+
|
|
27
|
+
// 1. Visit login page
|
|
28
|
+
cy.visit('/login')
|
|
29
|
+
|
|
30
|
+
// 2. Validate DevKeyring is visible
|
|
31
|
+
devKeyring.validateVisible()
|
|
32
|
+
|
|
33
|
+
// 3. Login as Owner using email
|
|
34
|
+
devKeyring.quickLoginByEmail(users.OWNER)
|
|
35
|
+
|
|
36
|
+
// 4. Validate dashboard access
|
|
37
|
+
cy.url().should('include', '/dashboard')
|
|
38
|
+
cy.get('[data-cy="dashboard-container"]').should('be.visible')
|
|
39
|
+
|
|
40
|
+
cy.log(`✅ Owner login successful (${users.OWNER})`)
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
describe('LOGIN_002: Member Login via DevKeyring', { tags: '@smoke' }, () => {
|
|
45
|
+
it('should login as Member and access dashboard', { tags: '@smoke' }, () => {
|
|
46
|
+
allure.severity('critical')
|
|
47
|
+
|
|
48
|
+
// 1. Visit login page
|
|
49
|
+
cy.visit('/login')
|
|
50
|
+
|
|
51
|
+
// 2. Validate DevKeyring is visible
|
|
52
|
+
devKeyring.validateVisible()
|
|
53
|
+
|
|
54
|
+
// 3. Login as Member using email
|
|
55
|
+
devKeyring.quickLoginByEmail(users.MEMBER)
|
|
56
|
+
|
|
57
|
+
// 4. Validate dashboard access
|
|
58
|
+
cy.url().should('include', '/dashboard')
|
|
59
|
+
cy.get('[data-cy="dashboard-container"]').should('be.visible')
|
|
60
|
+
|
|
61
|
+
cy.log(`✅ Member login successful (${users.MEMBER})`)
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
describe('LOGIN_003: Admin Login via DevKeyring', () => {
|
|
66
|
+
it('should login as Admin and access dashboard', () => {
|
|
67
|
+
// 1. Visit login page
|
|
68
|
+
cy.visit('/login')
|
|
69
|
+
|
|
70
|
+
// 2. Validate DevKeyring is visible
|
|
71
|
+
devKeyring.validateVisible()
|
|
72
|
+
|
|
73
|
+
// 3. Login as Admin using email
|
|
74
|
+
devKeyring.quickLoginByEmail(users.ADMIN)
|
|
75
|
+
|
|
76
|
+
// 4. Validate dashboard access
|
|
77
|
+
cy.url().should('include', '/dashboard')
|
|
78
|
+
cy.get('[data-cy="dashboard-container"]').should('be.visible')
|
|
79
|
+
|
|
80
|
+
cy.log(`✅ Admin login successful (${users.ADMIN})`)
|
|
81
|
+
})
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
describe('LOGOUT_001: User Logout Flow', () => {
|
|
85
|
+
it('should logout successfully and redirect to login', () => {
|
|
86
|
+
// Set desktop viewport to show TopNavbar (requires lg: 1024px+)
|
|
87
|
+
cy.viewport(1280, 800)
|
|
88
|
+
|
|
89
|
+
// 1. Login first as Owner
|
|
90
|
+
cy.visit('/login')
|
|
91
|
+
devKeyring.quickLoginByEmail(users.OWNER)
|
|
92
|
+
|
|
93
|
+
// Wait for dashboard to fully load
|
|
94
|
+
cy.url().should('include', '/dashboard')
|
|
95
|
+
cy.get('[data-cy="dashboard-container"]').should('be.visible')
|
|
96
|
+
|
|
97
|
+
// Wait for user menu to be available (session loaded)
|
|
98
|
+
// TopNavbar uses useAuth() which has loading state
|
|
99
|
+
cy.get('[data-cy="topnav-user-menu-trigger"]', { timeout: 15000 }).should('be.visible')
|
|
100
|
+
|
|
101
|
+
// 2. Logout via user menu
|
|
102
|
+
cy.get('[data-cy="topnav-user-menu-trigger"]').click()
|
|
103
|
+
cy.get('[data-cy="topnav-menu-signOut"]').should('be.visible').click()
|
|
104
|
+
|
|
105
|
+
// 3. Validate redirected to login and DevKeyring is visible again
|
|
106
|
+
cy.url().should('include', '/login')
|
|
107
|
+
devKeyring.validateVisible()
|
|
108
|
+
|
|
109
|
+
cy.log('✅ Logout successful')
|
|
110
|
+
})
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
after(() => {
|
|
114
|
+
cy.log('✅ Authentication tests completed')
|
|
115
|
+
})
|
|
116
|
+
})
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
---
|
|
2
|
+
feature: Password Reset Flow
|
|
3
|
+
priority: critical
|
|
4
|
+
tags: [auth, password-reset, security, user-flow]
|
|
5
|
+
grepTags: [uat, feat-auth, password-reset]
|
|
6
|
+
coverage: 8
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Password Reset Flow
|
|
10
|
+
|
|
11
|
+
> Tests for the password reset flow including page access, form validation, submission, and error handling. Actual email delivery is not tested as it requires external service integration.
|
|
12
|
+
|
|
13
|
+
## @test PWD-RESET-001: Access Password Reset Page
|
|
14
|
+
|
|
15
|
+
### Metadata
|
|
16
|
+
- **Priority:** Critical
|
|
17
|
+
- **Type:** Smoke
|
|
18
|
+
- **Tags:** password-reset, navigation
|
|
19
|
+
- **Grep:** `@smoke`
|
|
20
|
+
|
|
21
|
+
```gherkin:en
|
|
22
|
+
Scenario: Access password reset page from login
|
|
23
|
+
|
|
24
|
+
Given I am on the login page
|
|
25
|
+
When I click on the forgot password link
|
|
26
|
+
Then I should be on /forgot-password
|
|
27
|
+
And the password reset form should be visible
|
|
28
|
+
And the email input should be visible
|
|
29
|
+
And the submit button should be visible
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```gherkin:es
|
|
33
|
+
Scenario: Acceder a pagina de reset de password desde login
|
|
34
|
+
|
|
35
|
+
Given estoy en la pagina de login
|
|
36
|
+
When hago click en el enlace de olvide mi password
|
|
37
|
+
Then deberia estar en /forgot-password
|
|
38
|
+
And el formulario de reset deberia estar visible
|
|
39
|
+
And el input de email deberia estar visible
|
|
40
|
+
And el boton de enviar deberia estar visible
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Expected Results
|
|
44
|
+
- Forgot password link works
|
|
45
|
+
- Password reset page loads
|
|
46
|
+
- All form elements visible
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## @test PWD-RESET-002: Direct URL Access
|
|
51
|
+
|
|
52
|
+
### Metadata
|
|
53
|
+
- **Priority:** Normal
|
|
54
|
+
- **Type:** Smoke
|
|
55
|
+
- **Tags:** password-reset, direct-access
|
|
56
|
+
- **Grep:** `@smoke`
|
|
57
|
+
|
|
58
|
+
```gherkin:en
|
|
59
|
+
Scenario: Access password reset page directly via URL
|
|
60
|
+
|
|
61
|
+
Given I visit /forgot-password directly
|
|
62
|
+
Then the password reset container should be visible
|
|
63
|
+
And the email input should be visible
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```gherkin:es
|
|
67
|
+
Scenario: Acceder a pagina de reset directamente via URL
|
|
68
|
+
|
|
69
|
+
Given visito /forgot-password directamente
|
|
70
|
+
Then el contenedor de reset deberia estar visible
|
|
71
|
+
And el input de email deberia estar visible
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Expected Results
|
|
75
|
+
- Direct URL access works
|
|
76
|
+
- No authentication required
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## @test PWD-RESET-003: Submit Valid Email
|
|
81
|
+
|
|
82
|
+
### Metadata
|
|
83
|
+
- **Priority:** Critical
|
|
84
|
+
- **Type:** Smoke
|
|
85
|
+
- **Tags:** password-reset, submit
|
|
86
|
+
- **Grep:** `@smoke`
|
|
87
|
+
|
|
88
|
+
```gherkin:en
|
|
89
|
+
Scenario: Submit password reset with valid email format
|
|
90
|
+
|
|
91
|
+
Given I am on the password reset page
|
|
92
|
+
When I enter a valid email format (user@example.com)
|
|
93
|
+
And I click the submit button
|
|
94
|
+
Then I should see a success message
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
```gherkin:es
|
|
98
|
+
Scenario: Enviar reset de password con email valido
|
|
99
|
+
|
|
100
|
+
Given estoy en la pagina de reset de password
|
|
101
|
+
When ingreso un email con formato valido (user@example.com)
|
|
102
|
+
And hago click en el boton de enviar
|
|
103
|
+
Then deberia ver un mensaje de exito
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Expected Results
|
|
107
|
+
- Form submits successfully
|
|
108
|
+
- Success message displayed
|
|
109
|
+
- No email enumeration (same message for existing/non-existing)
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## @test PWD-RESET-004: Validate Empty Email
|
|
114
|
+
|
|
115
|
+
### Metadata
|
|
116
|
+
- **Priority:** High
|
|
117
|
+
- **Type:** Validation
|
|
118
|
+
- **Tags:** password-reset, validation, empty
|
|
119
|
+
|
|
120
|
+
```gherkin:en
|
|
121
|
+
Scenario: Show error for empty email field
|
|
122
|
+
|
|
123
|
+
Given I am on the password reset page
|
|
124
|
+
When I click submit without entering an email
|
|
125
|
+
Then I should see a required field error
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
```gherkin:es
|
|
129
|
+
Scenario: Mostrar error para campo email vacio
|
|
130
|
+
|
|
131
|
+
Given estoy en la pagina de reset de password
|
|
132
|
+
When hago click en enviar sin ingresar email
|
|
133
|
+
Then deberia ver un error de campo requerido
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Expected Results
|
|
137
|
+
- Validation error displayed
|
|
138
|
+
- Form not submitted
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## @test PWD-RESET-005: Validate Invalid Email Format
|
|
143
|
+
|
|
144
|
+
### Metadata
|
|
145
|
+
- **Priority:** High
|
|
146
|
+
- **Type:** Validation
|
|
147
|
+
- **Tags:** password-reset, validation, format
|
|
148
|
+
|
|
149
|
+
```gherkin:en
|
|
150
|
+
Scenario: Show error for invalid email format
|
|
151
|
+
|
|
152
|
+
Given I am on the password reset page
|
|
153
|
+
When I enter an invalid email format (not-an-email)
|
|
154
|
+
And I click the submit button
|
|
155
|
+
Then I should see an invalid email error
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
```gherkin:es
|
|
159
|
+
Scenario: Mostrar error para formato de email invalido
|
|
160
|
+
|
|
161
|
+
Given estoy en la pagina de reset de password
|
|
162
|
+
When ingreso un formato de email invalido (not-an-email)
|
|
163
|
+
And hago click en el boton de enviar
|
|
164
|
+
Then deberia ver un error de email invalido
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Expected Results
|
|
168
|
+
- Format validation works
|
|
169
|
+
- Clear error message
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## @test PWD-RESET-006: Back to Login Link
|
|
174
|
+
|
|
175
|
+
### Metadata
|
|
176
|
+
- **Priority:** Normal
|
|
177
|
+
- **Type:** Navigation
|
|
178
|
+
- **Tags:** password-reset, navigation
|
|
179
|
+
|
|
180
|
+
```gherkin:en
|
|
181
|
+
Scenario: Navigate back to login page
|
|
182
|
+
|
|
183
|
+
Given I am on the password reset page
|
|
184
|
+
When I click the back to login link
|
|
185
|
+
Then I should be on the login page
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
```gherkin:es
|
|
189
|
+
Scenario: Navegar de vuelta a pagina de login
|
|
190
|
+
|
|
191
|
+
Given estoy en la pagina de reset de password
|
|
192
|
+
When hago click en el enlace de volver a login
|
|
193
|
+
Then deberia estar en la pagina de login
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Expected Results
|
|
197
|
+
- Back link works
|
|
198
|
+
- Returns to login page
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## @test PWD-RESET-007: Submit with Known Test Email
|
|
203
|
+
|
|
204
|
+
### Metadata
|
|
205
|
+
- **Priority:** High
|
|
206
|
+
- **Type:** Regression
|
|
207
|
+
- **Tags:** password-reset, existing-user
|
|
208
|
+
|
|
209
|
+
```gherkin:en
|
|
210
|
+
Scenario: Handle submission with existing user email
|
|
211
|
+
|
|
212
|
+
Given I am on the password reset page
|
|
213
|
+
When I enter a known test email (carlos.mendoza@nextspark.dev)
|
|
214
|
+
And I click the submit button
|
|
215
|
+
Then I should see a success message
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
```gherkin:es
|
|
219
|
+
Scenario: Manejar envio con email de usuario existente
|
|
220
|
+
|
|
221
|
+
Given estoy en la pagina de reset de password
|
|
222
|
+
When ingreso un email de prueba conocido (carlos.mendoza@nextspark.dev)
|
|
223
|
+
And hago click en el boton de enviar
|
|
224
|
+
Then deberia ver un mensaje de exito
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Expected Results
|
|
228
|
+
- Same success message as non-existing email
|
|
229
|
+
- No email enumeration vulnerability
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## @test PWD-RESET-008: Form Keyboard Accessibility
|
|
234
|
+
|
|
235
|
+
### Metadata
|
|
236
|
+
- **Priority:** Normal
|
|
237
|
+
- **Type:** Accessibility
|
|
238
|
+
- **Tags:** password-reset, keyboard, a11y
|
|
239
|
+
|
|
240
|
+
```gherkin:en
|
|
241
|
+
Scenario: Submit form with Enter key
|
|
242
|
+
|
|
243
|
+
Given I am on the password reset page
|
|
244
|
+
When I enter an email and press Enter
|
|
245
|
+
Then the form should be submitted
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
```gherkin:es
|
|
249
|
+
Scenario: Enviar formulario con tecla Enter
|
|
250
|
+
|
|
251
|
+
Given estoy en la pagina de reset de password
|
|
252
|
+
When ingreso un email y presiono Enter
|
|
253
|
+
Then el formulario deberia ser enviado
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Expected Results
|
|
257
|
+
- Enter key submits form
|
|
258
|
+
- Keyboard navigation works
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## UI Elements
|
|
263
|
+
|
|
264
|
+
| Element | Selector | Description |
|
|
265
|
+
|---------|----------|-------------|
|
|
266
|
+
| Forgot Password Link | `[data-cy="login-forgot-password"]` | Link on login page |
|
|
267
|
+
| Form | `[data-cy="forgot-password-form"]` | Password reset form |
|
|
268
|
+
| Email Input | `[data-cy="forgot-password-email"]` | Email input field |
|
|
269
|
+
| Submit Button | `[data-cy="forgot-password-submit"]` | Submit button |
|
|
270
|
+
| Success Message | `[data-cy="forgot-password-success"]` | Success message |
|
|
271
|
+
| Error Message | `[data-cy="forgot-password-error"]` | Error message |
|
|
272
|
+
| Back to Login | `[data-cy="forgot-password-back"]` | Back to login link |
|
|
273
|
+
|
|
274
|
+
> Note: Tests use `AuthPOM` from `src/core/AuthPOM.ts` which loads selectors from `fixtures/selectors/auth.json`
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Summary
|
|
279
|
+
|
|
280
|
+
| Test ID | Block | Description | Tags |
|
|
281
|
+
|---------|-------|-------------|------|
|
|
282
|
+
| PWD-RESET-001 | Access | Page access from login | `@smoke` |
|
|
283
|
+
| PWD-RESET-002 | Access | Direct URL access | `@smoke` |
|
|
284
|
+
| PWD-RESET-003 | Submit | Submit valid email | `@smoke` |
|
|
285
|
+
| PWD-RESET-004 | Validation | Empty email error | |
|
|
286
|
+
| PWD-RESET-005 | Validation | Invalid format error | |
|
|
287
|
+
| PWD-RESET-006 | Navigation | Back to login | |
|
|
288
|
+
| PWD-RESET-007 | Submit | Existing user email | |
|
|
289
|
+
| PWD-RESET-008 | A11y | Keyboard accessibility | |
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Password Reset Flow Tests
|
|
5
|
+
*
|
|
6
|
+
* Tests the complete password reset flow:
|
|
7
|
+
* - Request password reset link
|
|
8
|
+
* - Validate form fields
|
|
9
|
+
* - Handle errors (invalid email, rate limiting)
|
|
10
|
+
* - Success message display
|
|
11
|
+
*
|
|
12
|
+
* Note: Actual email delivery and token validation are not tested here
|
|
13
|
+
* as they require external email service integration.
|
|
14
|
+
* Tests verify up to the point of email send request.
|
|
15
|
+
*
|
|
16
|
+
* Tags: @uat, @feat-auth, @password-reset
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import * as allure from 'allure-cypress'
|
|
20
|
+
|
|
21
|
+
import { AuthPOM } from '../../../src/core/AuthPOM'
|
|
22
|
+
|
|
23
|
+
describe('Authentication - Password Reset Flow', {
|
|
24
|
+
tags: ['@uat', '@feat-auth', '@password-reset']
|
|
25
|
+
}, () => {
|
|
26
|
+
const auth = new AuthPOM()
|
|
27
|
+
|
|
28
|
+
beforeEach(() => {
|
|
29
|
+
allure.epic('Authentication')
|
|
30
|
+
allure.feature('Password Reset')
|
|
31
|
+
// Clear any existing session
|
|
32
|
+
cy.clearCookies()
|
|
33
|
+
cy.clearLocalStorage()
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
describe('PWD-RESET-001: Access Password Reset Page', { tags: '@smoke' }, () => {
|
|
37
|
+
it('should access password reset page from login', { tags: '@smoke' }, () => {
|
|
38
|
+
allure.severity('critical')
|
|
39
|
+
allure.story('Page Access')
|
|
40
|
+
|
|
41
|
+
// 1. Visit login page
|
|
42
|
+
auth.visitLogin()
|
|
43
|
+
|
|
44
|
+
// 2. Show email form (forgot password link is inside email form section)
|
|
45
|
+
auth.showEmailLogin()
|
|
46
|
+
auth.waitForLoginForm()
|
|
47
|
+
|
|
48
|
+
// 3. Click on forgot password link
|
|
49
|
+
auth.clickForgotPassword()
|
|
50
|
+
|
|
51
|
+
// 4. Validate password reset page
|
|
52
|
+
cy.url().should('include', '/forgot-password')
|
|
53
|
+
cy.get(auth.selectors.forgotPasswordForm).should('be.visible')
|
|
54
|
+
cy.get(auth.selectors.forgotPasswordEmail).should('be.visible')
|
|
55
|
+
cy.get(auth.selectors.forgotPasswordSubmit).should('be.visible')
|
|
56
|
+
|
|
57
|
+
cy.log('✅ Password reset page accessible')
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
describe('PWD-RESET-002: Direct URL Access', { tags: '@smoke' }, () => {
|
|
62
|
+
it('should access password reset page directly via URL', { tags: '@smoke' }, () => {
|
|
63
|
+
allure.severity('normal')
|
|
64
|
+
allure.story('Direct Access')
|
|
65
|
+
|
|
66
|
+
// 1. Visit directly
|
|
67
|
+
auth.visitForgotPassword()
|
|
68
|
+
|
|
69
|
+
// 2. Validate page elements
|
|
70
|
+
cy.get(auth.selectors.forgotPasswordForm).should('be.visible')
|
|
71
|
+
cy.get(auth.selectors.forgotPasswordEmail).should('be.visible')
|
|
72
|
+
|
|
73
|
+
cy.log('✅ Direct access to password reset works')
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
describe('PWD-RESET-003: Submit Valid Email', { tags: '@smoke' }, () => {
|
|
78
|
+
it('should show success message for valid email format', { tags: '@smoke' }, () => {
|
|
79
|
+
allure.severity('critical')
|
|
80
|
+
allure.story('Submit Request')
|
|
81
|
+
|
|
82
|
+
// 1. Visit password reset page
|
|
83
|
+
auth.visitForgotPassword()
|
|
84
|
+
|
|
85
|
+
// 2. Request password reset
|
|
86
|
+
auth.requestPasswordReset('user@example.com')
|
|
87
|
+
|
|
88
|
+
// 3. Should show success message (even if email doesn't exist for security)
|
|
89
|
+
auth.waitForPasswordResetSuccess()
|
|
90
|
+
|
|
91
|
+
cy.log('✅ Password reset request submitted successfully')
|
|
92
|
+
})
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
describe('PWD-RESET-004: Validate Empty Email', () => {
|
|
96
|
+
it('should show error for empty email field', () => {
|
|
97
|
+
allure.severity('high')
|
|
98
|
+
allure.story('Validation')
|
|
99
|
+
|
|
100
|
+
// 1. Visit password reset page
|
|
101
|
+
auth.visitForgotPassword()
|
|
102
|
+
|
|
103
|
+
// 2. Submit without entering email
|
|
104
|
+
cy.get(auth.selectors.forgotPasswordSubmit).click()
|
|
105
|
+
|
|
106
|
+
// 3. Should show Zod validation error in UI
|
|
107
|
+
// The form uses react-hook-form with zod validation
|
|
108
|
+
// Empty email triggers validation error from zod schema
|
|
109
|
+
cy.contains('.text-destructive', 'Please enter a valid email address').should('be.visible')
|
|
110
|
+
|
|
111
|
+
cy.log('✅ Empty email validation works')
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
describe('PWD-RESET-005: Validate Invalid Email Format', () => {
|
|
116
|
+
it('should show error for invalid email format', () => {
|
|
117
|
+
allure.severity('high')
|
|
118
|
+
allure.story('Validation')
|
|
119
|
+
|
|
120
|
+
// 1. Visit password reset page
|
|
121
|
+
auth.visitForgotPassword()
|
|
122
|
+
|
|
123
|
+
// 2. Enter invalid email format
|
|
124
|
+
cy.get(auth.selectors.forgotPasswordEmail).type('not-an-email')
|
|
125
|
+
|
|
126
|
+
// 3. Submit form
|
|
127
|
+
cy.get(auth.selectors.forgotPasswordSubmit).click()
|
|
128
|
+
|
|
129
|
+
// 4. Should show validation error (HTML5 or custom)
|
|
130
|
+
cy.get(auth.selectors.forgotPasswordEmail).then(($input) => {
|
|
131
|
+
const input = $input[0] as HTMLInputElement
|
|
132
|
+
if (input.validity) {
|
|
133
|
+
expect(input.validity.valid).to.be.false
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
cy.log('✅ Invalid email format validation works')
|
|
138
|
+
})
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
describe('PWD-RESET-006: Back to Login Link', () => {
|
|
142
|
+
it('should navigate back to login page', () => {
|
|
143
|
+
allure.severity('normal')
|
|
144
|
+
allure.story('Navigation')
|
|
145
|
+
|
|
146
|
+
// 1. Visit password reset page
|
|
147
|
+
auth.visitForgotPassword()
|
|
148
|
+
|
|
149
|
+
// 2. Click back to login
|
|
150
|
+
auth.backToLogin()
|
|
151
|
+
|
|
152
|
+
// 3. Should be on login page
|
|
153
|
+
auth.assertOnLoginPage()
|
|
154
|
+
|
|
155
|
+
cy.log('✅ Back to login navigation works')
|
|
156
|
+
})
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
describe('PWD-RESET-007: Submit with Known Test Email', () => {
|
|
160
|
+
it('should handle submission with existing user email', () => {
|
|
161
|
+
allure.severity('high')
|
|
162
|
+
allure.story('Submit Request')
|
|
163
|
+
|
|
164
|
+
// 1. Visit password reset page
|
|
165
|
+
auth.visitForgotPassword()
|
|
166
|
+
|
|
167
|
+
// 2. Request reset for known test email
|
|
168
|
+
auth.requestPasswordReset('carlos.mendoza@nextspark.dev')
|
|
169
|
+
|
|
170
|
+
// 3. Should show success (same message for security - no email enumeration)
|
|
171
|
+
auth.waitForPasswordResetSuccess()
|
|
172
|
+
|
|
173
|
+
cy.log('✅ Password reset for existing user handled correctly')
|
|
174
|
+
})
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
describe('PWD-RESET-008: Form Keyboard Accessibility', () => {
|
|
178
|
+
it('should submit form with Enter key', () => {
|
|
179
|
+
allure.severity('normal')
|
|
180
|
+
allure.story('Accessibility')
|
|
181
|
+
|
|
182
|
+
// 1. Visit password reset page
|
|
183
|
+
auth.visitForgotPassword()
|
|
184
|
+
|
|
185
|
+
// 2. Enter email and press Enter
|
|
186
|
+
cy.get(auth.selectors.forgotPasswordEmail)
|
|
187
|
+
.type('user@example.com{enter}')
|
|
188
|
+
|
|
189
|
+
// 3. Should process submission and show success (async operation)
|
|
190
|
+
// Wait for the success message to appear after API call completes
|
|
191
|
+
auth.waitForPasswordResetSuccess()
|
|
192
|
+
|
|
193
|
+
cy.log('✅ Keyboard submission works')
|
|
194
|
+
})
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
after(() => {
|
|
198
|
+
cy.log('✅ Password reset flow tests completed')
|
|
199
|
+
})
|
|
200
|
+
})
|