From 676ba0e3e2dd19aa42e0946b2ff290588bea8cd6 Mon Sep 17 00:00:00 2001 From: Rob Marscher Date: Wed, 2 Oct 2024 13:08:23 -0400 Subject: [PATCH] Improved vitest and importing getInputString --- .../plugins/vite-plugin-fs-router-typegen.ts | 15 ++-- .../vite-plugin-fs-router-typegen.test.ts | 74 ++++++++++++------- 2 files changed, 55 insertions(+), 34 deletions(-) diff --git a/packages/waku/src/lib/plugins/vite-plugin-fs-router-typegen.ts b/packages/waku/src/lib/plugins/vite-plugin-fs-router-typegen.ts index dcbc1fdfb..1c7c4b5b6 100644 --- a/packages/waku/src/lib/plugins/vite-plugin-fs-router-typegen.ts +++ b/packages/waku/src/lib/plugins/vite-plugin-fs-router-typegen.ts @@ -3,17 +3,10 @@ import { readdir, writeFile } from 'node:fs/promises'; import { existsSync, readFileSync } from 'node:fs'; import { SRC_ENTRIES, EXTENSIONS } from '../constants.js'; import { joinPath } from '../utils/path.js'; +import { getInputString } from '../../router/common.js'; const SRC_PAGES = 'pages'; -// from waku/router/common -export function getInputString(path: string): string { - if (!path.startsWith('/')) { - throw new Error('Path should start with `/`'); - } - return path.slice(1); -} - // https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#sec-names-and-keywords // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_words @@ -50,7 +43,11 @@ export function getImportModuleNames(filePaths: string[]): { if (moduleNameCount[identifier]) { identifier = `${identifier}_${moduleNameCount[identifier]}`; } - moduleNames[getInputString(filePath)] = identifier; + try { + moduleNames[getInputString(filePath)] = identifier; + } catch (e) { + console.log(e); + } } return moduleNames; } diff --git a/packages/waku/tests/vite-plugin-fs-router-typegen.test.ts b/packages/waku/tests/vite-plugin-fs-router-typegen.test.ts index 44278cae4..9d02f7c59 100644 --- a/packages/waku/tests/vite-plugin-fs-router-typegen.test.ts +++ b/packages/waku/tests/vite-plugin-fs-router-typegen.test.ts @@ -4,21 +4,30 @@ import { getImportModuleNames, toIdentifier, } from '../src/lib/plugins/vite-plugin-fs-router-typegen.js'; -import { LoggingFunction, RollupLog } from 'rollup'; import { fileURLToPath } from 'node:url'; -import { build, FSWatcher, ViteDevServer } from 'vite'; -import path from 'node:path'; -import { existsSync, readFileSync, rmSync } from 'node:fs'; +import { FSWatcher, ViteDevServer } from 'vite'; +import { writeFile } from 'node:fs/promises'; -const root = fileURLToPath( - new URL('./fixtures', import.meta.url), -); +const root = fileURLToPath(new URL('./fixtures', import.meta.url)); -async function runTest(root: string, expectedEntriesGen: string, srcDir = 'plugin-fs-router-typegen') { - const entriesPath = path.join(root, srcDir, 'entries.gen.tsx'); - if (existsSync(entriesPath)) { - rmSync(entriesPath); - } +vi.mock('prettier', () => { + return { format: (x: string) => x, resolveConfig: () => ({}) }; +}); +vi.mock('node:fs/promises', async (importOriginal) => { + const mod = await importOriginal(); + return { + // https://vitest.dev/api/vi.html#vi-mock + // @ts-expect-error - docs say this should be inferred... + ...mod, + writeFile: vi.fn(), + }; +}); + +async function runTest( + root: string, + expectedEntriesGen: string, + srcDir = 'plugin-fs-router-typegen', +) { const plugin = fsRouterTypegenPlugin({ srcDir, }); @@ -26,20 +35,25 @@ async function runTest(root: string, expectedEntriesGen: string, srcDir = 'plugi expect(typeof plugin.configureServer).toBe('function'); expect(plugin.configResolved).toBeDefined(); expect(typeof plugin.configResolved).toBe('function'); - if (typeof plugin.configureServer !== 'function' || typeof plugin.configResolved !== 'function') { + if ( + typeof plugin.configureServer !== 'function' || + typeof plugin.configResolved !== 'function' + ) { return; } // @ts-expect-error - we're not passing the full Vite config await plugin.configResolved?.({ root }); - await plugin.configureServer?.({ watcher: { add: () => { }, on: () => {} } as unknown as FSWatcher } as ViteDevServer); - const generated = readFileSync(entriesPath, 'utf-8'); - expect(generated).toEqual(expectedEntriesGen); + await plugin.configureServer?.({ + watcher: { add: () => {}, on: () => {} } as unknown as FSWatcher, + } as ViteDevServer); + await vi.waitFor(async () => { + if (vi.mocked(writeFile).mock.lastCall === undefined) { + throw new Error('writeFile not called'); + } + }); + expect(vi.mocked(writeFile).mock.lastCall?.[1]).toContain(expectedEntriesGen); } -vi.mock('prettier', () => { - return { format: (x: string) => x, resolveConfig: () => ({ }) } -}) - describe('vite-plugin-fs-router-typegen', () => { test('generates valid module names for fs entries', async () => { expect(toIdentifier('/_layout.tsx')).toBe('Layout'); @@ -61,14 +75,24 @@ describe('vite-plugin-fs-router-typegen', () => { '/one__two_three.tsx', ]), ).toEqual({ - '/one-two-three.tsx': 'OneTwoThree', - '/one/two/three.tsx': 'OneTwoThree_1', - '/one_two_three.tsx': 'OneTwoThree_2', - '/one__two_three.tsx': 'OneTwoThree_3', + 'one-two-three.tsx': 'OneTwoThree', + 'one/two/three.tsx': 'OneTwoThree_1', + 'one_two_three.tsx': 'OneTwoThree_2', + 'one__two_three.tsx': 'OneTwoThree_3', }); }); test('creates the expected imports the generated entries file', async () => { - await runTest(root, `export * from './_layout';\n`); + await runTest( + root, + `import CategoryTagsIndex, { getConfig as CategoryTagsIndex_getConfig } from './pages/[category]/[...tags]/index'; +import CategoryLayout, { getConfig as CategoryLayout_getConfig } from './pages/[category]/_layout'; +import Layout, { getConfig as Layout_getConfig } from './pages/_layout'; +import Index, { getConfig as Index_getConfig } from './pages/index'; +import OneTwoThree, { getConfig as OneTwoThree_getConfig } from './pages/one-two-three'; +import OneTwoThree_1, { getConfig as OneTwoThree_1_getConfig } from './pages/one__two_three'; +import OneTwoThree_2, { getConfig as OneTwoThree_2_getConfig } from './pages/one_two_three'; +import ØnéTwoThree, { getConfig as ØnéTwoThree_getConfig } from './pages/øné_two_three';`, + ); }); });