diff --git a/packages/playground/assets/__tests__/assets.spec.ts b/packages/playground/assets/__tests__/assets.spec.ts index fd5982b73c05f9..d8d2bc3a2aaff6 100644 --- a/packages/playground/assets/__tests__/assets.spec.ts +++ b/packages/playground/assets/__tests__/assets.spec.ts @@ -1,6 +1,6 @@ import fs from 'fs' import path from 'path' -import { getBg, getColor, browserLogs, isBuild, testDir } from '../../testUtils' +import { getBg, getColor, isBuild, testDir } from '../../testUtils' const assetMatch = isBuild ? /\/foo\/assets\/asset\.\w{8}\.png/ @@ -9,7 +9,7 @@ const assetMatch = isBuild const iconMatch = isBuild ? `/foo/icon.png` : `icon.png` test('should have no 404s', () => { - browserLogs.forEach((msg) => { + pageLogs.forEach((msg) => { expect(msg).not.toMatch('404') }) }) diff --git a/packages/playground/hmr/__tests__/hmr.spec.ts b/packages/playground/hmr/__tests__/hmr.spec.ts new file mode 100644 index 00000000000000..3bd388eb16d2f4 --- /dev/null +++ b/packages/playground/hmr/__tests__/hmr.spec.ts @@ -0,0 +1,113 @@ +import { isBuild, editFile, untilUpdated } from '../../testUtils' + +test('should render', async () => { + expect(await page.textContent('.app')).toBe('1') + expect(await page.textContent('.dep')).toBe('1') + expect(await page.textContent('.nested')).toBe('1') +}) + +if (!isBuild) { + test('should connect', async () => { + expect(pageLogs.length).toBe(2) + expect(pageLogs.some((msg) => msg.match('connected'))).toBe(true) + pageLogs.length = 0 + }) + + test('self accept', async () => { + const el = await page.$('.app') + + editFile('hmr.js', (code) => code.replace('const foo = 1', 'const foo = 2')) + await untilUpdated(() => el.textContent(), '2') + + expect(pageLogs).toMatchObject([ + 'foo was: 1', + '(self-accepting 1) foo is now: 2', + '(self-accepting 2) foo is now: 2', + '[vite] hot updated: /hmr.js' + ]) + pageLogs.length = 0 + + editFile('hmr.js', (code) => code.replace('const foo = 2', 'const foo = 3')) + await untilUpdated(() => el.textContent(), '3') + + expect(pageLogs).toMatchObject([ + 'foo was: 2', + '(self-accepting 1) foo is now: 3', + '(self-accepting 2) foo is now: 3', + '[vite] hot updated: /hmr.js' + ]) + pageLogs.length = 0 + }) + + test('accept dep', async () => { + const el = await page.$('.dep') + + editFile('hmrDep.js', (code) => + code.replace('const foo = 1', 'const foo = 2') + ) + await untilUpdated(() => el.textContent(), '2') + + expect(pageLogs).toMatchObject([ + '(dep) foo was: 1', + '(dep) foo from dispose: 1', + '(single dep) foo is now: 2', + '(single dep) nested foo is now: 1', + '(multi deps) foo is now: 2', + '(multi deps) nested foo is now: 1', + '[vite] hot updated: /hmrDep.js via /hmr.js' + ]) + pageLogs.length = 0 + + editFile('hmrDep.js', (code) => + code.replace('const foo = 2', 'const foo = 3') + ) + await untilUpdated(() => el.textContent(), '3') + + expect(pageLogs).toMatchObject([ + '(dep) foo was: 2', + '(dep) foo from dispose: 2', + '(single dep) foo is now: 3', + '(single dep) nested foo is now: 1', + '(multi deps) foo is now: 3', + '(multi deps) nested foo is now: 1', + '[vite] hot updated: /hmrDep.js via /hmr.js' + ]) + pageLogs.length = 0 + }) + + test('nested dep propagation', async () => { + const el = await page.$('.nested') + + editFile('hmrNestedDep.js', (code) => + code.replace('const foo = 1', 'const foo = 2') + ) + await untilUpdated(() => el.textContent(), '2') + + expect(pageLogs).toMatchObject([ + '(dep) foo was: 3', + '(dep) foo from dispose: 3', + '(single dep) foo is now: 3', + '(single dep) nested foo is now: 2', + '(multi deps) foo is now: 3', + '(multi deps) nested foo is now: 2', + '[vite] hot updated: /hmrDep.js via /hmr.js' + ]) + pageLogs.length = 0 + + editFile('hmrNestedDep.js', (code) => + code.replace('const foo = 2', 'const foo = 3') + ) + await untilUpdated(() => el.textContent(), '3') + + expect(pageLogs).toMatchObject([ + '(dep) foo was: 3', + '(dep) foo from dispose: 3', + '(single dep) foo is now: 3', + '(single dep) nested foo is now: 3', + '(multi deps) foo is now: 3', + '(multi deps) nested foo is now: 3', + '[vite] hot updated: /hmrDep.js via /hmr.js' + ]) + pageLogs.length = 0 + }) +} diff --git a/packages/playground/hmr/hmr.js b/packages/playground/hmr/hmr.js index 2ff3b070d37f1f..0e470c74e27c27 100644 --- a/packages/playground/hmr/hmr.js +++ b/packages/playground/hmr/hmr.js @@ -1,26 +1,39 @@ -import './hmrDep.js' -import './style.css' +import { foo as depFoo, nestedFoo } from './hmrDep' -export const foo = 222233 +export const foo = 1 +text('.app', foo) +text('.dep', depFoo) +text('.nested', nestedFoo) if (import.meta.hot) { import.meta.hot.accept(({ foo }) => { - console.log('(self-accepting)1.foo is now:', foo) + console.log('(self-accepting 1) foo is now:', foo) }) import.meta.hot.accept(({ foo }) => { - console.log('(self-accepting)2.foo is now:', foo) + console.log('(self-accepting 2) foo is now:', foo) }) - import.meta.hot.accept('./hmrDep', ({ foo }) => { - console.log('(single dep) foo is now:', foo) + const handleDep = (type, newFoo, newNestedFoo) => { + console.log(`(${type}) foo is now: ${newFoo}`) + console.log(`(${type}) nested foo is now: ${newNestedFoo}`) + text('.dep', newFoo) + text('.nested', newNestedFoo) + } + + import.meta.hot.accept('./hmrDep', ({ foo, nestedFoo }) => { + handleDep('single dep', foo, nestedFoo) }) - import.meta.hot.accept(['./hmrDep'], (modules) => { - console.log('(multiple deps) foo is now:', modules[0].foo) + import.meta.hot.accept(['./hmrDep'], ([{ foo, nestedFoo }]) => { + handleDep('multi deps', foo, nestedFoo) }) import.meta.hot.dispose(() => { console.log(`foo was:`, foo) }) } + +function text(el, text) { + document.querySelector(el).textContent = text +} diff --git a/packages/playground/hmr/hmrDep.js b/packages/playground/hmr/hmrDep.js index c249a0cbf94ecc..9142a6c87cabf3 100644 --- a/packages/playground/hmr/hmrDep.js +++ b/packages/playground/hmr/hmrDep.js @@ -1,6 +1,5 @@ -import './hmrNestedDep' - -export const foo = 'from depppp' +export const foo = 1 +export { foo as nestedFoo } from './hmrNestedDep' if (import.meta.hot) { const data = import.meta.hot.data @@ -10,6 +9,6 @@ if (import.meta.hot) { import.meta.hot.dispose((data) => { console.log(`(dep) foo was: ${foo}`) - data.fromDispose = foo * 1033 + data.fromDispose = foo }) } diff --git a/packages/playground/hmr/hmrNestedDep.js b/packages/playground/hmr/hmrNestedDep.js index 7972d09effb427..766766a6260612 100644 --- a/packages/playground/hmr/hmrNestedDep.js +++ b/packages/playground/hmr/hmrNestedDep.js @@ -1 +1 @@ -console.log('I should log?') +export const foo = 1 diff --git a/packages/playground/hmr/index.html b/packages/playground/hmr/index.html new file mode 100644 index 00000000000000..3a421c5bba15e5 --- /dev/null +++ b/packages/playground/hmr/index.html @@ -0,0 +1,5 @@ + + +
+ + \ No newline at end of file diff --git a/packages/playground/hmr/package.json b/packages/playground/hmr/package.json new file mode 100644 index 00000000000000..97fb6577fb4d28 --- /dev/null +++ b/packages/playground/hmr/package.json @@ -0,0 +1,10 @@ +{ + "name": "test-hmr", + "private": true, + "version": "0.0.0", + "scripts": { + "dev": "vite", + "build": "vite build", + "debug": "node --inspect-brk ../../vite/bin/vite" + } +} diff --git a/packages/playground/testEnv.d.ts b/packages/playground/testEnv.d.ts index ebc9910e6fc953..d0f1cc057508fa 100644 --- a/packages/playground/testEnv.d.ts +++ b/packages/playground/testEnv.d.ts @@ -3,5 +3,6 @@ import { Page } from 'playwright-chromium' declare global { // injected by the custom jest env in scripts/jestEnv.js const page: Page + const pageLogs: string[] const __viteTestDir__: string } diff --git a/packages/playground/testUtils.ts b/packages/playground/testUtils.ts index f079546325a773..9210c126b39958 100644 --- a/packages/playground/testUtils.ts +++ b/packages/playground/testUtils.ts @@ -8,14 +8,6 @@ import slash from 'slash' import colors from 'css-color-names' import { ElementHandle } from 'playwright-chromium' -export const browserLogs = [] - -beforeAll(() => { - page.on('console', (msg) => { - browserLogs.push(msg.text()) - }) -}) - export const isBuild = !!process.env.VITE_TEST_BUILD const testPath = expect.getState().testPath @@ -79,7 +71,7 @@ export function editFile(filename: string, replacer: (str: string) => string) { * Poll a getter until the value it returns includes the expected value. */ export async function untilUpdated( - poll: () => Promise