From 9b40c3e7ad9b76494766e0c49fd9737b1de058b0 Mon Sep 17 00:00:00 2001 From: cinereal Date: Mon, 20 Jul 2026 11:34:00 +0200 Subject: [PATCH 1/2] test(@vue-vuetify): test `additionalProperties` reuses the parent form's AJV Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Kiara Grouwstra --- .../AdditionalPropertiesAjv.spec.ts | 43 +++++++++++++++++++ .../tests/unit/util/TestComponent.vue | 1 + packages/vue-vuetify/tests/unit/util/util.ts | 3 ++ 3 files changed, 47 insertions(+) create mode 100644 packages/vue-vuetify/tests/unit/additional/AdditionalPropertiesAjv.spec.ts diff --git a/packages/vue-vuetify/tests/unit/additional/AdditionalPropertiesAjv.spec.ts b/packages/vue-vuetify/tests/unit/additional/AdditionalPropertiesAjv.spec.ts new file mode 100644 index 0000000000..d99ae5a5e1 --- /dev/null +++ b/packages/vue-vuetify/tests/unit/additional/AdditionalPropertiesAjv.spec.ts @@ -0,0 +1,43 @@ +import { describe, it, expect, beforeEach } from 'vitest'; +import { clearAllIds, createAjv } from '@jsonforms/core'; +import { markRaw } from 'vue'; +import { extendedVuetifyRenderers } from '../../../src'; +import { mountJsonForms } from '../util/util'; + +// Check that `additionalProperties` reuses the parent form's AJV +describe('AdditionalProperties nested AJV', () => { + // A map whose key `pattern` is legal only without the `u` flag + const schema = { + type: 'object' as const, + properties: { + secretFiles: { + type: 'object' as const, + additionalProperties: { type: 'string' as const }, + propertyNames: { + pattern: '^"([^"$\\\\]|\\$(?!{)|\\\\.)*"$', + }, + }, + }, + }; + const uischema = { type: 'Control' as const, scope: '#' }; + + beforeEach(() => { + clearAllIds(); + }); + + it('mounts a map whose key pattern is only valid without the `u` flag', () => { + // A parent form configured with `unicodeRegExp: false` + const ajv = markRaw(createAjv({ unicodeRegExp: false })); + expect(() => + mountJsonForms( + { secretFiles: {} }, + schema, + extendedVuetifyRenderers, + uischema, + undefined, + undefined, + ajv, + ), + ).not.toThrow(); + }); +}); diff --git a/packages/vue-vuetify/tests/unit/util/TestComponent.vue b/packages/vue-vuetify/tests/unit/util/TestComponent.vue index eda1f44f16..4f62fbdeae 100644 --- a/packages/vue-vuetify/tests/unit/util/TestComponent.vue +++ b/packages/vue-vuetify/tests/unit/util/TestComponent.vue @@ -6,6 +6,7 @@ :uischema="uischema" :renderers="renderers" :config="config" + :ajv="ajv" :i18n="i18n" @change="onChange" /> diff --git a/packages/vue-vuetify/tests/unit/util/util.ts b/packages/vue-vuetify/tests/unit/util/util.ts index a5c6770354..00c63a83fd 100644 --- a/packages/vue-vuetify/tests/unit/util/util.ts +++ b/packages/vue-vuetify/tests/unit/util/util.ts @@ -4,6 +4,7 @@ import type { JsonSchema, UISchemaElement, } from '@jsonforms/core'; +import type Ajv from 'ajv'; import { mount } from '@vue/test-utils'; import TestComponent from './TestComponent.vue'; import { createVuetify } from 'vuetify'; @@ -25,6 +26,7 @@ export const mountJsonForms = ( uischema?: UISchemaElement, config?: any, i18n?: JsonFormsI18nState, + ajv?: Ajv, ) => { return mount(TestComponent, { global: { @@ -37,6 +39,7 @@ export const mountJsonForms = ( config, renderers: markRaw(renderers), i18n, + ajv, }, attachTo: document.body, }); From 758505de7c483e8d1bd0e6286b766a0d6f52648e Mon Sep 17 00:00:00 2001 From: Kiara Grouwstra Date: Sat, 18 Jul 2026 13:48:33 +0200 Subject: [PATCH 2/2] fix(@vue-vuetify): reuse the parent AJV Reuse the same AJV instance throughout JSONForms. Ensures that user configuration of AJV is retained. Signed-off-by: Kiara Grouwstra --- .../src/complex/components/AdditionalProperties.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/vue-vuetify/src/complex/components/AdditionalProperties.vue b/packages/vue-vuetify/src/complex/components/AdditionalProperties.vue index eade49467a..83bae23e6a 100644 --- a/packages/vue-vuetify/src/complex/components/AdditionalProperties.vue +++ b/packages/vue-vuetify/src/complex/components/AdditionalProperties.vue @@ -109,6 +109,7 @@ import { import { DispatchRenderer, JsonForms, + useAjv, useJsonForms, useJsonFormsControlWithDetail, useTranslator, @@ -410,8 +411,8 @@ export default defineComponent({ validationMode: parentValidationMode, i18n, middleware, - ajv, } = useJsonForms(); + const ajv = useAjv(); // if the new property name is not specified then hide any errors const validationMode = computed(() =>