Skip to content

Commit 4717b5c

Browse files
committed
chore: script component tests
Related to #1102
1 parent 5a340ef commit 4717b5c

File tree

4 files changed

+217
-1
lines changed

4 files changed

+217
-1
lines changed

packages/form-js-editor/test/spec/features/properties-panel/PropertiesPanel.spec.js

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3538,7 +3538,43 @@ describe('properties panel', function() {
35383538
'General': [
35393539
'Key',
35403540
'Target value',
3541-
'Compute on'
3541+
'Compute on',
3542+
"Do not submit the expression's result with the form submission"
3543+
],
3544+
'Condition': [
3545+
'Deactivate if'
3546+
],
3547+
'Layout': [
3548+
'Columns'
3549+
],
3550+
'Custom properties': []
3551+
});
3552+
3553+
});
3554+
3555+
});
3556+
3557+
3558+
describe('js function field', function() {
3559+
3560+
it('entries', function() {
3561+
3562+
// given
3563+
const field = schema.components.find(({ type }) => type === 'script');
3564+
3565+
bootstrapPropertiesPanel({
3566+
container,
3567+
field
3568+
});
3569+
3570+
// then
3571+
expectPanelStructure(container, {
3572+
'General': [
3573+
'Key',
3574+
'Function parameters',
3575+
'Javascript code',
3576+
'Compute on',
3577+
"Do not submit the function's result with the form submission",
35423578
],
35433579
'Condition': [
35443580
'Deactivate if'

packages/form-js-editor/test/spec/form.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@
33
"id": "Form_1",
44
"type": "default",
55
"components": [
6+
{
7+
"id": "Script_1",
8+
"type": "script",
9+
"key": "script",
10+
"jsFunction": "return [\"reading\", \"swimming\", \"running\"];",
11+
"functionParameters": "={}",
12+
"computeOn": "interval",
13+
"interval": 1000
14+
},
615
{
716
"id": "ExpressionField_1",
817
"type": "expression",

packages/form-js-playground/test/spec/form.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
{
22
"$schema": "../../../form-json-schema/resources/schema.json",
33
"components": [
4+
{
5+
"type": "script",
6+
"key": "otherHobbies",
7+
"jsFunction": "return [\"reading\", \"swimming\", \"running\"];",
8+
"functionParameters": "={}",
9+
"computeOn": "change",
10+
"interval": 1000
11+
},
412
{
513
"type": "expression",
614
"key": "expressionResult",
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
import {
2+
render
3+
} from '@testing-library/preact/pure';
4+
5+
import { JSFunctionField } from '../../../../../src/render/components/form-fields/JSFunctionField';
6+
7+
import { MockFormContext } from '../helper';
8+
9+
import { act } from 'preact/test-utils';
10+
11+
import {
12+
createFormContainer
13+
} from '../../../../TestHelper';
14+
15+
let container;
16+
17+
describe('JSFunctionField', function() {
18+
19+
beforeEach(function() {
20+
container = createFormContainer();
21+
});
22+
23+
24+
afterEach(function() {
25+
container.remove();
26+
});
27+
28+
29+
it('should evaluate with setValue', async function() {
30+
31+
// given
32+
const onChangeSpy = sinon.spy();
33+
const field = defaultField;
34+
const passedData = { value : 42 };
35+
36+
const services = {
37+
expressionLanguage: {
38+
isExpression: () => true,
39+
evaluate: () => {
40+
return passedData;
41+
}
42+
}
43+
};
44+
45+
// when
46+
act(() => {
47+
createJSFunctionField({ field, onChange: onChangeSpy, services });
48+
});
49+
50+
// wait for the iframe to compute the expression and pass it back
51+
await new Promise(r => setTimeout(r, 100)).then(() => {
52+
53+
// then
54+
expect(onChangeSpy).to.be.calledOnce;
55+
expect(onChangeSpy).to.be.calledWith({ field, value: 42 });
56+
});
57+
58+
});
59+
60+
61+
it('should evaluate with return', async function() {
62+
63+
// given
64+
const onChangeSpy = sinon.spy();
65+
const field = {
66+
...defaultField,
67+
jsFunction: 'return data.value'
68+
};
69+
const passedData = { value : 42 };
70+
71+
const services = {
72+
expressionLanguage: {
73+
isExpression: () => true,
74+
evaluate: () => {
75+
return passedData;
76+
}
77+
}
78+
};
79+
80+
// when
81+
act(() => {
82+
createJSFunctionField({ field, onChange: onChangeSpy, services });
83+
});
84+
85+
// wait for the iframe to compute the expression and pass it back
86+
await new Promise(r => setTimeout(r, 100)).then(() => {
87+
88+
// then
89+
expect(onChangeSpy).to.be.calledOnce;
90+
expect(onChangeSpy).to.be.calledWith({ field, value: 42 });
91+
});
92+
93+
});
94+
95+
96+
it('should evaluate multiple times when using interval', async function() {
97+
98+
// given
99+
const onChangeSpy = sinon.spy();
100+
const field = {
101+
...defaultField,
102+
computeOn: 'interval',
103+
interval: 100
104+
};
105+
const passedData = { value : 42 };
106+
107+
const services = {
108+
expressionLanguage: {
109+
isExpression: () => true,
110+
evaluate: () => {
111+
return passedData;
112+
}
113+
}
114+
};
115+
116+
// when
117+
act(() => {
118+
createJSFunctionField({ field, onChange: onChangeSpy, services });
119+
});
120+
121+
// wait for the iframe to compute the expression and pass it back
122+
await new Promise(r => setTimeout(r, 500)).then(() => {
123+
124+
// then
125+
126+
// deliberately underestimating the number of calls to account for potential timing issues
127+
expect(onChangeSpy.callCount > 3).to.be.true;
128+
expect(onChangeSpy).to.be.calledWith({ field, value: 42 });
129+
});
130+
131+
132+
});
133+
134+
});
135+
136+
// helpers //////////
137+
138+
const defaultField = {
139+
type: 'script',
140+
key: 'jsfunction',
141+
jsFunction: 'setValue(data.value)',
142+
computeOn: 'load'
143+
};
144+
145+
function createJSFunctionField({ services, ...restOptions } = {}) {
146+
const options = {
147+
field: defaultField,
148+
onChange: () => {},
149+
...restOptions
150+
};
151+
152+
return render(
153+
<MockFormContext
154+
services={ services }
155+
options={ options }>
156+
<JSFunctionField
157+
field={ options.field }
158+
onChange={ options.onChange } />
159+
</MockFormContext>, {
160+
container: options.container || container.querySelector('.fjs-form')
161+
}
162+
);
163+
}

0 commit comments

Comments
 (0)