diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index f92512bc8..404f42d3a 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -97,4 +97,4 @@ jobs: run: pnpm install --frozen-lockfile - name: Test - run: pnpm run test-ci + run: pnpm run test-scaffold && pnpm run test-ci diff --git a/.gitignore b/.gitignore index 9b5f3d7c8..307f58a86 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ dist .npmcache coverage .build +.test diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f1f733983..97319e08c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,6 +35,14 @@ I want to think you first for considering contributing to ZenStack 🙏🏻. It' pnpm build ``` +1. Scaffold the project used for testing + + ```bash + pnpm test-scaffold + ``` + + You only need to run this command once. + 1. Run tests ```bash diff --git a/jest.config.ts b/jest.config.ts index 917cf52f6..222e6fb2c 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -3,15 +3,19 @@ * https://jestjs.io/docs/configuration */ +import path from 'path'; + export default { // Automatically clear mock calls, instances, contexts and results before every test clearMocks: true, + globalSetup: path.join(__dirname, './test-setup.ts'), + // Indicates whether the coverage information should be collected while executing the test collectCoverage: true, // The directory where Jest should output its coverage files - coverageDirectory: 'tests/coverage', + coverageDirectory: path.join(__dirname, '.test/coverage'), // An array of regexp pattern strings used to skip coverage collection coveragePathIgnorePatterns: ['/node_modules/', '/tests/'], diff --git a/package.json b/package.json index 2d2d2e264..42168988a 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,9 @@ "scripts": { "build": "pnpm -r build", "lint": "pnpm -r lint", - "test": "ZENSTACK_TEST=1 pnpm -r run test --silent --forceExit", - "test-ci": "ZENSTACK_TEST=1 pnpm -r run test --silent --forceExit", + "test": "ZENSTACK_TEST=1 pnpm -r --parallel run test --silent --forceExit", + "test-ci": "ZENSTACK_TEST=1 pnpm -r --parallel run test --silent --forceExit", + "test-scaffold": "tsx script/test-scaffold.ts", "publish-all": "pnpm --filter \"./packages/**\" -r publish --access public", "publish-preview": "pnpm --filter \"./packages/**\" -r publish --force --registry https://preview.registry.zenstack.dev/", "unpublish-preview": "pnpm --recursive --shell-mode exec -- npm unpublish -f --registry https://preview.registry.zenstack.dev/ \"\\$PNPM_PACKAGE_NAME\"" @@ -30,6 +31,7 @@ "ts-jest": "^29.1.1", "ts-node": "^10.9.1", "tsup": "^8.0.1", + "tsx": "^4.7.1", "typescript": "^5.3.2" } } diff --git a/packages/testtools/package.json b/packages/testtools/package.json index 0aafe452e..38198a59e 100644 --- a/packages/testtools/package.json +++ b/packages/testtools/package.json @@ -11,7 +11,7 @@ "scripts": { "clean": "rimraf dist", "lint": "eslint src --ext ts", - "build": "pnpm lint && pnpm clean && tsc && copyfiles ./package.json ./LICENSE ./README.md dist && copyfiles -u 1 src/package.template.json src/.npmrc.template dist && pnpm pack dist --pack-destination '../../../.build'", + "build": "pnpm lint && pnpm clean && tsc && copyfiles ./package.json ./LICENSE ./README.md dist && pnpm pack dist --pack-destination '../../../.build'", "watch": "tsc --watch", "prepublishOnly": "pnpm build" }, diff --git a/packages/testtools/src/.npmrc.template b/packages/testtools/src/.npmrc.template deleted file mode 100644 index 14f2c2865..000000000 --- a/packages/testtools/src/.npmrc.template +++ /dev/null @@ -1 +0,0 @@ -cache=/.npmcache diff --git a/packages/testtools/src/package.template.json b/packages/testtools/src/package.template.json deleted file mode 100644 index 8ea542361..000000000 --- a/packages/testtools/src/package.template.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "test-run", - "version": "1.0.0", - "description": "", - "main": "index.js", - "keywords": [], - "author": "", - "license": "ISC", - "dependencies": { - "@prisma/client": "^4.8.0", - "@zenstackhq/runtime": "file:/packages/runtime/dist", - "@zenstackhq/swr": "file:/packages/plugins/swr/dist", - "@zenstackhq/trpc": "file:/packages/plugins/trpc/dist", - "@zenstackhq/openapi": "file:/packages/plugins/openapi/dist", - "prisma": "^4.8.0", - "typescript": "^4.9.3", - "zenstack": "file:/packages/schema/dist", - "zod": "^3.22.4", - "decimal.js": "^10.4.2" - } -} diff --git a/packages/testtools/src/schema.ts b/packages/testtools/src/schema.ts index f69a845cc..c570c6a30 100644 --- a/packages/testtools/src/schema.ts +++ b/packages/testtools/src/schema.ts @@ -35,14 +35,23 @@ export type FullDbClientContract = Record & { }; export function run(cmd: string, env?: Record, cwd?: string) { - const start = Date.now(); - execSync(cmd, { - stdio: 'pipe', - encoding: 'utf-8', - env: { ...process.env, DO_NOT_TRACK: '1', ...env }, - cwd, - }); - console.log('Execution took', Date.now() - start, 'ms', '-', cmd); + try { + const start = Date.now(); + execSync(cmd, { + stdio: 'pipe', + encoding: 'utf-8', + env: { ...process.env, DO_NOT_TRACK: '1', ...env }, + cwd, + }); + console.log('Execution took', Date.now() - start, 'ms', '-', cmd); + } catch (err) { + console.error('Command failed:', cmd, err); + throw err; + } +} + +export function installPackage(pkg: string, dev = false) { + run(`npm install ${dev ? '-D' : ''} --no-audit --no-fund ${pkg}`); } function normalizePath(p: string) { @@ -86,17 +95,17 @@ generator js { plugin meta { provider = '@core/model-meta' - preserveTsFiles = true + // preserveTsFiles = true } plugin policy { provider = '@core/access-policy' - preserveTsFiles = true + // preserveTsFiles = true } plugin zod { provider = '@core/zod' - preserveTsFiles = true + // preserveTsFiles = true modelOnly = ${!options.fullZod} } `; @@ -138,21 +147,29 @@ export async function loadSchema(schema: string, options?: SchemaLoadOptions) { const { name: projectRoot } = tmp.dirSync({ unsafeCleanup: true }); - const root = getWorkspaceRoot(__dirname); + const workspaceRoot = getWorkspaceRoot(__dirname); - if (!root) { + if (!workspaceRoot) { throw new Error('Could not find workspace root'); } - const pkgContent = fs.readFileSync(path.join(__dirname, 'package.template.json'), { encoding: 'utf-8' }); - fs.writeFileSync(path.join(projectRoot, 'package.json'), pkgContent.replaceAll('', root)); - - const npmrcContent = fs.readFileSync(path.join(__dirname, '.npmrc.template'), { encoding: 'utf-8' }); - fs.writeFileSync(path.join(projectRoot, '.npmrc'), npmrcContent.replaceAll('', root)); - console.log('Workdir:', projectRoot); process.chdir(projectRoot); + // copy project structure from scaffold (prepared by test-setup.ts) + fs.cpSync(path.join(workspaceRoot, '.test/scaffold'), projectRoot, { recursive: true, force: true }); + + // install local deps + const localInstallDeps = [ + 'packages/schema/dist', + 'packages/runtime/dist', + 'packages/plugins/swr/dist', + 'packages/plugins/trpc/dist', + 'packages/plugins/openapi/dist', + ]; + + run(`npm i --no-audit --no-fund ${localInstallDeps.map((d) => path.join(workspaceRoot, d)).join(' ')}`); + let zmodelPath = path.join(projectRoot, 'schema.zmodel'); const files = schema.split(FILE_SPLITTER); @@ -189,16 +206,16 @@ export async function loadSchema(schema: string, options?: SchemaLoadOptions) { } } - run('npm install'); - const outputArg = opt.output ? ` --output ${opt.output}` : ''; if (opt.customSchemaFilePath) { - run(`npx zenstack generate --schema ${zmodelPath} --no-dependency-check${outputArg}`, { + run(`npx zenstack generate --no-version-check --schema ${zmodelPath} --no-dependency-check${outputArg}`, { NODE_PATH: './node_modules', }); } else { - run(`npx zenstack generate --no-dependency-check${outputArg}`, { NODE_PATH: './node_modules' }); + run(`npx zenstack generate --no-version-check --no-dependency-check${outputArg}`, { + NODE_PATH: './node_modules', + }); } if (opt.pushDb) { @@ -209,10 +226,10 @@ export async function loadSchema(schema: string, options?: SchemaLoadOptions) { opt.extraDependencies?.push('@prisma/extension-pulse'); } - opt.extraDependencies?.forEach((dep) => { - console.log(`Installing dependency ${dep}`); - run(`npm install ${dep}`); - }); + if (opt.extraDependencies) { + console.log(`Installing dependency ${opt.extraDependencies.join(' ')}`); + installPackage(opt.extraDependencies.join(' ')); + } opt.copyDependencies?.forEach((dep) => { const pkgJson = JSON.parse(fs.readFileSync(path.join(dep, 'package.json'), { encoding: 'utf-8' })); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9dcef261b..b432b95c7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,6 +53,9 @@ importers: tsup: specifier: ^8.0.1 version: 8.0.1(ts-node@10.9.1)(typescript@5.3.2) + tsx: + specifier: ^4.7.1 + version: 4.7.1 typescript: specifier: ^5.3.2 version: 5.3.2 @@ -1594,6 +1597,15 @@ packages: tslib: 2.6.0 dev: true + /@esbuild/aix-ppc64@0.19.12: + resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-arm64@0.17.19: resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==} engines: {node: '>=12'} @@ -1612,6 +1624,15 @@ packages: dev: true optional: true + /@esbuild/android-arm64@0.19.12: + resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-arm64@0.19.4: resolution: {integrity: sha512-mRsi2vJsk4Bx/AFsNBqOH2fqedxn5L/moT58xgg51DjX1la64Z3Npicut2VbhvDFO26qjWtPMsVxCd80YTFVeg==} engines: {node: '>=12'} @@ -1648,6 +1669,15 @@ packages: dev: true optional: true + /@esbuild/android-arm@0.19.12: + resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-arm@0.19.4: resolution: {integrity: sha512-uBIbiYMeSsy2U0XQoOGVVcpIktjLMEKa7ryz2RLr7L/vTnANNEsPVAh4xOv7ondGz6ac1zVb0F8Jx20rQikffQ==} engines: {node: '>=12'} @@ -1675,6 +1705,15 @@ packages: dev: true optional: true + /@esbuild/android-x64@0.19.12: + resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-x64@0.19.4: resolution: {integrity: sha512-4iPufZ1TMOD3oBlGFqHXBpa3KFT46aLl6Vy7gwed0ZSYgHaZ/mihbYb4t7Z9etjkC9Al3ZYIoOaHrU60gcMy7g==} engines: {node: '>=12'} @@ -1702,6 +1741,15 @@ packages: dev: true optional: true + /@esbuild/darwin-arm64@0.19.12: + resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@esbuild/darwin-arm64@0.19.4: resolution: {integrity: sha512-Lviw8EzxsVQKpbS+rSt6/6zjn9ashUZ7Tbuvc2YENgRl0yZTktGlachZ9KMJUsVjZEGFVu336kl5lBgDN6PmpA==} engines: {node: '>=12'} @@ -1729,6 +1777,15 @@ packages: dev: true optional: true + /@esbuild/darwin-x64@0.19.12: + resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@esbuild/darwin-x64@0.19.4: resolution: {integrity: sha512-YHbSFlLgDwglFn0lAO3Zsdrife9jcQXQhgRp77YiTDja23FrC2uwnhXMNkAucthsf+Psr7sTwYEryxz6FPAVqw==} engines: {node: '>=12'} @@ -1756,6 +1813,15 @@ packages: dev: true optional: true + /@esbuild/freebsd-arm64@0.19.12: + resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/freebsd-arm64@0.19.4: resolution: {integrity: sha512-vz59ijyrTG22Hshaj620e5yhs2dU1WJy723ofc+KUgxVCM6zxQESmWdMuVmUzxtGqtj5heHyB44PjV/HKsEmuQ==} engines: {node: '>=12'} @@ -1783,6 +1849,15 @@ packages: dev: true optional: true + /@esbuild/freebsd-x64@0.19.12: + resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/freebsd-x64@0.19.4: resolution: {integrity: sha512-3sRbQ6W5kAiVQRBWREGJNd1YE7OgzS0AmOGjDmX/qZZecq8NFlQsQH0IfXjjmD0XtUYqr64e0EKNFjMUlPL3Cw==} engines: {node: '>=12'} @@ -1810,6 +1885,15 @@ packages: dev: true optional: true + /@esbuild/linux-arm64@0.19.12: + resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-arm64@0.19.4: resolution: {integrity: sha512-ZWmWORaPbsPwmyu7eIEATFlaqm0QGt+joRE9sKcnVUG3oBbr/KYdNE2TnkzdQwX6EDRdg/x8Q4EZQTXoClUqqA==} engines: {node: '>=12'} @@ -1837,6 +1921,15 @@ packages: dev: true optional: true + /@esbuild/linux-arm@0.19.12: + resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-arm@0.19.4: resolution: {integrity: sha512-z/4ArqOo9EImzTi4b6Vq+pthLnepFzJ92BnofU1jgNlcVb+UqynVFdoXMCFreTK7FdhqAzH0vmdwW5373Hm9pg==} engines: {node: '>=12'} @@ -1864,6 +1957,15 @@ packages: dev: true optional: true + /@esbuild/linux-ia32@0.19.12: + resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-ia32@0.19.4: resolution: {integrity: sha512-EGc4vYM7i1GRUIMqRZNCTzJh25MHePYsnQfKDexD8uPTCm9mK56NIL04LUfX2aaJ+C9vyEp2fJ7jbqFEYgO9lQ==} engines: {node: '>=12'} @@ -1900,6 +2002,15 @@ packages: dev: true optional: true + /@esbuild/linux-loong64@0.19.12: + resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-loong64@0.19.4: resolution: {integrity: sha512-WVhIKO26kmm8lPmNrUikxSpXcgd6HDog0cx12BUfA2PkmURHSgx9G6vA19lrlQOMw+UjMZ+l3PpbtzffCxFDRg==} engines: {node: '>=12'} @@ -1927,6 +2038,15 @@ packages: dev: true optional: true + /@esbuild/linux-mips64el@0.19.12: + resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-mips64el@0.19.4: resolution: {integrity: sha512-keYY+Hlj5w86hNp5JJPuZNbvW4jql7c1eXdBUHIJGTeN/+0QFutU3GrS+c27L+NTmzi73yhtojHk+lr2+502Mw==} engines: {node: '>=12'} @@ -1954,6 +2074,15 @@ packages: dev: true optional: true + /@esbuild/linux-ppc64@0.19.12: + resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-ppc64@0.19.4: resolution: {integrity: sha512-tQ92n0WMXyEsCH4m32S21fND8VxNiVazUbU4IUGVXQpWiaAxOBvtOtbEt3cXIV3GEBydYsY8pyeRMJx9kn3rvw==} engines: {node: '>=12'} @@ -1981,6 +2110,15 @@ packages: dev: true optional: true + /@esbuild/linux-riscv64@0.19.12: + resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-riscv64@0.19.4: resolution: {integrity: sha512-tRRBey6fG9tqGH6V75xH3lFPpj9E8BH+N+zjSUCnFOX93kEzqS0WdyJHkta/mmJHn7MBaa++9P4ARiU4ykjhig==} engines: {node: '>=12'} @@ -2008,6 +2146,15 @@ packages: dev: true optional: true + /@esbuild/linux-s390x@0.19.12: + resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-s390x@0.19.4: resolution: {integrity: sha512-152aLpQqKZYhThiJ+uAM4PcuLCAOxDsCekIbnGzPKVBRUDlgaaAfaUl5NYkB1hgY6WN4sPkejxKlANgVcGl9Qg==} engines: {node: '>=12'} @@ -2035,6 +2182,15 @@ packages: dev: true optional: true + /@esbuild/linux-x64@0.19.12: + resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-x64@0.19.4: resolution: {integrity: sha512-Mi4aNA3rz1BNFtB7aGadMD0MavmzuuXNTaYL6/uiYIs08U7YMPETpgNn5oue3ICr+inKwItOwSsJDYkrE9ekVg==} engines: {node: '>=12'} @@ -2062,6 +2218,15 @@ packages: dev: true optional: true + /@esbuild/netbsd-x64@0.19.12: + resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/netbsd-x64@0.19.4: resolution: {integrity: sha512-9+Wxx1i5N/CYo505CTT7T+ix4lVzEdz0uCoYGxM5JDVlP2YdDC1Bdz+Khv6IbqmisT0Si928eAxbmGkcbiuM/A==} engines: {node: '>=12'} @@ -2089,6 +2254,15 @@ packages: dev: true optional: true + /@esbuild/openbsd-x64@0.19.12: + resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/openbsd-x64@0.19.4: resolution: {integrity: sha512-MFsHleM5/rWRW9EivFssop+OulYVUoVcqkyOkjiynKBCGBj9Lihl7kh9IzrreDyXa4sNkquei5/DTP4uCk25xw==} engines: {node: '>=12'} @@ -2116,6 +2290,15 @@ packages: dev: true optional: true + /@esbuild/sunos-x64@0.19.12: + resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + /@esbuild/sunos-x64@0.19.4: resolution: {integrity: sha512-6Xq8SpK46yLvrGxjp6HftkDwPP49puU4OF0hEL4dTxqCbfx09LyrbUj/D7tmIRMj5D5FCUPksBbxyQhp8tmHzw==} engines: {node: '>=12'} @@ -2143,6 +2326,15 @@ packages: dev: true optional: true + /@esbuild/win32-arm64@0.19.12: + resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-arm64@0.19.4: resolution: {integrity: sha512-PkIl7Jq4mP6ke7QKwyg4fD4Xvn8PXisagV/+HntWoDEdmerB2LTukRZg728Yd1Fj+LuEX75t/hKXE2Ppk8Hh1w==} engines: {node: '>=12'} @@ -2170,6 +2362,15 @@ packages: dev: true optional: true + /@esbuild/win32-ia32@0.19.12: + resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-ia32@0.19.4: resolution: {integrity: sha512-ga676Hnvw7/ycdKB53qPusvsKdwrWzEyJ+AtItHGoARszIqvjffTwaaW3b2L6l90i7MO9i+dlAW415INuRhSGg==} engines: {node: '>=12'} @@ -2197,6 +2398,15 @@ packages: dev: true optional: true + /@esbuild/win32-x64@0.19.12: + resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + /@esbuild/win32-x64@0.19.4: resolution: {integrity: sha512-HP0GDNla1T3ZL8Ko/SHAS2GgtjOg+VmWnnYLhuTksr++EnduYB0f3Y2LzHsUwb2iQ13JGoY6G3R8h6Du/WG6uA==} engines: {node: '>=12'} @@ -7770,6 +7980,37 @@ packages: '@esbuild/win32-x64': 0.18.14 dev: true + /esbuild@0.19.12: + resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.19.12 + '@esbuild/android-arm': 0.19.12 + '@esbuild/android-arm64': 0.19.12 + '@esbuild/android-x64': 0.19.12 + '@esbuild/darwin-arm64': 0.19.12 + '@esbuild/darwin-x64': 0.19.12 + '@esbuild/freebsd-arm64': 0.19.12 + '@esbuild/freebsd-x64': 0.19.12 + '@esbuild/linux-arm': 0.19.12 + '@esbuild/linux-arm64': 0.19.12 + '@esbuild/linux-ia32': 0.19.12 + '@esbuild/linux-loong64': 0.19.12 + '@esbuild/linux-mips64el': 0.19.12 + '@esbuild/linux-ppc64': 0.19.12 + '@esbuild/linux-riscv64': 0.19.12 + '@esbuild/linux-s390x': 0.19.12 + '@esbuild/linux-x64': 0.19.12 + '@esbuild/netbsd-x64': 0.19.12 + '@esbuild/openbsd-x64': 0.19.12 + '@esbuild/sunos-x64': 0.19.12 + '@esbuild/win32-arm64': 0.19.12 + '@esbuild/win32-ia32': 0.19.12 + '@esbuild/win32-x64': 0.19.12 + dev: true + /esbuild@0.19.4: resolution: {integrity: sha512-x7jL0tbRRpv4QUyuDMjONtWFciygUxWaUM1kMX2zWxI0X2YWOt7MSA0g4UdeSiHM8fcYVzpQhKYOycZwxTdZkA==} engines: {node: '>=12'} @@ -8597,6 +8838,12 @@ packages: get-intrinsic: 1.2.1 dev: true + /get-tsconfig@4.7.2: + resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} + dependencies: + resolve-pkg-maps: 1.0.0 + dev: true + /giget@1.1.3: resolution: {integrity: sha512-zHuCeqtfgqgDwvXlR84UNgnJDuUHQcNI5OqWqFxxuk2BshuKbYhJWdxBsEo4PvKqoGh23lUAIvBNpChMLv7/9Q==} hasBin: true @@ -12958,6 +13205,10 @@ packages: engines: {node: '>=8'} dev: true + /resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + dev: true + /resolve.exports@2.0.2: resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} engines: {node: '>=10'} @@ -14255,6 +14506,17 @@ packages: typescript: 5.3.2 dev: true + /tsx@4.7.1: + resolution: {integrity: sha512-8d6VuibXHtlN5E3zFkgY8u4DX7Y3Z27zvvPKVmLon/D4AjuKzarkUBTLDBgj9iTQ0hg5xM7c/mYiRVM+HETf0g==} + engines: {node: '>=18.0.0'} + hasBin: true + dependencies: + esbuild: 0.19.12 + get-tsconfig: 4.7.2 + optionalDependencies: + fsevents: 2.3.3 + dev: true + /tty-table@4.2.1: resolution: {integrity: sha512-xz0uKo+KakCQ+Dxj1D/tKn2FSyreSYWzdkL/BYhgN6oMW808g8QRMuh1atAV9fjTPbWBjfbkKQpI/5rEcnAc7g==} engines: {node: '>=8.0.0'} diff --git a/script/test-scaffold.ts b/script/test-scaffold.ts new file mode 100644 index 000000000..ddf3c999a --- /dev/null +++ b/script/test-scaffold.ts @@ -0,0 +1,24 @@ +import path from 'path'; +import fs from 'fs'; +import { execSync } from 'child_process'; + +const scaffoldPath = path.join(__dirname, '../.test/scaffold'); +if (fs.existsSync(scaffoldPath)) { + fs.rmSync(scaffoldPath, { recursive: true, force: true }); +} +fs.mkdirSync(scaffoldPath, { recursive: true }); + +function run(cmd: string) { + console.log(`Running: ${cmd}, in ${scaffoldPath}`); + try { + execSync(cmd, { cwd: scaffoldPath, stdio: 'ignore' }); + } catch (err) { + console.error(`Test project scaffolding cmd error: ${err}`); + throw err; + } +} + +run('npm init -y'); +run('npm i --no-audit --no-fund typescript prisma @prisma/client zod decimal.js'); + +console.log('Test scaffold setup complete.'); diff --git a/test-setup.ts b/test-setup.ts new file mode 100644 index 000000000..9856ff4b5 --- /dev/null +++ b/test-setup.ts @@ -0,0 +1,9 @@ +import fs from 'fs'; +import path from 'path'; + +export default function globalSetup() { + if (!fs.existsSync(path.join(__dirname, '.test/scaffold/package-lock.json'))) { + console.error(`Test scaffold not found. Please run \`pnpm test-scaffold\` first.`); + process.exit(1); + } +} diff --git a/tests/integration/global-setup.js b/tests/integration/global-setup.js deleted file mode 100644 index 0d4b8e23e..000000000 --- a/tests/integration/global-setup.js +++ /dev/null @@ -1,10 +0,0 @@ -const { execSync } = require('child_process'); - -module.exports = function () { - console.log('npm install'); - execSync('npm install', { - encoding: 'utf-8', - stdio: 'inherit', - cwd: 'test-run', - }); -}; diff --git a/tests/integration/jest.config.ts b/tests/integration/jest.config.ts index 346f6faad..67a118269 100644 --- a/tests/integration/jest.config.ts +++ b/tests/integration/jest.config.ts @@ -1,30 +1,10 @@ +import baseConfig from '../../jest.config'; + /* * For a detailed explanation regarding each configuration property and type check, visit: * https://jestjs.io/docs/configuration */ export default { - // Automatically clear mock calls, instances, contexts and results before every test - clearMocks: true, - - // A map from regular expressions to paths to transformers - transform: { '^.+\\.tsx?$': 'ts-jest' }, - - testTimeout: 300000, - + ...baseConfig, setupFilesAfterEnv: ['./test-setup.ts'], - - // Indicates whether the coverage information should be collected while executing the test - collectCoverage: true, - - // The directory where Jest should output its coverage files - coverageDirectory: 'tests/coverage', - - // An array of regexp pattern strings used to skip coverage collection - coveragePathIgnorePatterns: ['/node_modules/', '/tests/'], - - // Indicates which provider should be used to instrument code for coverage - coverageProvider: 'v8', - - // A list of reporter names that Jest uses when writing coverage reports - coverageReporters: ['json', 'text', 'lcov', 'clover'], }; diff --git a/tests/integration/tests/cli/generate.test.ts b/tests/integration/tests/cli/generate.test.ts index 0367033bd..90f9e2311 100644 --- a/tests/integration/tests/cli/generate.test.ts +++ b/tests/integration/tests/cli/generate.test.ts @@ -1,11 +1,11 @@ /* eslint-disable @typescript-eslint/no-var-requires */ /// +import { installPackage } from '@zenstackhq/testtools'; import * as fs from 'fs'; import path from 'path'; import * as tmp from 'tmp'; import { createProgram } from '../../../../packages/schema/src/cli'; -import { execSync } from '../../../../packages/schema/src/utils/exec-utils'; import { createNpmrc } from './share'; describe('CLI generate command tests', () => { @@ -43,8 +43,8 @@ model Post { // set up project fs.writeFileSync('package.json', JSON.stringify({ name: 'my app', version: '1.0.0' })); createNpmrc(); - execSync('npm install prisma @prisma/client zod'); - execSync(`npm install ${path.join(__dirname, '../../../../packages/runtime/dist')}`); + installPackage('prisma @prisma/client zod'); + installPackage(path.join(__dirname, '../../../../packages/runtime/dist')); // set up schema fs.writeFileSync('schema.zmodel', MODEL, 'utf-8'); diff --git a/tests/integration/tests/cli/plugins.test.ts b/tests/integration/tests/cli/plugins.test.ts index 005a0f69b..716ac224e 100644 --- a/tests/integration/tests/cli/plugins.test.ts +++ b/tests/integration/tests/cli/plugins.test.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-var-requires */ /// -import { getWorkspaceNpmCacheFolder, run } from '@zenstackhq/testtools'; +import { getWorkspaceNpmCacheFolder, installPackage, run } from '@zenstackhq/testtools'; import * as fs from 'fs'; import * as path from 'path'; import * as tmp from 'tmp'; @@ -94,8 +94,8 @@ describe('CLI Plugins Tests', () => { switch (pm) { case 'npm': - run('npm install ' + deps); - run('npm install -D ' + devDeps); + installPackage(deps); + installPackage(devDeps, true); break; // case 'yarn': // run('yarn add ' + deps); diff --git a/tests/integration/tests/schema/todo.zmodel b/tests/integration/tests/schema/todo.zmodel index 733391bd1..079e3b1ef 100644 --- a/tests/integration/tests/schema/todo.zmodel +++ b/tests/integration/tests/schema/todo.zmodel @@ -14,7 +14,7 @@ generator js { plugin zod { provider = '@core/zod' - preserveTsFiles = true + // preserveTsFiles = true } /*