diff options
Diffstat (limited to 'packages/astro/test/astro-sync.test.js')
-rw-r--r-- | packages/astro/test/astro-sync.test.js | 214 |
1 files changed, 131 insertions, 83 deletions
diff --git a/packages/astro/test/astro-sync.test.js b/packages/astro/test/astro-sync.test.js index a92993eae..dfe4755d1 100644 --- a/packages/astro/test/astro-sync.test.js +++ b/packages/astro/test/astro-sync.test.js @@ -1,8 +1,10 @@ +// @ts-check import assert from 'node:assert/strict'; import * as fs from 'node:fs'; -import { before, describe, it } from 'node:test'; +import { beforeEach, describe, it } from 'node:test'; import { fileURLToPath } from 'node:url'; import ts from 'typescript'; +import { normalizePath } from 'vite'; import { loadFixture } from './test-utils.js'; const createFixture = () => { @@ -11,66 +13,79 @@ const createFixture = () => { /** @type {Record<string, string>} */ const writtenFiles = {}; + /** + * @param {string} path + */ + const getExpectedPath = (path) => + normalizePath(fileURLToPath(new URL(path, astroFixture.config.root))); + return { /** @param {string} root */ - async whenSyncing(root) { + async load(root) { astroFixture = await loadFixture({ root }); - - const envPath = new URL('env.d.ts', astroFixture.config.srcDir).href; - const typesDtsPath = new URL('.astro/types.d.ts', astroFixture.config.root).href; - + return astroFixture.config; + }, + clean() { + const envPath = new URL('env.d.ts', astroFixture.config.srcDir); + if (fs.existsSync(envPath)) { + fs.unlinkSync(new URL('env.d.ts', astroFixture.config.srcDir)); + } + fs.rmSync(new URL('./.astro/', astroFixture.config.root), { force: true, recursive: true }); + }, + async whenSyncing() { const fsMock = { ...fs, - existsSync(path, ...args) { - if (path.toString() === envPath) { - return false; - } - if (path.toString() === typesDtsPath) { - return true; - } - return fs.existsSync(path, ...args); - }, + /** + * @param {fs.PathLike} path + * @param {string} contents + */ writeFileSync(path, contents) { writtenFiles[path.toString()] = contents; + return fs.writeFileSync(path, contents); }, promises: { ...fs.promises, - async readFile(path, ...args) { - if (path.toString() === envPath) { - return `/// <reference path="astro/client" />`; - } else { - return fs.promises.readFile(path, ...args); - } - }, - async writeFile(path, contents) { + /** + * @param {fs.PathLike} path + * @param {string} contents + */ + writeFile(path, contents) { writtenFiles[path.toString()] = contents; + return fs.promises.writeFile(path, contents); }, }, }; - await astroFixture.sync({ - inlineConfig: { root: fileURLToPath(new URL(root, import.meta.url)) }, - fs: fsMock, - }); + await astroFixture.sync( + { root: fileURLToPath(astroFixture.config.root) }, + { + // @ts-ignore + fs: fsMock, + }, + ); }, /** @param {string} path */ thenFileShouldExist(path) { - const expectedPath = new URL(path, astroFixture.config.root).href; - assert.equal(writtenFiles.hasOwnProperty(expectedPath), true, `${path} does not exist`); + assert.equal( + writtenFiles.hasOwnProperty(getExpectedPath(path)), + true, + `${path} does not exist`, + ); }, /** * @param {string} path * @param {string} content * @param {string | undefined} error */ - thenFileContentShouldInclude(path, content, error) { - const expectedPath = new URL(path, astroFixture.config.root).href; - assert.equal(writtenFiles[expectedPath].includes(content), true, error); + thenFileContentShouldInclude(path, content, error = undefined) { + assert.equal(writtenFiles[getExpectedPath(path)].includes(content), true, error); }, + /** + * @param {string} path + */ thenFileShouldBeValidTypescript(path) { - const expectedPath = new URL(path, astroFixture.config.root).href; try { - const content = writtenFiles[expectedPath]; + const content = writtenFiles[getExpectedPath(path)]; const result = ts.transpileModule(content, { compilerOptions: { module: ts.ModuleKind.ESNext, @@ -91,33 +106,71 @@ const createFixture = () => { describe('astro sync', () => { /** @type {ReturnType<typeof createFixture>} */ let fixture; - before(async () => { + beforeEach(async () => { fixture = createFixture(); }); - it('Writes `src/env.d.ts` if none exists', async () => { - await fixture.whenSyncing('./fixtures/astro-basic/'); - fixture.thenFileShouldExist('src/env.d.ts'); - fixture.thenFileContentShouldInclude('src/env.d.ts', `/// <reference types="astro/client" />`); + describe('References', () => { + it('Writes `src/env.d.ts` if none exists', async () => { + await fixture.load('./fixtures/astro-basic/'); + fixture.clean(); + await fixture.whenSyncing(); + fixture.thenFileShouldExist('src/env.d.ts'); + fixture.thenFileContentShouldInclude( + 'src/env.d.ts', + `/// <reference path="../.astro/types.d.ts" />`, + ); + }); + + it('Updates `src/env.d.ts` if one exists', async () => { + const config = await fixture.load('./fixtures/astro-basic/'); + fixture.clean(); + fs.writeFileSync(new URL('./env.d.ts', config.srcDir), '// whatever', 'utf-8'); + await fixture.whenSyncing(); + fixture.thenFileShouldExist('src/env.d.ts'); + fixture.thenFileContentShouldInclude( + 'src/env.d.ts', + `/// <reference path="../.astro/types.d.ts" />`, + ); + }); + + it('Writes `src/types.d.ts`', async () => { + await fixture.load('./fixtures/astro-basic/'); + fixture.clean(); + await fixture.whenSyncing(); + fixture.thenFileShouldExist('.astro/types.d.ts'); + fixture.thenFileContentShouldInclude( + '.astro/types.d.ts', + `/// <reference types="astro/client" />`, + ); + }); }); describe('Content collections', () => { - it('Writes types to `.astro`', async () => { - await fixture.whenSyncing('./fixtures/content-collections/'); + it('Adds reference to `.astro/types.d.ts`', async () => { + await fixture.load('./fixtures/content-collections/'); + fixture.clean(); + await fixture.whenSyncing(); fixture.thenFileShouldExist('.astro/types.d.ts'); fixture.thenFileContentShouldInclude( '.astro/types.d.ts', + `/// <reference path="astro/content.d.ts" />`, + ); + fixture.thenFileShouldExist('.astro/astro/content.d.ts'); + fixture.thenFileContentShouldInclude( + '.astro/astro/content.d.ts', `declare module 'astro:content' {`, 'Types file does not include `astro:content` module declaration', ); - fixture.thenFileShouldBeValidTypescript('.astro/types.d.ts'); + fixture.thenFileShouldBeValidTypescript('.astro/astro/content.d.ts'); }); it('Writes types for empty collections', async () => { - await fixture.whenSyncing('./fixtures/content-collections-empty-dir/'); - fixture.thenFileShouldExist('.astro/types.d.ts'); + await fixture.load('./fixtures/content-collections-empty-dir/'); + fixture.clean(); + await fixture.whenSyncing(); fixture.thenFileContentShouldInclude( - '.astro/types.d.ts', + '.astro/astro/content.d.ts', `"blog": Record<string, { id: string; slug: string; @@ -129,7 +182,7 @@ describe('astro sync', () => { 'Types file does not include empty collection type', ); fixture.thenFileContentShouldInclude( - '.astro/types.d.ts', + '.astro/astro/content.d.ts', `"blogMeta": Record<string, { id: string; collection: "blogMeta"; @@ -138,60 +191,55 @@ describe('astro sync', () => { 'Types file does not include empty collection type', ); }); + }); - it('Adds type reference to `src/env.d.ts`', async () => { - await fixture.whenSyncing('./fixtures/content-collections/'); - fixture.thenFileShouldExist('src/env.d.ts'); + describe('astro:env', () => { + it('Adds reference to `.astro/types.d.ts`', async () => { + await fixture.load('./fixtures/astro-env/'); + fixture.clean(); + await fixture.whenSyncing(); + fixture.thenFileShouldExist('.astro/types.d.ts'); fixture.thenFileContentShouldInclude( - 'src/env.d.ts', - `/// <reference path="../.astro/types.d.ts" />`, + '.astro/types.d.ts', + `/// <reference path="astro/env.d.ts" />`, ); - }); - }); - - describe('Astro Env', () => { - it('Writes types to `.astro`', async () => { - await fixture.whenSyncing('./fixtures/astro-env/'); - fixture.thenFileShouldExist('.astro/env.d.ts'); + fixture.thenFileShouldExist('.astro/astro/env.d.ts'); fixture.thenFileContentShouldInclude( - '.astro/env.d.ts', + '.astro/astro/env.d.ts', `declare module 'astro:env/client' {`, 'Types file does not include `astro:env` module declaration', ); }); - it('Adds type reference to `src/env.d.ts`', async () => { - await fixture.whenSyncing('./fixtures/astro-env/'); - fixture.thenFileShouldExist('src/env.d.ts'); - fixture.thenFileContentShouldInclude( - 'src/env.d.ts', - `/// <reference path="../.astro/env.d.ts" />`, - ); - }); - it('Does not throw if a public variable is required', async () => { - let error = null; try { - await fixture.whenSyncing('./fixtures/astro-env-required-public/'); - } catch (e) { - error = e; + await fixture.load('./fixtures/astro-env-required-public/'); + fixture.clean(); + await fixture.whenSyncing(); + assert.ok(true); + } catch { + assert.fail(); } - - assert.equal(error, null, 'Syncing should not throw astro:env validation errors'); }); }); - describe('Astro Actions', () => { - // We can't check for the file existence or content yet because - // it's an integration and does not use the fs mock - - it('Adds type reference to `src/env.d.ts`', async () => { - await fixture.whenSyncing('./fixtures/actions/'); - fixture.thenFileShouldExist('src/env.d.ts'); + describe('astro:actions', () => { + it('Adds reference to `.astro/types.d.ts`', async () => { + await fixture.load('./fixtures/actions/'); + fixture.clean(); + await fixture.whenSyncing(); + fixture.thenFileShouldExist('.astro/types.d.ts'); fixture.thenFileContentShouldInclude( - 'src/env.d.ts', - `/// <reference path="../.astro/actions.d.ts" />`, + '.astro/types.d.ts', + `/// <reference path="astro/actions.d.ts" />`, + ); + fixture.thenFileShouldExist('.astro/astro/actions.d.ts'); + fixture.thenFileContentShouldInclude( + '.astro/astro/actions.d.ts', + `declare module "astro:actions" {`, + 'Types file does not include `astro:actions` module declaration', ); + fixture.thenFileShouldBeValidTypescript('.astro/astro/actions.d.ts'); }); }); }); |