@@ -20,7 +20,7 @@ describe('LiveController parent -> child component tests', () => {
2020
2121 it ( 'adds & removes the child correctly' , async ( ) => {
2222 const childTemplate = ( data : any ) => `
23- <div ${ initComponent ( data , { id : 'the-child-id' } ) } data-testid="child"></div>
23+ <div ${ initComponent ( data , { } , { id : 'the-child-id' } ) } data-testid="child"></div>
2424 ` ;
2525
2626 const test = await createTest ( { } , ( data : any ) => `
@@ -70,8 +70,8 @@ describe('LiveController parent -> child component tests', () => {
7070 it ( 'sends a map of child fingerprints on re-render' , async ( ) => {
7171 const test = await createTest ( { } , ( data : any ) => `
7272 <div ${ initComponent ( data ) } >
73- <div ${ initComponent ( { } , { id : 'the-child-id1' , fingerprint : 'child-fingerprint1' } ) } >Child1</div>
74- <div ${ initComponent ( { } , { id : 'the-child-id2' , fingerprint : 'child-fingerprint2' } ) } >Child2</div>
73+ <div ${ initComponent ( { } , { } , { id : 'the-child-id1' , fingerprint : 'child-fingerprint1' } ) } >Child1</div>
74+ <div ${ initComponent ( { } , { } , { id : 'the-child-id2' , fingerprint : 'child-fingerprint2' } ) } >Child2</div>
7575 </div>
7676 ` ) ;
7777
@@ -86,4 +86,100 @@ describe('LiveController parent -> child component tests', () => {
8686 test . component . render ( ) ;
8787 await waitFor ( ( ) => expect ( test . element ) . toHaveAttribute ( 'busy' ) ) ;
8888 } ) ;
89+
90+ it ( 'removes missing child component on re-render' , async ( ) => {
91+ const test = await createTest ( { renderChild : true } , ( data : any ) => `
92+ <div ${ initComponent ( data ) } >
93+ ${ data . renderChild
94+ ? `<div ${ initComponent ( { } , { } , { id : 'the-child-id' } ) } data-testid="child">Child Component</div>`
95+ : ''
96+ }
97+ </div>
98+ ` ) ;
99+
100+ test . expectsAjaxCall ( 'get' )
101+ . expectSentData ( test . initialData )
102+ . serverWillChangeData ( ( data : any ) => {
103+ data . renderChild = false ;
104+ } )
105+ . init ( ) ;
106+
107+ expect ( test . element ) . toHaveTextContent ( 'Child Component' )
108+ expect ( test . component . getChildren ( ) . size ) . toEqual ( 1 ) ;
109+ test . component . render ( ) ;
110+ // wait for child to disappear
111+ await waitFor ( ( ) => expect ( test . element ) . toHaveAttribute ( 'busy' ) ) ;
112+ await waitFor ( ( ) => expect ( test . element ) . not . toHaveAttribute ( 'busy' ) ) ;
113+ expect ( test . element ) . not . toHaveTextContent ( 'Child Component' )
114+ expect ( test . component . getChildren ( ) . size ) . toEqual ( 0 ) ;
115+ } ) ;
116+
117+ it ( 'adds new child component on re-render' , async ( ) => {
118+ const test = await createTest ( { renderChild : false } , ( data : any ) => `
119+ <div ${ initComponent ( data ) } >
120+ ${ data . renderChild
121+ ? `<div ${ initComponent ( { } , { } , { id : 'the-child-id' } ) } data-testid="child">Child Component</div>`
122+ : ''
123+ }
124+ </div>
125+ ` ) ;
126+
127+ test . expectsAjaxCall ( 'get' )
128+ . expectSentData ( test . initialData )
129+ . serverWillChangeData ( ( data : any ) => {
130+ data . renderChild = true ;
131+ } )
132+ . init ( ) ;
133+
134+ expect ( test . element ) . not . toHaveTextContent ( 'Child Component' )
135+ expect ( test . component . getChildren ( ) . size ) . toEqual ( 0 ) ;
136+ test . component . render ( ) ;
137+ // wait for child to disappear
138+ await waitFor ( ( ) => expect ( test . element ) . toHaveAttribute ( 'busy' ) ) ;
139+ await waitFor ( ( ) => expect ( test . element ) . not . toHaveAttribute ( 'busy' ) ) ;
140+ expect ( test . element ) . toHaveTextContent ( 'Child Component' )
141+ expect ( test . component . getChildren ( ) . size ) . toEqual ( 1 ) ;
142+ } ) ;
143+
144+ // it('existing child component that has no props is ignored', async () => {
145+ // const originalChild = `
146+ // <div ${initComponent({}, {}, {id: 'the-child-id'}) } data-testid="child">
147+ // Child Component
148+ // </div>
149+ // `;
150+ // const updatedChild = `
151+ // <div ${initComponent({}, {}, {id: 'the-child-id'}) } data-testid="child">
152+ // Child Component
153+ // </div>
154+ // `;
155+ //
156+ // const test = await createTest({useOriginalChild: true}, (data: any) => `
157+ // <div ${initComponent(data)}>
158+ // ${data.useUpdatedChild ? originalChild : updatedChild}
159+ // </div>
160+ // `);
161+ //
162+ // test.expectsAjaxCall('get')
163+ // .expectSentData(test.initialData)
164+ // .serverWillChangeData((data: any) => {
165+ // data.renderChild = true;
166+ // })
167+ // .init();
168+ //
169+ // expect(test.element).not.toHaveTextContent('Child Component')
170+ // expect(test.component.getChildren().size).toEqual(0);
171+ // test.component.render();
172+ // // wait for child to disappear
173+ // await waitFor(() => expect(test.element).toHaveAttribute('busy'));
174+ // await waitFor(() => expect(test.element).not.toHaveAttribute('busy'));
175+ // expect(test.element).toHaveTextContent('Child Component')
176+ // expect(test.component.getChildren().size).toEqual(1);
177+ // });
178+
179+
180+ // TODO: response comes back with existing child element but no props, child is untouched
181+ // TODO: response comes back with empty child element BUT with new fingerprint & props, those are pushed down onto the child, which will trigger a re-render
182+ // TODO: check above situation mixing element types - e.g. span vs div
183+ // TODO: check that data-live-id could be used to remove old component and use new component entirely, with fresh data
184+ // TODO: multiple children, even if they change position, are correctly handled
89185} ) ;
0 commit comments