@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,602 @@
|
|
|
1
|
+
/// <reference types="cypress" />
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tasks API - CRUD Tests
|
|
5
|
+
*
|
|
6
|
+
* Basic CRUD operations for /api/v1/tasks endpoints
|
|
7
|
+
* Uses superadmin API key for full access with team context
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import * as allure from 'allure-cypress'
|
|
11
|
+
|
|
12
|
+
const TaskAPIController = require('../../../src/controllers/TaskAPIController.js')
|
|
13
|
+
|
|
14
|
+
describe('Tasks API - CRUD Operations', {
|
|
15
|
+
tags: ['@api', '@feat-tasks', '@crud', '@regression']
|
|
16
|
+
}, () => {
|
|
17
|
+
let taskAPI: any
|
|
18
|
+
let createdTasks: any[] = []
|
|
19
|
+
|
|
20
|
+
// Superadmin API key for testing
|
|
21
|
+
const SUPERADMIN_API_KEY = 'test_api_key_for_testing_purposes_only_not_a_real_secret_key_abc123'
|
|
22
|
+
const TEAM_ID = 'team-tmt-001'
|
|
23
|
+
const BASE_URL = Cypress.config('baseUrl') || 'http://localhost:5173'
|
|
24
|
+
|
|
25
|
+
before(() => {
|
|
26
|
+
// Initialize API controller with superadmin API key and team context
|
|
27
|
+
taskAPI = new TaskAPIController(BASE_URL, SUPERADMIN_API_KEY, TEAM_ID)
|
|
28
|
+
cy.log('TaskAPIController initialized')
|
|
29
|
+
cy.log(`Base URL: ${BASE_URL}`)
|
|
30
|
+
cy.log(`Team ID: ${TEAM_ID}`)
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
allure.epic('API')
|
|
35
|
+
allure.feature('Tasks')
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
afterEach(() => {
|
|
39
|
+
// Cleanup: Delete tasks created during tests
|
|
40
|
+
if (createdTasks.length > 0) {
|
|
41
|
+
createdTasks.forEach((task: any) => {
|
|
42
|
+
if (task && task.id) {
|
|
43
|
+
taskAPI.deleteTask(task.id)
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
createdTasks = []
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
// ============================================================
|
|
51
|
+
// GET /api/v1/tasks - List Tasks
|
|
52
|
+
// ============================================================
|
|
53
|
+
describe('GET /api/v1/tasks - List Tasks', () => {
|
|
54
|
+
it('TASKS_API_001: Should list tasks with valid API key', { tags: '@smoke' }, () => {
|
|
55
|
+
allure.story('CRUD Operations')
|
|
56
|
+
allure.severity('critical')
|
|
57
|
+
taskAPI.getTasks().then((response: any) => {
|
|
58
|
+
taskAPI.validateSuccessResponse(response, 200)
|
|
59
|
+
taskAPI.validatePaginatedResponse(response)
|
|
60
|
+
expect(response.body.data).to.be.an('array')
|
|
61
|
+
|
|
62
|
+
cy.log(`Found ${response.body.data.length} tasks`)
|
|
63
|
+
cy.log(`Total tasks: ${response.body.info.total}`)
|
|
64
|
+
})
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('TASKS_API_002: Should list tasks with pagination', () => {
|
|
68
|
+
taskAPI.getTasks({ page: 1, limit: 5 }).then((response: any) => {
|
|
69
|
+
taskAPI.validatePaginatedResponse(response)
|
|
70
|
+
expect(response.body.info.page).to.eq(1)
|
|
71
|
+
expect(response.body.info.limit).to.eq(5)
|
|
72
|
+
expect(response.body.data.length).to.be.at.most(5)
|
|
73
|
+
|
|
74
|
+
cy.log(`Page 1, Limit 5: Got ${response.body.data.length} tasks`)
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
it('TASKS_API_003: Should filter tasks by status', () => {
|
|
79
|
+
// First create a task with known status
|
|
80
|
+
const taskData = taskAPI.generateRandomTaskData({ status: 'done' })
|
|
81
|
+
|
|
82
|
+
taskAPI.createTask(taskData).then((createResponse: any) => {
|
|
83
|
+
expect(createResponse.status).to.eq(201)
|
|
84
|
+
createdTasks.push(createResponse.body.data)
|
|
85
|
+
|
|
86
|
+
// Now filter by status
|
|
87
|
+
taskAPI.getTasks({ status: 'done' }).then((response: any) => {
|
|
88
|
+
taskAPI.validateSuccessResponse(response, 200)
|
|
89
|
+
|
|
90
|
+
// All returned tasks should have status 'done'
|
|
91
|
+
response.body.data.forEach((task: any) => {
|
|
92
|
+
expect(task.status).to.eq('done')
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
cy.log(`Found ${response.body.data.length} tasks with status 'done'`)
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
it('TASKS_API_004: Should filter tasks by priority', () => {
|
|
101
|
+
// First create a task with known priority
|
|
102
|
+
const taskData = taskAPI.generateRandomTaskData({ priority: 'high' })
|
|
103
|
+
|
|
104
|
+
taskAPI.createTask(taskData).then((createResponse: any) => {
|
|
105
|
+
expect(createResponse.status).to.eq(201)
|
|
106
|
+
createdTasks.push(createResponse.body.data)
|
|
107
|
+
|
|
108
|
+
// Now filter by priority
|
|
109
|
+
taskAPI.getTasks({ priority: 'high' }).then((response: any) => {
|
|
110
|
+
taskAPI.validateSuccessResponse(response, 200)
|
|
111
|
+
|
|
112
|
+
// All returned tasks should have priority 'high'
|
|
113
|
+
response.body.data.forEach((task: any) => {
|
|
114
|
+
expect(task.priority).to.eq('high')
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
cy.log(`Found ${response.body.data.length} tasks with priority 'high'`)
|
|
118
|
+
})
|
|
119
|
+
})
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
it('TASKS_API_005: Should search tasks by title/description', () => {
|
|
123
|
+
// Create a task with a unique searchable term
|
|
124
|
+
const uniqueTerm = `SearchTest${Date.now()}`
|
|
125
|
+
const taskData = taskAPI.generateRandomTaskData({
|
|
126
|
+
title: `Task with ${uniqueTerm} in title`,
|
|
127
|
+
description: 'Searchable task for testing'
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
taskAPI.createTask(taskData).then((createResponse: any) => {
|
|
131
|
+
expect(createResponse.status).to.eq(201)
|
|
132
|
+
createdTasks.push(createResponse.body.data)
|
|
133
|
+
|
|
134
|
+
// Search for the unique term
|
|
135
|
+
taskAPI.getTasks({ search: uniqueTerm }).then((response: any) => {
|
|
136
|
+
taskAPI.validateSuccessResponse(response, 200)
|
|
137
|
+
expect(response.body.data).to.be.an('array')
|
|
138
|
+
expect(response.body.data.length).to.be.greaterThan(0)
|
|
139
|
+
|
|
140
|
+
// Verify the found task contains our search term
|
|
141
|
+
const foundTask = response.body.data.find((t: any) => t.id === createResponse.body.data.id)
|
|
142
|
+
expect(foundTask).to.exist
|
|
143
|
+
expect(foundTask.title).to.include(uniqueTerm)
|
|
144
|
+
|
|
145
|
+
cy.log(`Search found ${response.body.data.length} tasks matching '${uniqueTerm}'`)
|
|
146
|
+
})
|
|
147
|
+
})
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
it('TASKS_API_006: Should return empty array for non-matching search', () => {
|
|
151
|
+
const nonExistentTerm = 'NonExistentSearchTerm123456789'
|
|
152
|
+
|
|
153
|
+
taskAPI.getTasks({ search: nonExistentTerm }).then((response: any) => {
|
|
154
|
+
taskAPI.validateSuccessResponse(response, 200)
|
|
155
|
+
expect(response.body.data).to.be.an('array')
|
|
156
|
+
expect(response.body.data.length).to.eq(0)
|
|
157
|
+
|
|
158
|
+
cy.log('Search with non-matching term returns empty array')
|
|
159
|
+
})
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
it('TASKS_API_007: Should reject request without API key', () => {
|
|
163
|
+
const originalApiKey = taskAPI.apiKey
|
|
164
|
+
taskAPI.setApiKey(null)
|
|
165
|
+
|
|
166
|
+
taskAPI.getTasks().then((response: any) => {
|
|
167
|
+
expect(response.status).to.eq(401)
|
|
168
|
+
expect(response.body.success).to.be.false
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
taskAPI.setApiKey(originalApiKey)
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
it('TASKS_API_008: Should reject request without x-team-id', () => {
|
|
175
|
+
const originalTeamId = taskAPI.teamId
|
|
176
|
+
taskAPI.setTeamId(null)
|
|
177
|
+
|
|
178
|
+
taskAPI.getTasks().then((response: any) => {
|
|
179
|
+
expect(response.status).to.eq(400)
|
|
180
|
+
expect(response.body.success).to.be.false
|
|
181
|
+
expect(response.body.code).to.eq('TEAM_CONTEXT_REQUIRED')
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
taskAPI.setTeamId(originalTeamId)
|
|
185
|
+
})
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
// ============================================================
|
|
189
|
+
// POST /api/v1/tasks - Create Task
|
|
190
|
+
// ============================================================
|
|
191
|
+
describe('POST /api/v1/tasks - Create Task', () => {
|
|
192
|
+
it('TASKS_API_010: Should create task with valid data', { tags: '@smoke' }, () => {
|
|
193
|
+
allure.story('CRUD Operations')
|
|
194
|
+
allure.severity('critical')
|
|
195
|
+
const taskData = taskAPI.generateRandomTaskData({
|
|
196
|
+
title: 'TestCreate - Full Task',
|
|
197
|
+
description: 'A complete task with all fields',
|
|
198
|
+
status: 'in-progress',
|
|
199
|
+
priority: 'high',
|
|
200
|
+
tags: ['testing', 'cypress'],
|
|
201
|
+
dueDate: '2025-12-31',
|
|
202
|
+
estimatedHours: 8.5
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
taskAPI.createTask(taskData).then((response: any) => {
|
|
206
|
+
taskAPI.validateSuccessResponse(response, 201)
|
|
207
|
+
taskAPI.validateTaskObject(response.body.data)
|
|
208
|
+
|
|
209
|
+
expect(response.body.data.title).to.eq(taskData.title)
|
|
210
|
+
expect(response.body.data.description).to.eq(taskData.description)
|
|
211
|
+
expect(response.body.data.status).to.eq(taskData.status)
|
|
212
|
+
expect(response.body.data.priority).to.eq(taskData.priority)
|
|
213
|
+
expect(response.body.data.tags).to.deep.eq(taskData.tags)
|
|
214
|
+
|
|
215
|
+
// Save for cleanup
|
|
216
|
+
createdTasks.push(response.body.data)
|
|
217
|
+
|
|
218
|
+
cy.log(`Created task: ${response.body.data.title}`)
|
|
219
|
+
})
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
it('TASKS_API_011: Should create task with minimal data and default values', () => {
|
|
223
|
+
const taskData = {
|
|
224
|
+
title: `Minimal Task ${Date.now()}`
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
taskAPI.createTask(taskData).then((response: any) => {
|
|
228
|
+
taskAPI.validateSuccessResponse(response, 201)
|
|
229
|
+
taskAPI.validateTaskObject(response.body.data)
|
|
230
|
+
|
|
231
|
+
// Verify default values
|
|
232
|
+
expect(response.body.data.title).to.eq(taskData.title)
|
|
233
|
+
expect(response.body.data.status).to.eq('todo')
|
|
234
|
+
expect(response.body.data.priority).to.eq('medium')
|
|
235
|
+
expect(response.body.data.completed).to.be.false
|
|
236
|
+
expect(response.body.data.tags).to.deep.eq([])
|
|
237
|
+
|
|
238
|
+
createdTasks.push(response.body.data)
|
|
239
|
+
cy.log(`Created task with defaults: ${response.body.data.id}`)
|
|
240
|
+
})
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
it('TASKS_API_012: Should create task with tags', () => {
|
|
244
|
+
const taskData = taskAPI.generateRandomTaskData({
|
|
245
|
+
tags: ['feature', 'priority', 'v2']
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
taskAPI.createTask(taskData).then((response: any) => {
|
|
249
|
+
taskAPI.validateSuccessResponse(response, 201)
|
|
250
|
+
|
|
251
|
+
expect(response.body.data.tags).to.be.an('array')
|
|
252
|
+
expect(response.body.data.tags).to.have.length(3)
|
|
253
|
+
expect(response.body.data.tags).to.include('feature')
|
|
254
|
+
expect(response.body.data.tags).to.include('priority')
|
|
255
|
+
expect(response.body.data.tags).to.include('v2')
|
|
256
|
+
|
|
257
|
+
createdTasks.push(response.body.data)
|
|
258
|
+
cy.log(`Created task with tags: ${response.body.data.tags.join(', ')}`)
|
|
259
|
+
})
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
it('TASKS_API_013: Should reject creation without title', () => {
|
|
263
|
+
const taskData = {
|
|
264
|
+
description: 'Task without title',
|
|
265
|
+
status: 'todo'
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
taskAPI.createTask(taskData).then((response: any) => {
|
|
269
|
+
expect(response.status).to.eq(400)
|
|
270
|
+
expect(response.body.success).to.be.false
|
|
271
|
+
})
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
it('TASKS_API_014: Should reject creation with invalid status', () => {
|
|
275
|
+
const taskData = taskAPI.generateRandomTaskData({
|
|
276
|
+
status: 'invalid-status'
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
taskAPI.createTask(taskData).then((response: any) => {
|
|
280
|
+
expect(response.status).to.eq(400)
|
|
281
|
+
expect(response.body.success).to.be.false
|
|
282
|
+
})
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
it('TASKS_API_015: Should reject creation with invalid priority', () => {
|
|
286
|
+
const taskData = taskAPI.generateRandomTaskData({
|
|
287
|
+
priority: 'invalid-priority'
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
taskAPI.createTask(taskData).then((response: any) => {
|
|
291
|
+
expect(response.status).to.eq(400)
|
|
292
|
+
expect(response.body.success).to.be.false
|
|
293
|
+
})
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
it('TASKS_API_016: Should reject creation without x-team-id', () => {
|
|
297
|
+
const originalTeamId = taskAPI.teamId
|
|
298
|
+
taskAPI.setTeamId(null)
|
|
299
|
+
|
|
300
|
+
const taskData = taskAPI.generateRandomTaskData()
|
|
301
|
+
|
|
302
|
+
taskAPI.createTask(taskData).then((response: any) => {
|
|
303
|
+
expect(response.status).to.eq(400)
|
|
304
|
+
expect(response.body.success).to.be.false
|
|
305
|
+
expect(response.body.code).to.eq('TEAM_CONTEXT_REQUIRED')
|
|
306
|
+
})
|
|
307
|
+
|
|
308
|
+
taskAPI.setTeamId(originalTeamId)
|
|
309
|
+
})
|
|
310
|
+
})
|
|
311
|
+
|
|
312
|
+
// ============================================================
|
|
313
|
+
// GET /api/v1/tasks/{id} - Get Task by ID
|
|
314
|
+
// ============================================================
|
|
315
|
+
describe('GET /api/v1/tasks/{id} - Get Task by ID', () => {
|
|
316
|
+
let testTask: any
|
|
317
|
+
|
|
318
|
+
beforeEach(() => {
|
|
319
|
+
// Create a test task for each test
|
|
320
|
+
const taskData = taskAPI.generateRandomTaskData({
|
|
321
|
+
title: 'TestGetById Task'
|
|
322
|
+
})
|
|
323
|
+
|
|
324
|
+
taskAPI.createTask(taskData).then((response: any) => {
|
|
325
|
+
testTask = response.body.data
|
|
326
|
+
createdTasks.push(testTask)
|
|
327
|
+
})
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
it('TASKS_API_020: Should get task by valid ID', () => {
|
|
331
|
+
cy.then(() => {
|
|
332
|
+
taskAPI.getTaskById(testTask.id).then((response: any) => {
|
|
333
|
+
taskAPI.validateSuccessResponse(response, 200)
|
|
334
|
+
taskAPI.validateTaskObject(response.body.data)
|
|
335
|
+
|
|
336
|
+
expect(response.body.data.id).to.eq(testTask.id)
|
|
337
|
+
expect(response.body.data.title).to.eq(testTask.title)
|
|
338
|
+
|
|
339
|
+
cy.log(`Got task by ID: ${testTask.id}`)
|
|
340
|
+
})
|
|
341
|
+
})
|
|
342
|
+
})
|
|
343
|
+
|
|
344
|
+
it('TASKS_API_021: Should return 404 for non-existent task', () => {
|
|
345
|
+
const nonExistentId = 'non-existent-task-id-12345'
|
|
346
|
+
|
|
347
|
+
taskAPI.getTaskById(nonExistentId).then((response: any) => {
|
|
348
|
+
expect(response.status).to.eq(404)
|
|
349
|
+
expect(response.body.success).to.be.false
|
|
350
|
+
})
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
it.skip('TASKS_API_022: Should reject access to other user\'s task', () => {
|
|
354
|
+
/**
|
|
355
|
+
* SKIPPED: This test cannot be completed with current setup
|
|
356
|
+
*
|
|
357
|
+
* Reason:
|
|
358
|
+
* - Superadmin API key bypasses RLS (is_superadmin() function)
|
|
359
|
+
* - Bug documented in pendings.md §1.1: API keys ignore team member roles
|
|
360
|
+
* - Cannot create API key with 'member' role to test userId isolation
|
|
361
|
+
*
|
|
362
|
+
* When the bug is fixed:
|
|
363
|
+
* - Create API key for member user in different team
|
|
364
|
+
* - Attempt to access task created by superadmin
|
|
365
|
+
* - Should return 404 (filtered by userId within team)
|
|
366
|
+
*/
|
|
367
|
+
cy.log('SKIPPED: Cannot test user isolation - superadmin bypasses RLS')
|
|
368
|
+
})
|
|
369
|
+
})
|
|
370
|
+
|
|
371
|
+
// ============================================================
|
|
372
|
+
// PATCH /api/v1/tasks/{id} - Update Task
|
|
373
|
+
// ============================================================
|
|
374
|
+
describe('PATCH /api/v1/tasks/{id} - Update Task', () => {
|
|
375
|
+
let testTask: any
|
|
376
|
+
|
|
377
|
+
beforeEach(() => {
|
|
378
|
+
// Create a test task for each test
|
|
379
|
+
const taskData = taskAPI.generateRandomTaskData({
|
|
380
|
+
title: 'TestUpdate Task',
|
|
381
|
+
status: 'todo',
|
|
382
|
+
priority: 'medium'
|
|
383
|
+
})
|
|
384
|
+
|
|
385
|
+
taskAPI.createTask(taskData).then((response: any) => {
|
|
386
|
+
testTask = response.body.data
|
|
387
|
+
createdTasks.push(testTask)
|
|
388
|
+
})
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
it('TASKS_API_030: Should update task with valid data', () => {
|
|
392
|
+
const updateData = {
|
|
393
|
+
title: 'Updated Task Title',
|
|
394
|
+
description: 'Updated description'
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
cy.then(() => {
|
|
398
|
+
taskAPI.updateTask(testTask.id, updateData).then((response: any) => {
|
|
399
|
+
taskAPI.validateSuccessResponse(response, 200)
|
|
400
|
+
taskAPI.validateTaskObject(response.body.data)
|
|
401
|
+
|
|
402
|
+
expect(response.body.data.title).to.eq(updateData.title)
|
|
403
|
+
expect(response.body.data.description).to.eq(updateData.description)
|
|
404
|
+
expect(response.body.data.id).to.eq(testTask.id)
|
|
405
|
+
|
|
406
|
+
cy.log(`Updated task: ${testTask.id}`)
|
|
407
|
+
})
|
|
408
|
+
})
|
|
409
|
+
})
|
|
410
|
+
|
|
411
|
+
it('TASKS_API_031: Should update task status', () => {
|
|
412
|
+
const updateData = {
|
|
413
|
+
status: 'in-progress'
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
cy.then(() => {
|
|
417
|
+
taskAPI.updateTask(testTask.id, updateData).then((response: any) => {
|
|
418
|
+
taskAPI.validateSuccessResponse(response, 200)
|
|
419
|
+
expect(response.body.data.status).to.eq(updateData.status)
|
|
420
|
+
|
|
421
|
+
cy.log(`Updated task status to: ${updateData.status}`)
|
|
422
|
+
})
|
|
423
|
+
})
|
|
424
|
+
})
|
|
425
|
+
|
|
426
|
+
it('TASKS_API_032: Should update task priority', () => {
|
|
427
|
+
const updateData = {
|
|
428
|
+
priority: 'urgent'
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
cy.then(() => {
|
|
432
|
+
taskAPI.updateTask(testTask.id, updateData).then((response: any) => {
|
|
433
|
+
taskAPI.validateSuccessResponse(response, 200)
|
|
434
|
+
expect(response.body.data.priority).to.eq(updateData.priority)
|
|
435
|
+
|
|
436
|
+
cy.log(`Updated task priority to: ${updateData.priority}`)
|
|
437
|
+
})
|
|
438
|
+
})
|
|
439
|
+
})
|
|
440
|
+
|
|
441
|
+
it('TASKS_API_033: Should update task tags', () => {
|
|
442
|
+
const updateData = {
|
|
443
|
+
tags: ['updated', 'modified', 'test']
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
cy.then(() => {
|
|
447
|
+
taskAPI.updateTask(testTask.id, updateData).then((response: any) => {
|
|
448
|
+
taskAPI.validateSuccessResponse(response, 200)
|
|
449
|
+
expect(response.body.data.tags).to.deep.eq(updateData.tags)
|
|
450
|
+
|
|
451
|
+
cy.log(`Updated task tags: ${updateData.tags.join(', ')}`)
|
|
452
|
+
})
|
|
453
|
+
})
|
|
454
|
+
})
|
|
455
|
+
|
|
456
|
+
it('TASKS_API_034: Should return 404 for non-existent task', () => {
|
|
457
|
+
const nonExistentId = 'non-existent-task-id-12345'
|
|
458
|
+
const updateData = { title: 'Updated' }
|
|
459
|
+
|
|
460
|
+
taskAPI.updateTask(nonExistentId, updateData).then((response: any) => {
|
|
461
|
+
expect(response.status).to.eq(404)
|
|
462
|
+
expect(response.body.success).to.be.false
|
|
463
|
+
})
|
|
464
|
+
})
|
|
465
|
+
|
|
466
|
+
it('TASKS_API_035: Should reject empty update body', () => {
|
|
467
|
+
cy.then(() => {
|
|
468
|
+
taskAPI.updateTask(testTask.id, {}).then((response: any) => {
|
|
469
|
+
expect(response.status).to.eq(400)
|
|
470
|
+
expect(response.body.success).to.be.false
|
|
471
|
+
})
|
|
472
|
+
})
|
|
473
|
+
})
|
|
474
|
+
})
|
|
475
|
+
|
|
476
|
+
// ============================================================
|
|
477
|
+
// DELETE /api/v1/tasks/{id} - Delete Task
|
|
478
|
+
// ============================================================
|
|
479
|
+
describe('DELETE /api/v1/tasks/{id} - Delete Task', () => {
|
|
480
|
+
let testTask: any
|
|
481
|
+
|
|
482
|
+
beforeEach(() => {
|
|
483
|
+
// Create a test task for each test
|
|
484
|
+
const taskData = taskAPI.generateRandomTaskData({
|
|
485
|
+
title: 'TestDelete Task'
|
|
486
|
+
})
|
|
487
|
+
|
|
488
|
+
taskAPI.createTask(taskData).then((response: any) => {
|
|
489
|
+
testTask = response.body.data
|
|
490
|
+
// Don't add to createdTasks - we'll delete manually
|
|
491
|
+
})
|
|
492
|
+
})
|
|
493
|
+
|
|
494
|
+
it('TASKS_API_040: Should delete task by valid ID', () => {
|
|
495
|
+
cy.then(() => {
|
|
496
|
+
taskAPI.deleteTask(testTask.id).then((response: any) => {
|
|
497
|
+
taskAPI.validateSuccessResponse(response, 200)
|
|
498
|
+
// Delete response has data.success and data.id
|
|
499
|
+
expect(response.body.data.success).to.be.true
|
|
500
|
+
expect(response.body.data.id).to.exist
|
|
501
|
+
|
|
502
|
+
cy.log(`Deleted task: ${testTask.id}`)
|
|
503
|
+
|
|
504
|
+
// Verify task was deleted
|
|
505
|
+
taskAPI.getTaskById(testTask.id).then((getResponse: any) => {
|
|
506
|
+
expect(getResponse.status).to.eq(404)
|
|
507
|
+
})
|
|
508
|
+
})
|
|
509
|
+
})
|
|
510
|
+
})
|
|
511
|
+
|
|
512
|
+
it('TASKS_API_041: Should return 404 for non-existent task', () => {
|
|
513
|
+
const nonExistentId = 'non-existent-task-id-12345'
|
|
514
|
+
|
|
515
|
+
taskAPI.deleteTask(nonExistentId).then((response: any) => {
|
|
516
|
+
expect(response.status).to.eq(404)
|
|
517
|
+
expect(response.body.success).to.be.false
|
|
518
|
+
})
|
|
519
|
+
|
|
520
|
+
// Add testTask to cleanup since we didn't delete it
|
|
521
|
+
createdTasks.push(testTask)
|
|
522
|
+
})
|
|
523
|
+
|
|
524
|
+
it('TASKS_API_042: Should verify deletion persists', () => {
|
|
525
|
+
cy.then(() => {
|
|
526
|
+
// Delete the task
|
|
527
|
+
taskAPI.deleteTask(testTask.id).then((deleteResponse: any) => {
|
|
528
|
+
expect(deleteResponse.status).to.eq(200)
|
|
529
|
+
|
|
530
|
+
// Immediate GET should return 404
|
|
531
|
+
taskAPI.getTaskById(testTask.id).then((getResponse1: any) => {
|
|
532
|
+
expect(getResponse1.status).to.eq(404)
|
|
533
|
+
|
|
534
|
+
// Second GET should also return 404 (deletion persisted)
|
|
535
|
+
taskAPI.getTaskById(testTask.id).then((getResponse2: any) => {
|
|
536
|
+
expect(getResponse2.status).to.eq(404)
|
|
537
|
+
cy.log('Verified deletion persists: task not found after multiple GET attempts')
|
|
538
|
+
})
|
|
539
|
+
})
|
|
540
|
+
})
|
|
541
|
+
})
|
|
542
|
+
})
|
|
543
|
+
})
|
|
544
|
+
|
|
545
|
+
// ============================================================
|
|
546
|
+
// Integration Test - Complete CRUD Lifecycle
|
|
547
|
+
// ============================================================
|
|
548
|
+
describe('Integration - Complete CRUD Lifecycle', () => {
|
|
549
|
+
it('TASKS_API_100: Should complete full lifecycle: Create -> Read -> Update -> Delete', () => {
|
|
550
|
+
const taskData = taskAPI.generateRandomTaskData({
|
|
551
|
+
title: 'Lifecycle Test Task',
|
|
552
|
+
description: 'Testing complete CRUD cycle',
|
|
553
|
+
status: 'todo',
|
|
554
|
+
priority: 'medium'
|
|
555
|
+
})
|
|
556
|
+
|
|
557
|
+
// 1. CREATE
|
|
558
|
+
taskAPI.createTask(taskData).then((createResponse: any) => {
|
|
559
|
+
taskAPI.validateSuccessResponse(createResponse, 201)
|
|
560
|
+
const createdTask = createResponse.body.data
|
|
561
|
+
cy.log(`1. Created task: ${createdTask.id}`)
|
|
562
|
+
|
|
563
|
+
// 2. READ
|
|
564
|
+
taskAPI.getTaskById(createdTask.id).then((readResponse: any) => {
|
|
565
|
+
taskAPI.validateSuccessResponse(readResponse, 200)
|
|
566
|
+
expect(readResponse.body.data.id).to.eq(createdTask.id)
|
|
567
|
+
expect(readResponse.body.data.title).to.eq(taskData.title)
|
|
568
|
+
cy.log(`2. Read task: ${createdTask.id}`)
|
|
569
|
+
|
|
570
|
+
// 3. UPDATE
|
|
571
|
+
const updateData = {
|
|
572
|
+
title: 'Updated Lifecycle Task',
|
|
573
|
+
status: 'in-progress',
|
|
574
|
+
priority: 'high'
|
|
575
|
+
}
|
|
576
|
+
taskAPI.updateTask(createdTask.id, updateData).then((updateResponse: any) => {
|
|
577
|
+
taskAPI.validateSuccessResponse(updateResponse, 200)
|
|
578
|
+
expect(updateResponse.body.data.title).to.eq(updateData.title)
|
|
579
|
+
expect(updateResponse.body.data.status).to.eq(updateData.status)
|
|
580
|
+
expect(updateResponse.body.data.priority).to.eq(updateData.priority)
|
|
581
|
+
cy.log(`3. Updated task: ${updateData.title}`)
|
|
582
|
+
|
|
583
|
+
// 4. DELETE
|
|
584
|
+
taskAPI.deleteTask(createdTask.id).then((deleteResponse: any) => {
|
|
585
|
+
taskAPI.validateSuccessResponse(deleteResponse, 200)
|
|
586
|
+
// Delete response has data.success instead of data.deleted
|
|
587
|
+
expect(deleteResponse.body.data.success).to.be.true
|
|
588
|
+
cy.log(`4. Deleted task: ${createdTask.id}`)
|
|
589
|
+
|
|
590
|
+
// 5. VERIFY DELETION
|
|
591
|
+
taskAPI.getTaskById(createdTask.id).then((finalResponse: any) => {
|
|
592
|
+
expect(finalResponse.status).to.eq(404)
|
|
593
|
+
cy.log(`5. Verified deletion: task not found (404)`)
|
|
594
|
+
cy.log('Full CRUD lifecycle completed successfully')
|
|
595
|
+
})
|
|
596
|
+
})
|
|
597
|
+
})
|
|
598
|
+
})
|
|
599
|
+
})
|
|
600
|
+
})
|
|
601
|
+
})
|
|
602
|
+
})
|