@nextsparkjs/theme-default 0.1.0-beta.49 → 0.1.0-beta.51
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/api/ai/chat/stream/route.ts +4 -1
- package/api/ai/orchestrator/route.ts +10 -3
- package/api/ai/single-agent/route.ts +10 -3
- package/api/ai/usage/route.ts +4 -1
- package/blocks/text-content/component.tsx +10 -8
- package/config/dashboard.config.ts +14 -0
- package/config/permissions.config.ts +11 -0
- package/messages/en/admin.json +12 -1
- package/messages/es/admin.json +12 -1
- package/migrations/093_pages_sample_data.sql +7 -7
- package/migrations/098_patterns_sample_data.sql +234 -0
- package/package.json +3 -3
- package/tests/cypress/e2e/_utils/selectors/block-editor.bdd.md +127 -3
- package/tests/cypress/e2e/_utils/selectors/block-editor.cy.ts +124 -0
- package/tests/cypress/e2e/ai/chat-api.cy.ts +50 -38
- package/tests/cypress/e2e/api/_core/security/security-headers.cy.ts +601 -0
- package/tests/cypress/e2e/patterns/patterns-in-pages.cy.ts +367 -0
- package/tests/cypress/fixtures/entities.json +9 -0
- package/tests/cypress/src/entities/PatternsPOM.ts +329 -0
- package/tests/cypress/src/entities/index.ts +2 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
feature: Block Editor UI Selectors Validation
|
|
3
3
|
priority: high
|
|
4
|
-
tags: [selectors, block-editor, page-builder, ui-validation]
|
|
5
|
-
grepTags: [ui-selectors, block-editor, selector-validation, SEL_BE_001, SEL_BE_002, SEL_BE_003, SEL_BE_004, SEL_BE_005, SEL_BE_006, SEL_BE_007]
|
|
6
|
-
coverage:
|
|
4
|
+
tags: [selectors, block-editor, page-builder, ui-validation, patterns]
|
|
5
|
+
grepTags: [ui-selectors, block-editor, selector-validation, SEL_BE_001, SEL_BE_002, SEL_BE_003, SEL_BE_004, SEL_BE_005, SEL_BE_006, SEL_BE_007, SEL_BE_008, SEL_BE_009]
|
|
6
|
+
coverage: 9
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
# Block Editor UI Selectors Validation
|
|
@@ -489,3 +489,127 @@ And deberia encontrar el boton de remover del item
|
|
|
489
489
|
|-----|------|-------|
|
|
490
490
|
| PageBuilderPOM | `themes/default/tests/cypress/src/features/PageBuilderPOM.ts` | Block editor selectors and methods |
|
|
491
491
|
| PagesPOM | `themes/default/tests/cypress/src/entities/PagesPOM.ts` | Pages entity selectors |
|
|
492
|
+
|
|
493
|
+
---
|
|
494
|
+
|
|
495
|
+
## @test SEL_BE_008: Patterns Tab Selectors
|
|
496
|
+
|
|
497
|
+
### Metadata
|
|
498
|
+
- **Priority:** High
|
|
499
|
+
- **Type:** Selector Validation
|
|
500
|
+
- **Tags:** block-editor, patterns, patterns-tab
|
|
501
|
+
- **Grep:** `@ui-selectors` `@SEL_BE_008` `@patterns`
|
|
502
|
+
- **Status:** Active (8 passing, 0 skipped)
|
|
503
|
+
|
|
504
|
+
```gherkin:en
|
|
505
|
+
Scenario: Patterns tab has all required selectors
|
|
506
|
+
|
|
507
|
+
Given I am logged in as developer
|
|
508
|
+
And I navigate to the page builder create page
|
|
509
|
+
When the editor loads
|
|
510
|
+
Then I should find the patterns tab button
|
|
511
|
+
When I click the patterns tab
|
|
512
|
+
Then I should find the patterns search input
|
|
513
|
+
And I should find the patterns list container
|
|
514
|
+
And I should find pattern cards for published patterns
|
|
515
|
+
And I should find pattern card icon
|
|
516
|
+
And I should find pattern card title
|
|
517
|
+
And I should find pattern card description
|
|
518
|
+
And I should find pattern card insert button
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
```gherkin:es
|
|
522
|
+
Scenario: El tab de patrones tiene todos los selectores requeridos
|
|
523
|
+
|
|
524
|
+
Given estoy logueado como developer
|
|
525
|
+
And navego a la pagina de crear page builder
|
|
526
|
+
When el editor carga
|
|
527
|
+
Then deberia encontrar el boton de tab de patrones
|
|
528
|
+
When hago click en el tab de patrones
|
|
529
|
+
Then deberia encontrar el input de busqueda de patrones
|
|
530
|
+
And deberia encontrar el contenedor de lista de patrones
|
|
531
|
+
And deberia encontrar tarjetas de patrones para patrones publicados
|
|
532
|
+
And deberia encontrar el icono de tarjeta de patron
|
|
533
|
+
And deberia encontrar el titulo de tarjeta de patron
|
|
534
|
+
And deberia encontrar la descripcion de tarjeta de patron
|
|
535
|
+
And deberia encontrar el boton de insertar de tarjeta de patron
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
### Expected Results
|
|
539
|
+
| Test ID | Selector Path | POM Accessor | data-cy Value |
|
|
540
|
+
|---------|---------------|--------------|---------------|
|
|
541
|
+
| SEL_BE_008_01 | blockPicker.tabPatterns | `[data-cy="block-picker-tab-patterns"]` | block-picker-tab-patterns |
|
|
542
|
+
| SEL_BE_008_02 | blockPicker.patternsSearch | `[data-cy="block-picker-patterns-search"]` | block-picker-patterns-search |
|
|
543
|
+
| SEL_BE_008_03 | blockPicker.patternsList | `[data-cy="block-picker-patterns-list"]` | block-picker-patterns-list |
|
|
544
|
+
| SEL_BE_008_04 | blockPicker.patternCard(id) | `[data-cy^="block-picker-pattern-card-"]` | block-picker-pattern-card-{id} |
|
|
545
|
+
| SEL_BE_008_05 | blockPicker.patternCardIcon(id) | `[data-cy^="block-picker-pattern-icon-"]` | block-picker-pattern-icon-{id} |
|
|
546
|
+
| SEL_BE_008_06 | blockPicker.patternCardTitle(id) | `[data-cy^="block-picker-pattern-title-"]` | block-picker-pattern-title-{id} |
|
|
547
|
+
| SEL_BE_008_07 | blockPicker.patternCardDescription(id) | `[data-cy^="block-picker-pattern-desc-"]` | block-picker-pattern-desc-{id} |
|
|
548
|
+
| SEL_BE_008_08 | blockPicker.patternCardInsertButton(id) | `[data-cy^="block-picker-pattern-insert-"]` | block-picker-pattern-insert-{id} |
|
|
549
|
+
|
|
550
|
+
### Notes
|
|
551
|
+
- Patterns tab is only visible when editing pages, NOT when editing patterns (prevents nesting)
|
|
552
|
+
- Tests use sample patterns from team-nextspark-001 (Newsletter CTA, Footer Links, etc.)
|
|
553
|
+
- Pattern cards are filtered by published status
|
|
554
|
+
|
|
555
|
+
---
|
|
556
|
+
|
|
557
|
+
## @test SEL_BE_009: Pattern Reference Selectors
|
|
558
|
+
|
|
559
|
+
### Metadata
|
|
560
|
+
- **Priority:** High
|
|
561
|
+
- **Type:** Selector Validation
|
|
562
|
+
- **Tags:** block-editor, patterns, pattern-reference
|
|
563
|
+
- **Grep:** `@ui-selectors` `@SEL_BE_009` `@patterns`
|
|
564
|
+
- **Status:** Active (5 passing, 0 skipped)
|
|
565
|
+
|
|
566
|
+
```gherkin:en
|
|
567
|
+
Scenario: Pattern reference has all required selectors when inserted
|
|
568
|
+
|
|
569
|
+
Given I am logged in as developer
|
|
570
|
+
And I navigate to the page builder create page
|
|
571
|
+
When the editor loads
|
|
572
|
+
And I switch to layout mode
|
|
573
|
+
And I click the patterns tab
|
|
574
|
+
And I insert a pattern
|
|
575
|
+
And I switch to preview mode
|
|
576
|
+
Then I should find the pattern reference container
|
|
577
|
+
And I should find the pattern reference badge
|
|
578
|
+
And I should find the pattern reference remove button
|
|
579
|
+
When I click on the pattern reference
|
|
580
|
+
Then I should find the pattern reference locked state indicator
|
|
581
|
+
And I should find the pattern reference edit link
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
```gherkin:es
|
|
585
|
+
Scenario: La referencia de patron tiene todos los selectores requeridos cuando se inserta
|
|
586
|
+
|
|
587
|
+
Given estoy logueado como developer
|
|
588
|
+
And navego a la pagina de crear page builder
|
|
589
|
+
When el editor carga
|
|
590
|
+
And cambio a modo layout
|
|
591
|
+
And hago click en el tab de patrones
|
|
592
|
+
And inserto un patron
|
|
593
|
+
And cambio a modo preview
|
|
594
|
+
Then deberia encontrar el contenedor de referencia de patron
|
|
595
|
+
And deberia encontrar el badge de referencia de patron
|
|
596
|
+
And deberia encontrar el boton de remover de referencia de patron
|
|
597
|
+
When hago click en la referencia de patron
|
|
598
|
+
Then deberia encontrar el indicador de estado bloqueado de referencia de patron
|
|
599
|
+
And deberia encontrar el link de editar de referencia de patron
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
### Expected Results
|
|
603
|
+
| Test ID | Selector Path | POM Accessor | data-cy Value |
|
|
604
|
+
|---------|---------------|--------------|---------------|
|
|
605
|
+
| SEL_BE_009_01 | patternReference.container(ref) | `[data-cy^="pattern-reference-"]` | pattern-reference-{ref} |
|
|
606
|
+
| SEL_BE_009_02 | patternReference.badge(ref) | `[data-cy^="pattern-reference-badge-"]` | pattern-reference-badge-{ref} |
|
|
607
|
+
| SEL_BE_009_03 | patternReference.remove(ref) | `[data-cy^="pattern-reference-remove-"]` | pattern-reference-remove-{ref} |
|
|
608
|
+
| SEL_BE_009_04 | patternReference.locked(ref) | `[data-cy^="pattern-reference-locked-"]` | pattern-reference-locked-{ref} |
|
|
609
|
+
| SEL_BE_009_05 | patternReference.editLink(ref) | `[data-cy^="pattern-reference-edit-link-"]` | pattern-reference-edit-link-{ref} |
|
|
610
|
+
|
|
611
|
+
### Notes
|
|
612
|
+
- Pattern reference is rendered in preview mode after inserting a pattern
|
|
613
|
+
- Locked state appears when the pattern reference is selected (prevents editing blocks within)
|
|
614
|
+
- Edit link allows navigating to the pattern editor to modify the source pattern
|
|
615
|
+
- Pattern reference can be removed like any other block
|
|
@@ -12,10 +12,14 @@
|
|
|
12
12
|
* - SEL_BE_005: Preview Canvas Selectors
|
|
13
13
|
* - SEL_BE_006: Block Properties Panel Selectors
|
|
14
14
|
* - SEL_BE_007: Array Fields Selectors
|
|
15
|
+
* - SEL_BE_008: Patterns Tab Selectors
|
|
16
|
+
* - SEL_BE_009: Pattern Reference Selectors
|
|
15
17
|
*
|
|
16
18
|
* Re-execution:
|
|
17
19
|
* pnpm tags @SEL_BE_001 # Run only Header tests
|
|
18
20
|
* pnpm tags @SEL_BE_004 # Run only Layout Canvas tests
|
|
21
|
+
* pnpm tags @SEL_BE_008 # Run only Patterns Tab tests
|
|
22
|
+
* pnpm tags @patterns # Run all patterns-related tests
|
|
19
23
|
* pnpm tags @ui-selectors # Run all selector tests
|
|
20
24
|
*/
|
|
21
25
|
|
|
@@ -472,4 +476,124 @@ describe('Block Editor Selectors Validation', {
|
|
|
472
476
|
})
|
|
473
477
|
})
|
|
474
478
|
})
|
|
479
|
+
|
|
480
|
+
// ===========================================================================
|
|
481
|
+
// SEL_BE_008: PATTERNS TAB SELECTORS
|
|
482
|
+
// ===========================================================================
|
|
483
|
+
describe('SEL_BE_008: Patterns Tab Selectors', { tags: ['@SEL_BE_008', '@patterns'] }, () => {
|
|
484
|
+
beforeEach(() => {
|
|
485
|
+
pom.visitCreate()
|
|
486
|
+
pom.waitForEditor()
|
|
487
|
+
})
|
|
488
|
+
|
|
489
|
+
it('SEL_BE_008_01: should find patterns tab button', { tags: '@SEL_BE_008_01' }, () => {
|
|
490
|
+
cy.get('[data-cy="block-picker-tab-patterns"]').should('exist').and('be.visible')
|
|
491
|
+
})
|
|
492
|
+
|
|
493
|
+
it('SEL_BE_008_02: should find patterns search input after clicking patterns tab', { tags: '@SEL_BE_008_02' }, () => {
|
|
494
|
+
cy.get('[data-cy="block-picker-tab-patterns"]').click()
|
|
495
|
+
cy.get('[data-cy="block-picker-patterns-search"]').should('exist').and('be.visible')
|
|
496
|
+
})
|
|
497
|
+
|
|
498
|
+
it('SEL_BE_008_03: should find patterns list container', { tags: '@SEL_BE_008_03' }, () => {
|
|
499
|
+
cy.get('[data-cy="block-picker-tab-patterns"]').click()
|
|
500
|
+
cy.get('[data-cy="block-picker-patterns-list"]').should('exist').and('be.visible')
|
|
501
|
+
})
|
|
502
|
+
|
|
503
|
+
it('SEL_BE_008_04: should find pattern cards for sample patterns', { tags: '@SEL_BE_008_04' }, () => {
|
|
504
|
+
cy.get('[data-cy="block-picker-tab-patterns"]').click()
|
|
505
|
+
// Wait for patterns to load
|
|
506
|
+
cy.wait(500)
|
|
507
|
+
// Check for pattern cards with specific IDs (using generic selector)
|
|
508
|
+
// Pattern cards should exist for published patterns
|
|
509
|
+
cy.get('[data-cy^="block-picker-pattern-card-"]').should('have.length.at.least', 1)
|
|
510
|
+
})
|
|
511
|
+
|
|
512
|
+
it('SEL_BE_008_05: should find pattern card icon element', { tags: '@SEL_BE_008_05' }, () => {
|
|
513
|
+
cy.get('[data-cy="block-picker-tab-patterns"]').click()
|
|
514
|
+
cy.wait(500)
|
|
515
|
+
// Icon selector pattern: block-picker-pattern-icon-{id}
|
|
516
|
+
cy.get('[data-cy^="block-picker-pattern-icon-"]').first().should('exist')
|
|
517
|
+
})
|
|
518
|
+
|
|
519
|
+
it('SEL_BE_008_06: should find pattern card title element', { tags: '@SEL_BE_008_06' }, () => {
|
|
520
|
+
cy.get('[data-cy="block-picker-tab-patterns"]').click()
|
|
521
|
+
cy.wait(500)
|
|
522
|
+
// Title selector pattern: block-picker-pattern-title-{id}
|
|
523
|
+
cy.get('[data-cy^="block-picker-pattern-title-"]').first().should('exist')
|
|
524
|
+
})
|
|
525
|
+
|
|
526
|
+
it('SEL_BE_008_07: should find pattern card description element', { tags: '@SEL_BE_008_07' }, () => {
|
|
527
|
+
cy.get('[data-cy="block-picker-tab-patterns"]').click()
|
|
528
|
+
cy.wait(500)
|
|
529
|
+
// Description selector pattern: block-picker-pattern-desc-{id}
|
|
530
|
+
cy.get('[data-cy^="block-picker-pattern-desc-"]').first().should('exist')
|
|
531
|
+
})
|
|
532
|
+
|
|
533
|
+
it('SEL_BE_008_08: should find pattern card insert button', { tags: '@SEL_BE_008_08' }, () => {
|
|
534
|
+
cy.get('[data-cy="block-picker-tab-patterns"]').click()
|
|
535
|
+
cy.wait(500)
|
|
536
|
+
// Insert button selector pattern: block-picker-pattern-insert-{id}
|
|
537
|
+
cy.get('[data-cy^="block-picker-pattern-insert-"]').first().should('exist')
|
|
538
|
+
})
|
|
539
|
+
})
|
|
540
|
+
|
|
541
|
+
// ===========================================================================
|
|
542
|
+
// SEL_BE_009: PATTERN REFERENCE SELECTORS
|
|
543
|
+
// ===========================================================================
|
|
544
|
+
describe('SEL_BE_009: Pattern Reference Selectors', { tags: ['@SEL_BE_009', '@patterns'] }, () => {
|
|
545
|
+
let patternRefId: string
|
|
546
|
+
|
|
547
|
+
beforeEach(() => {
|
|
548
|
+
pom.visitCreate()
|
|
549
|
+
pom.waitForEditor()
|
|
550
|
+
pom.switchToLayoutMode()
|
|
551
|
+
|
|
552
|
+
// Insert a pattern to create a pattern reference
|
|
553
|
+
cy.get('[data-cy="block-picker-tab-patterns"]').click()
|
|
554
|
+
cy.wait(500)
|
|
555
|
+
|
|
556
|
+
// Click insert on first available pattern
|
|
557
|
+
cy.get('[data-cy^="block-picker-pattern-insert-"]').first().click()
|
|
558
|
+
|
|
559
|
+
// Wait for pattern reference to be created
|
|
560
|
+
cy.wait(1000)
|
|
561
|
+
|
|
562
|
+
// Switch to preview mode to see pattern reference rendering
|
|
563
|
+
pom.switchToPreviewMode()
|
|
564
|
+
|
|
565
|
+
// Get the pattern reference ID from the first pattern-reference element
|
|
566
|
+
cy.get('[data-cy^="pattern-reference-"]').first()
|
|
567
|
+
.invoke('attr', 'data-cy')
|
|
568
|
+
.then((dataCy) => {
|
|
569
|
+
patternRefId = dataCy?.replace('pattern-reference-', '') || ''
|
|
570
|
+
cy.log(`Pattern reference ID: ${patternRefId}`)
|
|
571
|
+
})
|
|
572
|
+
})
|
|
573
|
+
|
|
574
|
+
it('SEL_BE_009_01: should find pattern reference container', { tags: '@SEL_BE_009_01' }, () => {
|
|
575
|
+
cy.get('[data-cy^="pattern-reference-"]').should('exist').and('be.visible')
|
|
576
|
+
})
|
|
577
|
+
|
|
578
|
+
it('SEL_BE_009_02: should find pattern reference badge', { tags: '@SEL_BE_009_02' }, () => {
|
|
579
|
+
cy.get('[data-cy^="pattern-reference-badge-"]').should('exist')
|
|
580
|
+
})
|
|
581
|
+
|
|
582
|
+
it('SEL_BE_009_03: should find pattern reference remove button', { tags: '@SEL_BE_009_03' }, () => {
|
|
583
|
+
cy.get('[data-cy^="pattern-reference-remove-"]').should('exist')
|
|
584
|
+
})
|
|
585
|
+
|
|
586
|
+
it('SEL_BE_009_04: should find pattern reference locked state when selected', { tags: '@SEL_BE_009_04' }, () => {
|
|
587
|
+
// Click on the pattern reference to select it
|
|
588
|
+
cy.get('[data-cy^="pattern-reference-"]').first().click()
|
|
589
|
+
cy.wait(500)
|
|
590
|
+
// Locked selector should appear when pattern reference is selected
|
|
591
|
+
cy.get('[data-cy^="pattern-reference-locked-"]').should('exist')
|
|
592
|
+
})
|
|
593
|
+
|
|
594
|
+
it('SEL_BE_009_05: should find pattern reference edit link', { tags: '@SEL_BE_009_05' }, () => {
|
|
595
|
+
// Edit link selector pattern: pattern-reference-edit-link-{ref}
|
|
596
|
+
cy.get('[data-cy^="pattern-reference-edit-link-"]').should('exist')
|
|
597
|
+
})
|
|
598
|
+
})
|
|
475
599
|
})
|
|
@@ -1,10 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* AI Chat Streaming API Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests the streaming chat endpoint at /api/v1/theme/default/ai/chat/stream
|
|
5
|
+
* This endpoint uses Server-Sent Events (SSE) for streaming responses.
|
|
6
|
+
*
|
|
7
|
+
* Note: Some tests check for JSON error responses before SSE streaming begins.
|
|
8
|
+
*/
|
|
9
|
+
describe('AI Chat Streaming API', {
|
|
2
10
|
tags: ['@api', '@feat-ai', '@crud']
|
|
3
11
|
}, () => {
|
|
4
12
|
// Test constants - Using superadmin API key for API-level tests
|
|
5
13
|
const API_KEY = 'test_api_key_for_testing_purposes_only_not_a_real_secret_key_abc123'
|
|
6
14
|
const TEAM_ID = 'team-personal-superadmin-003'
|
|
7
|
-
|
|
15
|
+
// Updated to use the correct streaming endpoint
|
|
16
|
+
const API_URL = '/api/v1/theme/default/ai/chat/stream'
|
|
8
17
|
|
|
9
18
|
const getHeaders = () => ({
|
|
10
19
|
'Content-Type': 'application/json',
|
|
@@ -12,35 +21,42 @@ describe('AI Chat API', {
|
|
|
12
21
|
'x-team-id': TEAM_ID
|
|
13
22
|
})
|
|
14
23
|
|
|
15
|
-
it('AI_CHAT_001: POST - returns
|
|
24
|
+
it('AI_CHAT_001: POST - returns SSE stream for valid message', { tags: '@smoke' }, () => {
|
|
16
25
|
cy.request({
|
|
17
26
|
method: 'POST',
|
|
18
27
|
url: API_URL,
|
|
19
28
|
headers: getHeaders(),
|
|
20
|
-
body: {
|
|
29
|
+
body: {
|
|
30
|
+
message: 'Hello',
|
|
31
|
+
agentName: 'general' // Required field for this endpoint
|
|
32
|
+
},
|
|
21
33
|
failOnStatusCode: false
|
|
22
34
|
}).then(response => {
|
|
23
|
-
//
|
|
35
|
+
// Streaming endpoint returns 200 with text/event-stream content type
|
|
36
|
+
// or error JSON if something goes wrong before streaming starts
|
|
24
37
|
if (response.status === 200) {
|
|
25
|
-
|
|
26
|
-
expect(response.
|
|
27
|
-
expect(response.body.data.sessionId).to.be.a('string')
|
|
38
|
+
// Check that it's a streaming response
|
|
39
|
+
expect(response.headers['content-type']).to.include('text/event-stream')
|
|
28
40
|
} else {
|
|
29
|
-
// If it fails,
|
|
30
|
-
cy.log('Request failed, possibly due to
|
|
41
|
+
// If it fails, log the reason (likely Ollama/LLM not running)
|
|
42
|
+
cy.log('Request failed, possibly due to LLM service not running:', response.body)
|
|
31
43
|
}
|
|
32
44
|
})
|
|
33
45
|
})
|
|
34
46
|
|
|
35
|
-
it('AI_CHAT_002: POST - returns
|
|
47
|
+
it('AI_CHAT_002: POST - returns error for empty message', () => {
|
|
36
48
|
cy.request({
|
|
37
49
|
method: 'POST',
|
|
38
50
|
url: API_URL,
|
|
39
51
|
headers: getHeaders(),
|
|
40
|
-
body: {
|
|
52
|
+
body: {
|
|
53
|
+
message: '',
|
|
54
|
+
agentName: 'general'
|
|
55
|
+
},
|
|
41
56
|
failOnStatusCode: false
|
|
42
57
|
}).then(response => {
|
|
43
|
-
|
|
58
|
+
// Should return 400 for validation error or 401 if auth checked first
|
|
59
|
+
expect(response.status).to.be.oneOf([400, 401])
|
|
44
60
|
expect(response.body.success).to.be.false
|
|
45
61
|
})
|
|
46
62
|
})
|
|
@@ -53,7 +69,10 @@ describe('AI Chat API', {
|
|
|
53
69
|
'Content-Type': 'application/json',
|
|
54
70
|
'x-team-id': TEAM_ID
|
|
55
71
|
},
|
|
56
|
-
body: {
|
|
72
|
+
body: {
|
|
73
|
+
message: 'Hello',
|
|
74
|
+
agentName: 'general'
|
|
75
|
+
},
|
|
57
76
|
failOnStatusCode: false
|
|
58
77
|
}).then(response => {
|
|
59
78
|
expect(response.status).to.eq(401)
|
|
@@ -61,7 +80,7 @@ describe('AI Chat API', {
|
|
|
61
80
|
})
|
|
62
81
|
})
|
|
63
82
|
|
|
64
|
-
it('AI_CHAT_004: POST - returns
|
|
83
|
+
it('AI_CHAT_004: POST - returns error without x-team-id header', () => {
|
|
65
84
|
cy.request({
|
|
66
85
|
method: 'POST',
|
|
67
86
|
url: API_URL,
|
|
@@ -69,39 +88,32 @@ describe('AI Chat API', {
|
|
|
69
88
|
'Content-Type': 'application/json',
|
|
70
89
|
'Authorization': `Bearer ${API_KEY}`
|
|
71
90
|
},
|
|
72
|
-
body: {
|
|
91
|
+
body: {
|
|
92
|
+
message: 'Hello',
|
|
93
|
+
agentName: 'general'
|
|
94
|
+
},
|
|
73
95
|
failOnStatusCode: false
|
|
74
96
|
}).then(response => {
|
|
75
|
-
|
|
76
|
-
expect(response.
|
|
97
|
+
// Returns 400 (TEAM_CONTEXT_REQUIRED) or 401 if auth checked first
|
|
98
|
+
expect(response.status).to.be.oneOf([400, 401])
|
|
99
|
+
expect(response.body.success).to.be.false
|
|
77
100
|
})
|
|
78
101
|
})
|
|
79
102
|
|
|
80
|
-
it('AI_CHAT_005: POST -
|
|
103
|
+
it('AI_CHAT_005: POST - returns error without agentName', () => {
|
|
81
104
|
cy.request({
|
|
82
105
|
method: 'POST',
|
|
83
106
|
url: API_URL,
|
|
84
107
|
headers: getHeaders(),
|
|
85
|
-
body: {
|
|
108
|
+
body: {
|
|
109
|
+
message: 'Hello'
|
|
110
|
+
// Missing agentName - required field
|
|
111
|
+
},
|
|
86
112
|
failOnStatusCode: false
|
|
87
|
-
}).then(
|
|
88
|
-
if
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
cy.request({
|
|
92
|
-
method: 'POST',
|
|
93
|
-
url: API_URL,
|
|
94
|
-
headers: getHeaders(),
|
|
95
|
-
body: { message: 'What is my name?', sessionId }
|
|
96
|
-
}).then(response2 => {
|
|
97
|
-
expect(response2.status).to.eq(200)
|
|
98
|
-
expect(response2.body.data.sessionId).to.eq(sessionId)
|
|
99
|
-
// Note: This assertion depends on the model's capability, so it might be flaky
|
|
100
|
-
// expect(response2.body.data.message.toLowerCase()).to.include('john')
|
|
101
|
-
})
|
|
102
|
-
} else {
|
|
103
|
-
cy.log('Skipping session test - Ollama not running')
|
|
104
|
-
}
|
|
113
|
+
}).then(response => {
|
|
114
|
+
// Should return 400 for validation error or 401 if auth checked first
|
|
115
|
+
expect(response.status).to.be.oneOf([400, 401])
|
|
116
|
+
expect(response.body.success).to.be.false
|
|
105
117
|
})
|
|
106
118
|
})
|
|
107
119
|
})
|