@nextsparkjs/theme-productivity 0.1.0-beta.38 → 0.1.0-beta.39

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/lib/selectors.ts CHANGED
@@ -9,8 +9,7 @@
9
9
  * - Cypress tests (via tests/cypress/src/selectors.ts)
10
10
  */
11
11
 
12
- import { createSelectorHelpers } from '@nextsparkjs/core/lib/test/selector-factory'
13
- import { CORE_SELECTORS } from '@nextsparkjs/core/lib/test/core-selectors'
12
+ import { createSelectorHelpers, CORE_SELECTORS } from '@nextsparkjs/testing/selectors'
14
13
 
15
14
  // =============================================================================
16
15
  // BLOCK SELECTORS
@@ -202,5 +201,5 @@ export type ThemeSelectorsType = typeof THEME_SELECTORS
202
201
  export type BlockSelectorsType = typeof BLOCK_SELECTORS
203
202
  export type EntitySelectorsType = typeof ENTITY_SELECTORS
204
203
  export type KanbanSelectorsType = typeof KANBAN_SELECTORS
205
- export type { Replacements } from '@nextsparkjs/core/lib/test/selector-factory'
204
+ export type { Replacements } from '@nextsparkjs/testing/selectors'
206
205
  export { CORE_SELECTORS }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextsparkjs/theme-productivity",
3
- "version": "0.1.0-beta.38",
3
+ "version": "0.1.0-beta.39",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./config/theme.config.ts",
@@ -12,7 +12,8 @@
12
12
  "react": "^19.0.0",
13
13
  "react-dom": "^19.0.0",
14
14
  "zod": "^4.0.0",
15
- "@nextsparkjs/core": "0.1.0-beta.38"
15
+ "@nextsparkjs/core": "0.1.0-beta.39",
16
+ "@nextsparkjs/testing": "0.1.0-beta.39"
16
17
  },
