@@ -201,14 +201,7 @@ describe('ReactOffscreen', () => {
201
201
});
202
202
// No layout effect.
203
203
expect(Scheduler).toHaveYielded(['Child']);
204
- if (gate(flags => flags.persistent)) {
205
- expect(root).toMatchRenderedOutput(<span hidden={true} prop="Child" />);
206
- } else {
207
- // TODO: Offscreen does not yet hide/unhide children correctly in mutation
208
- // mode. Until we do, it should only be used inside a host component
209
- // wrapper whose visibility is toggled simultaneously.
210
- expect(root).toMatchRenderedOutput(<span prop="Child" />);
211
- }
204
+ expect(root).toMatchRenderedOutput(<span hidden={true} prop="Child" />);
212
205
213
206
// Unhide the tree. The layout effect is mounted.
214
207
await act(async () => {
@@ -255,14 +248,7 @@ describe('ReactOffscreen', () => {
255
248
);
256
249
});
257
250
expect(Scheduler).toHaveYielded(['Unmount layout', 'Child']);
258
- if (gate(flags => flags.persistent)) {
259
- expect(root).toMatchRenderedOutput(<span hidden={true} prop="Child" />);
260
- } else {
261
- // TODO: Offscreen does not yet hide/unhide children correctly in mutation
262
- // mode. Until we do, it should only be used inside a host component
263
- // wrapper whose visibility is toggled simultaneously.
264
- expect(root).toMatchRenderedOutput(<span prop="Child" />);
265
- }
251
+ expect(root).toMatchRenderedOutput(<span hidden={true} prop="Child" />);
266
252
267
253
// Unhide the tree. The layout effect is re-mounted.
268
254
await act(async () => {
@@ -299,14 +285,7 @@ describe('ReactOffscreen', () => {
299
285
);
300
286
});
301
287
expect(Scheduler).toHaveYielded(['Child']);
302
- if (gate(flags => flags.persistent)) {
303
- expect(root).toMatchRenderedOutput(<span hidden={true} prop="Child" />);
304
- } else {
305
- // TODO: Offscreen does not yet hide/unhide children correctly in mutation
306
- // mode. Until we do, it should only be used inside a host component
307
- // wrapper whose visibility is toggled simultaneously.
308
- expect(root).toMatchRenderedOutput(<span prop="Child" />);
309
- }
288
+ expect(root).toMatchRenderedOutput(<span hidden={true} prop="Child" />);
310
289
311
290
// Show the tree. The layout effect is mounted.
312
291
await act(async () => {
@@ -328,14 +307,7 @@ describe('ReactOffscreen', () => {
328
307
);
329
308
});
330
309
expect(Scheduler).toHaveYielded(['Unmount layout', 'Child']);
331
- if (gate(flags => flags.persistent)) {
332
- expect(root).toMatchRenderedOutput(<span hidden={true} prop="Child" />);
333
- } else {
334
- // TODO: Offscreen does not yet hide/unhide children correctly in mutation
335
- // mode. Until we do, it should only be used inside a host component
336
- // wrapper whose visibility is toggled simultaneously.
337
- expect(root).toMatchRenderedOutput(<span prop="Child" />);
338
- }
310
+ expect(root).toMatchRenderedOutput(<span hidden={true} prop="Child" />);
339
311
});
340
312
341
313
// @gate experimental || www
@@ -385,4 +357,78 @@ describe('ReactOffscreen', () => {
385
357
});
386
358
expect(Scheduler).toHaveYielded(['Unmount layout']);
387
359
});
360
+
361
+ it('hides new insertions into an already hidden tree', async () => {
362
+ const root = ReactNoop.createRoot();
363
+ await act(async () => {
364
+ root.render(
365
+ <Offscreen mode="hidden">
366
+ <span>Hi</span>
367
+ </Offscreen>,
368
+ );
369
+ });
370
+ expect(root).toMatchRenderedOutput(<span hidden={true}>Hi</span>);
371
+
372
+ // Insert a new node into the hidden tree
373
+ await act(async () => {
374
+ root.render(
375
+ <Offscreen mode="hidden">
376
+ <span>Hi</span>
377
+ <span>Something new</span>
378
+ </Offscreen>,
379
+ );
380
+ });
381
+ expect(root).toMatchRenderedOutput(
382
+ <>
383
+ <span hidden={true}>Hi</span>
384
+ {/* This new node should also be hidden */}
385
+ <span hidden={true}>Something new</span>
386
+ </>,
387
+ );
388
+ });
389
+
390
+ it('hides updated nodes inside an already hidden tree', async () => {
391
+ const root = ReactNoop.createRoot();
392
+ await act(async () => {
393
+ root.render(
394
+ <Offscreen mode="hidden">
395
+ <span>Hi</span>
396
+ </Offscreen>,
397
+ );
398
+ });
399
+ expect(root).toMatchRenderedOutput(<span hidden={true}>Hi</span>);
400
+
401
+ // Set the `hidden` prop to on an already hidden node
402
+ await act(async () => {
403
+ root.render(
404
+ <Offscreen mode="hidden">
405
+ <span hidden={false}>Hi</span>
406
+ </Offscreen>,
407
+ );
408
+ });
409
+ // It should still be hidden, because the Offscreen container overrides it
410
+ expect(root).toMatchRenderedOutput(<span hidden={true}>Hi</span>);
411
+
412
+ // Unhide the boundary
413
+ await act(async () => {
414
+ root.render(
415
+ <Offscreen mode="visible">
416
+ <span hidden={true}>Hi</span>
417
+ </Offscreen>,
418
+ );
419
+ });
420
+ // It should still be hidden, because of the prop
421
+ expect(root).toMatchRenderedOutput(<span hidden={true}>Hi</span>);
422
+
423
+ // Remove the `hidden` prop
424
+ await act(async () => {
425
+ root.render(
426
+ <Offscreen mode="visible">
427
+ <span>Hi</span>
428
+ </Offscreen>,
429
+ );
430
+ });
431
+ // Now it's visible
432
+ expect(root).toMatchRenderedOutput(<span>Hi</span>);
433
+ });
388
434
});
0 commit comments