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