diff --git a/__tests__/e2e/external-data/files.data.ts b/__tests__/e2e/external-data/files.data.ts new file mode 100644 index 000000000..8bd57ee9b --- /dev/null +++ b/__tests__/e2e/external-data/files.data.ts @@ -0,0 +1,10 @@ +import { readFile } from 'node:fs/promises' + +export default { + watch: '../../fixtures/external-data/**/*.json', + async load(files: string[]) { + return Promise.all( + files.map(async (file) => JSON.parse(await readFile(file, 'utf-8'))) + ) + } +} diff --git a/__tests__/e2e/external-data/index.md b/__tests__/e2e/external-data/index.md new file mode 100644 index 000000000..f67a1d8d0 --- /dev/null +++ b/__tests__/e2e/external-data/index.md @@ -0,0 +1,7 @@ + + +# External data + +
{{ JSON.stringify(data) }}
diff --git a/__tests__/e2e/external-data/index.test.ts b/__tests__/e2e/external-data/index.test.ts new file mode 100644 index 000000000..ccd9ba6bd --- /dev/null +++ b/__tests__/e2e/external-data/index.test.ts @@ -0,0 +1,45 @@ +import { mkdir, readFile, rm, writeFile } from 'node:fs/promises' +import path from 'node:path' +import { fileURLToPath } from 'node:url' + +test('loads data outside the site root', async () => { + await goto('/external-data/') + expect(await page.textContent('pre#external-data')).toBe('[{"a":true}]') +}) + +test.runIf(!process.env.VITE_TEST_BUILD)( + 'updates external data when files change, are added, or are deleted', + async () => { + await goto('/external-data/') + const a = fileURLToPath( + new URL('../../fixtures/external-data/a.json', import.meta.url) + ) + const nested = fileURLToPath( + new URL('../../fixtures/external-data/nested/', import.meta.url) + ) + const original = await readFile(a, 'utf-8') + + async function expectData(data: unknown) { + await page.waitForFunction( + (expected) => + document.querySelector('pre#external-data')?.textContent === expected, + JSON.stringify(data) + ) + } + + try { + await writeFile(a, '{"a":false}\n') + await expectData([{ a: false }]) + + await mkdir(nested) + await writeFile(path.join(nested, 'b.json'), '{"b":true}\n') + await expectData([{ a: false }, { b: true }]) + + await rm(nested, { recursive: true }) + await expectData([{ a: false }]) + } finally { + await rm(nested, { recursive: true, force: true }) + await writeFile(a, original) + } + } +) diff --git a/__tests__/fixtures/external-data/a.json b/__tests__/fixtures/external-data/a.json new file mode 100644 index 000000000..ee2441f69 --- /dev/null +++ b/__tests__/fixtures/external-data/a.json @@ -0,0 +1 @@ +{ "a": true } diff --git a/src/node/plugins/staticDataPlugin.ts b/src/node/plugins/staticDataPlugin.ts index 594a473a4..9580eb109 100644 --- a/src/node/plugins/staticDataPlugin.ts +++ b/src/node/plugins/staticDataPlugin.ts @@ -128,6 +128,14 @@ async function loadData(id: string): Promise { watch = normalizeGlob(loaderModule.watch, base) load = loaderModule.load options = loaderModule.options || {} + + // Vite only watches the site root by default. Watch the glob bases too, + // so external files (including newly created ones) can trigger HMR. + server?.watcher.add( + watch + .filter((pattern) => !pattern.startsWith('!')) + .map((pattern) => pm.scan(pattern).base) + ) } // load the data