Skip to content

Commit 5072070

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 e642b3d commit 5072070

File tree

4 files changed

+141
-2
lines changed

4 files changed

+141
-2
lines changed

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: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,42 @@
11
import { expect } from 'chai';
22
import { mountJsonForms } from '../util';
33

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

3672
describe('OneOfRenderer.vue', () => {
73+
it('shows confirmation dialog when switching from boolean true to array', async () => {
74+
const wrapper = mountJsonForms(
75+
{ oneOfProp: true },
76+
schemaWithVariousTypes,
77+
uischemaWithVariousTypes
78+
);
79+
const oneOfSelect = wrapper.find('select');
80+
const dialog = wrapper.find('dialog');
81+
82+
expect(oneOfSelect.element.value).to.equal('0');
83+
expect(dialog.element.open).to.be.false;
84+
85+
await oneOfSelect.setValue('1');
86+
87+
expect(dialog.element.open).to.be.true;
88+
});
89+
90+
it('shows confirmation dialog when switching from boolean false to array', async () => {
91+
const wrapper = mountJsonForms(
92+
{ oneOfProp: false },
93+
schemaWithVariousTypes,
94+
uischemaWithVariousTypes
95+
);
96+
const oneOfSelect = wrapper.find('select');
97+
const dialog = wrapper.find('dialog');
98+
99+
expect(oneOfSelect.element.value).to.equal('0');
100+
expect(dialog.element.open).to.be.false;
101+
102+
await oneOfSelect.setValue('1');
103+
104+
expect(dialog.element.open).to.be.true;
105+
});
106+
107+
it('allows adding items after switching from boolean to array', async () => {
108+
const wrapper = mountJsonForms(
109+
{ oneOfProp: true },
110+
schemaWithVariousTypes,
111+
uischemaWithVariousTypes
112+
);
113+
const oneOfSelect = wrapper.find('select');
114+
115+
await oneOfSelect.setValue('1');
116+
117+
const confirmButton = wrapper.find('dialog button:last-child');
118+
await confirmButton.trigger('click');
119+
120+
const addButton = wrapper.find('.array-list-add');
121+
await addButton.trigger('click');
122+
123+
expect(wrapper.vm.data).to.deep.equal({ oneOfProp: [''] });
124+
});
125+
126+
it('does not show confirmation dialog when switching from undefined to array', async () => {
127+
const wrapper = mountJsonForms(
128+
{},
129+
schemaWithVariousTypes,
130+
uischemaWithVariousTypes
131+
);
132+
const oneOfSelect = wrapper.find('select');
133+
const dialog = wrapper.find('dialog');
134+
135+
await oneOfSelect.setValue('1');
136+
137+
expect(dialog.element.open).to.be.false;
138+
expect(wrapper.vm.data).to.deep.equal({});
139+
});
140+
141+
it('allows adding items after switching from object to array', async () => {
142+
const wrapper = mountJsonForms(
143+
{ oneOfProp: { name: 'test' } },
144+
schemaWithVariousTypes,
145+
uischemaWithVariousTypes
146+
);
147+
const oneOfSelect = wrapper.find('select');
148+
149+
expect(oneOfSelect.element.value).to.equal('2');
150+
151+
await oneOfSelect.setValue('1');
152+
153+
const confirmButton = wrapper.find('dialog button:last-child');
154+
await confirmButton.trigger('click');
155+
156+
const addButton = wrapper.find('.array-list-add');
157+
await addButton.trigger('click');
158+
159+
expect(wrapper.vm.data).to.deep.equal({ oneOfProp: [''] });
160+
});
161+
37162
it('render has a class', () => {
38163
const wrapper = mountJsonForms({ variant: 'b', b: 'b' }, schema, uischema);
39164
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+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
import '../setup';
12
export * from './util';

0 commit comments

Comments
 (0)