@@ -36,6 +36,15 @@ const waitForDrawerToOpen = async () => {
3636 } ) ;
3737} ;
3838
39+ const updateInputWithBlur = ( label : string , text : string ) => {
40+ const input = screen . getByLabelText ( label ) ;
41+ userEvent . clear ( input ) ;
42+ if ( text . length ) userEvent . type ( input , text ) ;
43+
44+ // Blur/unfocus the input.
45+ userEvent . click ( document . body ) ;
46+ } ;
47+
3948async function comboboxSelectItem (
4049 label : string ,
4150 value : string ,
@@ -136,8 +145,8 @@ describe('DiagramEditorSidePanel', function () {
136145 ) . to . be . visible ;
137146 } ) ;
138147
139- describe ( 'Field context drawer ' , function ( ) {
140- it ( 'should render a field context drawer when field is clicked ' , async function ( ) {
148+ describe ( 'When a field is selected ' , function ( ) {
149+ it ( 'should render a field context drawer' , async function ( ) {
141150 const result = renderDrawer ( ) ;
142151 result . plugin . store . dispatch ( selectField ( 'flights.airlines' , [ 'alias' ] ) ) ;
143152
@@ -154,7 +163,7 @@ describe('DiagramEditorSidePanel', function () {
154163 expect ( selectedTypes ) . to . include ( 'int' ) ;
155164 } ) ;
156165
157- it ( 'should render a nested field context drawer when field is clicked ' , async function ( ) {
166+ it ( 'should render a nested field context drawer' , async function ( ) {
158167 const result = renderDrawer ( ) ;
159168 result . plugin . store . dispatch (
160169 selectField ( 'flights.routes' , [ 'airline' , 'id' ] )
@@ -171,6 +180,87 @@ describe('DiagramEditorSidePanel', function () {
171180 expect ( selectedTypes ) . to . have . lengthOf ( 1 ) ;
172181 expect ( selectedTypes ) . to . include ( 'string' ) ;
173182 } ) ;
183+
184+ it ( 'should delete a field' , async function ( ) {
185+ const result = renderDrawer ( ) ;
186+ result . plugin . store . dispatch (
187+ selectField ( 'flights.routes' , [ 'airline' , 'id' ] )
188+ ) ;
189+
190+ await waitForDrawerToOpen ( ) ;
191+ expect ( screen . getByTitle ( 'routes.airline.id' ) ) . to . be . visible ;
192+
193+ userEvent . click ( screen . getByLabelText ( / d e l e t e f i e l d / i) ) ;
194+
195+ await waitFor ( ( ) => {
196+ expect ( screen . queryByText ( 'routes.airline.id' ) ) . not . to . exist ;
197+ } ) ;
198+ expect ( screen . queryByLabelText ( 'Name' ) ) . to . not . exist ;
199+
200+ const modifiedCollection = selectCurrentModelFromState (
201+ result . plugin . store . getState ( )
202+ ) . collections . find ( ( coll ) => {
203+ return coll . ns === 'flights.routes' ;
204+ } ) ;
205+
206+ expect (
207+ modifiedCollection ?. jsonSchema . properties ?. airline . properties
208+ ) . to . not . have . property ( 'id' ) ; // deleted field
209+ expect (
210+ modifiedCollection ?. jsonSchema . properties ?. airline . properties
211+ ) . to . have . property ( 'name' ) ; // sibling field remains
212+ } ) ;
213+
214+ it ( 'should rename a field and keep it selected' , async function ( ) {
215+ const result = renderDrawer ( ) ;
216+ result . plugin . store . dispatch (
217+ selectField ( 'flights.routes' , [ 'airline' , 'name' ] )
218+ ) ;
219+
220+ await waitForDrawerToOpen ( ) ;
221+ expect ( screen . getByTitle ( 'routes.airline.name' ) ) . to . be . visible ;
222+
223+ updateInputWithBlur ( 'Field name' , 'new_name' ) ;
224+
225+ await waitFor ( ( ) => {
226+ expect ( screen . queryByText ( 'routes.airline.name' ) ) . not . to . exist ;
227+ expect ( screen . queryByText ( 'routes.airline.new_name' ) ) . to . exist ;
228+ } ) ;
229+ } ) ;
230+
231+ it ( 'should not rename a field to an empty string' , async function ( ) {
232+ const result = renderDrawer ( ) ;
233+ result . plugin . store . dispatch (
234+ selectField ( 'flights.routes' , [ 'airline' , 'name' ] )
235+ ) ;
236+
237+ await waitForDrawerToOpen ( ) ;
238+ expect ( screen . getByTitle ( 'routes.airline.name' ) ) . to . be . visible ;
239+
240+ updateInputWithBlur ( 'Field name' , '' ) ;
241+
242+ await waitFor ( ( ) => {
243+ expect ( screen . queryByText ( 'Field name cannot be empty.' ) ) . to . exist ;
244+ expect ( screen . queryByText ( 'routes.airline.name' ) ) . to . exist ;
245+ } ) ;
246+ } ) ;
247+
248+ it ( 'should not rename a field to a duplicate' , async function ( ) {
249+ const result = renderDrawer ( ) ;
250+ result . plugin . store . dispatch (
251+ selectField ( 'flights.routes' , [ 'airline' , 'name' ] )
252+ ) ;
253+
254+ await waitForDrawerToOpen ( ) ;
255+ expect ( screen . getByTitle ( 'routes.airline.name' ) ) . to . be . visible ;
256+
257+ updateInputWithBlur ( 'Field name' , 'id' ) ;
258+
259+ await waitFor ( ( ) => {
260+ expect ( screen . queryByText ( 'Field already exists.' ) ) . to . exist ;
261+ expect ( screen . queryByText ( 'routes.airline.name' ) ) . to . exist ;
262+ } ) ;
263+ } ) ;
174264 } ) ;
175265
176266 it ( 'should change the content of the drawer when selecting different items' , async function ( ) {
@@ -456,11 +546,7 @@ describe('DiagramEditorSidePanel', function () {
456546 expect ( screen . getByLabelText ( 'Name' ) ) . to . have . value ( 'countries' ) ;
457547
458548 // Update the name.
459- userEvent . clear ( screen . getByLabelText ( 'Name' ) ) ;
460- userEvent . type ( screen . getByLabelText ( 'Name' ) , 'pineapple' ) ;
461-
462- // Blur/unfocus the input.
463- userEvent . click ( document . body ) ;
549+ updateInputWithBlur ( 'Name' , 'pineapple' ) ;
464550
465551 // Check the name in the model.
466552 const modifiedCollection = selectCurrentModelFromState (
@@ -486,11 +572,7 @@ describe('DiagramEditorSidePanel', function () {
486572 expect ( activeElement ) . to . equal ( nameInput ) ;
487573
488574 // Update the name.
489- userEvent . clear ( nameInput ) ;
490- userEvent . type ( nameInput , 'pineapple' ) ;
491-
492- // Blur/unfocus the input - now the collection should be names
493- userEvent . click ( document . body ) ;
575+ updateInputWithBlur ( 'Name' , 'pineapple' ) ;
494576
495577 // Check the name in the model.
496578 const newCollection = selectCurrentModelFromState (
@@ -516,7 +598,7 @@ describe('DiagramEditorSidePanel', function () {
516598 'false'
517599 ) ;
518600
519- userEvent . clear ( screen . getByLabelText ( 'Name' ) ) ;
601+ updateInputWithBlur ( 'Name' , '' ) ;
520602
521603 await waitFor ( ( ) => {
522604 expect ( screen . getByLabelText ( 'Name' ) ) . to . have . attribute (
@@ -525,9 +607,6 @@ describe('DiagramEditorSidePanel', function () {
525607 ) ;
526608 } ) ;
527609
528- // Blur/unfocus the input.
529- userEvent . click ( document . body ) ;
530-
531610 const notModifiedCollection = selectCurrentModelFromState (
532611 result . plugin . store . getState ( )
533612 ) . collections . find ( ( c : DataModelCollection ) => {
@@ -549,8 +628,7 @@ describe('DiagramEditorSidePanel', function () {
549628 'false'
550629 ) ;
551630
552- userEvent . clear ( screen . getByLabelText ( 'Name' ) ) ;
553- userEvent . type ( screen . getByLabelText ( 'Name' ) , 'airlines' ) ;
631+ updateInputWithBlur ( 'Name' , 'airlines' ) ;
554632
555633 await waitFor ( ( ) => {
556634 expect ( screen . getByLabelText ( 'Name' ) ) . to . have . attribute (
@@ -559,9 +637,6 @@ describe('DiagramEditorSidePanel', function () {
559637 ) ;
560638 } ) ;
561639
562- // Blur/unfocus the input.
563- userEvent . click ( document . body ) ;
564-
565640 const notModifiedCollection = selectCurrentModelFromState (
566641 result . plugin . store . getState ( )
567642 ) . collections . find ( ( c : DataModelCollection ) => {
0 commit comments