Skip to content

Commit

Permalink
feat: simple testing library (#275)
Browse files Browse the repository at this point in the history
Co-authored-by: Manuel Serret <[email protected]>
  • Loading branch information
AdrianGonz97 and manuel3108 authored Nov 11, 2024
1 parent 4e6552b commit 5941575
Show file tree
Hide file tree
Showing 125 changed files with 2,110 additions and 1,182 deletions.
6 changes: 5 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ jobs:
- run: pnpm build
- run: pnpm check
test:
runs-on: ubuntu-latest
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
Expand All @@ -48,5 +51,6 @@ jobs:
node-version: 18
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm exec playwright install chromium
- run: pnpm build
- run: pnpm test
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ package-lock.json
yarn.lock
vite.config.js.timestamp-*
/packages/create-svelte/template/CHANGELOG.md
.test-tmp
.test-output
2 changes: 0 additions & 2 deletions .prettierignore

This file was deleted.

1 change: 1 addition & 0 deletions community-adder-template/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
temp
.outputs
.test-output
25 changes: 14 additions & 11 deletions community-adder-template/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,28 @@
"name": "community-adder-template",
"private": true,
"version": "0.0.0",
"license": "MIT",
"type": "module",
"exports": "./src/index.js",
"keywords": [
"svelte-add-on",
"sv"
],
"license": "MIT",
"scripts": {
"create-temp": "sv create temp --types ts --template minimal --no-add-ons --no-install",
"start": "sv add -C temp --community file:../",
"create-temp": "sv create temp --check-types typescript --template skeleton --no-adders --no-install"
"test": "vitest run"
},
"files": [
"src",
"!src/**/*.test.*"
],
"exports": "./src/index.js",
"dependencies": {
"@sveltejs/cli-core": "workspace:*"
},
"devDependencies": {
"sv": "workspace:*"
"@playwright/test": "^1.48.2",
"sv": "workspace:*",
"vitest": "^2.1.4"
},
"files": [
"src",
"!src/**/*.test.*"
"keywords": [
"svelte-add-on",
"sv"
]
}
25 changes: 13 additions & 12 deletions community-adder-template/src/index.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { defineAdder, defineAdderOptions } from '@sveltejs/cli-core';
import { imports } from '@sveltejs/cli-core/js';
import { parseScript } from '@sveltejs/cli-core/parsers';
import { parseSvelte } from '@sveltejs/cli-core/parsers';

export const options = defineAdderOptions({
demo: {
question: 'Do you want to use a demo?',
type: 'boolean',
default: false
}
demo: {
question: 'Do you want to use a demo?',
type: 'boolean',
default: false
}
});

export const adder = defineAdder({
id: 'community-adder-template',
export default defineAdder({
id: 'community-addon',
environments: { kit: true, svelte: true },
options,
packages: [],
Expand All @@ -27,10 +27,11 @@ export const adder = defineAdder({
},
{
name: () => 'src/DemoComponent.svelte',
content: ({ content }) => {
const { ast, generateCode } = parseScript(content);
imports.addDefault(ast, '../adder-template-demo.txt?raw', 'Demo');
return generateCode();
content: ({ content, options, typescript }) => {
if (!options.demo) return content;
const { script, generateCode } = parseSvelte(content, { typescript });
imports.addDefault(script.ast, '../adder-template-demo.txt?raw', 'demo');
return generateCode({ script: script.generateCode(), template: '{demo}' });
}
}
]
Expand Down
28 changes: 28 additions & 0 deletions community-adder-template/tests/custom-addon.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import path from 'node:path';
import { expect } from '@playwright/test';
import { fixture, setupTest } from './setup/suite.js';
import addon from '../src/index.js';

const id = addon.id;
const { test, variants, prepareServer } = setupTest({ [id]: addon });

test.concurrent.for(variants)('demo - %s', async (variant, { page, ...ctx }) => {
const cwd = await ctx.run(variant, { [id]: { demo: true } });

// ...add files
if (variant.startsWith('kit')) {
const target = path.resolve(cwd, 'src', 'routes', '+page.svelte');
fixture({ name: '+page.svelte', target });
} else {
const target = path.resolve(cwd, 'src', 'App.svelte');
fixture({ name: 'App.svelte', target });
}

const { close } = await prepareServer({ cwd, page });
// kill server process when we're done
ctx.onTestFinished(async () => await close());

// expectations
const textContent = await page.getByTestId('demo').textContent();
expect(textContent).toContain('This is a text file made by the Community Adder Template demo!');
});
5 changes: 5 additions & 0 deletions community-adder-template/tests/fixtures/+page.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<script>
import demo from '../../adder-template-demo.txt?raw';
</script>

<span data-testid="demo">{demo}</span>
5 changes: 5 additions & 0 deletions community-adder-template/tests/fixtures/App.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<script>
import demo from '../adder-template-demo.txt?raw';
</script>

<span data-testid="demo">{demo}</span>
29 changes: 29 additions & 0 deletions community-adder-template/tests/setup/global.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { fileURLToPath } from 'node:url';
import { setup, type ProjectVariant } from 'sv/testing';
import type { GlobalSetupContext } from 'vitest/node';

const variants: ProjectVariant[] = ['kit-js', 'kit-ts', 'vite-js', 'vite-ts'];
const TEST_DIR = fileURLToPath(new URL('../../.test-output/', import.meta.url));

export default async function ({ provide }: GlobalSetupContext) {
// global setup (e.g. spin up docker containers)

// downloads different project configurations (sveltekit, js/ts, vite-only, etc)
const { templatesDir } = await setup({ cwd: TEST_DIR, variants, clean: true });

provide('testDir', TEST_DIR);
provide('templatesDir', templatesDir);
provide('variants', variants);

return async () => {
// tear down... (e.g. cleanup docker containers)
};
}

declare module 'vitest' {
export interface ProvidedContext {
testDir: string;
templatesDir: string;
variants: ProjectVariant[];
}
}
108 changes: 108 additions & 0 deletions community-adder-template/tests/setup/suite.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import fs from 'node:fs';
import path from 'node:path';
import { execSync } from 'node:child_process';
import * as vitest from 'vitest';
import { installAddon, type AddonMap, type OptionMap } from 'sv';
import { createProject, startPreview, type CreateProject, type ProjectVariant } from 'sv/testing';
import { chromium, type Browser, type Page } from '@playwright/test';
import { fileURLToPath } from 'node:url';

const cwd = vitest.inject('testDir');
const templatesDir = vitest.inject('templatesDir');
const variants = vitest.inject('variants');

const SETUP_DIR = fileURLToPath(new URL('.', import.meta.url));

type Fixtures<Addons extends AddonMap> = {
page: Page;
run(variant: ProjectVariant, options: OptionMap<Addons>): Promise<string>;
};

export function setupTest<Addons extends AddonMap>(addons: Addons) {
let create: CreateProject;
let browser: Browser;

const test = vitest.test.extend<Fixtures<Addons>>({} as any);

vitest.beforeAll(async () => {
browser = await chromium.launch();
return async () => {
await browser.close();
};
});

vitest.beforeAll(({ name }) => {
const testName = path.parse(name).name.replace('.test', '');

// constructs a builder for create test projects
create = createProject({ cwd, templatesDir, testName });

// creates a pnpm workspace in each addon dir
fs.writeFileSync(
path.resolve(cwd, testName, 'pnpm-workspace.yaml'),
`packages:\n - '**/*'`,
'utf8'
);
});

// runs before each test case
vitest.beforeEach<Fixtures<Addons>>(async (ctx) => {
const browserCtx = await browser.newContext();
ctx.page = await browserCtx.newPage();
ctx.run = async (variant, options) => {
const cwd = create({ testId: ctx.task.id, variant });

// test metadata
const metaPath = path.resolve(cwd, 'meta.json');
fs.writeFileSync(metaPath, JSON.stringify({ variant, options }, null, '\t'), 'utf8');

// run addon
await installAddon({ cwd, addons, options, packageManager: 'pnpm' });

return cwd;
};

return async () => {
await browserCtx.close();
// ...other tear downs
};
});

return {
test,
variants,
prepareServer
};
}

/**
* Installs dependencies, builds the project, and spins up the preview server
*/
async function prepareServer({ cwd, page }: { cwd: string; page: Page }) {
// install deps
execSync('pnpm install --no-frozen-lockfile', { cwd, stdio: 'pipe' });

// ...do commands and any other extra stuff

// build project
execSync('npm run build', { cwd, stdio: 'pipe' });

// start preview server `vite preview`
const { url, close } = await startPreview({ cwd });

// navigate to the page
await page.goto(url);

return { url, close };
}

/**
* Applies a fixture to the target path
*/
export function fixture({ name, target }: { name: string; target: string }) {
const fixturePath = path.resolve(SETUP_DIR, '..', 'fixtures', name);
if (!fs.existsSync(fixturePath)) {
throw new Error(`Fixture does not exist at: ${fixturePath}`);
}
fs.copyFileSync(fixturePath, target);
}
16 changes: 0 additions & 16 deletions community-adder-template/tests/tests.js

This file was deleted.

14 changes: 14 additions & 0 deletions community-adder-template/vitest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { defineConfig } from 'vitest/config';

const ONE_MINUTE = 1000 * 60;

export default defineConfig({
test: {
include: ['tests/**/*.test.{js,ts}'],
exclude: ['tests/setup/*'],
testTimeout: ONE_MINUTE * 3,
hookTimeout: ONE_MINUTE * 3,
maxConcurrency: 10,
globalSetup: ['tests/setup/global.ts']
}
});
5 changes: 3 additions & 2 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,11 @@ export default [
'packages/create/scripts/**/*',
'packages/create/templates/**/*',
'**/temp/*',
'.test-tmp/**/*',
'**/.test-output/*',
'**/dist/*',
'packages/**/tests/**/{output,input}.ts',
'rollup.config.js'
'rollup.config.js',
'community-adder-template/tests/*'
]
}
];
28 changes: 15 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
{
"name": "sv-monorepo",
"version": "0.0.1",
"description": "monorepo for sv and friends",
"private": true,
"version": "0.0.1",
"type": "module",
"description": "monorepo for sv and friends",
"engines": {
"pnpm": "^9.0.0"
},
"scripts": {
"build": "rollup -c",
"changeset:publish": "changeset publish",
"check": "pnpm --parallel check",
"lint": "pnpm --parallel lint && eslint --cache --cache-location node_modules/.eslintcache",
"format": "pnpm --parallel format",
"dev": "rollup --config --watch",
"build": "rollup -c",
"test": "pnpm --parallel test",
"changeset:publish": "changeset publish"
"format": "pnpm --parallel format",
"lint": "pnpm --parallel lint && eslint --cache --cache-location node_modules/.eslintcache",
"test": "vitest run --silent",
"test:ui": "vitest --ui"
},
"devDependencies": {
"@changesets/cli": "^2.27.9",
"@playwright/test": "^1.48.2",
"@rollup/plugin-commonjs": "^26.0.1",
"@rollup/plugin-dynamic-import-vars": "^2.1.2",
"@rollup/plugin-json": "^6.1.0",
Expand All @@ -23,7 +28,7 @@
"@sveltejs/eslint-config": "^8.1.0",
"@svitejs/changesets-changelog-github-compact": "^1.1.0",
"@types/node": "^22.3.0",
"@vitest/ui": "^2.0.5",
"@vitest/ui": "^2.1.4",
"eslint": "^9.10.0",
"magic-string": "^0.30.11",
"prettier": "^3.3.3",
Expand All @@ -37,10 +42,7 @@
"typescript": "^5.6.2",
"typescript-eslint": "^8.5.0",
"unplugin-isolated-decl": "^0.6.5",
"vitest": "^2.0.5"
"vitest": "^2.1.4"
},
"packageManager": "[email protected]",
"engines": {
"pnpm": "^9.0.0"
}
"packageManager": "[email protected]"
}
Loading

0 comments on commit 5941575

Please sign in to comment.