@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,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostsAPIController - Controller for interacting with the Posts API
|
|
3
|
+
* Encapsulates all CRUD operations for /api/v1/posts endpoints
|
|
4
|
+
*
|
|
5
|
+
* Requires:
|
|
6
|
+
* - API Key with posts:read, posts:write scopes (or superadmin with *)
|
|
7
|
+
* - x-team-id header for team context
|
|
8
|
+
*
|
|
9
|
+
* Entity characteristics:
|
|
10
|
+
* - Required fields: slug, title, blocks, locale
|
|
11
|
+
* - Optional fields: excerpt, featuredImage, SEO fields, categoryIds
|
|
12
|
+
* - Unique constraint: slug + locale
|
|
13
|
+
* - Relations: post_taxonomy_relations (many-to-many with taxonomies)
|
|
14
|
+
* - Uses PATCH for updates (standard)
|
|
15
|
+
*/
|
|
16
|
+
const BaseAPIController = require('./BaseAPIController')
|
|
17
|
+
const entitiesConfig = require('../../fixtures/entities.json')
|
|
18
|
+
|
|
19
|
+
const { slug } = entitiesConfig.entities.posts
|
|
20
|
+
|
|
21
|
+
class PostsAPIController extends BaseAPIController {
|
|
22
|
+
/**
|
|
23
|
+
* @param {string} baseUrl - Base URL for API requests
|
|
24
|
+
* @param {string|null} apiKey - API key for authentication
|
|
25
|
+
* @param {string|null} teamId - Team ID for x-team-id header
|
|
26
|
+
*/
|
|
27
|
+
constructor(baseUrl = 'http://localhost:5173', apiKey = null, teamId = null) {
|
|
28
|
+
super(baseUrl, apiKey, teamId, { slug })
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// ============================================================
|
|
32
|
+
// SEMANTIC ALIASES (for better readability in tests)
|
|
33
|
+
// ============================================================
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* GET /api/v1/posts - List posts
|
|
37
|
+
* @param {Object} options - Query options
|
|
38
|
+
* @param {number} [options.page] - Page number
|
|
39
|
+
* @param {number} [options.limit] - Results per page
|
|
40
|
+
* @param {string} [options.status] - Filter by status (draft, published, scheduled, archived)
|
|
41
|
+
* @param {string} [options.locale] - Filter by locale
|
|
42
|
+
* @param {boolean} [options.published] - Filter by published flag
|
|
43
|
+
* @param {string} [options.search] - Search in title/excerpt
|
|
44
|
+
* @param {string} [options.metas] - Metadata parameter
|
|
45
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
46
|
+
*/
|
|
47
|
+
getPosts(options = {}) {
|
|
48
|
+
return this.list(options)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* GET /api/v1/posts/{id} - Get post by ID
|
|
53
|
+
* @param {string} id - Post ID
|
|
54
|
+
* @param {Object} options - Additional options
|
|
55
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
56
|
+
*/
|
|
57
|
+
getPostById(id, options = {}) {
|
|
58
|
+
return this.getById(id, options)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* POST /api/v1/posts - Create post
|
|
63
|
+
* @param {Object} postData - Post data
|
|
64
|
+
* @param {string} postData.slug - Post slug (required)
|
|
65
|
+
* @param {string} postData.title - Post title (required)
|
|
66
|
+
* @param {string} postData.locale - Post locale (required)
|
|
67
|
+
* @param {Array} postData.blocks - Post blocks (required)
|
|
68
|
+
* @param {string} [postData.excerpt] - Post excerpt
|
|
69
|
+
* @param {string} [postData.featuredImage] - Featured image URL
|
|
70
|
+
* @param {string} [postData.status] - Status (draft, published, scheduled, archived)
|
|
71
|
+
* @param {boolean} [postData.published] - Published flag
|
|
72
|
+
* @param {string[]} [postData.categoryIds] - Category IDs
|
|
73
|
+
* @param {string} [postData.seoTitle] - SEO title
|
|
74
|
+
* @param {string} [postData.seoDescription] - SEO description
|
|
75
|
+
* @param {Object} [postData.metas] - Metadata object
|
|
76
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
77
|
+
*/
|
|
78
|
+
createPost(postData, options = {}) {
|
|
79
|
+
return this.create(postData, options)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* PUT /api/v1/posts/{id} - Update post
|
|
84
|
+
* @param {string} id - Post ID
|
|
85
|
+
* @param {Object} updateData - Data to update
|
|
86
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
87
|
+
*/
|
|
88
|
+
updatePost(id, updateData, options = {}) {
|
|
89
|
+
return this.update(id, updateData, options)
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* DELETE /api/v1/posts/{id} - Delete post
|
|
94
|
+
* @param {string} id - Post ID
|
|
95
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
96
|
+
*/
|
|
97
|
+
deletePost(id, options = {}) {
|
|
98
|
+
return this.delete(id, options)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ============================================================
|
|
102
|
+
// DATA GENERATORS
|
|
103
|
+
// ============================================================
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Generate random post data for testing
|
|
107
|
+
* @param {Object} overrides - Specific data to override
|
|
108
|
+
* @returns {Object} Generated post data
|
|
109
|
+
*/
|
|
110
|
+
generateRandomData(overrides = {}) {
|
|
111
|
+
return PostsAPIController.generateRandomPostData(overrides)
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Static method to generate random post data
|
|
116
|
+
* @param {Object} overrides - Specific data to override
|
|
117
|
+
* @returns {Object} Generated post data
|
|
118
|
+
*/
|
|
119
|
+
static generateRandomPostData(overrides = {}) {
|
|
120
|
+
const timestamp = Date.now()
|
|
121
|
+
const randomId = Math.random().toString(36).substring(2, 8)
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
slug: `test-post-${randomId}-${timestamp}`,
|
|
125
|
+
title: `Test Post ${randomId}`,
|
|
126
|
+
excerpt: `Test excerpt for post ${randomId}`,
|
|
127
|
+
locale: 'en',
|
|
128
|
+
published: false,
|
|
129
|
+
status: 'draft',
|
|
130
|
+
blocks: [],
|
|
131
|
+
categoryIds: [],
|
|
132
|
+
...overrides
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Create a test post and return its data
|
|
138
|
+
* @param {Object} overrides - Data overrides
|
|
139
|
+
* @returns {Cypress.Chainable} Promise resolving with created post data
|
|
140
|
+
*/
|
|
141
|
+
createTestPost(overrides = {}) {
|
|
142
|
+
return this.createTestEntity(overrides)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Clean up a test post
|
|
147
|
+
* @param {string} id - Post ID
|
|
148
|
+
* @returns {Cypress.Chainable} Delete response
|
|
149
|
+
*/
|
|
150
|
+
cleanupTestPost(id) {
|
|
151
|
+
return this.cleanup(id)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ============================================================
|
|
155
|
+
// ENTITY-SPECIFIC VALIDATORS
|
|
156
|
+
// ============================================================
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Validate post object structure
|
|
160
|
+
* @param {Object} post - Post object
|
|
161
|
+
* @param {boolean} allowMetas - If metas property is allowed
|
|
162
|
+
*/
|
|
163
|
+
validatePostObject(post, allowMetas = false) {
|
|
164
|
+
// Base fields
|
|
165
|
+
this.validateBaseEntityFields(post)
|
|
166
|
+
|
|
167
|
+
// Required post fields
|
|
168
|
+
expect(post).to.have.property('slug')
|
|
169
|
+
expect(post.slug).to.be.a('string')
|
|
170
|
+
|
|
171
|
+
expect(post).to.have.property('title')
|
|
172
|
+
expect(post.title).to.be.a('string')
|
|
173
|
+
|
|
174
|
+
expect(post).to.have.property('locale')
|
|
175
|
+
expect(post.locale).to.be.a('string')
|
|
176
|
+
|
|
177
|
+
expect(post).to.have.property('blocks')
|
|
178
|
+
expect(post.blocks).to.be.an('array')
|
|
179
|
+
|
|
180
|
+
// Status field (if present)
|
|
181
|
+
if (post.hasOwnProperty('status') && post.status !== null) {
|
|
182
|
+
expect(post.status).to.be.oneOf(['draft', 'published', 'scheduled', 'archived'])
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Published flag (if present)
|
|
186
|
+
if (post.hasOwnProperty('published')) {
|
|
187
|
+
expect(post.published).to.be.a('boolean')
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Categories relation (if present)
|
|
191
|
+
if (post.hasOwnProperty('categories')) {
|
|
192
|
+
expect(post.categories).to.be.an('array')
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Optional string fields
|
|
196
|
+
if (post.excerpt !== null && post.excerpt !== undefined) {
|
|
197
|
+
expect(post.excerpt).to.be.a('string')
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (post.featuredImage !== null && post.featuredImage !== undefined) {
|
|
201
|
+
expect(post.featuredImage).to.be.a('string')
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Metas if allowed
|
|
205
|
+
if (allowMetas && post.hasOwnProperty('metas')) {
|
|
206
|
+
expect(post.metas).to.be.an('object')
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// ============================================================
|
|
211
|
+
// METADATA HELPERS
|
|
212
|
+
// ============================================================
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Generate sample metadata for testing
|
|
216
|
+
* @param {string} type - Type of metadata ('seo', 'social', 'analytics')
|
|
217
|
+
* @returns {Object} Sample metadata
|
|
218
|
+
*/
|
|
219
|
+
generateSampleMetadata(type = 'seo') {
|
|
220
|
+
const sampleMetas = {
|
|
221
|
+
seo: {
|
|
222
|
+
seoTitle: 'Custom SEO Title',
|
|
223
|
+
seoDescription: 'Custom SEO description for search engines',
|
|
224
|
+
seoKeywords: 'test, post, cypress',
|
|
225
|
+
noindex: false,
|
|
226
|
+
nofollow: false
|
|
227
|
+
},
|
|
228
|
+
social: {
|
|
229
|
+
ogImage: '/images/og-image.jpg',
|
|
230
|
+
twitterCard: 'summary_large_image',
|
|
231
|
+
shareText: 'Check out this post!'
|
|
232
|
+
},
|
|
233
|
+
analytics: {
|
|
234
|
+
trackViews: true,
|
|
235
|
+
conversionGoal: 'signup',
|
|
236
|
+
utmSource: 'test'
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return { [type]: sampleMetas[type] || sampleMetas.seo }
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Export for CommonJS
|
|
245
|
+
module.exports = PostsAPIController
|
|
246
|
+
|
|
247
|
+
// For global use in Cypress
|
|
248
|
+
if (typeof window !== 'undefined') {
|
|
249
|
+
window.PostsAPIController = PostsAPIController
|
|
250
|
+
}
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TaskAPIController - Controller for interacting with the Tasks API
|
|
3
|
+
* Encapsulates all CRUD operations for /api/v1/tasks endpoints
|
|
4
|
+
*
|
|
5
|
+
* Requires:
|
|
6
|
+
* - API Key with tasks:read, tasks:write scopes (or superadmin with *)
|
|
7
|
+
* - x-team-id header for team context
|
|
8
|
+
*/
|
|
9
|
+
const BaseAPIController = require('./BaseAPIController')
|
|
10
|
+
const entitiesConfig = require('../../fixtures/entities.json')
|
|
11
|
+
|
|
12
|
+
const { slug } = entitiesConfig.entities.tasks
|
|
13
|
+
|
|
14
|
+
class TaskAPIController extends BaseAPIController {
|
|
15
|
+
/**
|
|
16
|
+
* @param {string} baseUrl - Base URL for API requests
|
|
17
|
+
* @param {string|null} apiKey - API key for authentication
|
|
18
|
+
* @param {string|null} teamId - Team ID for x-team-id header
|
|
19
|
+
*/
|
|
20
|
+
constructor(baseUrl = 'http://localhost:5173', apiKey = null, teamId = null) {
|
|
21
|
+
super(baseUrl, apiKey, teamId, { slug })
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// ============================================================
|
|
25
|
+
// SEMANTIC ALIASES (for backward compatibility)
|
|
26
|
+
// ============================================================
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* GET /api/v1/tasks - Get list of tasks
|
|
30
|
+
* @param {Object} options - Query options
|
|
31
|
+
* @param {number} [options.page] - Page number
|
|
32
|
+
* @param {number} [options.limit] - Results per page
|
|
33
|
+
* @param {string} [options.status] - Filter by status (todo, in-progress, review, done, blocked)
|
|
34
|
+
* @param {string} [options.priority] - Filter by priority (low, medium, high, urgent)
|
|
35
|
+
* @param {string} [options.metas] - Metadata parameter ('all', 'key1,key2', etc.)
|
|
36
|
+
* @param {string} [options.search] - Search in title/description
|
|
37
|
+
* @param {Object} [options.headers] - Additional headers
|
|
38
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
39
|
+
*/
|
|
40
|
+
getTasks(options = {}) {
|
|
41
|
+
return this.list(options)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* GET /api/v1/tasks/{id} - Get specific task by ID
|
|
46
|
+
* @param {string} id - Task ID
|
|
47
|
+
* @param {Object} options - Additional options
|
|
48
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
49
|
+
*/
|
|
50
|
+
getTaskById(id, options = {}) {
|
|
51
|
+
return this.getById(id, options)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* POST /api/v1/tasks - Create new task
|
|
56
|
+
* @param {Object} taskData - Task data
|
|
57
|
+
* @param {string} taskData.title - Task title (required)
|
|
58
|
+
* @param {string} [taskData.description] - Task description
|
|
59
|
+
* @param {string} [taskData.status] - Status: todo, in-progress, review, done, blocked
|
|
60
|
+
* @param {string} [taskData.priority] - Priority: low, medium, high, urgent
|
|
61
|
+
* @param {string[]} [taskData.tags] - Array of tags
|
|
62
|
+
* @param {string} [taskData.dueDate] - Due date YYYY-MM-DD
|
|
63
|
+
* @param {number} [taskData.estimatedHours] - Estimated hours
|
|
64
|
+
* @param {Object} [taskData.metas] - Metadata object
|
|
65
|
+
* @param {Object} options - Additional options
|
|
66
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
67
|
+
*/
|
|
68
|
+
createTask(taskData, options = {}) {
|
|
69
|
+
return this.create(taskData, options)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* PATCH /api/v1/tasks/{id} - Update task
|
|
74
|
+
* @param {string} id - Task ID
|
|
75
|
+
* @param {Object} updateData - Data to update
|
|
76
|
+
* @param {Object} options - Additional options
|
|
77
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
78
|
+
*/
|
|
79
|
+
updateTask(id, updateData, options = {}) {
|
|
80
|
+
return this.update(id, updateData, options)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* DELETE /api/v1/tasks/{id} - Delete task
|
|
85
|
+
* @param {string} id - Task ID
|
|
86
|
+
* @param {Object} options - Additional options
|
|
87
|
+
* @returns {Cypress.Chainable} Cypress response
|
|
88
|
+
*/
|
|
89
|
+
deleteTask(id, options = {}) {
|
|
90
|
+
return this.delete(id, options)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ============================================================
|
|
94
|
+
// DATA GENERATORS
|
|
95
|
+
// ============================================================
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Generate random task data for testing
|
|
99
|
+
* @param {Object} overrides - Specific data to override
|
|
100
|
+
* @returns {Object} Generated task data
|
|
101
|
+
*/
|
|
102
|
+
generateRandomData(overrides = {}) {
|
|
103
|
+
return this.generateRandomTaskData(overrides)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Generate random task data for testing
|
|
108
|
+
* @param {Object} overrides - Specific data to override
|
|
109
|
+
* @returns {Object} Generated task data
|
|
110
|
+
*/
|
|
111
|
+
generateRandomTaskData(overrides = {}) {
|
|
112
|
+
const timestamp = Date.now()
|
|
113
|
+
const randomId = Math.random().toString(36).substring(2, 8)
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
title: `Test Task ${randomId} - ${timestamp}`,
|
|
117
|
+
description: `Description for test task created at ${new Date().toISOString()}`,
|
|
118
|
+
status: 'todo',
|
|
119
|
+
priority: 'medium',
|
|
120
|
+
tags: [],
|
|
121
|
+
...overrides
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Create a test task and return its data
|
|
127
|
+
* @param {Object} taskData - Task data (optional)
|
|
128
|
+
* @returns {Cypress.Chainable} Promise resolving with created task data
|
|
129
|
+
*/
|
|
130
|
+
createTestTask(taskData = {}) {
|
|
131
|
+
return this.createTestEntity(taskData)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Clean up a test task (delete it)
|
|
136
|
+
* @param {string} id - Task ID
|
|
137
|
+
* @returns {Cypress.Chainable} Delete response
|
|
138
|
+
*/
|
|
139
|
+
cleanupTestTask(id) {
|
|
140
|
+
return this.cleanup(id)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ============================================================
|
|
144
|
+
// ENTITY-SPECIFIC VALIDATORS
|
|
145
|
+
// ============================================================
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Validate task object structure
|
|
149
|
+
* @param {Object} task - Task object
|
|
150
|
+
* @param {boolean} allowMetas - If metas property is allowed
|
|
151
|
+
*/
|
|
152
|
+
validateTaskObject(task, allowMetas = false) {
|
|
153
|
+
// Base fields
|
|
154
|
+
this.validateBaseEntityFields(task)
|
|
155
|
+
|
|
156
|
+
// Required entity fields
|
|
157
|
+
expect(task).to.have.property('title')
|
|
158
|
+
expect(task.title).to.be.a('string')
|
|
159
|
+
|
|
160
|
+
// Optional fields with defaults
|
|
161
|
+
expect(task).to.have.property('status')
|
|
162
|
+
expect(task.status).to.be.oneOf(['todo', 'in-progress', 'review', 'done', 'blocked'])
|
|
163
|
+
|
|
164
|
+
expect(task).to.have.property('priority')
|
|
165
|
+
expect(task.priority).to.be.oneOf(['low', 'medium', 'high', 'urgent'])
|
|
166
|
+
|
|
167
|
+
expect(task).to.have.property('completed')
|
|
168
|
+
expect(task.completed).to.be.a('boolean')
|
|
169
|
+
|
|
170
|
+
expect(task).to.have.property('tags')
|
|
171
|
+
expect(task.tags).to.be.an('array')
|
|
172
|
+
|
|
173
|
+
// Optional fields that can be null
|
|
174
|
+
if (task.description !== null && task.description !== undefined) {
|
|
175
|
+
expect(task.description).to.be.a('string')
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (task.dueDate !== null && task.dueDate !== undefined) {
|
|
179
|
+
expect(task.dueDate).to.be.a('string')
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (task.estimatedHours !== null && task.estimatedHours !== undefined) {
|
|
183
|
+
// Note: NUMERIC type comes back as string from PostgreSQL
|
|
184
|
+
expect(typeof task.estimatedHours === 'number' || typeof task.estimatedHours === 'string').to.be.true
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Validate metas if present
|
|
188
|
+
if (allowMetas && task.hasOwnProperty('metas')) {
|
|
189
|
+
expect(task.metas).to.be.an('object')
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ============================================================
|
|
194
|
+
// METADATA HELPERS
|
|
195
|
+
// ============================================================
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Generate sample metadata for testing
|
|
199
|
+
* @param {string} type - Type of metadata ('uiPreferences', 'notifications', 'tracking', 'customFields')
|
|
200
|
+
* @returns {Object} Sample metadata
|
|
201
|
+
*/
|
|
202
|
+
generateSampleMetadata(type = 'uiPreferences') {
|
|
203
|
+
const sampleMetas = {
|
|
204
|
+
uiPreferences: {
|
|
205
|
+
colorLabel: 'blue',
|
|
206
|
+
showInKanban: true,
|
|
207
|
+
collapsed: false,
|
|
208
|
+
customIcon: 'star'
|
|
209
|
+
},
|
|
210
|
+
notifications: {
|
|
211
|
+
emailOnDue: true,
|
|
212
|
+
reminderDays: 3,
|
|
213
|
+
notifyAssignee: true,
|
|
214
|
+
channels: ['email', 'slack']
|
|
215
|
+
},
|
|
216
|
+
tracking: {
|
|
217
|
+
actualHours: 5.5,
|
|
218
|
+
startedAt: '2025-12-01T10:00:00Z',
|
|
219
|
+
completedAt: null,
|
|
220
|
+
progressPercent: 75
|
|
221
|
+
},
|
|
222
|
+
customFields: {
|
|
223
|
+
clientRef: 'PRJ-001',
|
|
224
|
+
department: 'Engineering',
|
|
225
|
+
billable: true,
|
|
226
|
+
hourlyRate: 150
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return { [type]: sampleMetas[type] || sampleMetas.uiPreferences }
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Export class for use in tests
|
|
235
|
+
module.exports = TaskAPIController
|
|
236
|
+
|
|
237
|
+
// For global use in Cypress
|
|
238
|
+
if (typeof window !== 'undefined') {
|
|
239
|
+
window.TaskAPIController = TaskAPIController
|
|
240
|
+
}
|