diff --git a/frontend_src/vstutils/fields/dynamic/DynamicFieldMixin.vue b/frontend_src/vstutils/fields/dynamic/DynamicFieldMixin.vue index f8f3701e..1f8186fb 100644 --- a/frontend_src/vstutils/fields/dynamic/DynamicFieldMixin.vue +++ b/frontend_src/vstutils/fields/dynamic/DynamicFieldMixin.vue @@ -38,15 +38,20 @@ } watch(parentValues, (newValues, oldValues) => { - if (!deepEqual(newValues, oldValues)) { - realField.value = props.field.getRealField(newValues); - setValue({ - field: props.field.name, - value: savedValues.has(realField.value) - ? savedValues.get(realField.value) - : realField.value.getInitialValue(), - }); + if (deepEqual(newValues, oldValues)) { + return; } + const newField = props.field.getRealField(newValues); + if (newField.isEqual(realField.value)) { + return; + } + realField.value = newField; + setValue({ + field: props.field.name, + value: savedValues.has(realField.value) + ? savedValues.get(realField.value) + : realField.value.getInitialValue(), + }); }); return { realField, setValue }; diff --git a/frontend_src/vstutils/fields/dynamic/__tests__/DynamicField.test.ts b/frontend_src/vstutils/fields/dynamic/__tests__/DynamicField.test.ts new file mode 100644 index 00000000..fd8d34d2 --- /dev/null +++ b/frontend_src/vstutils/fields/dynamic/__tests__/DynamicField.test.ts @@ -0,0 +1,58 @@ +import { beforeAll, describe, expect, test, jest } from '@jest/globals'; +import { StringField } from '@/vstutils/fields/text'; +import { DynamicField } from '../DynamicField'; +import { createApp } from '@/unittests'; +import VueI18n from 'vue-i18n'; +import { nextTick, reactive } from 'vue'; +import { mount } from '@vue/test-utils'; + +let app: Awaited>; + +beforeAll(async () => { + app = await createApp(); +}); + +describe('DynamicField', () => { + test('real field with same structure will not trigger value reset', async () => { + const field = new DynamicField({ + name: 'field', + type: 'string', + 'x-options': { + field: ['someField'], + types: {}, + }, + }); + + // Override getRealField to return field of same type but different instance + field.getRealField = function getRealField() { + return new StringField({ + name: 'field', + type: 'string', + }); + }; + + const data = reactive({ someField: 'val 1', field: 'initial value' }); + const setValue = jest.fn(); + const wrapper = mount( + { + template: ``, + components: { Field: field.getComponent() }, + setup() { + return { + field, + data: data, + setValue, + }; + }, + }, + { localVue: app.vue, i18n: new VueI18n() }, + ); + + expect(wrapper.html()).toMatch(/initial value/); + expect(setValue).toBeCalledTimes(0); + data.someField = 'val 2'; + await nextTick(); + expect(wrapper.html()).toMatch(/initial value/); + expect(setValue).toBeCalledTimes(0); + }); +}); diff --git a/vstutils/__init__.py b/vstutils/__init__.py index f5fc1f4f..132d1ab5 100644 --- a/vstutils/__init__.py +++ b/vstutils/__init__.py @@ -1,2 +1,2 @@ # pylint: disable=django-not-available -__version__: str = '5.8.11' +__version__: str = '5.8.12'