11import { describe , it , expect } from 'vitest' ;
2- import { fireEvent , render } from '@testing-library/svelte' ;
2+ import { fireEvent , render , screen } from '@testing-library/svelte' ;
33
44import JSchema from '../src/lib/components/common/jschema/JSchema.svelte' ;
55
66describe ( 'JSchema' , ( ) => {
7- it ( 'NumberProperty with title' , async ( ) => {
8- const result = renderSchemaWithSingleProperty ( {
9- title : 'Number title' ,
10- type : 'integer'
11- } ) ;
7+ it ( 'Required NumberProperty with title' , async ( ) => {
8+ const result = renderSchemaWithSingleProperty (
9+ {
10+ title : 'Number title' ,
11+ type : 'integer'
12+ } ,
13+ true
14+ ) ;
15+ checkBold ( result . getByText ( 'Number title' ) , true ) ;
1216 const spinbutton = result . getByRole ( 'spinbutton' , { name : 'Number title' } ) ;
1317 expect ( spinbutton ) . toBeDefined ( ) ;
1418 } ) ;
1519
16- it ( 'NumberProperty without title' , async ( ) => {
20+ it ( 'Optional NumberProperty without title' , async ( ) => {
1721 const result = renderSchemaWithSingleProperty ( { type : 'integer' } ) ;
22+ checkBold ( result . getByText ( 'Number argument' ) , false ) ;
1823 const spinbutton = result . getByRole ( 'spinbutton' , { name : 'Number argument' } ) ;
1924 expect ( spinbutton ) . toBeDefined ( ) ;
2025 } ) ;
2126
22- it ( 'StringProperty with title' , async ( ) => {
23- const result = renderSchemaWithSingleProperty ( {
24- title : 'String title' ,
25- type : 'string'
26- } ) ;
27+ it ( 'NumberProperty referenced' , async ( ) => {
28+ const result = renderSchemaWithReferencedProperty ( { type : 'number' } ) ;
29+ checkBold ( result . getByText ( 'Number argument' ) , false ) ;
30+ const spinbutton = result . getByRole ( 'spinbutton' , { name : 'Number argument' } ) ;
31+ expect ( spinbutton ) . toBeDefined ( ) ;
32+ } ) ;
33+
34+ it ( 'Required StringProperty with title' , async ( ) => {
35+ const result = renderSchemaWithSingleProperty (
36+ {
37+ title : 'String title' ,
38+ type : 'string'
39+ } ,
40+ true
41+ ) ;
42+ checkBold ( result . getByText ( 'String title' ) , true ) ;
2743 const textbox = result . getByRole ( 'textbox' , { name : 'String title' } ) ;
2844 expect ( textbox ) . toBeDefined ( ) ;
2945 } ) ;
3046
31- it ( 'StringProperty without title' , async ( ) => {
47+ it ( 'Optional StringProperty without title' , async ( ) => {
3248 const result = renderSchemaWithSingleProperty ( { type : 'string' } ) ;
49+ checkBold ( result . getByText ( 'String argument' ) , false ) ;
3350 const textbox = result . getByRole ( 'textbox' , { name : 'String argument' } ) ;
3451 expect ( textbox ) . toBeDefined ( ) ;
3552 } ) ;
3653
37- it ( 'EnumProperty with title' , async ( ) => {
54+ it ( 'StringProperty referenced' , async ( ) => {
55+ const result = renderSchemaWithReferencedProperty ( { type : 'string' } ) ;
56+ checkBold ( result . getByText ( 'String argument' ) , false ) ;
57+ const textbox = result . getByRole ( 'textbox' , { name : 'String argument' } ) ;
58+ expect ( textbox ) . toBeDefined ( ) ;
59+ } ) ;
60+
61+ it ( 'Required EnumProperty with title' , async ( ) => {
62+ const result = renderSchemaWithSingleProperty (
63+ {
64+ title : 'Enum title' ,
65+ enum : [ 'option1' , 'option2' ] ,
66+ type : 'string'
67+ } ,
68+ true
69+ ) ;
70+ checkBold ( result . getByText ( 'Enum title' ) , true ) ;
71+ const combobox = result . getByRole ( 'combobox' , { name : 'Enum title' } ) ;
72+ const options = combobox . querySelectorAll ( 'option' ) ;
73+ expect ( options [ 0 ] . text ) . eq ( 'Select...' ) ;
74+ expect ( options [ 1 ] . value ) . eq ( 'option1' ) ;
75+ expect ( options [ 2 ] . value ) . eq ( 'option2' ) ;
76+ } ) ;
77+
78+ it ( 'Optional EnumProperty without title' , async ( ) => {
3879 const result = renderSchemaWithSingleProperty ( {
39- title : 'Enum title' ,
4080 enum : [ 'option1' , 'option2' ] ,
4181 type : 'string'
4282 } ) ;
43- const combobox = result . getByRole ( 'combobox' , { name : 'Enum title' } ) ;
83+ checkBold ( result . getByText ( 'Enum argument' ) , false ) ;
84+ const combobox = result . getByRole ( 'combobox' , { name : 'Enum argument' } ) ;
4485 const options = combobox . querySelectorAll ( 'option' ) ;
4586 expect ( options [ 0 ] . text ) . eq ( 'Select...' ) ;
4687 expect ( options [ 1 ] . value ) . eq ( 'option1' ) ;
4788 expect ( options [ 2 ] . value ) . eq ( 'option2' ) ;
4889 } ) ;
4990
50- it ( 'EnumProperty without title ' , async ( ) => {
51- const result = renderSchemaWithSingleProperty ( {
91+ it ( 'EnumProperty referenced ' , async ( ) => {
92+ const result = renderSchemaWithReferencedProperty ( {
5293 enum : [ 'option1' , 'option2' ] ,
5394 type : 'string'
5495 } ) ;
96+ checkBold ( result . getByText ( 'Enum argument' ) , false ) ;
5597 const combobox = result . getByRole ( 'combobox' , { name : 'Enum argument' } ) ;
5698 const options = combobox . querySelectorAll ( 'option' ) ;
5799 expect ( options [ 0 ] . text ) . eq ( 'Select...' ) ;
58100 expect ( options [ 1 ] . value ) . eq ( 'option1' ) ;
59101 expect ( options [ 2 ] . value ) . eq ( 'option2' ) ;
60102 } ) ;
61103
62- it ( 'BooleanProperty with title' , async ( ) => {
63- const result = renderSchemaWithSingleProperty ( {
64- title : 'Boolean title' ,
65- type : 'boolean'
66- } ) ;
104+ it ( 'Required BooleanProperty with title' , async ( ) => {
105+ const result = renderSchemaWithSingleProperty (
106+ {
107+ title : 'Boolean title' ,
108+ type : 'boolean'
109+ } ,
110+ true
111+ ) ;
67112 const title = result . getByText ( 'Boolean title' ) ;
113+ checkBold ( title , true ) ;
68114 expect ( title ) . toBeDefined ( ) ;
69115 const checkbox = result . getByRole ( 'checkbox' ) ;
70116 expect ( checkbox ) . toBeDefined ( ) ;
71117 } ) ;
72118
73119 it ( 'BooleanProperty without title' , async ( ) => {
74- const result = renderSchemaWithSingleProperty ( { type : 'boolean' } ) ;
120+ const result = renderSchemaWithSingleProperty ( { type : 'boolean' } , false ) ;
75121 const title = result . getByText ( 'Boolean argument' ) ;
122+ checkBold ( title , false ) ;
123+ expect ( title ) . toBeDefined ( ) ;
124+ const checkbox = result . getByRole ( 'checkbox' ) ;
125+ expect ( checkbox ) . toBeDefined ( ) ;
126+ } ) ;
127+
128+ it ( 'BooleanProperty referenced' , async ( ) => {
129+ const result = renderSchemaWithReferencedProperty ( { type : 'boolean' } ) ;
130+ const title = result . getByText ( 'Boolean argument' ) ;
131+ checkBold ( title , false ) ;
76132 expect ( title ) . toBeDefined ( ) ;
77133 const checkbox = result . getByRole ( 'checkbox' ) ;
78134 expect ( checkbox ) . toBeDefined ( ) ;
@@ -102,25 +158,35 @@ describe('JSchema', () => {
102158 expect ( spinbutton . getAttribute ( 'max' ) ) . toBe ( '9' ) ;
103159 } ) ;
104160
105- it ( 'ArrayProperty with default values' , async ( ) => {
106- const result = renderSchemaWithSingleProperty ( {
107- type : 'array' ,
108- items : { type : 'string' } ,
109- default : [ 'foo' , 'bar' ]
110- } ) ;
161+ it ( 'Optional ArrayProperty with default values' , async ( ) => {
162+ const result = renderSchemaWithSingleProperty (
163+ {
164+ title : 'ArrayProperty' ,
165+ type : 'array' ,
166+ items : { type : 'string' } ,
167+ default : [ 'foo' , 'bar' ]
168+ } ,
169+ false
170+ ) ;
171+ checkBold ( result . getByText ( 'ArrayProperty' ) , false ) ;
111172 const inputs = result . getAllByRole ( 'textbox' ) ;
112173 expect ( inputs . length ) . eq ( 2 ) ;
113174 expect ( inputs [ 0 ] . value ) . eq ( 'foo' ) ;
114175 expect ( inputs [ 1 ] . value ) . eq ( 'bar' ) ;
115176 } ) ;
116177
117- it ( 'ArrayProperty with minItems and maxItems' , async ( ) => {
118- const result = renderSchemaWithSingleProperty ( {
119- type : 'array' ,
120- items : { type : 'string' } ,
121- minItems : 3 ,
122- maxItems : 5
123- } ) ;
178+ it ( 'Required ArrayProperty with minItems and maxItems' , async ( ) => {
179+ const result = renderSchemaWithSingleProperty (
180+ {
181+ title : 'ArrayProperty' ,
182+ type : 'array' ,
183+ items : { type : 'string' } ,
184+ minItems : 3 ,
185+ maxItems : 5
186+ } ,
187+ true
188+ ) ;
189+ checkBold ( result . getByText ( 'ArrayProperty' ) , true ) ;
124190 let inputs = result . getAllByRole ( 'textbox' ) ;
125191 expect ( inputs . length ) . eq ( 3 ) ;
126192 const addBtn = result . getByRole ( 'button' , { name : 'Add argument to list' } ) ;
@@ -130,21 +196,156 @@ describe('JSchema', () => {
130196 inputs = result . getAllByRole ( 'textbox' ) ;
131197 expect ( inputs . length ) . eq ( 5 ) ;
132198 } ) ;
199+
200+ it ( 'Optional ArrayProperty with minItems and maxItems' , async ( ) => {
201+ const result = renderSchemaWithSingleProperty (
202+ {
203+ title : 'ArrayProperty' ,
204+ type : 'array' ,
205+ items : { type : 'string' } ,
206+ minItems : 2 ,
207+ maxItems : 3
208+ } ,
209+ false
210+ ) ;
211+ checkBold ( result . getByText ( 'ArrayProperty' ) , false ) ;
212+ let inputs = result . queryAllByRole ( 'textbox' ) ;
213+ expect ( inputs . length ) . eq ( 0 ) ;
214+ const addBtn = result . getByRole ( 'button' , { name : 'Add argument to list' } ) ;
215+ await fireEvent . click ( addBtn ) ;
216+ await fireEvent . click ( addBtn ) ;
217+ await fireEvent . click ( addBtn ) ;
218+ await fireEvent . click ( addBtn ) ;
219+ inputs = result . queryAllByRole ( 'textbox' ) ;
220+ expect ( inputs . length ) . eq ( 3 ) ;
221+ } ) ;
222+
223+ it ( 'Required nested objects' , async ( ) => {
224+ const result = renderSchema ( {
225+ title : 'Args' ,
226+ type : 'object' ,
227+ properties : {
228+ requiredReferencedProperty : {
229+ $ref : '#/definitions/Ref1'
230+ } ,
231+ optionalArray : {
232+ title : 'array1 (optional)' ,
233+ type : 'array' ,
234+ items : {
235+ title : 'array1 item title' ,
236+ type : 'object' ,
237+ properties : {
238+ array1RequiredInteger : {
239+ title : 'array1RequiredInteger' ,
240+ type : 'integer'
241+ } ,
242+ array1OptionalInteger : {
243+ title : 'array1OptionalInteger' ,
244+ type : 'integer'
245+ }
246+ } ,
247+ required : [ 'array1RequiredInteger' ]
248+ }
249+ }
250+ } ,
251+ required : [ 'requiredReferencedProperty' ] ,
252+ definitions : {
253+ Ref1 : {
254+ title : 'Ref1' ,
255+ type : 'object' ,
256+ properties : {
257+ ref1RequiredArray : {
258+ title : 'ref1RequiredArray' ,
259+ type : 'array' ,
260+ items : {
261+ $ref : '#/definitions/Ref2'
262+ }
263+ } ,
264+ ref1RequiredString : {
265+ title : 'ref1RequiredString' ,
266+ type : 'string'
267+ } ,
268+ ref1OptionalString : {
269+ title : 'ref1OptionalString' ,
270+ type : 'string'
271+ }
272+ } ,
273+ required : [ 'ref1RequiredArray' , 'ref1RequiredString' ]
274+ } ,
275+ Ref2 : {
276+ title : 'Ref2' ,
277+ type : 'object' ,
278+ properties : {
279+ ref2RequiredString : {
280+ title : 'ref2RequiredString' ,
281+ type : 'string'
282+ } ,
283+ ref2OptionalString : {
284+ title : 'ref2OptionalString' ,
285+ type : 'string'
286+ }
287+ } ,
288+ required : [ 'ref2RequiredString' ]
289+ }
290+ }
291+ } ) ;
292+
293+ // Insert element into first array
294+ let addBtn = result . getAllByRole ( 'button' , { name : 'Add argument to list' } ) [ 0 ] ;
295+ await fireEvent . click ( addBtn ) ;
296+
297+ // Insert element into ref1 array
298+ addBtn = result . getAllByRole ( 'button' , { name : 'Add argument to list' } ) [ 1 ] ;
299+ await fireEvent . click ( addBtn ) ;
300+
301+ checkBold ( result . getByText ( 'Ref1' ) , true ) ;
302+ checkBold ( result . getByText ( 'array1 (optional)' ) , false ) ;
303+ checkBold ( result . getByText ( 'array1RequiredInteger' ) , true ) ;
304+ checkBold ( result . getByText ( 'array1OptionalInteger' ) , false ) ;
305+ checkBold ( result . getByText ( 'ref1RequiredArray' ) , true ) ;
306+ checkBold ( result . getByText ( 'ref1RequiredString' ) , true ) ;
307+ checkBold ( result . getByText ( 'ref1OptionalString' ) , false ) ;
308+ checkBold ( result . getByText ( 'ref2RequiredString' ) , true ) ;
309+ checkBold ( result . getByText ( 'ref2OptionalString' ) , false ) ;
310+ } ) ;
133311} ) ;
134312
135313/**
136314 * @param {object } schemaProperty
315+ * @param {boolean } required
137316 */
138- function renderSchemaWithSingleProperty ( schemaProperty ) {
139- return renderSchema ( {
317+ function renderSchemaWithSingleProperty ( schemaProperty , required = false ) {
318+ const schema = {
140319 title : 'Args' ,
141320 type : 'object' ,
142321 properties : {
143322 testProp : schemaProperty
323+ }
324+ } ;
325+ if ( required ) {
326+ schema . required = [ 'testProp' ] ;
327+ }
328+ return renderSchema ( schema ) ;
329+ }
330+
331+ /**
332+ * @param {object } schemaProperty
333+ */
334+ function renderSchemaWithReferencedProperty ( schemaProperty ) {
335+ return renderSchema ( {
336+ title : 'Args' ,
337+ type : 'object' ,
338+ properties : {
339+ testProp : {
340+ $ref : '#/definitions/Ref'
341+ }
144342 } ,
145- required : [ 'testProp' ]
343+ definitions : {
344+ Ref : schemaProperty
345+ }
146346 } ) ;
147347}
348+
148349/**
149350 * @param {object } schema
150351 * @param {object } schemaData
@@ -154,3 +355,15 @@ function renderSchema(schema, schemaData = {}) {
154355 props : { schema, schemaData }
155356 } ) ;
156357}
358+
359+ /**
360+ * @param {HTMLElement } element
361+ * @param {boolean } expected
362+ */
363+ function checkBold ( element , expected ) {
364+ const isBold = element . classList . contains ( 'fw-bold' ) ;
365+ if ( isBold !== expected ) {
366+ screen . debug ( element ) ;
367+ }
368+ expect ( isBold ) . eq ( expected ) ;
369+ }
0 commit comments