Files
gremiumhub/legalconsenthub/test/unit/composables/useSectionSpawning.spec.ts

465 lines
15 KiB
TypeScript

import { describe, it, expect } from 'vitest'
import { useSectionSpawning } from '../../../app/composables/useSectionSpawning'
import type {
FormElementSectionDto,
FormElementSubSectionDto,
FormElementDto,
FormOptionDto,
SectionSpawnTriggerDto,
FormElementType
} from '../../../.api-client'
// Helper to create a FormOptionDto
function createOption(value: string, label: string): FormOptionDto {
return {
value,
label,
processingPurpose: 'NONE',
employeeDataCategory: 'NONE'
}
}
// Helper to create a FormElementDto
function createFormElement(
reference: string,
title: string,
type: FormElementType,
options: FormOptionDto[] = [],
sectionSpawnTriggers: SectionSpawnTriggerDto[] = []
): FormElementDto {
return {
id: `id-${reference}`,
reference,
title,
type,
options,
sectionSpawnTriggers
}
}
// Helper to create a SectionSpawnTriggerDto
function createSpawnTrigger(
templateReference: string,
conditionType: 'SHOW' | 'HIDE' = 'SHOW',
expectedValue: string = 'true',
operator: 'EQUALS' | 'NOT_EQUALS' | 'IS_EMPTY' | 'IS_NOT_EMPTY' | 'CONTAINS' | 'NOT_CONTAINS' = 'EQUALS'
): SectionSpawnTriggerDto {
return {
templateReference,
sectionSpawnConditionType: conditionType,
sectionSpawnExpectedValue: expectedValue,
sectionSpawnOperator: operator
}
}
// Helper to create a template section with title interpolation
function createTemplateSection(
templateReference: string,
title: string,
titleTemplate?: string,
shortTitle?: string,
description?: string,
formElementSubSections: FormElementSubSectionDto[] = []
): FormElementSectionDto {
return {
id: `template-${templateReference}`,
title,
shortTitle,
description,
titleTemplate,
isTemplate: true,
templateReference,
formElementSubSections
}
}
describe('useSectionSpawning', () => {
it('should remove spawned section when condition no longer met', () => {
const { processSpawnTriggers } = useSectionSpawning()
const templateSection = createTemplateSection('template-1', 'Template Section')
const spawnedSection: FormElementSectionDto = {
id: 'spawned-1',
title: 'Spawned Section',
isTemplate: false,
spawnedFromElementReference: 'trigger_1',
templateReference: 'template-1',
formElementSubSections: []
}
const trigger = createSpawnTrigger('template-1', 'SHOW', 'true', 'EQUALS')
const triggerElement = createFormElement(
'trigger_1',
'Trigger',
'SELECT',
[createOption('true', 'No'), createOption('false', 'Yes')],
[trigger]
)
const sections = [templateSection, spawnedSection]
const result = processSpawnTriggers(sections, [triggerElement])
expect(result).toHaveLength(1)
expect(result[0]!.isTemplate).toBe(true)
})
it('should NOT remove spawned section if another trigger for same template still satisfies condition', () => {
const { processSpawnTriggers } = useSectionSpawning()
const templateSection = createTemplateSection('template-1', 'Template Section')
const spawnedSection: FormElementSectionDto = {
id: 'spawned-1',
title: 'Spawned Section',
isTemplate: false,
spawnedFromElementReference: 'trigger_1',
templateReference: 'template-1',
formElementSubSections: []
}
const trigger1 = createSpawnTrigger('template-1', 'SHOW', 'true', 'EQUALS')
const trigger2 = createSpawnTrigger('template-1', 'SHOW', 'maybe', 'EQUALS')
const triggerElement = createFormElement(
'trigger_1',
'Trigger',
'SELECT',
[createOption('false', 'No'), createOption('false', 'Yes'), createOption('true', 'Maybe')],
[trigger1, trigger2]
)
const sections = [templateSection, spawnedSection]
const result = processSpawnTriggers(sections, [triggerElement])
expect(result).toHaveLength(2)
expect(result[1]!.spawnedFromElementReference).toBe('trigger_1')
})
it('should update titles with {{triggerValue}} interpolation when value changes', () => {
const { processSpawnTriggers } = useSectionSpawning()
const templateSection = createTemplateSection(
'template-1',
'Section title',
'Section template title {{triggerValue}}',
'Short title {{triggerValue}}',
'Description {{triggerValue}}'
)
const spawnedSection: FormElementSectionDto = {
id: 'spawned-1',
title: 'Section OldValue',
shortTitle: 'Short OldValue',
description: 'Description OldValue',
isTemplate: false,
spawnedFromElementReference: 'trigger_1',
templateReference: 'template-1',
formElementSubSections: []
}
const trigger = createSpawnTrigger('template-1', 'SHOW', 'yes', 'EQUALS')
const triggerElement = createFormElement(
'trigger_1',
'Trigger',
'SELECT',
[createOption('false', 'No'), createOption('true', 'Yes')],
[trigger]
)
const sections = [templateSection, spawnedSection]
const result = processSpawnTriggers(sections, [triggerElement])
expect(result[1]!.title).toBe('Section template title Yes')
expect(result[1]!.shortTitle).toBe('Short title Yes')
expect(result[1]!.description).toBe('Description Yes')
})
it('should insert spawned section after template section', () => {
const { processSpawnTriggers } = useSectionSpawning()
const templateSection = createTemplateSection('template-1', 'Template Section')
const otherSection: FormElementSectionDto = {
id: 'other-1',
title: 'Other Section',
isTemplate: false,
formElementSubSections: []
}
const trigger = createSpawnTrigger('template-1', 'SHOW', 'Yes', 'EQUALS')
const triggerElement = createFormElement(
'trigger_1',
'Trigger',
'SELECT',
[createOption('false', 'No'), createOption('true', 'Yes')],
[trigger]
)
const sections = [templateSection, otherSection]
const result = processSpawnTriggers(sections, [triggerElement])
expect(result).toHaveLength(3)
expect(result[0]!.isTemplate).toBe(true)
expect(result[1]!.spawnedFromElementReference).toBe('trigger_1')
expect(result[2]!.id).toBe('other-1')
})
it('should handle TEXTFIELD element value extraction', () => {
const { processSpawnTriggers } = useSectionSpawning()
const templateSection = createTemplateSection('template-1', 'Section {{triggerValue}}', 'Section {{triggerValue}}')
const trigger = createSpawnTrigger('template-1', 'SHOW', 'john', 'EQUALS')
const triggerElement = createFormElement('trigger_1', 'Name', 'TEXTFIELD', [createOption('john', '')], [trigger])
const sections = [templateSection]
const result = processSpawnTriggers(sections, [triggerElement])
expect(result).toHaveLength(2)
expect(result[1]!.title).toBe('Section john')
})
it('should interpolate shortTitle with {{triggerValue}}', () => {
const { processSpawnTriggers } = useSectionSpawning()
const templateSection = createTemplateSection('template-1', 'Template', undefined, 'Short {{triggerValue}}')
const spawnedSection: FormElementSectionDto = {
id: 'spawned-1',
title: 'Spawned',
shortTitle: 'Short OldValue',
isTemplate: false,
spawnedFromElementReference: 'trigger_1',
templateReference: 'template-1',
formElementSubSections: []
}
const trigger = createSpawnTrigger('template-1', 'SHOW', 'yes', 'EQUALS')
const triggerElement = createFormElement(
'trigger_1',
'Trigger',
'SELECT',
[createOption('false', 'No'), createOption('true', 'Yes')],
[trigger]
)
const sections = [templateSection, spawnedSection]
const result = processSpawnTriggers(sections, [triggerElement])
expect(result[1]!.shortTitle).toBe('Short Yes')
})
it('should interpolate description with {{triggerValue}}', () => {
const { processSpawnTriggers } = useSectionSpawning()
const templateSection = createTemplateSection(
'template-1',
'Template',
undefined,
undefined,
'Description {{triggerValue}}'
)
const spawnedSection: FormElementSectionDto = {
id: 'spawned-1',
title: 'Spawned',
description: 'Description OldValue',
isTemplate: false,
spawnedFromElementReference: 'trigger_1',
templateReference: 'template-1',
formElementSubSections: []
}
const trigger = createSpawnTrigger('template-1', 'SHOW', 'yes', 'EQUALS')
const triggerElement = createFormElement(
'trigger_1',
'Trigger',
'SELECT',
[createOption('false', 'No'), createOption('true', 'Yes')],
[trigger]
)
const sections = [templateSection, spawnedSection]
const result = processSpawnTriggers(sections, [triggerElement])
expect(result[1]!.description).toBe('Description Yes')
})
it('should preserve non-triggering elements during processing', () => {
const { processSpawnTriggers } = useSectionSpawning()
const templateSection = createTemplateSection('template-1', 'Template')
const nonTriggerElement = createFormElement('other_1', 'Other', 'TEXTFIELD', [createOption('value', '')])
const trigger = createSpawnTrigger('template-1', 'SHOW', 'Yes', 'EQUALS')
const triggerElement = createFormElement(
'trigger_1',
'Trigger',
'SELECT',
[createOption('false', 'No'), createOption('true', 'Yes')],
[trigger]
)
const sections = [templateSection]
const result = processSpawnTriggers(sections, [triggerElement, nonTriggerElement])
expect(result).toHaveLength(2)
expect(result[1]!.spawnedFromElementReference).toBe('trigger_1')
})
it('should handle empty trigger list on element', () => {
const { processSpawnTriggers } = useSectionSpawning()
const templateSection = createTemplateSection('template-1', 'Template')
const triggerElement = createFormElement(
'trigger_1',
'Trigger',
'SELECT',
[createOption('false', 'No'), createOption('true', 'Yes')],
[]
)
const sections = [templateSection]
const result = processSpawnTriggers(sections, [triggerElement])
expect(result).toHaveLength(1)
})
describe('operators', () => {
describe('EQUALS', () => {
it('should spawn section when SHOW/EQUALS condition is met with SELECT element', () => {
const { processSpawnTriggers } = useSectionSpawning()
const templateSection = createTemplateSection('template-1', 'Template Section', 'Section Title Template')
const trigger = createSpawnTrigger('template-1', 'SHOW', 'Yes', 'EQUALS')
const triggerElement = createFormElement(
'trigger_1',
'Trigger',
'SELECT',
[createOption('false', 'No'), createOption('true', 'Yes')],
[trigger]
)
const result = processSpawnTriggers([templateSection], [triggerElement])
expect(result).toHaveLength(2)
expect(result[1]!.spawnedFromElementReference).toBe('trigger_1')
expect(result[1]!.templateReference).toBe('template-1')
expect(result[1]!.title).toBe('Section Title Template')
})
it('should NOT spawn section when SHOW/EQUALS condition is NOT met', () => {
const { processSpawnTriggers } = useSectionSpawning()
const templateSection = createTemplateSection('template-1', 'Template Section')
const trigger = createSpawnTrigger('template-1', 'SHOW', 'Yes', 'EQUALS')
const triggerElement = createFormElement(
'trigger_1',
'Trigger',
'SELECT',
[createOption('true', 'No'), createOption('false', 'Yes')],
[trigger]
)
const sections = [templateSection]
const result = processSpawnTriggers(sections, [triggerElement])
expect(result).toHaveLength(1)
})
it('should handle case-insensitive comparison for EQUALS operator', () => {
const { processSpawnTriggers } = useSectionSpawning()
const templateSection = createTemplateSection('template-1', 'Template')
const trigger = createSpawnTrigger('template-1', 'SHOW', 'YES', 'EQUALS')
const triggerElement = createFormElement(
'trigger_1',
'Trigger',
'SELECT',
[createOption('false', 'No'), createOption('true', 'yes')],
[trigger]
)
const sections = [templateSection]
const result = processSpawnTriggers(sections, [triggerElement])
expect(result).toHaveLength(2)
})
})
describe('NOT_EQUALS', () => {
it('should handle NOT_EQUALS operator', () => {
const { processSpawnTriggers } = useSectionSpawning()
const templateSection = createTemplateSection('template-1', 'Template')
const trigger = createSpawnTrigger('template-1', 'SHOW', 'Yes', 'NOT_EQUALS')
const triggerElement = createFormElement(
'trigger_1',
'Trigger',
'SELECT',
[createOption('true', 'No'), createOption('false', 'Yes')],
[trigger]
)
const sections = [templateSection]
const result = processSpawnTriggers(sections, [triggerElement])
expect(result).toHaveLength(2)
expect(result[1]!.spawnedFromElementReference).toBe('trigger_1')
})
})
describe('IS_EMPTY', () => {
it('should handle IS_EMPTY operator', () => {
const { processSpawnTriggers } = useSectionSpawning()
const templateSection = createTemplateSection('template-1', 'Template Section')
const trigger = createSpawnTrigger('template-1', 'SHOW', 'PLACEHOLDER', 'IS_EMPTY')
const triggerElement = createFormElement('trigger_1', 'Trigger', 'TEXTFIELD', [createOption('', '')], [trigger])
const sections = [templateSection]
const result = processSpawnTriggers(sections, [triggerElement])
expect(result).toHaveLength(2)
expect(result[1]!.spawnedFromElementReference).toBe('trigger_1')
})
})
describe('IS_NOT_EMPTY', () => {
it('should handle IS_NOT_EMPTY operator', () => {
const { processSpawnTriggers } = useSectionSpawning()
const templateSection = createTemplateSection('template-1', 'Template Section')
const trigger = createSpawnTrigger('template-1', 'SHOW', 'PLACEHOLDER', 'IS_NOT_EMPTY')
const triggerElement = createFormElement(
'trigger_1',
'Trigger',
'TEXTFIELD',
[createOption('some value', '')],
[trigger]
)
const sections = [templateSection]
const result = processSpawnTriggers(sections, [triggerElement])
expect(result).toHaveLength(2)
expect(result[1]!.spawnedFromElementReference).toBe('trigger_1')
})
})
describe('HIDE', () => {
it('should handle HIDE condition type', () => {
const { processSpawnTriggers } = useSectionSpawning()
const templateSection = createTemplateSection('template-1', 'Template Section')
const trigger = createSpawnTrigger('template-1', 'HIDE', 'No', 'EQUALS')
const triggerElement = createFormElement(
'trigger_1',
'Trigger',
'SELECT',
[createOption('true', 'No'), createOption('false', 'Yes')],
[trigger]
)
const sections = [templateSection]
const result = processSpawnTriggers(sections, [triggerElement])
expect(result).toHaveLength(1)
})
})
})
})