Skip to content

Commit 2b52d78

Browse files
committed
vue-vanilla: Fix OneOfRenderer.vue not clearing some primitive values
Replace isEmpty check with check against undefined because isEmpty always returns true for boolean values, 0, empty strings and objects without props. This lead to errors when switching from any of these to an array and trying to add elements there. Also adds unit tests for this. fixes #2506
1 parent 9fb248f commit 2b52d78

3 files changed

Lines changed: 141 additions & 2 deletions

File tree

packages/vue-vanilla/src/complex/OneOfRenderer.vue

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ import {
8888
RendererProps,
8989
useJsonFormsOneOfControl,
9090
} from '@jsonforms/vue';
91-
import isEmpty from 'lodash/isEmpty';
9291
import { defineComponent, inject, nextTick, ref } from 'vue';
9392
import { useVanillaControl } from '../util';
9493
import { ControlWrapper } from '../controls';
@@ -158,7 +157,7 @@ const controlRenderer = defineComponent({
158157
const target = event.target as any;
159158
this.selectIndex = target.value;
160159
161-
if (this.control.enabled && !isEmpty(this.control.data)) {
160+
if (this.control.enabled && this.control.data !== undefined) {
162161
this.showDialog();
163162
nextTick(() => {
164163
this.newSelectedIndex = this.selectIndex;

packages/vue-vanilla/tests/unit/complex/OneOfRenderer.spec.ts

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,43 @@
11
import { expect } from 'chai';
2+
import '../setup';
23
import { mountJsonForms } from '../util';
34

5+
const schemaWithVariousTypes = {
6+
type: 'object',
7+
properties: {
8+
oneOfProp: {
9+
title: 'Boolean or Array',
10+
oneOf: [
11+
{
12+
title: 'Boolean',
13+
type: 'boolean',
14+
},
15+
{
16+
title: 'Array',
17+
type: 'array',
18+
items: {
19+
type: 'string',
20+
},
21+
},
22+
{
23+
title: 'Object',
24+
type: 'object',
25+
properties: {
26+
name: {
27+
type: 'string',
28+
},
29+
},
30+
},
31+
],
32+
},
33+
},
34+
};
35+
36+
const uischemaWithVariousTypes = {
37+
type: 'Control',
38+
scope: '#/properties/oneOfProp',
39+
};
40+
441
const schema = {
542
title: 'My Object',
643
oneOf: [
@@ -34,6 +71,95 @@ const uischema = {
3471
};
3572

3673
describe('OneOfRenderer.vue', () => {
74+
it('shows confirmation dialog when switching from boolean true to array', async () => {
75+
const wrapper = mountJsonForms(
76+
{ oneOfProp: true },
77+
schemaWithVariousTypes,
78+
uischemaWithVariousTypes
79+
);
80+
const oneOfSelect = wrapper.find('select');
81+
const dialog = wrapper.find('dialog');
82+
83+
expect(oneOfSelect.element.value).to.equal('0');
84+
expect(dialog.element.open).to.be.false;
85+
86+
await oneOfSelect.setValue('1');
87+
88+
expect(dialog.element.open).to.be.true;
89+
});
90+
91+
it('shows confirmation dialog when switching from boolean false to array', async () => {
92+
const wrapper = mountJsonForms(
93+
{ oneOfProp: false },
94+
schemaWithVariousTypes,
95+
uischemaWithVariousTypes
96+
);
97+
const oneOfSelect = wrapper.find('select');
98+
const dialog = wrapper.find('dialog');
99+
100+
expect(oneOfSelect.element.value).to.equal('0');
101+
expect(dialog.element.open).to.be.false;
102+
103+
await oneOfSelect.setValue('1');
104+
105+
expect(dialog.element.open).to.be.true;
106+
});
107+
108+
it('allows adding items after switching from boolean to array', async () => {
109+
const wrapper = mountJsonForms(
110+
{ oneOfProp: true },
111+
schemaWithVariousTypes,
112+
uischemaWithVariousTypes
113+
);
114+
const oneOfSelect = wrapper.find('select');
115+
116+
await oneOfSelect.setValue('1');
117+
118+
const confirmButton = wrapper.find('dialog button:last-child');
119+
await confirmButton.trigger('click');
120+
121+
const addButton = wrapper.find('.array-list-add');
122+
await addButton.trigger('click');
123+
124+
expect(wrapper.vm.data).to.deep.equal({ oneOfProp: [''] });
125+
});
126+
127+
it('does not show confirmation dialog when switching from undefined to array', async () => {
128+
const wrapper = mountJsonForms(
129+
{},
130+
schemaWithVariousTypes,
131+
uischemaWithVariousTypes
132+
);
133+
const oneOfSelect = wrapper.find('select');
134+
const dialog = wrapper.find('dialog');
135+
136+
await oneOfSelect.setValue('1');
137+
138+
expect(dialog.element.open).to.be.false;
139+
expect(wrapper.vm.data).to.deep.equal({});
140+
});
141+
142+
it('allows adding items after switching from object to array', async () => {
143+
const wrapper = mountJsonForms(
144+
{ oneOfProp: { name: 'test' } },
145+
schemaWithVariousTypes,
146+
uischemaWithVariousTypes
147+
);
148+
const oneOfSelect = wrapper.find('select');
149+
150+
expect(oneOfSelect.element.value).to.equal('2');
151+
152+
await oneOfSelect.setValue('1');
153+
154+
const confirmButton = wrapper.find('dialog button:last-child');
155+
await confirmButton.trigger('click');
156+
157+
const addButton = wrapper.find('.array-list-add');
158+
await addButton.trigger('click');
159+
160+
expect(wrapper.vm.data).to.deep.equal({ oneOfProp: [''] });
161+
});
162+
37163
it('render has a class', () => {
38164
const wrapper = mountJsonForms({ variant: 'b', b: 'b' }, schema, uischema);
39165
expect(wrapper.find('div.one-of').exists()).to.be.true;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// JSDOM doesn't support HTMLDialogElement.showModal() and close(), so we need to polyfill/mock them
2+
// Also see https://github.com/jsdom/jsdom/issues/3294
3+
if (typeof HTMLDialogElement !== 'undefined') {
4+
HTMLDialogElement.prototype.showModal =
5+
HTMLDialogElement.prototype.showModal ||
6+
function (this: HTMLDialogElement) {
7+
this.setAttribute('open', '');
8+
};
9+
HTMLDialogElement.prototype.close =
10+
HTMLDialogElement.prototype.close ||
11+
function (this: HTMLDialogElement) {
12+
this.removeAttribute('open');
13+
};
14+
}

0 commit comments

Comments
 (0)