Best JavaScript code snippet using playwright-internal
useMutableSource-test.internal.js
Source:useMutableSource-test.internal.js
...116 function createMutableSource(source) {117 return React.createMutableSource(source, param => param.version);118 }119 function Component({getSnapshot, label, mutableSource, subscribe}) {120 const snapshot = useMutableSource(mutableSource, getSnapshot, subscribe);121 Scheduler.unstable_yieldValue(`${label}:${snapshot}`);122 return <div>{`${label}:${snapshot}`}</div>;123 }124 beforeEach(loadModules);125 // @gate experimental126 it('should subscribe to a source and schedule updates when it changes', () => {127 const source = createSource('one');128 const mutableSource = createMutableSource(source);129 act(() => {130 ReactNoop.renderToRootWithID(131 <>132 <Component133 label="a"134 getSnapshot={defaultGetSnapshot}135 mutableSource={mutableSource}136 subscribe={defaultSubscribe}137 />138 <Component139 label="b"140 getSnapshot={defaultGetSnapshot}141 mutableSource={mutableSource}142 subscribe={defaultSubscribe}143 />144 </>,145 'root',146 () => Scheduler.unstable_yieldValue('Sync effect'),147 );148 expect(Scheduler).toFlushAndYieldThrough([149 'a:one',150 'b:one',151 'Sync effect',152 ]);153 // Subscriptions should be passive154 expect(source.listenerCount).toBe(0);155 ReactNoop.flushPassiveEffects();156 expect(source.listenerCount).toBe(2);157 // Changing values should schedule an update with React158 source.value = 'two';159 expect(Scheduler).toFlushAndYieldThrough(['a:two', 'b:two']);160 // Umounting a component should remove its subscriptino.161 ReactNoop.renderToRootWithID(162 <>163 <Component164 label="a"165 getSnapshot={defaultGetSnapshot}166 mutableSource={mutableSource}167 subscribe={defaultSubscribe}168 />169 </>,170 'root',171 () => Scheduler.unstable_yieldValue('Sync effect'),172 );173 expect(Scheduler).toFlushAndYield(['a:two', 'Sync effect']);174 ReactNoop.flushPassiveEffects();175 expect(source.listenerCount).toBe(1);176 // Umounting a root should remove the remaining event listeners177 ReactNoop.unmountRootWithID('root');178 expect(Scheduler).toFlushAndYield([]);179 ReactNoop.flushPassiveEffects();180 expect(source.listenerCount).toBe(0);181 // Changes to source should not trigger an updates or warnings.182 source.value = 'three';183 expect(Scheduler).toFlushAndYield([]);184 });185 });186 // @gate experimental187 it('should restart work if a new source is mutated during render', () => {188 const source = createSource('one');189 const mutableSource = createMutableSource(source);190 act(() => {191 ReactNoop.render(192 <>193 <Component194 label="a"195 getSnapshot={defaultGetSnapshot}196 mutableSource={mutableSource}197 subscribe={defaultSubscribe}198 />199 <Component200 label="b"201 getSnapshot={defaultGetSnapshot}202 mutableSource={mutableSource}203 subscribe={defaultSubscribe}204 />205 </>,206 () => Scheduler.unstable_yieldValue('Sync effect'),207 );208 // Do enough work to read from one component209 expect(Scheduler).toFlushAndYieldThrough(['a:one']);210 // Mutate source before continuing work211 source.value = 'two';212 // Render work should restart and the updated value should be used213 expect(Scheduler).toFlushAndYield(['a:two', 'b:two', 'Sync effect']);214 });215 });216 // @gate experimental217 it('should schedule an update if a new source is mutated between render and commit (subscription)', () => {218 const source = createSource('one');219 const mutableSource = createMutableSource(source);220 act(() => {221 ReactNoop.render(222 <>223 <Component224 label="a"225 getSnapshot={defaultGetSnapshot}226 mutableSource={mutableSource}227 subscribe={defaultSubscribe}228 />229 <Component230 label="b"231 getSnapshot={defaultGetSnapshot}232 mutableSource={mutableSource}233 subscribe={defaultSubscribe}234 />235 </>,236 () => Scheduler.unstable_yieldValue('Sync effect'),237 );238 // Finish rendering239 expect(Scheduler).toFlushAndYieldThrough([240 'a:one',241 'b:one',242 'Sync effect',243 ]);244 // Mutate source before subscriptions are attached245 expect(source.listenerCount).toBe(0);246 source.value = 'two';247 // Mutation should be detected, and a new render should be scheduled248 expect(Scheduler).toFlushAndYield(['a:two', 'b:two']);249 });250 });251 // @gate experimental252 it('should unsubscribe and resubscribe if a new source is used', () => {253 const sourceA = createSource('a-one');254 const mutableSourceA = createMutableSource(sourceA);255 const sourceB = createSource('b-one');256 const mutableSourceB = createMutableSource(sourceB);257 act(() => {258 ReactNoop.render(259 <Component260 label="only"261 getSnapshot={defaultGetSnapshot}262 mutableSource={mutableSourceA}263 subscribe={defaultSubscribe}264 />,265 () => Scheduler.unstable_yieldValue('Sync effect'),266 );267 expect(Scheduler).toFlushAndYield(['only:a-one', 'Sync effect']);268 ReactNoop.flushPassiveEffects();269 expect(sourceA.listenerCount).toBe(1);270 // Changing values should schedule an update with React271 sourceA.value = 'a-two';272 expect(Scheduler).toFlushAndYield(['only:a-two']);273 // If we re-render with a new source, the old one should be unsubscribed.274 ReactNoop.render(275 <Component276 label="only"277 getSnapshot={defaultGetSnapshot}278 mutableSource={mutableSourceB}279 subscribe={defaultSubscribe}280 />,281 () => Scheduler.unstable_yieldValue('Sync effect'),282 );283 expect(Scheduler).toFlushAndYield(['only:b-one', 'Sync effect']);284 ReactNoop.flushPassiveEffects();285 expect(sourceA.listenerCount).toBe(0);286 expect(sourceB.listenerCount).toBe(1);287 // Changing to original source should not schedule updates with React288 sourceA.value = 'a-three';289 expect(Scheduler).toFlushAndYield([]);290 // Changing new source value should schedule an update with React291 sourceB.value = 'b-two';292 expect(Scheduler).toFlushAndYield(['only:b-two']);293 });294 });295 // @gate experimental296 it('should unsubscribe and resubscribe if a new subscribe function is provided', () => {297 const source = createSource('a-one');298 const mutableSource = createMutableSource(source);299 const unsubscribeA = jest.fn();300 const subscribeA = jest.fn(s => {301 const unsubscribe = defaultSubscribe(s);302 return () => {303 unsubscribe();304 unsubscribeA();305 };306 });307 const unsubscribeB = jest.fn();308 const subscribeB = jest.fn(s => {309 const unsubscribe = defaultSubscribe(s);310 return () => {311 unsubscribe();312 unsubscribeB();313 };314 });315 act(() => {316 ReactNoop.renderToRootWithID(317 <Component318 label="only"319 getSnapshot={defaultGetSnapshot}320 mutableSource={mutableSource}321 subscribe={subscribeA}322 />,323 'root',324 () => Scheduler.unstable_yieldValue('Sync effect'),325 );326 expect(Scheduler).toFlushAndYield(['only:a-one', 'Sync effect']);327 ReactNoop.flushPassiveEffects();328 expect(source.listenerCount).toBe(1);329 expect(subscribeA).toHaveBeenCalledTimes(1);330 // If we re-render with a new subscription function,331 // the old unsubscribe function should be called.332 ReactNoop.renderToRootWithID(333 <Component334 label="only"335 getSnapshot={defaultGetSnapshot}336 mutableSource={mutableSource}337 subscribe={subscribeB}338 />,339 'root',340 () => Scheduler.unstable_yieldValue('Sync effect'),341 );342 expect(Scheduler).toFlushAndYield(['only:a-one', 'Sync effect']);343 ReactNoop.flushPassiveEffects();344 expect(source.listenerCount).toBe(1);345 expect(unsubscribeA).toHaveBeenCalledTimes(1);346 expect(subscribeB).toHaveBeenCalledTimes(1);347 // Unmounting should call the newer unsunscribe.348 ReactNoop.unmountRootWithID('root');349 expect(Scheduler).toFlushAndYield([]);350 ReactNoop.flushPassiveEffects();351 expect(source.listenerCount).toBe(0);352 expect(unsubscribeB).toHaveBeenCalledTimes(1);353 });354 });355 // @gate experimental356 it('should re-use previously read snapshot value when reading is unsafe', () => {357 const source = createSource('one');358 const mutableSource = createMutableSource(source);359 act(() => {360 ReactNoop.render(361 <>362 <Component363 label="a"364 getSnapshot={defaultGetSnapshot}365 mutableSource={mutableSource}366 subscribe={defaultSubscribe}367 />368 <Component369 label="b"370 getSnapshot={defaultGetSnapshot}371 mutableSource={mutableSource}372 subscribe={defaultSubscribe}373 />374 </>,375 () => Scheduler.unstable_yieldValue('Sync effect'),376 );377 expect(Scheduler).toFlushAndYield(['a:one', 'b:one', 'Sync effect']);378 // Changing values should schedule an update with React.379 // Start working on this update but don't finish it.380 source.value = 'two';381 expect(Scheduler).toFlushAndYieldThrough(['a:two']);382 // Re-renders that occur before the udpate is processed383 // should reuse snapshot so long as the config has not changed384 ReactNoop.flushSync(() => {385 ReactNoop.render(386 <>387 <Component388 label="a"389 getSnapshot={defaultGetSnapshot}390 mutableSource={mutableSource}391 subscribe={defaultSubscribe}392 />393 <Component394 label="b"395 getSnapshot={defaultGetSnapshot}396 mutableSource={mutableSource}397 subscribe={defaultSubscribe}398 />399 </>,400 () => Scheduler.unstable_yieldValue('Sync effect'),401 );402 });403 expect(Scheduler).toHaveYielded(['a:one', 'b:one', 'Sync effect']);404 expect(Scheduler).toFlushAndYield(['a:two', 'b:two']);405 });406 });407 // @gate experimental408 it('should read from source on newly mounted subtree if no pending updates are scheduled for source', () => {409 const source = createSource('one');410 const mutableSource = createMutableSource(source);411 act(() => {412 ReactNoop.render(413 <>414 <Component415 label="a"416 getSnapshot={defaultGetSnapshot}417 mutableSource={mutableSource}418 subscribe={defaultSubscribe}419 />420 </>,421 () => Scheduler.unstable_yieldValue('Sync effect'),422 );423 expect(Scheduler).toFlushAndYield(['a:one', 'Sync effect']);424 ReactNoop.render(425 <>426 <Component427 label="a"428 getSnapshot={defaultGetSnapshot}429 mutableSource={mutableSource}430 subscribe={defaultSubscribe}431 />432 <Component433 label="b"434 getSnapshot={defaultGetSnapshot}435 mutableSource={mutableSource}436 subscribe={defaultSubscribe}437 />438 </>,439 () => Scheduler.unstable_yieldValue('Sync effect'),440 );441 expect(Scheduler).toFlushAndYield(['a:one', 'b:one', 'Sync effect']);442 });443 });444 // @gate experimental445 it('should throw and restart render if source and snapshot are unavailable during an update', () => {446 const source = createSource('one');447 const mutableSource = createMutableSource(source);448 act(() => {449 ReactNoop.render(450 <>451 <Component452 label="a"453 getSnapshot={defaultGetSnapshot}454 mutableSource={mutableSource}455 subscribe={defaultSubscribe}456 />457 <Component458 label="b"459 getSnapshot={defaultGetSnapshot}460 mutableSource={mutableSource}461 subscribe={defaultSubscribe}462 />463 </>,464 () => Scheduler.unstable_yieldValue('Sync effect'),465 );466 expect(Scheduler).toFlushAndYield(['a:one', 'b:one', 'Sync effect']);467 ReactNoop.flushPassiveEffects();468 // Changing values should schedule an update with React.469 // Start working on this update but don't finish it.470 Scheduler.unstable_runWithPriority(Scheduler.unstable_LowPriority, () => {471 source.value = 'two';472 expect(Scheduler).toFlushAndYieldThrough(['a:two']);473 });474 const newGetSnapshot = s => 'new:' + defaultGetSnapshot(s);475 // Force a higher priority render with a new config.476 // This should signal that the snapshot is not safe and trigger a full re-render.477 Scheduler.unstable_runWithPriority(478 Scheduler.unstable_UserBlockingPriority,479 () => {480 ReactNoop.render(481 <>482 <Component483 label="a"484 getSnapshot={newGetSnapshot}485 mutableSource={mutableSource}486 subscribe={defaultSubscribe}487 />488 <Component489 label="b"490 getSnapshot={newGetSnapshot}491 mutableSource={mutableSource}492 subscribe={defaultSubscribe}493 />494 </>,495 () => Scheduler.unstable_yieldValue('Sync effect'),496 );497 },498 );499 expect(Scheduler).toFlushAndYieldThrough([500 'a:new:two',501 'b:new:two',502 'Sync effect',503 ]);504 });505 });506 // @gate experimental507 it('should throw and restart render if source and snapshot are unavailable during a sync update', () => {508 const source = createSource('one');509 const mutableSource = createMutableSource(source);510 act(() => {511 ReactNoop.render(512 <>513 <Component514 label="a"515 getSnapshot={defaultGetSnapshot}516 mutableSource={mutableSource}517 subscribe={defaultSubscribe}518 />519 <Component520 label="b"521 getSnapshot={defaultGetSnapshot}522 mutableSource={mutableSource}523 subscribe={defaultSubscribe}524 />525 </>,526 () => Scheduler.unstable_yieldValue('Sync effect'),527 );528 expect(Scheduler).toFlushAndYield(['a:one', 'b:one', 'Sync effect']);529 ReactNoop.flushPassiveEffects();530 // Changing values should schedule an update with React.531 // Start working on this update but don't finish it.532 Scheduler.unstable_runWithPriority(Scheduler.unstable_LowPriority, () => {533 source.value = 'two';534 expect(Scheduler).toFlushAndYieldThrough(['a:two']);535 });536 const newGetSnapshot = s => 'new:' + defaultGetSnapshot(s);537 // Force a higher priority render with a new config.538 // This should signal that the snapshot is not safe and trigger a full re-render.539 ReactNoop.flushSync(() => {540 ReactNoop.render(541 <>542 <Component543 label="a"544 getSnapshot={newGetSnapshot}545 mutableSource={mutableSource}546 subscribe={defaultSubscribe}547 />548 <Component549 label="b"550 getSnapshot={newGetSnapshot}551 mutableSource={mutableSource}552 subscribe={defaultSubscribe}553 />554 </>,555 () => Scheduler.unstable_yieldValue('Sync effect'),556 );557 });558 expect(Scheduler).toHaveYielded([559 'a:new:two',560 'b:new:two',561 'Sync effect',562 ]);563 });564 });565 // @gate experimental566 it('should only update components whose subscriptions fire', () => {567 const source = createComplexSource('a:one', 'b:one');568 const mutableSource = createMutableSource(source);569 // Subscribe to part of the store.570 const getSnapshotA = s => s.valueA;571 const subscribeA = (s, callback) => s.subscribeA(callback);572 const getSnapshotB = s => s.valueB;573 const subscribeB = (s, callback) => s.subscribeB(callback);574 act(() => {575 ReactNoop.render(576 <>577 <Component578 label="a"579 getSnapshot={getSnapshotA}580 mutableSource={mutableSource}581 subscribe={subscribeA}582 />583 <Component584 label="b"585 getSnapshot={getSnapshotB}586 mutableSource={mutableSource}587 subscribe={subscribeB}588 />589 </>,590 () => Scheduler.unstable_yieldValue('Sync effect'),591 );592 expect(Scheduler).toFlushAndYield(['a:a:one', 'b:b:one', 'Sync effect']);593 // Changes to part of the store (e.g. A) should not render other parts.594 source.valueA = 'a:two';595 expect(Scheduler).toFlushAndYield(['a:a:two']);596 source.valueB = 'b:two';597 expect(Scheduler).toFlushAndYield(['b:b:two']);598 });599 });600 // @gate experimental601 it('should detect tearing in part of the store not yet subscribed to', () => {602 const source = createComplexSource('a:one', 'b:one');603 const mutableSource = createMutableSource(source);604 // Subscribe to part of the store.605 const getSnapshotA = s => s.valueA;606 const subscribeA = (s, callback) => s.subscribeA(callback);607 const getSnapshotB = s => s.valueB;608 const subscribeB = (s, callback) => s.subscribeB(callback);609 act(() => {610 ReactNoop.render(611 <>612 <Component613 label="a"614 getSnapshot={getSnapshotA}615 mutableSource={mutableSource}616 subscribe={subscribeA}617 />618 </>,619 () => Scheduler.unstable_yieldValue('Sync effect'),620 );621 expect(Scheduler).toFlushAndYield(['a:a:one', 'Sync effect']);622 // Because the store has not chagned yet, there are no pending updates,623 // so it is considered safe to read from when we start this render.624 ReactNoop.render(625 <>626 <Component627 label="a"628 getSnapshot={getSnapshotA}629 mutableSource={mutableSource}630 subscribe={subscribeA}631 />632 <Component633 label="b"634 getSnapshot={getSnapshotB}635 mutableSource={mutableSource}636 subscribe={subscribeB}637 />638 <Component639 label="c"640 getSnapshot={getSnapshotB}641 mutableSource={mutableSource}642 subscribe={subscribeB}643 />644 </>,645 () => Scheduler.unstable_yieldValue('Sync effect'),646 );647 expect(Scheduler).toFlushAndYieldThrough(['a:a:one', 'b:b:one']);648 // Mutating the source should trigger a tear detection on the next read,649 // which should throw and re-render the entire tree.650 source.valueB = 'b:two';651 expect(Scheduler).toFlushAndYield([652 'a:a:one',653 'b:b:two',654 'c:b:two',655 'Sync effect',656 ]);657 });658 });659 // @gate experimental660 it('does not schedule an update for subscriptions that fire with an unchanged snapshot', () => {661 const MockComponent = jest.fn(Component);662 const source = createSource('one');663 const mutableSource = createMutableSource(source);664 act(() => {665 ReactNoop.render(666 <MockComponent667 label="only"668 getSnapshot={defaultGetSnapshot}669 mutableSource={mutableSource}670 subscribe={defaultSubscribe}671 />,672 () => Scheduler.unstable_yieldValue('Sync effect'),673 );674 expect(Scheduler).toFlushAndYieldThrough(['only:one', 'Sync effect']);675 ReactNoop.flushPassiveEffects();676 expect(source.listenerCount).toBe(1);677 // Notify subscribe function but don't change the value678 source.value = 'one';679 expect(Scheduler).toFlushWithoutYielding();680 });681 });682 // @gate experimental683 it('should throw and restart if getSnapshot changes between scheduled update and re-render', () => {684 const source = createSource('one');685 const mutableSource = createMutableSource(source);686 const newGetSnapshot = s => 'new:' + defaultGetSnapshot(s);687 let updateGetSnapshot;688 function WrapperWithState() {689 const tuple = React.useState(() => defaultGetSnapshot);690 updateGetSnapshot = tuple[1];691 return (692 <Component693 label="only"694 getSnapshot={tuple[0]}695 mutableSource={mutableSource}696 subscribe={defaultSubscribe}697 />698 );699 }700 act(() => {701 ReactNoop.render(<WrapperWithState />, () =>702 Scheduler.unstable_yieldValue('Sync effect'),703 );704 expect(Scheduler).toFlushAndYield(['only:one', 'Sync effect']);705 ReactNoop.flushPassiveEffects();706 // Change the source (and schedule an update).707 Scheduler.unstable_runWithPriority(Scheduler.unstable_LowPriority, () => {708 source.value = 'two';709 });710 // Schedule a higher priority update that changes getSnapshot.711 Scheduler.unstable_runWithPriority(712 Scheduler.unstable_UserBlockingPriority,713 () => {714 updateGetSnapshot(() => newGetSnapshot);715 },716 );717 expect(Scheduler).toFlushAndYield(['only:new:two']);718 });719 });720 // @gate experimental721 it('should recover from a mutation during yield when other work is scheduled', () => {722 const source = createSource('one');723 const mutableSource = createMutableSource(source);724 act(() => {725 // Start a render that uses the mutable source.726 ReactNoop.render(727 <>728 <Component729 label="a"730 getSnapshot={defaultGetSnapshot}731 mutableSource={mutableSource}732 subscribe={defaultSubscribe}733 />734 <Component735 label="b"736 getSnapshot={defaultGetSnapshot}737 mutableSource={mutableSource}738 subscribe={defaultSubscribe}739 />740 </>,741 );742 expect(Scheduler).toFlushAndYieldThrough(['a:one']);743 // Mutate source744 source.value = 'two';745 // Now render something different.746 ReactNoop.render(<div />);747 expect(Scheduler).toFlushAndYield([]);748 });749 });750 // @gate experimental751 it('should not throw if the new getSnapshot returns the same snapshot value', () => {752 const source = createSource('one');753 const mutableSource = createMutableSource(source);754 const onRenderA = jest.fn();755 const onRenderB = jest.fn();756 let updateGetSnapshot;757 function WrapperWithState() {758 const tuple = React.useState(() => defaultGetSnapshot);759 updateGetSnapshot = tuple[1];760 return (761 <Component762 label="b"763 getSnapshot={tuple[0]}764 mutableSource={mutableSource}765 subscribe={defaultSubscribe}766 />767 );768 }769 act(() => {770 ReactNoop.render(771 <>772 <React.Profiler id="a" onRender={onRenderA}>773 <Component774 label="a"775 getSnapshot={defaultGetSnapshot}776 mutableSource={mutableSource}777 subscribe={defaultSubscribe}778 />779 </React.Profiler>780 <React.Profiler id="b" onRender={onRenderB}>781 <WrapperWithState />782 </React.Profiler>783 </>,784 () => Scheduler.unstable_yieldValue('Sync effect'),785 );786 expect(Scheduler).toFlushAndYield(['a:one', 'b:one', 'Sync effect']);787 ReactNoop.flushPassiveEffects();788 expect(onRenderA).toHaveBeenCalledTimes(1);789 expect(onRenderB).toHaveBeenCalledTimes(1);790 // If B's getSnapshot function updates, but the snapshot it returns is the same,791 // only B should re-render (to update its state).792 updateGetSnapshot(() => s => defaultGetSnapshot(s));793 expect(Scheduler).toFlushAndYield(['b:one']);794 ReactNoop.flushPassiveEffects();795 expect(onRenderA).toHaveBeenCalledTimes(1);796 expect(onRenderB).toHaveBeenCalledTimes(2);797 });798 });799 // @gate experimental800 it('should not throw if getSnapshot changes but the source can be safely read from anyway', () => {801 const source = createSource('one');802 const mutableSource = createMutableSource(source);803 const newGetSnapshot = s => 'new:' + defaultGetSnapshot(s);804 let updateGetSnapshot;805 function WrapperWithState() {806 const tuple = React.useState(() => defaultGetSnapshot);807 updateGetSnapshot = tuple[1];808 return (809 <Component810 label="only"811 getSnapshot={tuple[0]}812 mutableSource={mutableSource}813 subscribe={defaultSubscribe}814 />815 );816 }817 act(() => {818 ReactNoop.render(<WrapperWithState />, () =>819 Scheduler.unstable_yieldValue('Sync effect'),820 );821 expect(Scheduler).toFlushAndYield(['only:one', 'Sync effect']);822 ReactNoop.flushPassiveEffects();823 // Change the source (and schedule an update)824 // but also change the snapshot function too.825 ReactNoop.batchedUpdates(() => {826 source.value = 'two';827 updateGetSnapshot(() => newGetSnapshot);828 });829 expect(Scheduler).toFlushAndYield(['only:new:two']);830 });831 });832 // @gate experimental833 it('should still schedule an update if an eager selector throws after a mutation', () => {834 const source = createSource({835 friends: [836 {id: 1, name: 'Foo'},837 {id: 2, name: 'Bar'},838 ],839 });840 const mutableSource = createMutableSource(source);841 function FriendsList() {842 const getSnapshot = React.useCallback(843 ({value}) => Array.from(value.friends),844 [],845 );846 const friends = useMutableSource(847 mutableSource,848 getSnapshot,849 defaultSubscribe,850 );851 return (852 <ul>853 {friends.map(friend => (854 <Friend key={friend.id} id={friend.id} />855 ))}856 </ul>857 );858 }859 function Friend({id}) {860 const getSnapshot = React.useCallback(861 ({value}) => {862 // This selector is intentionally written in a way that will throw863 // if no matching friend exists in the store.864 return value.friends.find(friend => friend.id === id).name;865 },866 [id],867 );868 const name = useMutableSource(869 mutableSource,870 getSnapshot,871 defaultSubscribe,872 );873 Scheduler.unstable_yieldValue(`${id}:${name}`);874 return <li>{name}</li>;875 }876 act(() => {877 ReactNoop.render(<FriendsList />, () =>878 Scheduler.unstable_yieldValue('Sync effect'),879 );880 expect(Scheduler).toFlushAndYield(['1:Foo', '2:Bar', 'Sync effect']);881 // This mutation will cause the "Bar" component to throw,882 // since its value will no longer be a part of the store.883 // Mutable source should still schedule an update though,884 // which should unmount "Bar" and mount "Baz".885 source.value = {886 friends: [887 {id: 1, name: 'Foo'},888 {id: 3, name: 'Baz'},889 ],890 };891 expect(Scheduler).toFlushAndYield(['1:Foo', '3:Baz']);892 });893 });894 // @gate experimental895 it('should not warn about updates that fire between unmount and passive unsubcribe', () => {896 const source = createSource('one');897 const mutableSource = createMutableSource(source);898 function Wrapper() {899 React.useLayoutEffect(() => () => {900 Scheduler.unstable_yieldValue('layout unmount');901 });902 return (903 <Component904 label="only"905 getSnapshot={defaultGetSnapshot}906 mutableSource={mutableSource}907 subscribe={defaultSubscribe}908 />909 );910 }911 act(() => {912 ReactNoop.renderToRootWithID(<Wrapper />, 'root', () =>913 Scheduler.unstable_yieldValue('Sync effect'),914 );915 expect(Scheduler).toFlushAndYield(['only:one', 'Sync effect']);916 ReactNoop.flushPassiveEffects();917 // Umounting a root should remove the remaining event listeners in a passive effect918 ReactNoop.unmountRootWithID('root');919 expect(Scheduler).toFlushAndYieldThrough(['layout unmount']);920 // Changes to source should not cause a warning,921 // even though the unsubscribe hasn't run yet (since it's a pending passive effect).922 source.value = 'two';923 expect(Scheduler).toFlushAndYield([]);924 });925 });926 // @gate experimental927 it('should support inline selectors and updates that are processed after selector change', async () => {928 const source = createSource({929 a: 'initial',930 b: 'initial',931 });932 const mutableSource = createMutableSource(source);933 const getSnapshotA = () => source.value.a;934 const getSnapshotB = () => source.value.b;935 function mutateB(newB) {936 source.value = {937 ...source.value,938 b: newB,939 };940 }941 function App({getSnapshot}) {942 const state = useMutableSource(943 mutableSource,944 getSnapshot,945 defaultSubscribe,946 );947 return state;948 }949 const root = ReactNoop.createRoot();950 await act(async () => {951 root.render(<App getSnapshot={getSnapshotA} />);952 });953 expect(root).toMatchRenderedOutput('initial');954 await act(async () => {955 mutateB('Updated B');956 root.render(<App getSnapshot={getSnapshotB} />);957 });958 expect(root).toMatchRenderedOutput('Updated B');959 await act(async () => {960 mutateB('Another update');961 });962 expect(root).toMatchRenderedOutput('Another update');963 });964 // @gate experimental965 it('should clear the update queue when getSnapshot changes with pending lower priority updates', async () => {966 const source = createSource({967 a: 'initial',968 b: 'initial',969 });970 const mutableSource = createMutableSource(source);971 const getSnapshotA = () => source.value.a;972 const getSnapshotB = () => source.value.b;973 function mutateA(newA) {974 source.value = {975 ...source.value,976 a: newA,977 };978 }979 function mutateB(newB) {980 source.value = {981 ...source.value,982 b: newB,983 };984 }985 function App({toggle}) {986 const state = useMutableSource(987 mutableSource,988 toggle ? getSnapshotB : getSnapshotA,989 defaultSubscribe,990 );991 const result = (toggle ? 'B: ' : 'A: ') + state;992 return result;993 }994 const root = ReactNoop.createRoot();995 await act(async () => {996 root.render(<App toggle={false} />);997 });998 expect(root).toMatchRenderedOutput('A: initial');999 await act(async () => {1000 ReactNoop.discreteUpdates(() => {1001 // Update both A and B to the same value1002 mutateA('Update');1003 mutateB('Update');1004 // Toggle to B in the same batch1005 root.render(<App toggle={true} />);1006 });1007 // Mutate A at lower priority. This should never be rendered, because1008 // by the time we get to the lower priority, we've already switched1009 // to B.1010 mutateA('OOPS! This mutation should be ignored');1011 });1012 expect(root).toMatchRenderedOutput('B: Update');1013 });1014 // @gate experimental1015 it('should clear the update queue when source changes with pending lower priority updates', async () => {1016 const sourceA = createSource('initial');1017 const sourceB = createSource('initial');1018 const mutableSourceA = createMutableSource(sourceA);1019 const mutableSourceB = createMutableSource(sourceB);1020 function App({toggle}) {1021 const state = useMutableSource(1022 toggle ? mutableSourceB : mutableSourceA,1023 defaultGetSnapshot,1024 defaultSubscribe,1025 );1026 const result = (toggle ? 'B: ' : 'A: ') + state;1027 return result;1028 }1029 const root = ReactNoop.createRoot();1030 await act(async () => {1031 root.render(<App toggle={false} />);1032 });1033 expect(root).toMatchRenderedOutput('A: initial');1034 await act(async () => {1035 ReactNoop.discreteUpdates(() => {1036 // Update both A and B to the same value1037 sourceA.value = 'Update';1038 sourceB.value = 'Update';1039 // Toggle to B in the same batch1040 root.render(<App toggle={true} />);1041 });1042 // Mutate A at lower priority. This should never be rendered, because1043 // by the time we get to the lower priority, we've already switched1044 // to B.1045 sourceA.value = 'OOPS! This mutation should be ignored';1046 });1047 expect(root).toMatchRenderedOutput('B: Update');1048 });1049 // @gate experimental1050 it('should always treat reading as potentially unsafe when getSnapshot changes between renders', async () => {1051 const source = createSource({1052 a: 'foo',1053 b: 'bar',1054 });1055 const mutableSource = createMutableSource(source);1056 const getSnapshotA = () => source.value.a;1057 const getSnapshotB = () => source.value.b;1058 function mutateA(newA) {1059 source.value = {1060 ...source.value,1061 a: newA,1062 };1063 }1064 function App({getSnapshotFirst, getSnapshotSecond}) {1065 const first = useMutableSource(1066 mutableSource,1067 getSnapshotFirst,1068 defaultSubscribe,1069 );1070 const second = useMutableSource(1071 mutableSource,1072 getSnapshotSecond,1073 defaultSubscribe,1074 );1075 let result = `x: ${first}, y: ${second}`;1076 if (getSnapshotFirst === getSnapshotSecond) {1077 // When both getSnapshot functions are equal,1078 // the two values must be consistent.1079 if (first !== second) {1080 result = 'Oops, tearing!';1081 }1082 }1083 React.useEffect(() => {1084 Scheduler.unstable_yieldValue(result);1085 }, [result]);1086 return result;1087 }1088 const root = ReactNoop.createRoot();1089 await act(async () => {1090 root.render(1091 <App1092 getSnapshotFirst={getSnapshotA}1093 getSnapshotSecond={getSnapshotB}1094 />,1095 );1096 });1097 // x and y start out reading from different parts of the store.1098 expect(Scheduler).toHaveYielded(['x: foo, y: bar']);1099 await act(async () => {1100 ReactNoop.discreteUpdates(() => {1101 // At high priority, toggle y so that it reads from A instead of B.1102 // Simultaneously, mutate A.1103 mutateA('baz');1104 root.render(1105 <App1106 getSnapshotFirst={getSnapshotA}1107 getSnapshotSecond={getSnapshotA}1108 />,1109 );1110 // If this update were processed before the next mutation,1111 // it would be expected to yield "baz" and "baz".1112 });1113 // At lower priority, mutate A again.1114 // This happens to match the initial value of B.1115 mutateA('bar');1116 // When this update is processed,1117 // it is expected to yield "bar" and "bar".1118 });1119 // Check that we didn't commit any inconsistent states.1120 // The actual sequence of work will be:1121 // 1. React renders the high-pri update, sees a new getSnapshot, detects the source has been further mutated, and throws1122 // 2. React re-renders with all pending updates, including the second mutation, and renders "bar" and "bar".1123 expect(Scheduler).toHaveYielded(['x: bar, y: bar']);1124 });1125 // @gate experimental1126 it('getSnapshot changes and then source is mutated in between paint and passive effect phase', async () => {1127 const source = createSource({1128 a: 'foo',1129 b: 'bar',1130 });1131 const mutableSource = createMutableSource(source);1132 function mutateB(newB) {1133 source.value = {1134 ...source.value,1135 b: newB,1136 };1137 }1138 const getSnapshotA = () => source.value.a;1139 const getSnapshotB = () => source.value.b;1140 function App({getSnapshot}) {1141 const value = useMutableSource(1142 mutableSource,1143 getSnapshot,1144 defaultSubscribe,1145 );1146 Scheduler.unstable_yieldValue('Render: ' + value);1147 React.useEffect(() => {1148 Scheduler.unstable_yieldValue('Commit: ' + value);1149 }, [value]);1150 return value;1151 }1152 const root = ReactNoop.createRoot();1153 await act(async () => {1154 root.render(<App getSnapshot={getSnapshotA} />);1155 });1156 expect(Scheduler).toHaveYielded(['Render: foo', 'Commit: foo']);1157 await act(async () => {1158 // Switch getSnapshot to read from B instead1159 root.render(<App getSnapshot={getSnapshotB} />);1160 // Render and finish the tree, but yield right after paint, before1161 // the passive effects have fired.1162 expect(Scheduler).toFlushUntilNextPaint(['Render: bar']);1163 // Then mutate B.1164 mutateB('baz');1165 });1166 expect(Scheduler).toHaveYielded([1167 // Fires the effect from the previous render1168 'Commit: bar',1169 // During that effect, it should detect that the snapshot has changed1170 // and re-render.1171 'Render: baz',1172 'Commit: baz',1173 ]);1174 expect(root).toMatchRenderedOutput('baz');1175 });1176 // @gate experimental1177 it('getSnapshot changes and then source is mutated in between paint and passive effect phase, case 2', async () => {1178 const source = createSource({1179 a: 'a0',1180 b: 'b0',1181 });1182 const mutableSource = createMutableSource(source);1183 const getSnapshotA = () => source.value.a;1184 const getSnapshotB = () => source.value.b;1185 function mutateA(newA) {1186 source.value = {1187 ...source.value,1188 a: newA,1189 };1190 }1191 function App({getSnapshotFirst, getSnapshotSecond}) {1192 const first = useMutableSource(1193 mutableSource,1194 getSnapshotFirst,1195 defaultSubscribe,1196 );1197 const second = useMutableSource(1198 mutableSource,1199 getSnapshotSecond,1200 defaultSubscribe,1201 );1202 return `first: ${first}, second: ${second}`;1203 }1204 const root = ReactNoop.createRoot();1205 await act(async () => {1206 root.render(1207 <App1208 getSnapshotFirst={getSnapshotA}1209 getSnapshotSecond={getSnapshotB}1210 />,1211 );1212 });1213 expect(root.getChildrenAsJSX()).toEqual('first: a0, second: b0');1214 await act(async () => {1215 // Switch the second getSnapshot to also read from A1216 root.render(1217 <App1218 getSnapshotFirst={getSnapshotA}1219 getSnapshotSecond={getSnapshotA}1220 />,1221 );1222 // Render and finish the tree, but yield right after paint, before1223 // the passive effects have fired.1224 expect(Scheduler).toFlushUntilNextPaint([]);1225 // Now mutate A. Both hooks should update.1226 // This is at high priority so that it doesn't get batched with default1227 // priority updates that might fire during the passive effect1228 ReactNoop.discreteUpdates(() => {1229 mutateA('a1');1230 });1231 expect(Scheduler).toFlushUntilNextPaint([]);1232 expect(root.getChildrenAsJSX()).toEqual('first: a1, second: a1');1233 });1234 expect(root.getChildrenAsJSX()).toEqual('first: a1, second: a1');1235 });1236 // @gate experimental1237 it('getSnapshot changes and then source is mutated during interleaved event', async () => {1238 const {useEffect} = React;1239 const source = createComplexSource('1', '2');1240 const mutableSource = createMutableSource(source);1241 // Subscribe to part of the store.1242 const getSnapshotA = s => s.valueA;1243 const subscribeA = (s, callback) => s.subscribeA(callback);1244 const configA = [getSnapshotA, subscribeA];1245 const getSnapshotB = s => s.valueB;1246 const subscribeB = (s, callback) => s.subscribeB(callback);1247 const configB = [getSnapshotB, subscribeB];1248 function App({parentConfig, childConfig}) {1249 const [getSnapshot, subscribe] = parentConfig;1250 const parentValue = useMutableSource(1251 mutableSource,1252 getSnapshot,1253 subscribe,1254 );1255 Scheduler.unstable_yieldValue('Parent: ' + parentValue);1256 return (1257 <Child1258 parentConfig={parentConfig}1259 childConfig={childConfig}1260 parentValue={parentValue}1261 />1262 );1263 }1264 function Child({parentConfig, childConfig, parentValue}) {1265 const [getSnapshot, subscribe] = childConfig;1266 const childValue = useMutableSource(1267 mutableSource,1268 getSnapshot,1269 subscribe,1270 );1271 Scheduler.unstable_yieldValue('Child: ' + childValue);1272 let result = `${parentValue}, ${childValue}`;1273 if (parentConfig === childConfig) {1274 // When both components read using the same config, the two values1275 // must be consistent.1276 if (parentValue !== childValue) {1277 result = 'Oops, tearing!';1278 }1279 }1280 useEffect(() => {1281 Scheduler.unstable_yieldValue('Commit: ' + result);1282 }, [result]);1283 return result;1284 }1285 const root = ReactNoop.createRoot();1286 await act(async () => {1287 root.render(<App parentConfig={configA} childConfig={configB} />);1288 });1289 expect(Scheduler).toHaveYielded(['Parent: 1', 'Child: 2', 'Commit: 1, 2']);1290 await act(async () => {1291 // Switch the parent and the child to read using the same config1292 root.render(<App parentConfig={configB} childConfig={configB} />);1293 // Start rendering the parent, but yield before rendering the child1294 expect(Scheduler).toFlushAndYieldThrough(['Parent: 2']);1295 // Mutate the config. This is at lower priority so that 1) to make sure1296 // it doesn't happen to get batched with the in-progress render, and 2)1297 // so it doesn't interrupt the in-progress render.1298 Scheduler.unstable_runWithPriority(1299 Scheduler.unstable_IdlePriority,1300 () => {1301 source.valueB = '3';1302 },1303 );1304 });1305 expect(Scheduler).toHaveYielded([1306 // The partial render completes1307 'Child: 2',1308 'Commit: 2, 2',1309 // Then we start rendering the low priority mutation1310 'Parent: 3',1311 // Eventually the child corrects itself, because of the check that1312 // occurs when re-subscribing.1313 'Child: 3',1314 'Commit: 3, 3',1315 ]);1316 });1317 // @gate experimental1318 it('should not tear with newly mounted component when updates were scheduled at a lower priority', async () => {1319 const source = createSource('one');1320 const mutableSource = createMutableSource(source);1321 let committedA = null;1322 let committedB = null;1323 const onRender = () => {1324 if (committedB !== null) {1325 expect(committedA).toBe(committedB);1326 }1327 };1328 function ComponentA() {1329 const snapshot = useMutableSource(1330 mutableSource,1331 defaultGetSnapshot,1332 defaultSubscribe,1333 );1334 Scheduler.unstable_yieldValue(`a:${snapshot}`);1335 React.useEffect(() => {1336 committedA = snapshot;1337 }, [snapshot]);1338 return <div>{`a:${snapshot}`}</div>;1339 }1340 function ComponentB() {1341 const snapshot = useMutableSource(1342 mutableSource,1343 defaultGetSnapshot,1344 defaultSubscribe,1345 );1346 Scheduler.unstable_yieldValue(`b:${snapshot}`);1347 React.useEffect(() => {1348 committedB = snapshot;1349 }, [snapshot]);1350 return <div>{`b:${snapshot}`}</div>;1351 }1352 // Mount ComponentA with data version 11353 act(() => {1354 ReactNoop.render(1355 <React.Profiler id="root" onRender={onRender}>...
useMutableSourceHydration-test.js
Source:useMutableSourceHydration-test.js
...113 },114 };115 }116 function Component({getSnapshot, label, mutableSource, subscribe}) {117 const snapshot = useMutableSource(mutableSource, getSnapshot, subscribe);118 Scheduler.unstable_yieldValue(`${label}:${snapshot}`);119 return <div>{`${label}:${snapshot}`}</div>;120 }121 // @gate enableUseMutableSource122 it('should render and hydrate', () => {123 const source = createSource('one');124 const mutableSource = createMutableSource(source, param => param.version);125 function TestComponent() {126 return (127 <Component128 label="only"129 getSnapshot={defaultGetSnapshot}130 mutableSource={mutableSource}131 subscribe={defaultSubscribe}...
index.js
Source:index.js
...142 }143 return (prevSnapshot = snapshot);144 };145 }, []);146 const snapshot = useMutableSource(147 proxy[MUTABLE_SOURCE],148 getSnapshot,149 subscribe150 );151 const proxyCache = useMemo(() => new WeakMap(), []); // per-hook proxyCache152 return createDeepProxy(snapshot, affected, proxyCache);153};...
demo27.js
Source:demo27.js
...32 // 1ã mutableSource å°±æ¯æ们åæå建ç33 // 2ã 第äºä¸ªæ¯è·åæ°æ®çæ¹æ³ï¼useMutableSourceä¼ærefä½ä¸ºåæ°ä¼ å
¥getSnapshot34 // 3ã 第ä¸ä¸ªæ¯è®¢é
äºä»¶ useMutableSourceä¼ä¼ å
¥ä¸ä¸ªrefåä¸ä¸ªcallabck35 // å¨ç»ä»¶ä¸æ¯æ§è¡ä¸æ¬¡å°±ä¼å°±ä¼æï¼æ°æ®æºä¸è·åæ°æ®çæ¹å¼ä»¥åæ°ç订é
æ¹æ³ä¼ å
¥36 return React.useMutableSource(mutableSource, getData || getSnapshot, subscribe);37 }38 // è¿è¡æ°æ®ä¿®æ¹ï¼å¹¿æå°æ¯ä¸ªè®¢é
çç»ä»¶39 const dispatch = (value) => {40 // ä¿®æ¹æ°æ®41 ref.current = value;42 // ä¿®æ¹äºæ°æ®ä»¥åï¼å°±ä¼æ§è¡lisenteræ¹æ³ï¼ç¶åæ¯ä¸ªè®¢é
ä¼æ§è¡getSnapshotæ¹æ³43 // è¿éçæ¯ä¸ªlistenerå°±æ¯React.useMutableSourceæ¶åä¼ å
¥çcallback44 ref.listeners.forEach(listener => listener());45 }46 return [47 useStore,48 dispatch,49 ]50}...
Recoil_ReactMode.js
Source:Recoil_ReactMode.js
1/**2 * Copyright (c) Facebook, Inc. and its affiliates.3 *4 * This source code is licensed under the MIT license found in the5 * LICENSE file in the root directory of this source tree.6 *7 * @emails oncall+recoil8 * @flow strict-local9 * @format10 */11'use strict';12const React = require('react');13const gkx = require('recoil-shared/util/Recoil_gkx');14export opaque type MutableSource = {};15const createMutableSource: <StoreState, Version>(16 {current: StoreState},17 () => Version,18) => MutableSource =19 // flowlint-next-line unclear-type:off20 (React: any).createMutableSource ?? (React: any).unstable_createMutableSource;21const useMutableSource: <StoreState, T>(22 MutableSource,23 () => T,24 (StoreState, () => void) => () => void,25) => T =26 // flowlint-next-line unclear-type:off27 (React: any).useMutableSource ?? (React: any).unstable_useMutableSource;28// https://github.com/reactwg/react-18/discussions/8629const useSyncExternalStore: <T>(30 subscribe: (() => void) => () => void,31 getSnapshot: () => T,32 getServerSnapshot?: () => T,33) => T =34 // flowlint-next-line unclear-type:off35 (React: any).useSyncExternalStore ??36 // flowlint-next-line unclear-type:off37 (React: any).unstable_useSyncExternalStore;38type ReactMode =39 | 'TRANSITION_SUPPORT'40 | 'SYNC_EXTERNAL_STORE'41 | 'MUTABLE_SOURCE'42 | 'LEGACY';43/**44 * mode: The React API and approach to use for syncing state with React45 * early: Re-renders from Recoil updates occur:46 * 1) earlier47 * 2) in sync with React updates in the same batch48 * 3) before transaction observers instead of after.49 * concurrent: Is the current mode compatible with Concurrent Mode and useTransition()50 */51function reactMode(): {mode: ReactMode, early: boolean, concurrent: boolean} {52 // NOTE: This mode is currently broken with some Suspense cases53 // see Recoil_selector-test.js54 if (gkx('recoil_transition_support')) {55 return {mode: 'TRANSITION_SUPPORT', early: true, concurrent: true};56 }57 if (gkx('recoil_sync_external_store') && useSyncExternalStore != null) {58 return {mode: 'SYNC_EXTERNAL_STORE', early: true, concurrent: false};59 }60 if (61 gkx('recoil_mutable_source') &&62 useMutableSource != null &&63 typeof window !== 'undefined' &&64 !window.$disableRecoilValueMutableSource_TEMP_HACK_DO_NOT_USE65 ) {66 return gkx('recoil_suppress_rerender_in_callback')67 ? {mode: 'MUTABLE_SOURCE', early: true, concurrent: true}68 : {mode: 'MUTABLE_SOURCE', early: false, concurrent: false};69 }70 return gkx('recoil_suppress_rerender_in_callback')71 ? {mode: 'LEGACY', early: true, concurrent: false}72 : {mode: 'LEGACY', early: false, concurrent: false};73}74// TODO Need to figure out if there is a standard/open-source equivalent to see if hot module replacement is happening:75function isFastRefreshEnabled(): boolean {76 // @fb-only: const {isAcceptingUpdate} = require('__debug');77 // @fb-only: return typeof isAcceptingUpdate === 'function' && isAcceptingUpdate();78 return false; // @oss-only79}80module.exports = {81 createMutableSource,82 useMutableSource,83 useSyncExternalStore,84 reactMode,85 isFastRefreshEnabled,...
Recoil_mutableSource.js
Source:Recoil_mutableSource.js
1/**2 * Copyright (c) Facebook, Inc. and its affiliates.3 *4 * This source code is licensed under the MIT license found in the5 * LICENSE file in the root directory of this source tree.6 *7 * @emails oncall+recoil8 * @flow strict9 * @format10 */11'use strict';12const React = require('react');13// FIXME T271055928259966014const useMutableSource: Function = // flowlint-line unclear-type:off15 (React: any).useMutableSource ?? (React: any).unstable_useMutableSource; // flowlint-line unclear-type:off16function mutableSourceExists(): boolean {17 return (18 useMutableSource &&19 !(20 typeof window !== 'undefined' &&21 window.$disableRecoilValueMutableSource_TEMP_HACK_DO_NOT_USE22 )23 );24}25module.exports = {26 mutableSourceExists,27 useMutableSource,...
useMutableSource.js
Source:useMutableSource.js
1/*2export {3 unstable_createMutableSource as createMutableSource,4 unstable_useMutableSource as useMutableSource,5} from 'react'6*/7// emulation with use-subscription8import { useMemo } from "react";9import { useSubscription } from "use-subscription";10const TARGET = Symbol();11export const createMutableSource = (target, _getVersion) => ({12 [TARGET]: target,13});14export const useMutableSource = (source, getSnapshot, subscribe) => {15 const subscription = useMemo(16 () => ({17 getCurrentValue: () => getSnapshot(source[TARGET]),18 subscribe: (callback) => subscribe(source[TARGET], callback),19 }),20 [source, getSnapshot, subscribe]21 );22 return useSubscription(subscription);...
Using AI Code Generation
1const { chromium } = require('playwright');2const { useMutableSource } = require('playwright/lib/server/supplements/recorder/recorderSupplement');3(async () => {4 const browser = await chromium.launch({ headless: false });5 const context = await browser.newContext();6 const page = await context.newPage();7 const source = await page._delegate;8 const { recorderSupplement } = await useMutableSource(source);9 await recorderSupplement.start();10 await recorderSupplement.stop();11 await browser.close();12})();13{14 {
Using AI Code Generation
1const { chromium } = require('playwright');2(async () => {3 const browser = await chromium.launch();4 const context = await browser.newContext();5 const page = await context.newPage();6 const source = await page._delegate.useMutableSource();7 console.log(source);8 await browser.close();9})();
Using AI Code Generation
1const { useMutableSource } = require('playwright');2const source = {3 getSnapshot: () => {4 return { value: 1 };5 },6 subscribe: (callback) => {7 const id = setInterval(() => {8 callback();9 }, 1000);10 return () => clearInterval(id);11 },12};13const mutableSource = useMutableSource(source, () => 1);14const { useSource } = require('playwright');15const playwrightSource = useSource(() => {16 return {17 getSnapshot: () => {18 return { value: 1 };19 },20 subscribe: (callback) => {21 const id = setInterval(() => {22 callback();23 }, 1000);24 return () => clearInterval(id);25 },26 };27});28const { useSource } = require('playwright');29const playwrightSource = useSource(() => {30 return {31 getSnapshot: () => {32 return { value: 1 };33 },34 subscribe: (callback) => {35 const id = setInterval(() => {36 callback();37 }, 1000);38 return () => clearInterval(id);39 },40 };41});42const playwrightSource = useSource(() => {43 return {44 getSnapshot: () => {45 return { value: 1 };46 },47 subscribe: (callback) => {48 const id = setInterval(() => {49 callback();50 }, 1000);51 return () => clearInterval(id);52 },53 };54});55const { useSource } = require('playwright');56const playwrightSource = useSource(() => {57 return {58 getSnapshot: () => {59 return { value: 1 };60 },61 subscribe: (callback) => {62 const id = setInterval(() => {63 callback();64 }, 1000);65 return () => clearInterval(id);66 },67 };68});69const { useSource } = require('playwright');70const playwrightSource = useSource(() => {71 return {72 getSnapshot: () => {73 return { value: 1 };74 },75 subscribe: (callback) => {76 const id = setInterval(() => {77 callback();78 }, 1000);79 return () => clearInterval(id);80 },81 };82});
Using AI Code Generation
1const { useMutableSource } = require('@playwright/test/lib/mutableSource');2const { test } = useMutableSource('test');3const { useTestState } = require('@playwright/test/lib/testState');4const testInfo = useTestState();5const { useWorker } = require('@playwright/test/lib/worker');6const workerInfo = useWorker();7const { useFixture } = require('@playwright/test/lib/fixture');8const { test } = useFixture('test');9const { useTestResult } = require('@playwright/test/lib/testResult');10const testResult = useTestResult();11const { useProject } = require('@playwright/test/lib/project');12const projectInfo = useProject();13const { useBrowser } = require('@playwright/test/lib/browser');14const browser = useBrowser();15const { usePage } = require('@playwright/test/lib/page');16const page = usePage();17const { useBrowserContext } = require('@playwright/test/lib/browserContext');18const context = useBrowserContext();19const { useVideo } = require('@playwright/test/lib/video');20const video = useVideo();21const { useArtifacts } = require('@playwright/test/lib/artifacts');22const artifacts = useArtifacts();23const { useTrace } = require('@playwright/test/lib/trace');24const trace = useTrace();25const { useSnapshot } = require('@playwright/test/lib/snapshot');26const snapshot = useSnapshot();27const { useOutput } = require('@playwright/test/lib/output');28const output = useOutput();
Using AI Code Generation
1const {useMutableSource} = require('playwright');2const {createMutableSource} = require('playwright/lib/server/mutableSource');3const {createServer} = require('http');4const {createReadStream} = require('fs');5const {join} = require('path');6const {promisify} = require('util');7const finalhandler = require('finalhandler');8const serveStatic = require('serve-static');9const serve = serveStatic(join(__dirname, 'public'));10const server = createServer((req, res) => {11 const done = finalhandler(req, res);12 serve(req, res, done);13});14const port = 8080;15server.listen(port, () => console.log(`Listening on ${port}`));16const mutableSource = createMutableSource();17const {subscribe, update} = mutableSource;18const readFile = promisify(createReadStream);19const readFileAndSend = async (path) => {20 const stream = readFile(path);21 for await (const chunk of stream) {22 await update(chunk);23 }24};25readFileAndSend(join(__dirname, 'public', 'file.txt'));26const source = useMutableSource(mutableSource, (chunk) => {27 console.log(chunk.toString());28});29const {test} = require('@playwright/test');30test('test', async ({page}) => {31 const element = await page.$('div');32 const text = await element.textContent();33 expect(text).toBe('Hello World!');34});35All contributions are welcome. Please see the [Playwright contributing guide](
Using AI Code Generation
1const { useMutableSource } = require('playwright-core/lib/server/supplements/mutableSource');2const source = useMutableSource();3const { useMutableSource } = require('playwright-core/lib/server/supplements/mutableSource');4const source = useMutableSource();5const { getPlaywright } = require('playwright-core/lib/server/supplements/mutableSource');6const playwright = getPlaywright();7const { useMutableSource } = require('playwright-core/lib/server/supplements/mutableSource');8const source = useMutableSource();9const { getPlaywright } = require('playwright-core/lib/server/supplements/mutableSource');10const playwright = getPlaywright();11const { useMutableSource } = require('playwright-core/lib/server/supplements/mutableSource');12const source = useMutableSource();13const { getPlaywright } = require('playwright-core/lib/server/supplements/mutableSource');14const playwright = getPlaywright();15const { useMutableSource } = require('playwright-core/lib/server/supplements/mutableSource');16const source = useMutableSource();17const { getPlaywright } = require('playwright-core/lib/server/supplements/mutableSource');18const playwright = getPlaywright();19const { useMutableSource } = require('playwright-core/lib/server/supplements/mutableSource');20const source = useMutableSource();21const { getPlaywright } = require('playwright-core/lib/server/supplements/mutableSource');22const playwright = getPlaywright();23const { useMutableSource } = require('playwright-core/lib/server/supplements/mutableSource');24const source = useMutableSource();25const { getPlaywright } = require('playwright-core/lib/server/supplements/mutableSource');26const playwright = getPlaywright();27const { useMutableSource } = require('playwright-core/lib/server/supplements/mutableSource');28const source = useMutableSource();29const { getPlaywright } =
Using AI Code Generation
1const { useMutableSource } = require('playwright');2(async () => {3 const source = await useMutableSource();4 console.log(source);5})();6{ browserName: 'chromium',7 platformName: 'linux' }
Using AI Code Generation
1const { useMutableSource } = require('@playwright/test');2const { test, expect } = useTestModule();3test('useMutableSource', async ({ page }) => {4 const { source, getSnapshot } = useMutableSource();5 expect(await getSnapshot(page)).toContain('Playwright');6});7const { useTestModule } = require('@playwright/test');8module.exports = {9 use: {10 },11};12module.exports.useTestModule = () => {13 const source = new Map();14 const getSnapshot = (page) => page.textContent('text=Playwright');15 return {16 };17};
Using AI Code Generation
1const { useMutableSource } = require('@playwright/test');2const { source } = require('./source');3const mySource = useMutableSource(source, () => {4 return source.value;5});6const { createSource } = require('@playwright/test');7const source = createSource({8});9module.exports = {10};11const { createSource, updateSource } = require('@playwright/test');12const source = createSource({13});14updateSource(source, {15});16const { createSource, updateSource } = require('@playwright/test');17const source = createSource({18});19updateSource(source, {20});21const { createSource, updateSource } = require('@playwright/test');22const source = createSource({23});24updateSource(source, {25});26const { createSource, updateSource } = require('@playwright/test');27const source = createSource({28});29updateSource(source, {30});31const { createSource, updateSource } = require('@playwright/test');32const source = createSource({33});34updateSource(source, {35});36const { createSource, updateSource } = require('@playwright/test');37const source = createSource({
LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!