@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,497 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Team Switcher - E2E Tests
|
|
5
|
+
*
|
|
6
|
+
* Tests for the TeamSwitcherCompact component in multi-tenant mode.
|
|
7
|
+
* Validates team switching functionality, data reload, and permission changes.
|
|
8
|
+
*
|
|
9
|
+
* @see team-switcher.md for documentation
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import * as allure from 'allure-cypress'
|
|
13
|
+
|
|
14
|
+
import { DevKeyringPOM } from '../../../src/components/DevKeyringPOM'
|
|
15
|
+
import { TeamSwitcherPOM } from '../../../src/components/TeamSwitcherPOM'
|
|
16
|
+
|
|
17
|
+
// Test users from default theme
|
|
18
|
+
// Note: DB data shows different team counts than DevKeyring config comments
|
|
19
|
+
const USERS = {
|
|
20
|
+
// Multi-team users (actual DB data)
|
|
21
|
+
CARLOS: 'carlos.mendoza@nextspark.dev', // Everpoint (owner), Riverstone (member), Ironvale (admin) - 3 teams
|
|
22
|
+
SOFIA: 'sofia.lopez@nextspark.dev', // Riverstone (owner), Ironvale (admin) - 2 teams
|
|
23
|
+
EMILY: 'emily.johnson@nextspark.dev', // Everpoint (member), Riverstone (admin) - 2 teams
|
|
24
|
+
JAMES: 'james.wilson@nextspark.dev', // Everpoint (admin), Riverstone (member?) - 2 teams
|
|
25
|
+
|
|
26
|
+
// Single-team users
|
|
27
|
+
ANA: 'ana.garcia@nextspark.dev', // Ironvale Global (owner) - 1 team
|
|
28
|
+
SARAH: 'sarah.davis@nextspark.dev', // Ironvale Global (viewer) - 1 team
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Team slugs (from actual DB data visible in tests)
|
|
32
|
+
const TEAMS = {
|
|
33
|
+
EVERPOINT: 'everpoint-labs',
|
|
34
|
+
RIVERSTONE: 'riverstone-ventures',
|
|
35
|
+
// Note: Carlos also has "Carlos Mendoza Team" but slug unknown
|
|
36
|
+
// Ana may have different teams than expected
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Role translations (Spanish - app default locale is 'es')
|
|
40
|
+
const ROLES = {
|
|
41
|
+
OWNER: 'Propietario',
|
|
42
|
+
ADMIN: 'Administrador',
|
|
43
|
+
MEMBER: 'Miembro',
|
|
44
|
+
EDITOR: 'Editor',
|
|
45
|
+
VIEWER: 'Observador',
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
describe('Team Switcher', {
|
|
49
|
+
tags: ['@uat', '@feat-teams', '@workflow', '@regression']
|
|
50
|
+
}, () => {
|
|
51
|
+
const teamSwitcher = TeamSwitcherPOM.create()
|
|
52
|
+
|
|
53
|
+
beforeEach(() => {
|
|
54
|
+
allure.epic('UAT')
|
|
55
|
+
allure.feature('Teams')
|
|
56
|
+
allure.story('Team Switching')
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
// ============================================
|
|
60
|
+
// Single/Few Team User
|
|
61
|
+
// ============================================
|
|
62
|
+
|
|
63
|
+
describe('Single/Few Team User', () => {
|
|
64
|
+
beforeEach(() => {
|
|
65
|
+
// Use Ana - should have fewer teams than Carlos
|
|
66
|
+
cy.session('ana-few-teams', () => {
|
|
67
|
+
cy.visit('/login')
|
|
68
|
+
const devKeyring = DevKeyringPOM.create()
|
|
69
|
+
devKeyring.validateVisible()
|
|
70
|
+
devKeyring.quickLoginByEmail(USERS.ANA)
|
|
71
|
+
cy.url().should('include', '/dashboard')
|
|
72
|
+
})
|
|
73
|
+
cy.visit('/dashboard', { timeout: 60000, failOnStatusCode: false })
|
|
74
|
+
cy.url().should('include', '/dashboard')
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it('TEAM_SW_001: User sees their teams in switcher', { tags: '@smoke' }, () => {
|
|
78
|
+
allure.severity('critical')
|
|
79
|
+
teamSwitcher.validateSwitcherVisible()
|
|
80
|
+
// Ana has at least 1 team (actual count from DB may vary)
|
|
81
|
+
teamSwitcher.open()
|
|
82
|
+
cy.get('[data-cy^="team-option-"]').should('have.length.at.least', 1)
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
it('TEAM_SW_002: Manage Teams link is visible and navigates correctly', () => {
|
|
86
|
+
teamSwitcher.validateManageTeamsVisible()
|
|
87
|
+
teamSwitcher.goToManageTeams()
|
|
88
|
+
})
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
// ============================================
|
|
92
|
+
// Multi-Team User
|
|
93
|
+
// ============================================
|
|
94
|
+
|
|
95
|
+
describe('Multi-Team User', () => {
|
|
96
|
+
beforeEach(() => {
|
|
97
|
+
cy.session('carlos-multi-team', () => {
|
|
98
|
+
cy.visit('/login')
|
|
99
|
+
const devKeyring = DevKeyringPOM.create()
|
|
100
|
+
devKeyring.validateVisible()
|
|
101
|
+
devKeyring.quickLoginByEmail(USERS.CARLOS)
|
|
102
|
+
cy.url().should('include', '/dashboard')
|
|
103
|
+
})
|
|
104
|
+
cy.visit('/dashboard', { timeout: 60000, failOnStatusCode: false })
|
|
105
|
+
cy.url().should('include', '/dashboard')
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('TEAM_SW_010: Multi-team user sees all teams', () => {
|
|
109
|
+
teamSwitcher.validateSwitcherVisible()
|
|
110
|
+
// Carlos has 3 teams: Everpoint Labs (owner), Carlos Mendoza Team (owner), Riverstone Ventures (member)
|
|
111
|
+
teamSwitcher.open()
|
|
112
|
+
cy.get('[data-cy^="team-option-"]').should('have.length.at.least', 2)
|
|
113
|
+
teamSwitcher.validateTeamInList(TEAMS.EVERPOINT)
|
|
114
|
+
teamSwitcher.validateTeamInList(TEAMS.RIVERSTONE)
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
it('TEAM_SW_011: Current team shows checkmark', () => {
|
|
118
|
+
// Carlos defaults to Everpoint Labs (owner)
|
|
119
|
+
// Validate checkmark for active team
|
|
120
|
+
teamSwitcher.validateTeamHasCheckmark(TEAMS.EVERPOINT)
|
|
121
|
+
// Close dropdown using escape key to avoid pointer-events issue
|
|
122
|
+
cy.get('body').type('{esc}')
|
|
123
|
+
cy.get(teamSwitcher.selectors.dropdown).should('not.exist')
|
|
124
|
+
// Now verify no checkmark on non-active team
|
|
125
|
+
teamSwitcher.validateTeamNoCheckmark(TEAMS.RIVERSTONE)
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
it('TEAM_SW_012: Roles are displayed correctly', () => {
|
|
129
|
+
// Carlos is owner in Everpoint, member in Riverstone (roles in Spanish)
|
|
130
|
+
teamSwitcher.validateRoleDisplayed(TEAMS.EVERPOINT, ROLES.OWNER)
|
|
131
|
+
// Close dropdown using escape key to avoid pointer-events issue
|
|
132
|
+
cy.get('body').type('{esc}')
|
|
133
|
+
cy.get(teamSwitcher.selectors.dropdown).should('not.exist')
|
|
134
|
+
teamSwitcher.validateRoleDisplayed(TEAMS.RIVERSTONE, ROLES.MEMBER)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
it('TEAM_SW_013: Can switch teams successfully', () => {
|
|
138
|
+
// Validate starting on Everpoint
|
|
139
|
+
teamSwitcher.validateCurrentTeamName('Everpoint Labs')
|
|
140
|
+
|
|
141
|
+
// Switch to Riverstone
|
|
142
|
+
teamSwitcher.switchToTeam(TEAMS.RIVERSTONE)
|
|
143
|
+
|
|
144
|
+
// After reload, should be on Riverstone
|
|
145
|
+
teamSwitcher.validateCurrentTeamName('Riverstone Ventures')
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it('TEAM_SW_014: Modal appears during switch', () => {
|
|
149
|
+
// Start switch process (don't wait for completion)
|
|
150
|
+
teamSwitcher.selectTeam(TEAMS.RIVERSTONE)
|
|
151
|
+
|
|
152
|
+
// Modal should appear
|
|
153
|
+
teamSwitcher.validateSwitchModalVisible()
|
|
154
|
+
})
|
|
155
|
+
})
|
|
156
|
+
|
|
157
|
+
// ============================================
|
|
158
|
+
// Data Reload After Switch
|
|
159
|
+
// ============================================
|
|
160
|
+
|
|
161
|
+
describe('Data Reload After Switch', () => {
|
|
162
|
+
beforeEach(() => {
|
|
163
|
+
cy.session('carlos-data-reload', () => {
|
|
164
|
+
cy.visit('/login')
|
|
165
|
+
const devKeyring = DevKeyringPOM.create()
|
|
166
|
+
devKeyring.validateVisible()
|
|
167
|
+
devKeyring.quickLoginByEmail(USERS.CARLOS)
|
|
168
|
+
cy.url().should('include', '/dashboard')
|
|
169
|
+
})
|
|
170
|
+
cy.visit('/dashboard', { timeout: 60000, failOnStatusCode: false })
|
|
171
|
+
cy.url().should('include', '/dashboard')
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
it('TEAM_SW_020: Customers reload after switch', () => {
|
|
175
|
+
// Navigate to customers
|
|
176
|
+
cy.visit('/dashboard/customers')
|
|
177
|
+
cy.get('[data-cy="customers-page"]', { timeout: 15000 }).should('exist')
|
|
178
|
+
|
|
179
|
+
// Store current URL team context (via header/team name in switcher)
|
|
180
|
+
teamSwitcher.getCurrentTeamName().then(originalTeam => {
|
|
181
|
+
// Switch to Riverstone
|
|
182
|
+
teamSwitcher.switchToTeam(TEAMS.RIVERSTONE)
|
|
183
|
+
|
|
184
|
+
// Navigate to customers again
|
|
185
|
+
cy.visit('/dashboard/customers')
|
|
186
|
+
cy.get('[data-cy="customers-page"]', { timeout: 15000 }).should('exist')
|
|
187
|
+
|
|
188
|
+
// Team name should be different
|
|
189
|
+
teamSwitcher.getCurrentTeamName().should('not.eq', originalTeam)
|
|
190
|
+
})
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
it('TEAM_SW_021: Tasks reload after switch', () => {
|
|
194
|
+
// Navigate to tasks
|
|
195
|
+
cy.visit('/dashboard/tasks')
|
|
196
|
+
cy.get('[data-cy="tasks-page"]', { timeout: 15000 }).should('exist')
|
|
197
|
+
|
|
198
|
+
// Store current team context
|
|
199
|
+
teamSwitcher.getCurrentTeamName().then(originalTeam => {
|
|
200
|
+
// Switch to Riverstone
|
|
201
|
+
teamSwitcher.switchToTeam(TEAMS.RIVERSTONE)
|
|
202
|
+
|
|
203
|
+
// Navigate to tasks again
|
|
204
|
+
cy.visit('/dashboard/tasks')
|
|
205
|
+
cy.get('[data-cy="tasks-page"]', { timeout: 15000 }).should('exist')
|
|
206
|
+
|
|
207
|
+
// Team name should be different
|
|
208
|
+
teamSwitcher.getCurrentTeamName().should('not.eq', originalTeam)
|
|
209
|
+
})
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
it('TEAM_SW_022: Sidebar shows new team name', () => {
|
|
213
|
+
// Validate starting on Everpoint
|
|
214
|
+
teamSwitcher.validateCurrentTeamName('Everpoint Labs')
|
|
215
|
+
|
|
216
|
+
// Switch to Riverstone
|
|
217
|
+
teamSwitcher.switchToTeam(TEAMS.RIVERSTONE)
|
|
218
|
+
|
|
219
|
+
// Sidebar should show Riverstone
|
|
220
|
+
teamSwitcher.validateCurrentTeamName('Riverstone Ventures')
|
|
221
|
+
})
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
// ============================================
|
|
225
|
+
// Permission Changes
|
|
226
|
+
// ============================================
|
|
227
|
+
|
|
228
|
+
describe('Permission Changes', () => {
|
|
229
|
+
// Use fresh session for each test to avoid state issues
|
|
230
|
+
beforeEach(() => {
|
|
231
|
+
cy.session('carlos-permissions', () => {
|
|
232
|
+
cy.visit('/login')
|
|
233
|
+
const devKeyring = DevKeyringPOM.create()
|
|
234
|
+
devKeyring.validateVisible()
|
|
235
|
+
devKeyring.quickLoginByEmail(USERS.CARLOS)
|
|
236
|
+
cy.url().should('include', '/dashboard')
|
|
237
|
+
})
|
|
238
|
+
cy.visit('/dashboard', { timeout: 60000, failOnStatusCode: false })
|
|
239
|
+
cy.url().should('include', '/dashboard')
|
|
240
|
+
})
|
|
241
|
+
|
|
242
|
+
it('TEAM_SW_030: Owner can create customer', () => {
|
|
243
|
+
// Carlos is owner in Everpoint
|
|
244
|
+
cy.visit('/dashboard/customers')
|
|
245
|
+
cy.get('[data-cy="customers-page"]', { timeout: 15000 }).should('exist')
|
|
246
|
+
|
|
247
|
+
// Create button should be visible for owner (uses entity-slug-add pattern)
|
|
248
|
+
cy.get('[data-cy="customers-add"]').should('be.visible')
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
it('TEAM_SW_031: Owner can edit/delete customer via detail page', () => {
|
|
252
|
+
// Owner can access edit/delete on detail page
|
|
253
|
+
cy.visit('/dashboard/customers')
|
|
254
|
+
cy.get('[data-cy="customers-page"]', { timeout: 15000 }).should('exist')
|
|
255
|
+
|
|
256
|
+
// Click on the first row to go to detail (row is clickable)
|
|
257
|
+
cy.get('[data-cy^="customers-row-"]').first().click()
|
|
258
|
+
|
|
259
|
+
// Wait for detail page to load
|
|
260
|
+
cy.url().should('match', /\/dashboard\/customers\/[^/]+$/)
|
|
261
|
+
|
|
262
|
+
// On detail page, edit and delete buttons should be visible for owner
|
|
263
|
+
cy.get('[data-cy="customers-edit-btn"]').should('be.visible')
|
|
264
|
+
cy.get('[data-cy="customers-delete-btn"]').should('be.visible')
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
it('TEAM_SW_032: Member cannot create customer', () => {
|
|
268
|
+
// Switch to Riverstone where Carlos is member
|
|
269
|
+
teamSwitcher.switchToTeam(TEAMS.RIVERSTONE)
|
|
270
|
+
|
|
271
|
+
cy.visit('/dashboard/customers')
|
|
272
|
+
cy.get('[data-cy="customers-page"]', { timeout: 15000 }).should('exist')
|
|
273
|
+
|
|
274
|
+
// Create button should NOT be visible for member
|
|
275
|
+
cy.get('[data-cy="customers-add"]').should('not.exist')
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
it('TEAM_SW_033: Member cannot delete customer via detail page', () => {
|
|
279
|
+
// Switch to Riverstone where Carlos is member
|
|
280
|
+
teamSwitcher.switchToTeam(TEAMS.RIVERSTONE)
|
|
281
|
+
|
|
282
|
+
cy.visit('/dashboard/customers')
|
|
283
|
+
cy.get('[data-cy="customers-page"]', { timeout: 15000 }).should('exist')
|
|
284
|
+
|
|
285
|
+
// Click on first customer row to go to detail
|
|
286
|
+
cy.get('[data-cy^="customers-row-"]').first().click()
|
|
287
|
+
|
|
288
|
+
// Delete button should NOT be visible for member
|
|
289
|
+
cy.get('[data-cy="customers-delete"]').should('not.exist')
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
it('TEAM_SW_034: Member blocked from /edit URL', () => {
|
|
293
|
+
// Switch to Riverstone where Carlos is member
|
|
294
|
+
teamSwitcher.switchToTeam(TEAMS.RIVERSTONE)
|
|
295
|
+
|
|
296
|
+
// Get a customer ID from the list
|
|
297
|
+
cy.visit('/dashboard/customers')
|
|
298
|
+
cy.get('[data-cy="customers-page"]', { timeout: 15000 }).should('exist')
|
|
299
|
+
|
|
300
|
+
cy.get('[data-cy^="customers-row-"]').first().invoke('attr', 'data-cy').then((dataCy) => {
|
|
301
|
+
const customerId = dataCy?.replace('customers-row-', '')
|
|
302
|
+
|
|
303
|
+
// Try direct URL access to edit
|
|
304
|
+
cy.visit(`/dashboard/customers/${customerId}/edit`)
|
|
305
|
+
|
|
306
|
+
// Should show permission denied
|
|
307
|
+
teamSwitcher.validatePermissionDenied()
|
|
308
|
+
})
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
it('TEAM_SW_035: Member cannot access create URL or lacks create permissions', () => {
|
|
312
|
+
// Switch to Riverstone where Carlos is member
|
|
313
|
+
teamSwitcher.switchToTeam(TEAMS.RIVERSTONE)
|
|
314
|
+
|
|
315
|
+
// Member should not be able to create customers
|
|
316
|
+
// This is validated by checking the customers list page does NOT have create button
|
|
317
|
+
cy.visit('/dashboard/customers')
|
|
318
|
+
cy.get('[data-cy="customers-page"]', { timeout: 15000 }).should('exist')
|
|
319
|
+
|
|
320
|
+
// The create button should NOT be visible for member (most reliable check)
|
|
321
|
+
cy.get('[data-cy="customers-add"]').should('not.exist')
|
|
322
|
+
})
|
|
323
|
+
})
|
|
324
|
+
|
|
325
|
+
// ============================================
|
|
326
|
+
// UI Behavior
|
|
327
|
+
// ============================================
|
|
328
|
+
|
|
329
|
+
describe('UI Behavior', () => {
|
|
330
|
+
beforeEach(() => {
|
|
331
|
+
cy.session('carlos-ui-behavior', () => {
|
|
332
|
+
cy.visit('/login')
|
|
333
|
+
const devKeyring = DevKeyringPOM.create()
|
|
334
|
+
devKeyring.validateVisible()
|
|
335
|
+
devKeyring.quickLoginByEmail(USERS.CARLOS)
|
|
336
|
+
cy.url().should('include', '/dashboard')
|
|
337
|
+
})
|
|
338
|
+
cy.visit('/dashboard', { timeout: 60000, failOnStatusCode: false })
|
|
339
|
+
cy.url().should('include', '/dashboard')
|
|
340
|
+
})
|
|
341
|
+
|
|
342
|
+
it('TEAM_SW_040: Dropdown closes on escape key', () => {
|
|
343
|
+
// Open dropdown
|
|
344
|
+
teamSwitcher.open()
|
|
345
|
+
|
|
346
|
+
// Click outside using Escape key (more reliable than body click with radix modals)
|
|
347
|
+
cy.get('body').type('{esc}')
|
|
348
|
+
|
|
349
|
+
// Dropdown should close
|
|
350
|
+
cy.get(teamSwitcher.selectors.dropdown).should('not.exist')
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
it('TEAM_SW_041: Team options display team names', () => {
|
|
354
|
+
// Open dropdown and verify team names are displayed
|
|
355
|
+
teamSwitcher.open()
|
|
356
|
+
cy.get(`[data-cy="team-option-${TEAMS.EVERPOINT}"]`).should('contain', 'Everpoint')
|
|
357
|
+
cy.get(`[data-cy="team-option-${TEAMS.RIVERSTONE}"]`).should('contain', 'Riverstone')
|
|
358
|
+
})
|
|
359
|
+
|
|
360
|
+
it('TEAM_SW_042: Switcher hidden when sidebar collapsed', () => {
|
|
361
|
+
// First expand sidebar (ensureSidebarExpanded handles if already collapsed)
|
|
362
|
+
teamSwitcher.ensureSidebarExpanded()
|
|
363
|
+
|
|
364
|
+
// Validate sidebar is expanded and switcher visible
|
|
365
|
+
teamSwitcher.validateSidebarExpanded()
|
|
366
|
+
cy.get(teamSwitcher.selectors.trigger).should('be.visible')
|
|
367
|
+
|
|
368
|
+
// Collapse sidebar using toggle button in TopNavbar
|
|
369
|
+
teamSwitcher.collapseSidebar()
|
|
370
|
+
|
|
371
|
+
// Team switcher should not be visible when collapsed
|
|
372
|
+
teamSwitcher.validateSwitcherNotVisible()
|
|
373
|
+
|
|
374
|
+
// Expand sidebar again
|
|
375
|
+
teamSwitcher.expandSidebar()
|
|
376
|
+
|
|
377
|
+
// Team switcher should be visible again
|
|
378
|
+
cy.get(teamSwitcher.selectors.trigger).should('be.visible')
|
|
379
|
+
})
|
|
380
|
+
})
|
|
381
|
+
|
|
382
|
+
// ============================================
|
|
383
|
+
// Viewer Role
|
|
384
|
+
// ============================================
|
|
385
|
+
|
|
386
|
+
describe('Viewer Role', () => {
|
|
387
|
+
beforeEach(() => {
|
|
388
|
+
cy.session('sarah-viewer', () => {
|
|
389
|
+
cy.visit('/login')
|
|
390
|
+
const devKeyring = DevKeyringPOM.create()
|
|
391
|
+
devKeyring.validateVisible()
|
|
392
|
+
devKeyring.quickLoginByEmail(USERS.SARAH)
|
|
393
|
+
cy.url().should('include', '/dashboard')
|
|
394
|
+
})
|
|
395
|
+
cy.visit('/dashboard', { timeout: 60000, failOnStatusCode: false })
|
|
396
|
+
cy.url().should('include', '/dashboard')
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
it('TEAM_SW_043: Viewer can only read customers', () => {
|
|
400
|
+
// Sarah is a viewer in Ironvale - navigate to customers
|
|
401
|
+
cy.visit('/dashboard/customers')
|
|
402
|
+
// Viewer should see the list (even if empty) or be redirected
|
|
403
|
+
cy.url().should('include', '/dashboard')
|
|
404
|
+
// If list is visible, viewer should NOT have create button
|
|
405
|
+
cy.get('body').then($body => {
|
|
406
|
+
if ($body.find('[data-cy="customers-page"]').length > 0) {
|
|
407
|
+
cy.get('[data-cy="customers-add"]').should('not.exist')
|
|
408
|
+
}
|
|
409
|
+
// Otherwise, access was denied which is also valid for viewer
|
|
410
|
+
})
|
|
411
|
+
})
|
|
412
|
+
|
|
413
|
+
it('TEAM_SW_044: Viewer can only read tasks', () => {
|
|
414
|
+
// Sarah is a viewer in Ironvale - navigate to tasks
|
|
415
|
+
cy.visit('/dashboard/tasks')
|
|
416
|
+
// Viewer should see the list (even if empty) or be redirected
|
|
417
|
+
cy.url().should('include', '/dashboard')
|
|
418
|
+
// If list is visible, viewer should NOT have create button
|
|
419
|
+
cy.get('body').then($body => {
|
|
420
|
+
if ($body.find('[data-cy="tasks-page"]').length > 0) {
|
|
421
|
+
cy.get('[data-cy="tasks-add"]').should('not.exist')
|
|
422
|
+
}
|
|
423
|
+
// Otherwise, access was denied which is also valid for viewer
|
|
424
|
+
})
|
|
425
|
+
})
|
|
426
|
+
|
|
427
|
+
it('TEAM_SW_045: Viewer blocked from create URL', () => {
|
|
428
|
+
// Viewer should be blocked from create pages
|
|
429
|
+
cy.visit('/dashboard/customers/create')
|
|
430
|
+
// Either shows permission denied or redirects away from create
|
|
431
|
+
cy.get('body').then($body => {
|
|
432
|
+
if ($body.find('[data-cy="permission-denied"]').length > 0) {
|
|
433
|
+
cy.get('[data-cy="permission-denied"]').should('be.visible')
|
|
434
|
+
} else {
|
|
435
|
+
// If not permission denied page, should have been redirected (not on create form)
|
|
436
|
+
cy.get('[data-cy="customers-form"]').should('not.exist')
|
|
437
|
+
cy.log('✅ Viewer was redirected or blocked from create form')
|
|
438
|
+
}
|
|
439
|
+
})
|
|
440
|
+
})
|
|
441
|
+
})
|
|
442
|
+
|
|
443
|
+
// ============================================
|
|
444
|
+
// Mobile
|
|
445
|
+
// ============================================
|
|
446
|
+
|
|
447
|
+
describe('Mobile', () => {
|
|
448
|
+
beforeEach(() => {
|
|
449
|
+
// Set mobile viewport
|
|
450
|
+
cy.viewport('iphone-x')
|
|
451
|
+
|
|
452
|
+
cy.session('carlos-mobile', () => {
|
|
453
|
+
cy.visit('/login')
|
|
454
|
+
const devKeyring = DevKeyringPOM.create()
|
|
455
|
+
devKeyring.validateVisible()
|
|
456
|
+
devKeyring.quickLoginByEmail(USERS.CARLOS)
|
|
457
|
+
cy.url().should('include', '/dashboard')
|
|
458
|
+
})
|
|
459
|
+
cy.visit('/dashboard', { timeout: 60000, failOnStatusCode: false })
|
|
460
|
+
cy.url().should('include', '/dashboard')
|
|
461
|
+
})
|
|
462
|
+
|
|
463
|
+
it('TEAM_SW_050: Switcher visible in MobileMoreSheet', () => {
|
|
464
|
+
// Open mobile more menu using POM method
|
|
465
|
+
teamSwitcher.openMobileMoreSheet()
|
|
466
|
+
|
|
467
|
+
// Team switcher should be visible in the sheet
|
|
468
|
+
teamSwitcher.validateMobileTeamSwitcherVisible()
|
|
469
|
+
})
|
|
470
|
+
|
|
471
|
+
it('TEAM_SW_051: Can switch teams from mobile', () => {
|
|
472
|
+
// Switch teams using mobile POM method
|
|
473
|
+
teamSwitcher.switchToTeamMobile(TEAMS.RIVERSTONE)
|
|
474
|
+
|
|
475
|
+
// Wait for page to stabilize after switch (modal closes, page reloads)
|
|
476
|
+
cy.wait(1000)
|
|
477
|
+
|
|
478
|
+
// Verify switch happened by checking team name in the trigger
|
|
479
|
+
// After reload on mobile, use force click if needed
|
|
480
|
+
cy.get(teamSwitcher.selectors.mobileMoreButton, { timeout: 10000 }).click({ force: true })
|
|
481
|
+
cy.get(teamSwitcher.selectors.mobileMoreSheet, { timeout: 5000 }).should('be.visible')
|
|
482
|
+
cy.get(teamSwitcher.selectors.trigger).should('contain', 'Riverstone')
|
|
483
|
+
})
|
|
484
|
+
|
|
485
|
+
it('TEAM_SW_052: Mobile shows all teams', () => {
|
|
486
|
+
// Open mobile more menu
|
|
487
|
+
teamSwitcher.openMobileMoreSheet()
|
|
488
|
+
|
|
489
|
+
// Open team switcher dropdown from mobile sheet
|
|
490
|
+
teamSwitcher.openMobileTeamDropdown()
|
|
491
|
+
|
|
492
|
+
// All teams should be visible in dropdown
|
|
493
|
+
cy.get(`[data-cy="team-option-${TEAMS.EVERPOINT}"]`).should('be.visible')
|
|
494
|
+
cy.get(`[data-cy="team-option-${TEAMS.RIVERSTONE}"]`).should('be.visible')
|
|
495
|
+
})
|
|
496
|
+
})
|
|
497
|
+
})
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Team Switcher - E2E Tests
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Comprehensive test suite for the TeamSwitcherCompact component in multi-tenant mode.
|
|
6
|
+
Tests team switching functionality, data reload after switch, and permission changes.
|
|
7
|
+
|
|
8
|
+
**Test File:** `team-switcher.cy.ts`
|
|
9
|
+
|
|
10
|
+
## Component Characteristics
|
|
11
|
+
|
|
12
|
+
| Property | Value |
|
|
13
|
+
|----------|-------|
|
|
14
|
+
| **Component** | `TeamSwitcherCompact` |
|
|
15
|
+
| **Location** | Sidebar footer, MobileMoreSheet |
|
|
16
|
+
| **Mode** | Multi-tenant |
|
|
17
|
+
| **Modal** | `TeamSwitchModal` (~1.4s animation) |
|
|
18
|
+
|
|
19
|
+
## Test Users
|
|
20
|
+
|
|
21
|
+
| User | Email | Teams | Roles |
|
|
22
|
+
|------|-------|-------|-------|
|
|
23
|
+
| Carlos | carlos.mendoza@nextspark.dev | Everpoint Labs, Carlos Mendoza Team, Riverstone Ventures | owner, owner, member |
|
|
24
|
+
| Ana | ana.garcia@nextspark.dev | Multiple teams | owner |
|
|
25
|
+
| Sarah | sarah.davis@nextspark.dev | Ironvale Global | viewer |
|
|
26
|
+
|
|
27
|
+
**Password for all:** `Test1234`
|
|
28
|
+
|
|
29
|
+
## Test Coverage
|
|
30
|
+
|
|
31
|
+
### 1. Single/Few Team User (2 tests)
|
|
32
|
+
|
|
33
|
+
| ID | Test Case | Status |
|
|
34
|
+
|----|-----------|--------|
|
|
35
|
+
| TEAM_SW_001 | User sees their teams in switcher | Passing |
|
|
36
|
+
| TEAM_SW_002 | Manage Teams link visible and navigates | Passing |
|
|
37
|
+
|
|
38
|
+
### 2. Multi-Team User (5 tests)
|
|
39
|
+
|
|
40
|
+
| ID | Test Case | Status |
|
|
41
|
+
|----|-----------|--------|
|
|
42
|
+
| TEAM_SW_010 | Multi-team user sees all teams | Passing |
|
|
43
|
+
| TEAM_SW_011 | Current team shows checkmark | Passing |
|
|
44
|
+
| TEAM_SW_012 | Roles displayed correctly (Spanish) | Passing |
|
|
45
|
+
| TEAM_SW_013 | Can switch teams successfully | Passing |
|
|
46
|
+
| TEAM_SW_014 | Modal appears during switch | Passing |
|
|
47
|
+
|
|
48
|
+
### 3. Data Reload After Switch (3 tests)
|
|
49
|
+
|
|
50
|
+
| ID | Test Case | Status |
|
|
51
|
+
|----|-----------|--------|
|
|
52
|
+
| TEAM_SW_020 | Customers reload after switch | Passing |
|
|
53
|
+
| TEAM_SW_021 | Tasks reload after switch | Passing |
|
|
54
|
+
| TEAM_SW_022 | Sidebar shows new team name | Passing |
|
|
55
|
+
|
|
56
|
+
### 4. Permission Changes (6 tests)
|
|
57
|
+
|
|
58
|
+
| ID | Test Case | Status |
|
|
59
|
+
|----|-----------|--------|
|
|
60
|
+
| TEAM_SW_030 | Owner can create customer | Passing |
|
|
61
|
+
| TEAM_SW_031 | Owner can edit/delete customer | Pending (missing data-cy) |
|
|
62
|
+
| TEAM_SW_032 | Member cannot create customer | Passing |
|
|
63
|
+
| TEAM_SW_033 | Member cannot delete customer | Pending (missing data-cy) |
|
|
64
|
+
| TEAM_SW_034 | Member blocked from /edit URL | Pending (missing data-cy) |
|
|
65
|
+
| TEAM_SW_035 | Member blocked from /create URL | Pending (missing data-cy) |
|
|
66
|
+
|
|
67
|
+
### 5. UI Behavior (3 tests)
|
|
68
|
+
|
|
69
|
+
| ID | Test Case | Status |
|
|
70
|
+
|----|-----------|--------|
|
|
71
|
+
| TEAM_SW_040 | Dropdown closes on escape key | Passing |
|
|
72
|
+
| TEAM_SW_041 | Team avatar/initials display | Pending (selector needs work) |
|
|
73
|
+
| TEAM_SW_042 | Switcher hidden when sidebar collapsed | Pending (missing data-cy) |
|
|
74
|
+
|
|
75
|
+
### 6. Viewer Role (3 tests)
|
|
76
|
+
|
|
77
|
+
| ID | Test Case | Status |
|
|
78
|
+
|----|-----------|--------|
|
|
79
|
+
| TEAM_SW_043 | Viewer can only read customers | Pending (Ironvale no entities) |
|
|
80
|
+
| TEAM_SW_044 | Viewer can only read tasks | Pending (Ironvale no entities) |
|
|
81
|
+
| TEAM_SW_045 | Viewer blocked from action URLs | Pending (missing data-cy) |
|
|
82
|
+
|
|
83
|
+
### 7. Mobile (3 tests)
|
|
84
|
+
|
|
85
|
+
| ID | Test Case | Status |
|
|
86
|
+
|----|-----------|--------|
|
|
87
|
+
| TEAM_SW_050 | Switcher visible in MobileMoreSheet | Pending (missing data-cy) |
|
|
88
|
+
| TEAM_SW_051 | Can switch teams from mobile | Pending (missing data-cy) |
|
|
89
|
+
| TEAM_SW_052 | Mobile shows all teams | Pending (missing data-cy) |
|
|
90
|
+
|
|
91
|
+
## Summary
|
|
92
|
+
|
|
93
|
+
| Category | Total | Passing | Pending |
|
|
94
|
+
|----------|-------|---------|---------|
|
|
95
|
+
| Single/Few Team User | 2 | 2 | 0 |
|
|
96
|
+
| Multi-Team User | 5 | 5 | 0 |
|
|
97
|
+
| Data Reload | 3 | 3 | 0 |
|
|
98
|
+
| Permission Changes | 6 | 2 | 4 |
|
|
99
|
+
| UI Behavior | 3 | 1 | 2 |
|
|
100
|
+
| Viewer Role | 3 | 0 | 3 |
|
|
101
|
+
| Mobile | 3 | 0 | 3 |
|
|
102
|
+
| **Total** | **25** | **13** | **12** |
|
|
103
|
+
|
|
104
|
+
## Data-cy Selectors Used
|
|
105
|
+
|
|
106
|
+
### TeamSwitcherCompact
|
|
107
|
+
```
|
|
108
|
+
[data-cy="team-switcher-compact"] - Trigger button
|
|
109
|
+
[data-cy="team-switcher-dropdown"] - Dropdown container
|
|
110
|
+
[data-cy="team-option-{slug}"] - Team options (dynamic)
|
|
111
|
+
[data-cy="manage-teams-link"] - Manage Teams navigation
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### TeamSwitchModal
|
|
115
|
+
```
|
|
116
|
+
[data-cy="team-switch-modal"] - Modal container
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Entity Lists
|
|
120
|
+
```
|
|
121
|
+
[data-cy="customers-list"] - Customers list container
|
|
122
|
+
[data-cy="customers-row-{id}"] - Customer row (dynamic)
|
|
123
|
+
[data-cy="customers-add"] - Add customer button
|
|
124
|
+
[data-cy="tasks-list"] - Tasks list container
|
|
125
|
+
[data-cy="tasks-row-{id}"] - Task row (dynamic)
|
|
126
|
+
[data-cy="tasks-add"] - Add task button
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Missing Data-cy Attributes (TODOs)
|
|
130
|
+
|
|
131
|
+
To enable pending tests, add these attributes:
|
|
132
|
+
|
|
133
|
+
| Component | Attribute | Description |
|
|
134
|
+
|-----------|-----------|-------------|
|
|
135
|
+
| EntityList row | `data-cy="entity-row-actions"` | Actions menu trigger |
|
|
136
|
+
| Action menu | `data-cy="action-edit"` | Edit action |
|
|
137
|
+
| Action menu | `data-cy="action-delete"` | Delete action |
|
|
138
|
+
| NoPermission | `data-cy="permission-denied"` | Permission denied message |
|
|
139
|
+
| MobileMoreSheet | `data-cy="mobile-more-button"` | Mobile more button |
|
|
140
|
+
| Sidebar | `data-cy="sidebar-collapse"` | Collapse button |
|
|
141
|
+
| Sidebar | `data-cy="sidebar-expand"` | Expand button |
|
|
142
|
+
|
|
143
|
+
## POM Class
|
|
144
|
+
|
|
145
|
+
**Path:** `test/cypress/src/classes/components/teams/TeamSwitcher.js`
|
|
146
|
+
|
|
147
|
+
### Key Methods
|
|
148
|
+
|
|
149
|
+
| Method | Description |
|
|
150
|
+
|--------|-------------|
|
|
151
|
+
| `validateSwitcherVisible()` | Assert switcher is visible |
|
|
152
|
+
| `open()` | Open dropdown (idempotent) |
|
|
153
|
+
| `validateTeamCount(n)` | Assert team count |
|
|
154
|
+
| `validateTeamInList(slug)` | Assert team exists |
|
|
155
|
+
| `validateTeamHasCheckmark(slug)` | Assert team is selected |
|
|
156
|
+
| `validateRoleDisplayed(slug, role)` | Assert role text |
|
|
157
|
+
| `switchToTeam(slug)` | Switch and wait for completion |
|
|
158
|
+
| `validateSwitchModalVisible()` | Assert modal during switch |
|
|
159
|
+
| `goToManageTeams()` | Navigate to team settings |
|
|
160
|
+
|
|
161
|
+
## Role Translations (Spanish)
|
|
162
|
+
|
|
163
|
+
| English | Spanish |
|
|
164
|
+
|---------|---------|
|
|
165
|
+
| Owner | Propietario |
|
|
166
|
+
| Admin | Administrador |
|
|
167
|
+
| Member | Miembro |
|
|
168
|
+
| Viewer | Visualizador |
|
|
169
|
+
|
|
170
|
+
## Key Behaviors
|
|
171
|
+
|
|
172
|
+
### Team Switching Flow
|
|
173
|
+
1. User clicks team in dropdown
|
|
174
|
+
2. `TeamSwitchModal` appears (~1.4s animation)
|
|
175
|
+
3. Progress bar fills
|
|
176
|
+
4. Page reloads with new team context
|
|
177
|
+
5. Data (customers/tasks) reloads for new team
|
|
178
|
+
|
|
179
|
+
### Permission Enforcement
|
|
180
|
+
- **Owner**: Full CRUD access
|
|
181
|
+
- **Admin**: Create/Read/Update (no delete)
|
|
182
|
+
- **Member**: Read only (no create/edit/delete buttons)
|
|
183
|
+
- **Viewer**: Read only
|
|
184
|
+
|
|
185
|
+
### Session Management
|
|
186
|
+
Tests use `cy.session()` for performance:
|
|
187
|
+
- `ana-few-teams` - Single/few team user session
|
|
188
|
+
- `carlos-multi-team` - Multi-team user session
|
|
189
|
+
- `carlos-data-reload` - Data reload tests session
|
|
190
|
+
- `carlos-permissions` - Permission tests session
|
|
191
|
+
- `carlos-ui-behavior` - UI behavior tests session
|
|
192
|
+
- `sarah-viewer` - Viewer role session
|
|
193
|
+
|
|
194
|
+
## Related Files
|
|
195
|
+
|
|
196
|
+
- `core/components/teams/TeamSwitcherCompact.tsx` - Main component
|
|
197
|
+
- `core/components/teams/TeamSwitchModal.tsx` - Transition modal
|
|
198
|
+
- `test/cypress/src/classes/components/teams/TeamSwitcher.js` - POM class
|