17
18
  "nextspark": {
18
19
  "type": "theme",
@@ -2,11 +2,9 @@
2
2
  * Productivity Theme Session Helpers
3
3
  *
4
4
  * Direct login functions for Productivity theme tests using theme-specific users.
5
- * These helpers don't depend on ACTIVE_THEME environment variable.
5
+ * Uses API-based login for faster and more stable authentication.
6
6
  */
7
7
 
8
- import { DevKeyring } from '../../../../../../test/cypress/src/classes/components/auth/DevKeyring.js'
9
-
10
8
  /**
11
9
  * Productivity Test Users - from app.config.ts devKeyring
12
10
  */
@@ -17,22 +15,85 @@ export const PRODUCTIVITY_USERS = {
17
15
  MEMBER_MARKETING: 'prod_member_marcos@nextspark.dev', // Marcos Silva - Marketing Hub (member)
18
16
  } as const
19
17
 
18
+ // Default test password for demo users
19
+ const TEST_PASSWORD = Cypress.env('TEST_PASSWORD') || 'Test1234'
20
+ const API_TIMEOUT = 60000
21
+
22
+ /**
23
+ * API login helper
24
+ */
25
+ function apiLogin(email: string, password: string = TEST_PASSWORD): Cypress.Chainable<boolean> {
26
+ return cy.request({
27
+ method: 'POST',
28
+ url: '/api/auth/sign-in/email',
29
+ body: { email, password },
30
+ timeout: API_TIMEOUT,
31
+ failOnStatusCode: false
32
+ }).then((response) => {
33
+ if (response.status === 200) {
34
+ return true
35
+ } else {
36
+ cy.log(`⚠️ API login failed with status ${response.status}`)
37
+ return false
38
+ }
39
+ })
40
+ }
41
+
42
+ /**
43
+ * Setup team context after login
44
+ */
45
+ function setupTeamContext(preferredRole?: string) {
46
+ cy.request({
47
+ method: 'GET',
48
+ url: '/api/v1/teams',
49
+ timeout: API_TIMEOUT,
50
+ failOnStatusCode: false
51
+ }).then((teamsResponse) => {
52
+ if (teamsResponse.status === 200 && teamsResponse.body?.data?.length > 0) {
53
+ const teams = teamsResponse.body.data
54
+ let selectedTeam = teams[0]
55
+ if (preferredRole) {
56
+ const teamWithRole = teams.find((t: { role: string }) => t.role === preferredRole)
57
+ if (teamWithRole) {
58
+ selectedTeam = teamWithRole
59
+ }
60
+ }
61
+ const teamId = selectedTeam.id
62
+ cy.log(`✅ Setting active team: ${selectedTeam.name} (${teamId})`)
63
+ cy.window().then((win) => {
64
+ win.localStorage.setItem('activeTeamId', teamId)
65
+ })
66
+ cy.request({
67
+ method: 'POST',
68
+ url: '/api/v1/teams/switch',
69
+ body: { teamId },
70
+ timeout: API_TIMEOUT,
71
+ failOnStatusCode: false
72
+ })
73
+ }
74
+ })
75
+ }
76
+
20
77
  /**
21
78
  * Login as Productivity Owner (Patricia Torres)
22
79
  * Has owner role in Product Team and Marketing Hub
23
- * Session is cached and reused across tests
24
80
  */
25
81
  export function loginAsProductivityOwner() {
26
82
  cy.session('productivity-owner-session', () => {
27
- cy.visit('/login')
28
- const devKeyring = new DevKeyring()
29
- devKeyring.validateVisible()
30
- devKeyring.quickLoginByEmail(PRODUCTIVITY_USERS.OWNER)
31
- cy.url().should('include', '/dashboard')
83
+ apiLogin(PRODUCTIVITY_USERS.OWNER).then((success) => {
84
+ if (success) {
85
+ cy.visit('/dashboard', { timeout: 60000 })
86
+ }
87
+ cy.url().should('include', '/dashboard')
88
+ setupTeamContext()
89
+ })
32
90
  }, {
33
91
  validate: () => {
34
- cy.visit('/dashboard')
35
- cy.url().should('include', '/dashboard')
92
+ cy.request({
93
+ url: '/api/auth/get-session',
94
+ timeout: API_TIMEOUT,
95
+ failOnStatusCode: false
96
+ }).its('status').should('eq', 200)
36
97
  }
37
98
  })
38
99
  }
@@ -40,19 +101,23 @@ export function loginAsProductivityOwner() {
40
101
  /**
41
102
  * Login as Productivity Admin (Lucas Luna)
42
103
  * Has admin role in Product Team, member role in Marketing Hub
43
- * Session is cached and reused across tests
44
104
  */
45
105
  export function loginAsProductivityAdmin() {
46
106
  cy.session('productivity-admin-session', () => {
47
- cy.visit('/login')
48
- const devKeyring = new DevKeyring()
49
- devKeyring.validateVisible()
50
- devKeyring.quickLoginByEmail(PRODUCTIVITY_USERS.ADMIN)
51
- cy.url().should('include', '/dashboard')
107
+ apiLogin(PRODUCTIVITY_USERS.ADMIN).then((success) => {
108
+ if (success) {
109
+ cy.visit('/dashboard', { timeout: 60000 })
110
+ }
111
+ cy.url().should('include', '/dashboard')
112
+ setupTeamContext()
113
+ })
52
114
  }, {
53
115
  validate: () => {
54
- cy.visit('/dashboard')
55
- cy.url().should('include', '/dashboard')
116
+ cy.request({
117
+ url: '/api/auth/get-session',
118
+ timeout: API_TIMEOUT,
119
+ failOnStatusCode: false
120
+ }).its('status').should('eq', 200)
56
121
  }
57
122
  })
58
123
  }
@@ -60,19 +125,23 @@ export function loginAsProductivityAdmin() {
60
125
  /**
61
126
  * Login as Productivity Member - Product Team (Diana Rios)
62
127
  * Has member role in Product Team only
63
- * Session is cached and reused across tests
64
128
  */
65
129
  export function loginAsProductivityMember() {
66
130
  cy.session('productivity-member-session', () => {
67
- cy.visit('/login')
68
- const devKeyring = new DevKeyring()
69
- devKeyring.validateVisible()
70
- devKeyring.quickLoginByEmail(PRODUCTIVITY_USERS.MEMBER_PRODUCT)
71
- cy.url().should('include', '/dashboard')
131
+ apiLogin(PRODUCTIVITY_USERS.MEMBER_PRODUCT).then((success) => {
132
+ if (success) {
133
+ cy.visit('/dashboard', { timeout: 60000 })
134
+ }
135
+ cy.url().should('include', '/dashboard')
136
+ setupTeamContext('member')
137
+ })
72
138
  }, {
73
139
  validate: () => {
74
- cy.visit('/dashboard')
75
- cy.url().should('include', '/dashboard')
140
+ cy.request({
141
+ url: '/api/auth/get-session',
142
+ timeout: API_TIMEOUT,
143
+ failOnStatusCode: false
144
+ }).its('status').should('eq', 200)
76
145
  }
77
146
  })
78
147
  }
@@ -80,26 +149,28 @@ export function loginAsProductivityMember() {
80
149
  /**
81
150
  * Login as Productivity Member - Marketing Hub (Marcos Silva)
82
151
  * Has member role in Marketing Hub only
83
- * Session is cached and reused across tests
84
152
  */
85
153
  export function loginAsProductivityMemberMarketing() {
86
154
  cy.session('productivity-member-marketing-session', () => {
87
- cy.visit('/login')
88
- const devKeyring = new DevKeyring()
89
- devKeyring.validateVisible()
90
- devKeyring.quickLoginByEmail(PRODUCTIVITY_USERS.MEMBER_MARKETING)
91
- cy.url().should('include', '/dashboard')
155
+ apiLogin(PRODUCTIVITY_USERS.MEMBER_MARKETING).then((success) => {
156
+ if (success) {
157
+ cy.visit('/dashboard', { timeout: 60000 })
158
+ }
159
+ cy.url().should('include', '/dashboard')
160
+ setupTeamContext('member')
161
+ })
92
162
  }, {
93
163
  validate: () => {
94
- cy.visit('/dashboard')
95
- cy.url().should('include', '/dashboard')
164
+ cy.request({
165
+ url: '/api/auth/get-session',
166
+ timeout: API_TIMEOUT,
167
+ failOnStatusCode: false
168
+ }).its('status').should('eq', 200)
96
169
  }
97
170
  })
98
171
  }
99
172
 
100
- /**
101
- * Alias for loginAsProductivityOwner (convenience function)
102
- */
103
- export function loginAsOwner() {
104
- return loginAsProductivityOwner()
105
- }
173
+ // Aliases for convenience
174
+ export const loginAsOwner = loginAsProductivityOwner
175
+ export const loginAsAdmin = loginAsProductivityAdmin
176
+ export const loginAsMember = loginAsProductivityMember
@@ -16,9 +16,6 @@ const themeRoot = path.resolve(__dirname, '..')
16
16
  const projectRoot = path.resolve(__dirname, '../../../..')
17
17
  const narrationsOutputDir = path.join(__dirname, 'cypress/videos/narrations')
18
18
 
19
- // Detect if running in npm mode (no packages/core folder) vs monorepo
20
- const isNpmMode = !fs.existsSync(path.join(projectRoot, 'packages/core'))
21
-
22
19
  // Load environment variables
23
20
  import dotenv from 'dotenv'
24
21
  dotenv.config({ path: path.join(projectRoot, '.env') })
@@ -31,22 +28,13 @@ export default defineConfig({
31
28
  // Base URL for the application
32
29
  baseUrl: `http://localhost:${port}`,
33
30
 
34
- // Spec patterns: theme tests (core tests only in monorepo)
35
- specPattern: isNpmMode
36
- ? [
37
- // npm mode: only theme tests
38
- path.join(__dirname, 'cypress/e2e/**/*.cy.{js,ts}'),
39
- ]
40
- : [
41
- // Monorepo: core tests + theme tests
42
- path.join(projectRoot, 'packages/core/tests/cypress/e2e/core/**/*.cy.{js,ts}'),
43
- path.join(__dirname, 'cypress/e2e/**/*.cy.{js,ts}'),
44
- ],
45
-
46
- // Support file (theme-local in npm mode, core in monorepo)
47
- supportFile: isNpmMode
48
- ? path.join(__dirname, 'cypress/support/e2e.ts')
49
- : path.join(projectRoot, 'packages/core/tests/cypress/support/e2e.ts'),
31
+ // Spec patterns: theme tests only
32
+ specPattern: [
33
+ path.join(__dirname, 'cypress/e2e/**/*.cy.{js,ts}'),
34
+ ],
35
+
36
+ // Support file (always theme-local)
37
+ supportFile: path.join(__dirname, 'cypress/support/e2e.ts'),
50
38
 
51
39
  // Fixtures folder (theme-specific)
52
40
  fixturesFolder: path.join(__dirname, 'cypress/fixtures'),