| | |
| | import { createSandbox } from 'development-sandbox' |
| | import { FileRef, nextTestSetup } from 'e2e-utils' |
| | import path from 'path' |
| | import { outdent } from 'outdent' |
| |
|
| | describe('ReactRefreshRequire app', () => { |
| | const { next } = nextTestSetup({ |
| | files: new FileRef(path.join(__dirname, 'fixtures', 'default-template')), |
| | skipStart: true, |
| | }) |
| |
|
| | |
| | test('re-runs accepted modules', async () => { |
| | await using sandbox = await createSandbox(next) |
| | const { session } = sandbox |
| |
|
| | await session.patch( |
| | 'index.js', |
| | `export default function Noop() { return null; };` |
| | ) |
| |
|
| | await session.write( |
| | './foo.js', |
| | `window.log.push('init FooV1'); require('./bar');` |
| | ) |
| | await session.write( |
| | './bar.js', |
| | `window.log.push('init BarV1'); export default function Bar() { return null; };` |
| | ) |
| |
|
| | await session.evaluate(() => ((window as any).log = [])) |
| | await session.patch( |
| | 'index.js', |
| | `require('./foo'); export default function Noop() { return null; };` |
| | ) |
| | expect(await session.evaluate(() => (window as any).log)).toEqual([ |
| | 'init FooV1', |
| | 'init BarV1', |
| | ]) |
| |
|
| | |
| | |
| | await session.evaluate(() => ((window as any).log = [])) |
| | await session.patch( |
| | './bar.js', |
| | `window.log.push('init BarV2'); export default function Bar() { return null; };` |
| | ) |
| | expect(await session.evaluate(() => (window as any).log)).toEqual([ |
| | 'init BarV2', |
| | ]) |
| |
|
| | |
| | |
| | await session.evaluate(() => ((window as any).log = [])) |
| | await session.patch( |
| | './bar.js', |
| | `window.log.push('init BarV3'); export default function Bar() { return null; };` |
| | ) |
| | expect(await session.evaluate(() => (window as any).log)).toEqual([ |
| | 'init BarV3', |
| | ]) |
| |
|
| | |
| | |
| | |
| | }) |
| |
|
| | |
| | test('propagates a hot update to closest accepted module', async () => { |
| | await using sandbox = await createSandbox(next) |
| | const { session } = sandbox |
| |
|
| | await session.patch( |
| | 'index.js', |
| | `export default function Noop() { return null; };` |
| | ) |
| |
|
| | await session.write( |
| | './foo.js', |
| | outdent` |
| | window.log.push('init FooV1'); |
| | require('./bar'); |
| | |
| | // Exporting a component marks it as auto-accepting. |
| | export default function Foo() {}; |
| | ` |
| | ) |
| |
|
| | await session.write('./bar.js', `window.log.push('init BarV1');`) |
| |
|
| | await session.evaluate(() => ((window as any).log = [])) |
| | await session.patch( |
| | 'index.js', |
| | `require('./foo'); export default function Noop() { return null; };` |
| | ) |
| |
|
| | expect(await session.evaluate(() => (window as any).log)).toEqual([ |
| | 'init FooV1', |
| | 'init BarV1', |
| | ]) |
| |
|
| | |
| | |
| | await session.evaluate(() => ((window as any).log = [])) |
| | await session.patch('./bar.js', `window.log.push('init BarV2');`) |
| | expect(await session.evaluate(() => (window as any).log)).toEqual([ |
| | |
| | |
| | |
| | 'init FooV1', |
| | 'init BarV2', |
| | |
| | |
| | |
| | ]) |
| |
|
| | |
| | |
| | await session.evaluate(() => ((window as any).log = [])) |
| | await session.patch('./bar.js', `window.log.push('init BarV3');`) |
| | expect(await session.evaluate(() => (window as any).log)).toEqual([ |
| | |
| | |
| | |
| | 'init FooV1', |
| | 'init BarV3', |
| | |
| | |
| | |
| | ]) |
| |
|
| | |
| | |
| | await session.evaluate(() => ((window as any).log = [])) |
| | await session.patch( |
| | './bar.js', |
| | outdent` |
| | window.log.push('init BarV3'); |
| | // Exporting a component marks it as auto-accepting. |
| | export default function Bar() {}; |
| | ` |
| | ) |
| | expect(await session.evaluate(() => (window as any).log)).toEqual([ |
| | |
| | |
| | |
| | 'init FooV1', |
| | 'init BarV3', |
| | |
| | |
| | |
| | ]) |
| |
|
| | |
| | await session.evaluate(() => ((window as any).log = [])) |
| | await session.patch( |
| | './bar.js', |
| | outdent` |
| | window.log.push('init BarV4'); |
| | export default function Bar() {}; |
| | ` |
| | ) |
| | expect(await session.evaluate(() => (window as any).log)).toEqual([ |
| | 'init BarV4', |
| | ]) |
| |
|
| | |
| | |
| | |
| | }) |
| | |
| | test('propagates hot update to all inverse dependencies', async () => { |
| | await using sandbox = await createSandbox(next) |
| | const { session } = sandbox |
| |
|
| | await session.patch( |
| | 'index.js', |
| | `export default function Noop() { return null; };` |
| | ) |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | await session.write( |
| | 'root.js', |
| | outdent` |
| | window.log.push('init RootV1'); |
| | |
| | import './middleA'; |
| | import './middleB'; |
| | import './middleC'; |
| | |
| | export default function Root() {}; |
| | ` |
| | ) |
| | await session.write( |
| | 'middleA.js', |
| | outdent` |
| | log.push('init MiddleAV1'); |
| | |
| | import './leaf'; |
| | |
| | export default function MiddleA() {}; |
| | ` |
| | ) |
| | await session.write( |
| | 'middleB.js', |
| | outdent` |
| | log.push('init MiddleBV1'); |
| | |
| | import './leaf'; |
| | |
| | export default function MiddleB() {}; |
| | ` |
| | ) |
| | |
| | |
| | await session.write( |
| | 'middleC.js', |
| | `log.push('init MiddleCV1'); export default {};` |
| | ) |
| |
|
| | |
| | await session.write( |
| | 'leaf.js', |
| | `log.push('init LeafV1'); export default {};` |
| | ) |
| |
|
| | |
| | await session.evaluate(() => ((window as any).log = [])) |
| | await session.patch( |
| | 'index.js', |
| | `require('./root'); export default function Noop() { return null; };` |
| | ) |
| |
|
| | expect(await session.evaluate(() => (window as any).log)).toEqual([ |
| | 'init LeafV1', |
| | 'init MiddleAV1', |
| | 'init MiddleBV1', |
| | 'init MiddleCV1', |
| | 'init RootV1', |
| | ]) |
| |
|
| | |
| | |
| | await session.evaluate(() => ((window as any).log = [])) |
| | await session.patch( |
| | 'leaf.js', |
| | `log.push('init LeafV2'); export default {};` |
| | ) |
| | expect(await session.evaluate(() => (window as any).log)).toEqual([ |
| | 'init LeafV2', |
| | 'init MiddleAV1', |
| | 'init MiddleBV1', |
| | ]) |
| |
|
| | |
| | await session.evaluate(() => ((window as any).log = [])) |
| | await session.patch( |
| | 'leaf.js', |
| | `log.push('init LeafV3'); export default {};` |
| | ) |
| | expect(await session.evaluate(() => (window as any).log)).toEqual([ |
| | 'init LeafV3', |
| | 'init MiddleAV1', |
| | 'init MiddleBV1', |
| | ]) |
| |
|
| | |
| | await session.evaluate(() => ((window as any).log = [])) |
| | await session.patch( |
| | 'middleB.js', |
| | outdent` |
| | log.push('init MiddleBV2'); |
| | |
| | import './leaf'; |
| | |
| | export default function MiddleB() {}; |
| | ` |
| | ) |
| | expect(await session.evaluate(() => (window as any).log)).toEqual([ |
| | 'init MiddleBV2', |
| | ]) |
| |
|
| | |
| | await session.evaluate(() => ((window as any).log = [])) |
| |
|
| | await session.patch( |
| | 'middleC.js', |
| | `log.push('init MiddleCV2'); export default {};` |
| | ) |
| | expect(await session.evaluate(() => (window as any).log)).toEqual([ |
| | 'init MiddleCV2', |
| | 'init RootV1', |
| | ]) |
| |
|
| | |
| | |
| | |
| | }) |
| |
|
| | |
| | test('runs dependencies before dependents', async () => { |
| | |
| | }) |
| |
|
| | |
| | test('provides fresh value for module.exports in parents', async () => { |
| | |
| | }) |
| |
|
| | |
| | test('provides fresh value for exports.* in parents', async () => { |
| | |
| | }) |
| |
|
| | |
| | test('provides fresh value for ES6 named import in parents', async () => { |
| | |
| | }) |
| |
|
| | |
| | test('provides fresh value for ES6 default import in parents', async () => { |
| | |
| | }) |
| |
|
| | |
| | test('stops update propagation after module-level errors', async () => { |
| | |
| | }) |
| |
|
| | |
| | test('can continue hot updates after module-level errors with module.exports', async () => { |
| | |
| | }) |
| |
|
| | |
| | test('can continue hot updates after module-level errors with ES6 exports', async () => { |
| | |
| | }) |
| |
|
| | |
| | test('does not accumulate stale exports over time', async () => { |
| | |
| | }) |
| |
|
| | |
| | test('bails out if update bubbles to the root via the only path', async () => { |
| | |
| | }) |
| |
|
| | |
| | test('bails out if the update bubbles to the root via one of the paths', async () => { |
| | |
| | }) |
| |
|
| | |
| | |
| | test.skip('propagates a module that stops accepting in next version', async () => { |
| | await using sandbox = await createSandbox(next) |
| | const { session } = sandbox |
| |
|
| | |
| | await session.write( |
| | './foo.js', |
| | `;(typeof global !== 'undefined' ? global : window).log.push('init FooV1'); import './bar'; export default function Foo() {};` |
| | ) |
| | |
| | await session.write( |
| | './bar.js', |
| | `;(typeof global !== 'undefined' ? global : window).log.push('init BarV1'); export default function Bar() {};` |
| | ) |
| |
|
| | |
| | await session.patch( |
| | 'index.js', |
| | `;(typeof global !== 'undefined' ? global : window).log = []; require('./foo'); export default () => null;` |
| | ) |
| | expect(await session.evaluate(() => (window as any).log)).toEqual([ |
| | 'init BarV1', |
| | 'init FooV1', |
| | ]) |
| |
|
| | let didFullRefresh = false |
| | |
| | await session.evaluate(() => ((window as any).log = [])) |
| | didFullRefresh = |
| | didFullRefresh || |
| | !(await session.patch( |
| | './bar.js', |
| | `window.log.push('init BarV1.1'); export default function Bar() {};` |
| | )) |
| | expect(await session.evaluate(() => (window as any).log)).toEqual([ |
| | 'init BarV1.1', |
| | ]) |
| |
|
| | |
| | |
| | await session.evaluate(() => ((window as any).log = [])) |
| | didFullRefresh = |
| | didFullRefresh || |
| | !(await session.patch( |
| | './bar.js', |
| | |
| | |
| | |
| | |
| | |
| | |
| | `window.log.push('init BarV2'); export {};` |
| | )) |
| | |
| | |
| | |
| | expect(await session.evaluate(() => (window as any).log)).toEqual([ |
| | |
| | |
| | |
| | 'init BarV2', |
| | 'init BarV2', |
| | 'init FooV1', |
| | ]) |
| |
|
| | |
| | await session.evaluate(() => ((window as any).log = [])) |
| | didFullRefresh = |
| | didFullRefresh || |
| | !(await session.patch( |
| | './bar.js', |
| | `window.log.push('init BarV2'); export default function Bar() {};` |
| | )) |
| | |
| | |
| | expect(await session.evaluate(() => (window as any).log)).toEqual([ |
| | 'init BarV2', |
| | 'init FooV1', |
| | ]) |
| |
|
| | |
| | |
| |
|
| | |
| | expect(didFullRefresh).toBe(false) |
| |
|
| | |
| | await session.evaluate(() => ((window as any).log = [])) |
| | didFullRefresh = |
| | didFullRefresh || |
| | !(await session.patch( |
| | './bar.js', |
| | `window.log.push('init BarV3'); export default function Bar() {};` |
| | )) |
| | expect(await session.evaluate(() => (window as any).log)).toEqual([ |
| | 'init BarV3', |
| | ]) |
| |
|
| | |
| | |
| | |
| | await session.evaluate(() => window.localStorage.setItem('init', '')) |
| | didFullRefresh = |
| | didFullRefresh || |
| | !(await session.patch( |
| | './foo.js', |
| | ` |
| | if (typeof window !== 'undefined' && window.localStorage) { |
| | window.localStorage.setItem('init', 'init FooV2') |
| | } |
| | export function Foo() {}; |
| | export function FooFoo() {};` |
| | )) |
| |
|
| | |
| | expect( |
| | await session.evaluate(() => window.localStorage.getItem('init')) |
| | ).toEqual('init FooV2') |
| |
|
| | |
| | expect(didFullRefresh).toBe(true) |
| | }) |
| |
|
| | |
| | test('can replace a module before it is loaded', async () => { |
| | |
| | }) |
| | }) |
| |
|