From b4da17ccd0baf41eba44024b6a9cc7a4c78e9bea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1ximo=20Mussini?= Date: Wed, 12 Jan 2022 15:48:11 -0300 Subject: [PATCH] test: add test coverage for `resolveViteBase` (#175) --- .github/workflows/{js-lint.yml => js.yml} | 12 ++- vite-plugin-ruby/package.json | 7 +- vite-plugin-ruby/pnpm-lock.yaml | 125 ++++++++++++++++++---- vite-plugin-ruby/pnpm-workspace.yaml | 3 +- vite-plugin-ruby/src/config.ts | 24 +++-- vite-plugin-ruby/tests/config.spec.ts | 32 ++++++ vite-plugin-ruby/tests/package.json | 7 ++ vite-plugin-ruby/tests/tsconfig.json | 18 ++++ vite-plugin-ruby/tsup.config.ts | 1 + vite-plugin-ruby/vitest.config.ts | 10 ++ 10 files changed, 203 insertions(+), 36 deletions(-) rename .github/workflows/{js-lint.yml => js.yml} (69%) create mode 100644 vite-plugin-ruby/tests/config.spec.ts create mode 100644 vite-plugin-ruby/tests/package.json create mode 100644 vite-plugin-ruby/tests/tsconfig.json create mode 100644 vite-plugin-ruby/vitest.config.ts diff --git a/.github/workflows/js-lint.yml b/.github/workflows/js.yml similarity index 69% rename from .github/workflows/js-lint.yml rename to .github/workflows/js.yml index 75595866..3636eeaf 100644 --- a/.github/workflows/js-lint.yml +++ b/.github/workflows/js.yml @@ -1,10 +1,10 @@ -name: JS lint +name: JS Build & Test on: [push, pull_request] jobs: build: - name: JS Lint + name: Vite Plugin Ruby strategy: matrix: @@ -25,7 +25,11 @@ jobs: with: version: 5.13.6 run_install: | + - cwd: vite-plugin-ruby - recursive: false - - name: Lint - run: pnpm lint + - name: Build + run: pnpm -C vite-plugin-ruby build + + - name: Test + run: pnpm -C vite-plugin-ruby test diff --git a/vite-plugin-ruby/package.json b/vite-plugin-ruby/package.json index dc36ff79..4de4e081 100644 --- a/vite-plugin-ruby/package.json +++ b/vite-plugin-ruby/package.json @@ -36,8 +36,9 @@ "dev": "npm run build -- --watch", "example:dev": "npm -C example run dev", "example:build": "npm -C example run build", - "build": "rimraf -rf dist && tsup src/index.ts", + "build": "tsup src/index.ts", "prepublishOnly": "npm run build", + "test": "vitest", "postpublish": "PACKAGE_VERSION=$(cat package.json | grep \\\"version\\\" | head -1 | awk -F: '{ print $2 }' | sed 's/[\",]//g' | tr -d '[[:space:]]') && git tag vite-plugin-ruby@$PACKAGE_VERSION && git push --tags" }, "dependencies": { @@ -50,11 +51,11 @@ "devDependencies": { "@types/debug": "^4.1.7", "@types/node": "^14.18.5", - "rimraf": "^3.0.2", "rollup": "^2.63.0", "standard-version": "^9.3.2", "tsup": "^5.11.10", "typescript": "^4.5.4", - "vite": "^2.7.10" + "vite": "^2.7.10", + "vitest": "^0.0.141" } } diff --git a/vite-plugin-ruby/pnpm-lock.yaml b/vite-plugin-ruby/pnpm-lock.yaml index bdc5dd12..480988a5 100644 --- a/vite-plugin-ruby/pnpm-lock.yaml +++ b/vite-plugin-ruby/pnpm-lock.yaml @@ -8,24 +8,24 @@ importers: '@types/node': ^14.18.5 debug: ^4.3 fast-glob: ^3.2 - rimraf: ^3.0.2 rollup: ^2.63.0 standard-version: ^9.3.2 tsup: ^5.11.10 typescript: ^4.5.4 vite: ^2.7.10 + vitest: ^0.0.141 dependencies: debug: 4.3.3 fast-glob: 3.2.7 devDependencies: '@types/debug': 4.1.7 '@types/node': 14.18.5 - rimraf: 3.0.2 rollup: 2.63.0 standard-version: 9.3.2 tsup: 5.11.10_typescript@4.5.4 typescript: 4.5.4 vite: 2.7.10 + vitest: 0.0.141 example: specifiers: @@ -47,6 +47,12 @@ importers: vite-plugin-ruby: link:.. vue: 3.2.26 + tests: + specifiers: + vite-plugin-ruby: workspace:* + devDependencies: + vite-plugin-ruby: link:.. + packages: /@babel/code-frame/7.16.7: @@ -104,6 +110,16 @@ packages: '@nodelib/fs.scandir': 2.1.5 fastq: 1.13.0 + /@types/chai-subset/1.3.3: + resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} + dependencies: + '@types/chai': 4.3.0 + dev: true + + /@types/chai/4.3.0: + resolution: {integrity: sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw==} + dev: true + /@types/debug/4.1.7: resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==} dependencies: @@ -291,6 +307,10 @@ packages: engines: {node: '>=0.10.0'} dev: true + /assertion-error/1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + dev: true + /balanced-match/1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true @@ -344,6 +364,18 @@ packages: engines: {node: '>=6'} dev: true + /chai/4.3.4: + resolution: {integrity: sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA==} + engines: {node: '>=4'} + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.2 + deep-eql: 3.0.1 + get-func-name: 2.0.0 + pathval: 1.1.1 + type-detect: 4.0.8 + dev: true + /chalk/2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -353,6 +385,10 @@ packages: supports-color: 5.5.0 dev: true + /check-error/1.0.2: + resolution: {integrity: sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=} + dev: true + /chokidar/3.5.2: resolution: {integrity: sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==} engines: {node: '>= 8.10.0'} @@ -651,6 +687,13 @@ packages: engines: {node: '>=0.10.0'} dev: true + /deep-eql/3.0.1: + resolution: {integrity: sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==} + engines: {node: '>=0.12'} + dependencies: + type-detect: 4.0.8 + dev: true + /detect-indent/6.1.0: resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==} engines: {node: '>=8'} @@ -1101,6 +1144,10 @@ packages: engines: {node: 6.* || 8.* || >= 10.*} dev: true + /get-func-name/2.0.0: + resolution: {integrity: sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=} + dev: true + /get-pkg-repo/4.2.1: resolution: {integrity: sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==} engines: {node: '>=6.9.0'} @@ -1169,17 +1216,6 @@ packages: path-is-absolute: 1.0.1 dev: true - /glob/7.2.0: - resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.0.4 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - /globby/11.0.4: resolution: {integrity: sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg==} engines: {node: '>=10'} @@ -1383,6 +1419,11 @@ packages: strip-bom: 3.0.0 dev: true + /local-pkg/0.4.1: + resolution: {integrity: sha512-lL87ytIGP2FU5PWwNDo0w3WhIo2gopIAxPg9RxDYF7m4rr5ahuZxP22xnJHIvaLTe4Z9P6uKKY2UHiwyB4pcrw==} + engines: {node: '>=14'} + dev: true + /locate-path/2.0.0: resolution: {integrity: sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=} engines: {node: '>=4'} @@ -1698,6 +1739,10 @@ packages: engines: {node: '>=8'} dev: true + /pathval/1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + dev: true + /picocolors/1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: true @@ -1859,13 +1904,6 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - /rimraf/3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - hasBin: true - dependencies: - glob: 7.2.0 - dev: true - /rollup/2.63.0: resolution: {integrity: sha512-nps0idjmD+NXl6OREfyYXMn/dar3WGcyKn+KBzPdaLecub3x/LrId0wUcthcr8oZUAcZAR8NKcfGGFlNgGL1kQ==} engines: {node: '>=10.0.0'} @@ -2122,6 +2160,16 @@ packages: readable-stream: 3.6.0 dev: true + /tinypool/0.1.1: + resolution: {integrity: sha512-sW2fQZ2BRb/GX5v55NkHiTrbMLx0eX0xNpP+VGhOe2f7Oo04+LeClDyM19zCE/WCy7jJ8kzIJ0Ojrxj3UhN9Sg==} + engines: {node: '>=14.0.0'} + dev: true + + /tinyspy/0.2.8: + resolution: {integrity: sha512-4VXqQzzh9gC5uOLk77cLr9R3wqJq07xJlgM9IUdCNJCet139r+046ETKbU1x7mGs7B0k7eopyH5U6yflbBXNyA==} + engines: {node: '>=14.0.0'} + dev: true + /to-regex-range/5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -2171,6 +2219,11 @@ packages: - ts-node dev: true + /type-detect/4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + dev: true + /type-fest/0.18.1: resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} engines: {node: '>=10'} @@ -2263,6 +2316,38 @@ packages: fsevents: 2.3.2 dev: true + /vitest/0.0.141: + resolution: {integrity: sha512-CQwNWGbifAs5OrG1MXyiveeFT3KYpU/UZiZzNUR5ZHMUWKam9OeoDX0U3sFuyaERp/0b2vhoL0oaMccY2PJPSQ==} + engines: {node: '>=14.14.0'} + hasBin: true + peerDependencies: + '@vitest/ui': '*' + c8: '*' + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@vitest/ui': + optional: true + c8: + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@types/chai': 4.3.0 + '@types/chai-subset': 1.3.3 + chai: 4.3.4 + local-pkg: 0.4.1 + tinypool: 0.1.1 + tinyspy: 0.2.8 + vite: 2.7.10 + transitivePeerDependencies: + - less + - sass + - stylus + dev: true + /vue/3.2.26: resolution: {integrity: sha512-KD4lULmskL5cCsEkfhERVRIOEDrfEL9CwAsLYpzptOGjaGFNWo3BQ9g8MAb7RaIO71rmVOziZ/uEN/rHwcUIhg==} dependencies: diff --git a/vite-plugin-ruby/pnpm-workspace.yaml b/vite-plugin-ruby/pnpm-workspace.yaml index c4b7c6fa..febced56 100644 --- a/vite-plugin-ruby/pnpm-workspace.yaml +++ b/vite-plugin-ruby/pnpm-workspace.yaml @@ -1,2 +1,3 @@ packages: - - example/ \ No newline at end of file + - example/ + - tests/ diff --git a/vite-plugin-ruby/src/config.ts b/vite-plugin-ruby/src/config.ts index b03d8dda..d33e5599 100644 --- a/vite-plugin-ruby/src/config.ts +++ b/vite-plugin-ruby/src/config.ts @@ -7,7 +7,7 @@ import { booleanOption, loadJsonConfig, configOptionFromEnv, slash } from './uti import { Config, ResolvedConfig, UnifiedConfig, MultiEnvConfig, Entrypoints } from './types' // Internal: Default configuration that is also read from Ruby. -const defaultConfig: ResolvedConfig = loadJsonConfig(resolve(__dirname, '../default.vite.json')) +export const defaultConfig: ResolvedConfig = loadJsonConfig(resolve(__dirname, '../default.vite.json')) // Internal: Returns the files defined in the entrypoints directory that should // be processed by rollup. @@ -98,13 +98,21 @@ function coerceConfigurationValues (config: ResolvedConfig, projectRoot: string, const buildOutputDir = join(config.publicDir, config.publicOutputDir) const outDir = relative(root, buildOutputDir) // Vite expects it to be relative - // Add the asset host to enable usage of a CDN. - const assetHost = config.assetHost || '' - const assetHostWithProtocol = assetHost && !assetHost.startsWith('http') ? `//${assetHost}` : assetHost - const host = assetHostWithProtocol || config.base || '' - const suffix = config.publicOutputDir ? `${slash(config.publicOutputDir)}/` : '' - const base = `${host}/${suffix}` - + const base = resolveViteBase(config) const entrypoints = resolveEntrypointFiles(projectRoot, root, config) return { ...config, root, outDir, base, entrypoints } } + +// Internal: Configures Vite's base according to the asset host and publicOutputDir. +export function resolveViteBase ({ assetHost, base, publicOutputDir }: ResolvedConfig) { + if (assetHost && !assetHost.startsWith('http')) assetHost = `//${assetHost}` + + return [ + ensureTrailingSlash(assetHost || base || '/'), + publicOutputDir ? ensureTrailingSlash(slash(publicOutputDir)) : '', + ].join('') +} + +function ensureTrailingSlash (path: string) { + return path.endsWith('/') ? path : `${path}/` +} diff --git a/vite-plugin-ruby/tests/config.spec.ts b/vite-plugin-ruby/tests/config.spec.ts new file mode 100644 index 00000000..3eb06840 --- /dev/null +++ b/vite-plugin-ruby/tests/config.spec.ts @@ -0,0 +1,32 @@ +import { describe, test, expect } from 'vitest' +import { defaultConfig, resolveViteBase } from '@plugin/config' +import type { ResolvedConfig } from '@plugin/types' + +const expectBaseFor = (config: ResolvedConfig) => + expect(resolveViteBase({ ...defaultConfig, ...config })) + +describe('resolveViteBase', () => { + test('default usage', () => { + expectBaseFor({}).toEqual('/vite/') + expectBaseFor({ publicOutputDir: '' }).toEqual('/') + expectBaseFor({ publicOutputDir: 'assets/frontend' }).toEqual('/assets/frontend/') + }) + + test('windows compatibility', () => { + expectBaseFor({ publicOutputDir: 'assets\\frontend' }).toEqual('/assets/frontend/') + }) + + test('custom base', () => { + expectBaseFor({ base: '/sub' }).toEqual('/sub/vite/') + expectBaseFor({ base: '/sub/' }).toEqual('/sub/vite/') + expectBaseFor({ base: '/sub', publicOutputDir: '' }).toEqual('/sub/') + expectBaseFor({ base: '/sub/', publicOutputDir: '' }).toEqual('/sub/') + }) + + test('supports asset host', () => { + expectBaseFor({ assetHost: 'assets-cdn.com' }).toEqual('//assets-cdn.com/vite/') + expectBaseFor({ assetHost: 'https://assets-cdn.com' }).toEqual('https://assets-cdn.com/vite/') + expectBaseFor({ assetHost: 'assets-cdn.com', publicOutputDir: '' }).toEqual('//assets-cdn.com/') + expectBaseFor({ assetHost: 'http://assets-cdn.com', publicOutputDir: '' }).toEqual('http://assets-cdn.com/') + }) +}) diff --git a/vite-plugin-ruby/tests/package.json b/vite-plugin-ruby/tests/package.json new file mode 100644 index 00000000..86f83c6e --- /dev/null +++ b/vite-plugin-ruby/tests/package.json @@ -0,0 +1,7 @@ +{ + "name": "vite-plugin-ruby-tests", + "private": true, + "devDependencies": { + "vite-plugin-ruby": "workspace:*" + } +} diff --git a/vite-plugin-ruby/tests/tsconfig.json b/vite-plugin-ruby/tests/tsconfig.json new file mode 100644 index 00000000..e070a0c9 --- /dev/null +++ b/vite-plugin-ruby/tests/tsconfig.json @@ -0,0 +1,18 @@ +{ + "include": ["."], + "exclude": ["**/dist/**"], + "compilerOptions": { + "target": "esnext", + "module": "esnext", + "outDir": "dist", + "allowJs": true, + "esModuleInterop": true, + "moduleResolution": "node", + "baseUrl": ".", + "jsx": "preserve", + "types": ["vite/client", "vitest", "node"], + "paths": { + "@plugin/*": ["src/*"] + }, + } +} diff --git a/vite-plugin-ruby/tsup.config.ts b/vite-plugin-ruby/tsup.config.ts index 12c3d379..57bbefb3 100644 --- a/vite-plugin-ruby/tsup.config.ts +++ b/vite-plugin-ruby/tsup.config.ts @@ -1,5 +1,6 @@ import type { Options } from 'tsup' export const tsup: Options = { + clean: true, dts: true, sourcemap: true, target: 'node12', diff --git a/vite-plugin-ruby/vitest.config.ts b/vite-plugin-ruby/vitest.config.ts new file mode 100644 index 00000000..16fb877d --- /dev/null +++ b/vite-plugin-ruby/vitest.config.ts @@ -0,0 +1,10 @@ +import { resolve } from 'path' +import { defineConfig } from 'vite' + +export default defineConfig({ + resolve: { + alias: { + '@plugin': resolve(__dirname, 'src'), + }, + }, +})