feat(frontend): Add useFormElementDuplication test
This commit is contained in:
@@ -198,7 +198,7 @@ const hasOverflow = ref(false)
|
|||||||
const { evaluateFormElementVisibility } = useFormElementVisibility()
|
const { evaluateFormElementVisibility } = useFormElementVisibility()
|
||||||
const { clearHiddenFormElementValues } = useFormElementValueClearing()
|
const { clearHiddenFormElementValues } = useFormElementValueClearing()
|
||||||
const { processSpawnTriggers } = useSectionSpawning()
|
const { processSpawnTriggers } = useSectionSpawning()
|
||||||
const { cloneElement } = useClonableElements()
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
const { isSwiping } = usePointerSwipe(stepperScrollEl, {
|
const { isSwiping } = usePointerSwipe(stepperScrollEl, {
|
||||||
threshold: 0,
|
threshold: 0,
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
import type { FormElementDto } from '~~/.api-client'
|
import type { FormElementDto } from '~~/.api-client'
|
||||||
|
|
||||||
export function useClonableElements() {
|
export function useFormElementDuplication() {
|
||||||
function cloneElement(element: FormElementDto, existingElements: FormElementDto[]): FormElementDto {
|
function cloneElement(elementToClone: FormElementDto, existingElements: FormElementDto[]): FormElementDto {
|
||||||
const newReference = element.reference ? generateNextReference(existingElements, element.reference) : undefined
|
const newReference = elementToClone.reference
|
||||||
const isTextField = element.type === 'TEXTAREA' || element.type === 'TEXTFIELD'
|
? generateNextReference(existingElements, elementToClone.reference)
|
||||||
|
: undefined
|
||||||
|
const isTextField = elementToClone.type === 'TEXTAREA' || elementToClone.type === 'TEXTFIELD'
|
||||||
|
|
||||||
const clonedElement = JSON.parse(JSON.stringify(element)) as FormElementDto
|
const clonedElement = JSON.parse(JSON.stringify(elementToClone)) as FormElementDto
|
||||||
const resetOptions = clonedElement.options.map((option) => ({
|
const resetOptions = clonedElement.options.map((option) => ({
|
||||||
...option,
|
...option,
|
||||||
value: isTextField ? '' : option.value
|
value: isTextField ? '' : option.value
|
||||||
@@ -38,12 +38,13 @@
|
|||||||
"@nuxt/eslint": "1.1.0",
|
"@nuxt/eslint": "1.1.0",
|
||||||
"@nuxt/test-utils": "^3.21.0",
|
"@nuxt/test-utils": "^3.21.0",
|
||||||
"@openapitools/openapi-generator-cli": "2.16.3",
|
"@openapitools/openapi-generator-cli": "2.16.3",
|
||||||
|
"@pinia/testing": "^0.1.7",
|
||||||
|
"@vitest/coverage-v8": "4.0.16",
|
||||||
"@vue/test-utils": "^2.4.6",
|
"@vue/test-utils": "^2.4.6",
|
||||||
"eslint": "9.20.1",
|
"eslint": "9.20.1",
|
||||||
"happy-dom": "^20.0.11",
|
"happy-dom": "^20.0.11",
|
||||||
"prettier": "3.5.1",
|
"prettier": "3.5.1",
|
||||||
"typescript": "5.7.3",
|
"typescript": "5.7.3",
|
||||||
"@pinia/testing": "^0.1.7",
|
|
||||||
"vitest": "^4.0.16",
|
"vitest": "^4.0.16",
|
||||||
"vue-tsc": "2.2.2"
|
"vue-tsc": "2.2.2"
|
||||||
},
|
},
|
||||||
|
|||||||
99
legalconsenthub/pnpm-lock.yaml
generated
99
legalconsenthub/pnpm-lock.yaml
generated
@@ -63,6 +63,9 @@ importers:
|
|||||||
'@pinia/testing':
|
'@pinia/testing':
|
||||||
specifier: ^0.1.7
|
specifier: ^0.1.7
|
||||||
version: 0.1.7(pinia@3.0.3(typescript@5.7.3)(vue@3.5.26(typescript@5.7.3)))(vue@3.5.26(typescript@5.7.3))
|
version: 0.1.7(pinia@3.0.3(typescript@5.7.3)(vue@3.5.26(typescript@5.7.3)))(vue@3.5.26(typescript@5.7.3))
|
||||||
|
'@vitest/coverage-v8':
|
||||||
|
specifier: 4.0.16
|
||||||
|
version: 4.0.16(vitest@4.0.16(@types/node@20.19.27)(happy-dom@20.0.11)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))
|
||||||
'@vue/test-utils':
|
'@vue/test-utils':
|
||||||
specifier: ^2.4.6
|
specifier: ^2.4.6
|
||||||
version: 2.4.6
|
version: 2.4.6
|
||||||
@@ -231,6 +234,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==}
|
resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
|
'@bcoe/v8-coverage@1.0.2':
|
||||||
|
resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==}
|
||||||
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
'@bomb.sh/tab@0.0.10':
|
'@bomb.sh/tab@0.0.10':
|
||||||
resolution: {integrity: sha512-6ALS2rh/4LKn0Yxwm35V6LcgQuSiECHbqQo7+9g4rkgGyXZ0siOc8K+IuWIq/4u0Zkv2mevP9QSqgKhGIvLJMw==}
|
resolution: {integrity: sha512-6ALS2rh/4LKn0Yxwm35V6LcgQuSiECHbqQo7+9g4rkgGyXZ0siOc8K+IuWIq/4u0Zkv2mevP9QSqgKhGIvLJMw==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -2370,6 +2377,15 @@ packages:
|
|||||||
vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0
|
vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0
|
||||||
vue: ^3.2.25
|
vue: ^3.2.25
|
||||||
|
|
||||||
|
'@vitest/coverage-v8@4.0.16':
|
||||||
|
resolution: {integrity: sha512-2rNdjEIsPRzsdu6/9Eq0AYAzYdpP6Bx9cje9tL3FE5XzXRQF1fNU9pe/1yE8fCrS0HD+fBtt6gLPh6LI57tX7A==}
|
||||||
|
peerDependencies:
|
||||||
|
'@vitest/browser': 4.0.16
|
||||||
|
vitest: 4.0.16
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@vitest/browser':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@vitest/expect@4.0.16':
|
'@vitest/expect@4.0.16':
|
||||||
resolution: {integrity: sha512-eshqULT2It7McaJkQGLkPjPjNph+uevROGuIMJdG3V+0BSR2w9u6J9Lwu+E8cK5TETlfou8GRijhafIMhXsimA==}
|
resolution: {integrity: sha512-eshqULT2It7McaJkQGLkPjPjNph+uevROGuIMJdG3V+0BSR2w9u6J9Lwu+E8cK5TETlfou8GRijhafIMhXsimA==}
|
||||||
|
|
||||||
@@ -2694,6 +2710,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==}
|
resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==}
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
|
|
||||||
|
ast-v8-to-istanbul@0.3.12:
|
||||||
|
resolution: {integrity: sha512-BRRC8VRZY2R4Z4lFIL35MwNXmwVqBityvOIwETtsCSwvjl0IdgFsy9NhdaA6j74nUdtJJlIypeRhpDam19Wq3g==}
|
||||||
|
|
||||||
ast-walker-scope@0.6.2:
|
ast-walker-scope@0.6.2:
|
||||||
resolution: {integrity: sha512-1UWOyC50xI3QZkRuDj6PqDtpm1oHWtYs+NQGwqL/2R11eN3Q81PHAHPM0SWW3BNQm53UDwS//Jv8L4CCVLM1bQ==}
|
resolution: {integrity: sha512-1UWOyC50xI3QZkRuDj6PqDtpm1oHWtYs+NQGwqL/2R11eN3Q81PHAHPM0SWW3BNQm53UDwS//Jv8L4CCVLM1bQ==}
|
||||||
engines: {node: '>=16.14.0'}
|
engines: {node: '>=16.14.0'}
|
||||||
@@ -3804,6 +3823,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==}
|
resolution: {integrity: sha512-puUZAUKT5m8Zzvs72XWy3HtvVbTWljRE66cP60bxJzAqf2DgICo7lYTY2IHUmLnNpjYvw5bvmoHvPc0QO2a62w==}
|
||||||
engines: {node: ^16.14.0 || >=18.0.0}
|
engines: {node: ^16.14.0 || >=18.0.0}
|
||||||
|
|
||||||
|
html-escaper@2.0.2:
|
||||||
|
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
|
||||||
|
|
||||||
html-to-text@9.0.5:
|
html-to-text@9.0.5:
|
||||||
resolution: {integrity: sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==}
|
resolution: {integrity: sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
@@ -3997,6 +4019,22 @@ packages:
|
|||||||
isomorphic.js@0.2.5:
|
isomorphic.js@0.2.5:
|
||||||
resolution: {integrity: sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==}
|
resolution: {integrity: sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==}
|
||||||
|
|
||||||
|
istanbul-lib-coverage@3.2.2:
|
||||||
|
resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
|
istanbul-lib-report@3.0.1:
|
||||||
|
resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
istanbul-lib-source-maps@5.0.6:
|
||||||
|
resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
|
istanbul-reports@3.2.0:
|
||||||
|
resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==}
|
||||||
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
iterare@1.2.1:
|
iterare@1.2.1:
|
||||||
resolution: {integrity: sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==}
|
resolution: {integrity: sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
@@ -4020,6 +4058,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==}
|
resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
|
|
||||||
|
js-tokens@10.0.0:
|
||||||
|
resolution: {integrity: sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==}
|
||||||
|
|
||||||
js-tokens@4.0.0:
|
js-tokens@4.0.0:
|
||||||
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
|
||||||
|
|
||||||
@@ -4265,6 +4306,10 @@ packages:
|
|||||||
magicast@0.5.1:
|
magicast@0.5.1:
|
||||||
resolution: {integrity: sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==}
|
resolution: {integrity: sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==}
|
||||||
|
|
||||||
|
make-dir@4.0.0:
|
||||||
|
resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==}
|
||||||
|
engines: {node: '>=10'}
|
||||||
|
|
||||||
markdown-it@14.1.0:
|
markdown-it@14.1.0:
|
||||||
resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==}
|
resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
@@ -6348,6 +6393,8 @@ snapshots:
|
|||||||
'@babel/helper-string-parser': 7.27.1
|
'@babel/helper-string-parser': 7.27.1
|
||||||
'@babel/helper-validator-identifier': 7.28.5
|
'@babel/helper-validator-identifier': 7.28.5
|
||||||
|
|
||||||
|
'@bcoe/v8-coverage@1.0.2': {}
|
||||||
|
|
||||||
'@bomb.sh/tab@0.0.10(cac@6.7.14)(citty@0.1.6)':
|
'@bomb.sh/tab@0.0.10(cac@6.7.14)(citty@0.1.6)':
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
cac: 6.7.14
|
cac: 6.7.14
|
||||||
@@ -8750,6 +8797,23 @@ snapshots:
|
|||||||
vite: 7.3.0(@types/node@20.19.27)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)
|
vite: 7.3.0(@types/node@20.19.27)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)
|
||||||
vue: 3.5.26(typescript@5.7.3)
|
vue: 3.5.26(typescript@5.7.3)
|
||||||
|
|
||||||
|
'@vitest/coverage-v8@4.0.16(vitest@4.0.16(@types/node@20.19.27)(happy-dom@20.0.11)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2))':
|
||||||
|
dependencies:
|
||||||
|
'@bcoe/v8-coverage': 1.0.2
|
||||||
|
'@vitest/utils': 4.0.16
|
||||||
|
ast-v8-to-istanbul: 0.3.12
|
||||||
|
istanbul-lib-coverage: 3.2.2
|
||||||
|
istanbul-lib-report: 3.0.1
|
||||||
|
istanbul-lib-source-maps: 5.0.6
|
||||||
|
istanbul-reports: 3.2.0
|
||||||
|
magicast: 0.5.1
|
||||||
|
obug: 2.1.1
|
||||||
|
std-env: 3.10.0
|
||||||
|
tinyrainbow: 3.0.3
|
||||||
|
vitest: 4.0.16(@types/node@20.19.27)(happy-dom@20.0.11)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.1)(yaml@2.8.2)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
'@vitest/expect@4.0.16':
|
'@vitest/expect@4.0.16':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@standard-schema/spec': 1.1.0
|
'@standard-schema/spec': 1.1.0
|
||||||
@@ -9141,6 +9205,12 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
|
ast-v8-to-istanbul@0.3.12:
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/trace-mapping': 0.3.31
|
||||||
|
estree-walker: 3.0.3
|
||||||
|
js-tokens: 10.0.0
|
||||||
|
|
||||||
ast-walker-scope@0.6.2:
|
ast-walker-scope@0.6.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/parser': 7.28.5
|
'@babel/parser': 7.28.5
|
||||||
@@ -10363,6 +10433,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
lru-cache: 10.4.3
|
lru-cache: 10.4.3
|
||||||
|
|
||||||
|
html-escaper@2.0.2: {}
|
||||||
|
|
||||||
html-to-text@9.0.5:
|
html-to-text@9.0.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@selderee/plugin-htmlparser2': 0.11.0
|
'@selderee/plugin-htmlparser2': 0.11.0
|
||||||
@@ -10552,6 +10624,27 @@ snapshots:
|
|||||||
|
|
||||||
isomorphic.js@0.2.5: {}
|
isomorphic.js@0.2.5: {}
|
||||||
|
|
||||||
|
istanbul-lib-coverage@3.2.2: {}
|
||||||
|
|
||||||
|
istanbul-lib-report@3.0.1:
|
||||||
|
dependencies:
|
||||||
|
istanbul-lib-coverage: 3.2.2
|
||||||
|
make-dir: 4.0.0
|
||||||
|
supports-color: 7.2.0
|
||||||
|
|
||||||
|
istanbul-lib-source-maps@5.0.6:
|
||||||
|
dependencies:
|
||||||
|
'@jridgewell/trace-mapping': 0.3.31
|
||||||
|
debug: 4.4.3
|
||||||
|
istanbul-lib-coverage: 3.2.2
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
|
istanbul-reports@3.2.0:
|
||||||
|
dependencies:
|
||||||
|
html-escaper: 2.0.2
|
||||||
|
istanbul-lib-report: 3.0.1
|
||||||
|
|
||||||
iterare@1.2.1: {}
|
iterare@1.2.1: {}
|
||||||
|
|
||||||
jackspeak@3.4.3:
|
jackspeak@3.4.3:
|
||||||
@@ -10574,6 +10667,8 @@ snapshots:
|
|||||||
|
|
||||||
js-cookie@3.0.5: {}
|
js-cookie@3.0.5: {}
|
||||||
|
|
||||||
|
js-tokens@10.0.0: {}
|
||||||
|
|
||||||
js-tokens@4.0.0: {}
|
js-tokens@4.0.0: {}
|
||||||
|
|
||||||
js-tokens@9.0.1: {}
|
js-tokens@9.0.1: {}
|
||||||
@@ -10803,6 +10898,10 @@ snapshots:
|
|||||||
'@babel/types': 7.28.5
|
'@babel/types': 7.28.5
|
||||||
source-map-js: 1.2.1
|
source-map-js: 1.2.1
|
||||||
|
|
||||||
|
make-dir@4.0.0:
|
||||||
|
dependencies:
|
||||||
|
semver: 7.7.3
|
||||||
|
|
||||||
markdown-it@14.1.0:
|
markdown-it@14.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
argparse: 2.0.1
|
argparse: 2.0.1
|
||||||
|
|||||||
@@ -0,0 +1,285 @@
|
|||||||
|
import { describe, it, expect } from 'vitest'
|
||||||
|
import { useFormElementDuplication } from '../../../app/composables/useFormElementDuplication'
|
||||||
|
import type { FormElementDto, FormOptionDto, 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[] = [],
|
||||||
|
description?: string
|
||||||
|
): FormElementDto {
|
||||||
|
return {
|
||||||
|
id: `id-${reference}`,
|
||||||
|
reference,
|
||||||
|
title,
|
||||||
|
type,
|
||||||
|
options,
|
||||||
|
description
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('useFormElementDuplication', () => {
|
||||||
|
describe('cloneElement()', () => {
|
||||||
|
it('should generate incremented reference from existing reference with suffix', () => {
|
||||||
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
|
const elementToClone = createFormElement('modul_1', 'Module', 'TEXTFIELD', [createOption('value', '')])
|
||||||
|
const existingElements: FormElementDto[] = [elementToClone]
|
||||||
|
|
||||||
|
const cloned = cloneElement(elementToClone, existingElements)
|
||||||
|
|
||||||
|
expect(cloned.reference).toBe('modul_2')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle reference without numeric suffix (defaults to _2)', () => {
|
||||||
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
|
const elementToClone = createFormElement('modul', 'Module', 'TEXTFIELD', [createOption('value', '')])
|
||||||
|
const existingElements: FormElementDto[] = [elementToClone]
|
||||||
|
|
||||||
|
const cloned = cloneElement(elementToClone, existingElements)
|
||||||
|
|
||||||
|
expect(cloned.reference).toBe('modul_2')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should clear id and formElementSubSectionId on cloned element', () => {
|
||||||
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
|
const elementToClone = createFormElement('elem_1', 'Element', 'TEXTFIELD', [createOption('value', '')])
|
||||||
|
elementToClone.id = 'some-uuid-id'
|
||||||
|
elementToClone.formElementSubSectionId = 'subsection-uuid'
|
||||||
|
const existingElements: FormElementDto[] = [elementToClone]
|
||||||
|
|
||||||
|
const cloned = cloneElement(elementToClone, existingElements)
|
||||||
|
|
||||||
|
expect(cloned.id).toBeUndefined()
|
||||||
|
expect(cloned.formElementSubSectionId).toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should deep clone element (modifying clone does not affect original)', () => {
|
||||||
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
|
const elementToClone = createFormElement('elem_1', 'Element', 'SELECT', [
|
||||||
|
createOption('true', 'Yes'),
|
||||||
|
createOption('false', 'No')
|
||||||
|
])
|
||||||
|
const existingElements: FormElementDto[] = [elementToClone]
|
||||||
|
|
||||||
|
const cloned = cloneElement(elementToClone, existingElements)
|
||||||
|
|
||||||
|
cloned.options[0]!.value = 'modified'
|
||||||
|
cloned.title = 'Modified Title'
|
||||||
|
|
||||||
|
expect(elementToClone.options[0]!.value).toBe('true')
|
||||||
|
expect(elementToClone.title).toBe('Element')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle multiple existing clones and generate correct next reference', () => {
|
||||||
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
|
const element1 = createFormElement('modul_1', 'Module', 'TEXTFIELD', [createOption('value1', '')])
|
||||||
|
const element2 = createFormElement('modul_2', 'Module', 'TEXTFIELD', [createOption('value2', '')])
|
||||||
|
const element3 = createFormElement('modul_3', 'Module', 'TEXTFIELD', [createOption('value3', '')])
|
||||||
|
const existingElements: FormElementDto[] = [element1, element2, element3]
|
||||||
|
|
||||||
|
const cloned = cloneElement(element1, existingElements)
|
||||||
|
|
||||||
|
expect(cloned.reference).toBe('modul_4')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle elements with no options', () => {
|
||||||
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
|
const elementToClone = createFormElement('elem_1', 'Element', 'TEXTFIELD', [])
|
||||||
|
const existingElements: FormElementDto[] = [elementToClone]
|
||||||
|
|
||||||
|
const cloned = cloneElement(elementToClone, existingElements)
|
||||||
|
|
||||||
|
expect(cloned.options).toEqual([])
|
||||||
|
expect(cloned.reference).toBe('elem_2')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle sparse numeric suffix correctly', () => {
|
||||||
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
|
const element1 = createFormElement('item_1', 'Item', 'TEXTFIELD', [createOption('v1', '')])
|
||||||
|
const element3 = createFormElement('item_3', 'Item', 'TEXTFIELD', [createOption('v3', '')])
|
||||||
|
const existingElements: FormElementDto[] = [element1, element3]
|
||||||
|
|
||||||
|
const cloned = cloneElement(element1, existingElements)
|
||||||
|
|
||||||
|
expect(cloned.reference).toBe('item_4')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle element with formElementSubSectionId undefined already', () => {
|
||||||
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
|
const elementToClone = createFormElement('elem_1', 'Element', 'TEXTFIELD', [createOption('value', '')])
|
||||||
|
const existingElements: FormElementDto[] = [elementToClone]
|
||||||
|
|
||||||
|
const cloned = cloneElement(elementToClone, existingElements)
|
||||||
|
|
||||||
|
expect(cloned.formElementSubSectionId).toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('option value handling by form element type', () => {
|
||||||
|
it('should reset TEXTAREA option values to empty string', () => {
|
||||||
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
|
const elementToClone = createFormElement('textarea_1', 'My Title', 'TEXTAREA', [
|
||||||
|
createOption('Original text content', '')
|
||||||
|
])
|
||||||
|
const existingElements: FormElementDto[] = [elementToClone]
|
||||||
|
|
||||||
|
const cloned = cloneElement(elementToClone, existingElements)
|
||||||
|
|
||||||
|
expect(cloned.options[0]!.value).toBe('')
|
||||||
|
expect(cloned.reference).toBe('textarea_2')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should reset TEXTFIELD option values to empty string', () => {
|
||||||
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
|
const elementToClone = createFormElement('textfield_1', 'My Title', 'TEXTFIELD', [
|
||||||
|
createOption('Original text content', '')
|
||||||
|
])
|
||||||
|
const existingElements: FormElementDto[] = [elementToClone]
|
||||||
|
|
||||||
|
const cloned = cloneElement(elementToClone, existingElements)
|
||||||
|
|
||||||
|
expect(cloned.options[0]!.value).toBe('')
|
||||||
|
expect(cloned.reference).toBe('textfield_2')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should preserve SELECT option values', () => {
|
||||||
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
|
const elementToClone = createFormElement('select_1', 'Choice', 'SELECT', [
|
||||||
|
createOption('false', 'Option A'),
|
||||||
|
createOption('true', 'Option B')
|
||||||
|
])
|
||||||
|
const existingElements: FormElementDto[] = [elementToClone]
|
||||||
|
|
||||||
|
const cloned = cloneElement(elementToClone, existingElements)
|
||||||
|
|
||||||
|
expect(cloned.options[0]!.value).toBe('false')
|
||||||
|
expect(cloned.options[1]!.value).toBe('true')
|
||||||
|
expect(cloned.reference).toBe('select_2')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should preserve CHECKBOX option values', () => {
|
||||||
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
|
const elementToClone = createFormElement('checkbox_1', 'Features', 'CHECKBOX', [
|
||||||
|
createOption('true', 'Feature A'),
|
||||||
|
createOption('false', 'Feature B')
|
||||||
|
])
|
||||||
|
const existingElements: FormElementDto[] = [elementToClone]
|
||||||
|
|
||||||
|
const cloned = cloneElement(elementToClone, existingElements)
|
||||||
|
|
||||||
|
expect(cloned.options[0]!.value).toBe('true')
|
||||||
|
expect(cloned.options[1]!.value).toBe('false')
|
||||||
|
expect(cloned.reference).toBe('checkbox_2')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should preserve RADIOBUTTON option values', () => {
|
||||||
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
|
const elementToClone = createFormElement('radio_1', 'Gender', 'RADIOBUTTON', [
|
||||||
|
createOption('true', 'Male'),
|
||||||
|
createOption('false', 'Female')
|
||||||
|
])
|
||||||
|
const existingElements: FormElementDto[] = [elementToClone]
|
||||||
|
|
||||||
|
const cloned = cloneElement(elementToClone, existingElements)
|
||||||
|
|
||||||
|
expect(cloned.options[0]!.value).toBe('true')
|
||||||
|
expect(cloned.options[1]!.value).toBe('false')
|
||||||
|
expect(cloned.reference).toBe('radio_2')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle SWITCH element option values', () => {
|
||||||
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
|
const elementToClone = createFormElement('switch_1', 'Enable', 'SWITCH', [createOption('true', 'Enabled')])
|
||||||
|
const existingElements: FormElementDto[] = [elementToClone]
|
||||||
|
|
||||||
|
const cloned = cloneElement(elementToClone, existingElements)
|
||||||
|
|
||||||
|
expect(cloned.options[0]!.value).toBe('true')
|
||||||
|
expect(cloned.reference).toBe('switch_2')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle DATE element option values', () => {
|
||||||
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
|
const elementToClone = createFormElement('date_1', 'Start Date', 'DATE', [createOption('2024-01-15', 'label')])
|
||||||
|
const existingElements: FormElementDto[] = [elementToClone]
|
||||||
|
|
||||||
|
const cloned = cloneElement(elementToClone, existingElements)
|
||||||
|
|
||||||
|
expect(cloned.options[0]!.value).toBe('2024-01-15')
|
||||||
|
expect(cloned.reference).toBe('date_2')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle RICH_TEXT element option values', () => {
|
||||||
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
|
const elementToClone = createFormElement('richtext_1', 'Notes', 'RICH_TEXT', [
|
||||||
|
createOption('<p>Content</p>', '')
|
||||||
|
])
|
||||||
|
const existingElements: FormElementDto[] = [elementToClone]
|
||||||
|
|
||||||
|
const cloned = cloneElement(elementToClone, existingElements)
|
||||||
|
|
||||||
|
expect(cloned.options[0]!.value).toBe('<p>Content</p>')
|
||||||
|
expect(cloned.reference).toBe('richtext_2')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should handle TABLE element option values', () => {
|
||||||
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
|
const elementToClone = createFormElement('table_1', 'Employees', 'TABLE', [
|
||||||
|
createOption('["row1", "row2"]', 'Name'),
|
||||||
|
createOption('["dev", "designer"]', 'Role')
|
||||||
|
])
|
||||||
|
const existingElements: FormElementDto[] = [elementToClone]
|
||||||
|
|
||||||
|
const cloned = cloneElement(elementToClone, existingElements)
|
||||||
|
|
||||||
|
expect(cloned.options[0]!.value).toBe('["row1", "row2"]')
|
||||||
|
expect(cloned.options[1]!.value).toBe('["dev", "designer"]')
|
||||||
|
expect(cloned.reference).toBe('table_2')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should preserve all FormOptionDto properties when cloning', () => {
|
||||||
|
const { cloneElement } = useFormElementDuplication()
|
||||||
|
|
||||||
|
const option = createOption('true', 'Yes')
|
||||||
|
option.processingPurpose = 'BUSINESS_PROCESS'
|
||||||
|
option.employeeDataCategory = 'SENSITIVE'
|
||||||
|
|
||||||
|
const elementToClone = createFormElement('elem_1', 'Element', 'SELECT', [option])
|
||||||
|
const existingElements: FormElementDto[] = [elementToClone]
|
||||||
|
|
||||||
|
const cloned = cloneElement(elementToClone, existingElements)
|
||||||
|
|
||||||
|
expect(cloned.options[0]!.processingPurpose).toBe('BUSINESS_PROCESS')
|
||||||
|
expect(cloned.options[0]!.employeeDataCategory).toBe('SENSITIVE')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user