Skip to content
This repository has been archived by the owner on Oct 20, 2024. It is now read-only.

chore: use vitest #480

Closed
wants to merge 14 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/gold-houses-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@svelte-add/testing-library": minor
---

feat: allow more flexible testing
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
/.changeset/
CHANGELOG.md
packages/website/.svelte-kit/
packages/tests/.snapshots/
packages/tests/.outputs/
adders/*/README.md
adders/*/package.json
temp/
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pnpm svelte-add tailwindcss
Alternatively you can also run the testsuite of a adder with this command:

```sh
pnpm test tailwindcss mdsvex
pnpm test -t tailwindcss
```

And if you have made changes to the core packages, you should probably run the full test suite for all adders. But keep in mind, this takes time!
Expand Down
1 change: 1 addition & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ export default tseslint.config(
'packages/dev-utils/build',
'packages/testing-library/build',
'packages/tests/.outputs',
'packages/tests/.snapshots',
'packages/tests/build',
'packages/website/.svelte-kit',
'packages/website/build',
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
"website:dev": "pnpm -C ./packages/website dev",
"website:build": "pnpm -C ./packages/website build",
"website:preview": "pnpm -C ./packages/website preview",
"test": "node ./packages/tests/build/index.js",
"test": "pnpm -F @svelte-add/tests exec vitest",
"test:ui": "pnpm -F @svelte-add/tests exec vitest --ui",
"test:related": "pnpm -F @svelte-add/tests exec vitest related ./packages/tests/integration.ts --ui",
"check": "tsc --project tsconfig.json --noEmit",
"utils:dependencies": "node ./packages/dev-utils/build/index.js dependencies && pnpm prettier:fix",
"postinstall": "pnpm -F @svelte-add/testing-library exec playwright install chromium"
Expand Down
17 changes: 15 additions & 2 deletions packages/core/adder/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,18 @@ export type AddersExecutionPlan = {
selectAddersToApply?: AddersToApplySelector;
};

export type AddersExecutionResult = {
success: boolean;
outputDirectory: string;
changedFiles?: Set<string>;
};

export async function executeAdder<Args extends OptionDefinition>(
adderDetails: AdderDetails<Args>,
executingAdderInfo: ExecutingAdderInfo,
remoteControlOptions: RemoteControlOptions | undefined = undefined,
) {
await executeAdders([adderDetails], executingAdderInfo, remoteControlOptions);
return await executeAdders([adderDetails], executingAdderInfo, remoteControlOptions);
}

export async function executeAdders<Args extends OptionDefinition>(
Expand Down Expand Up @@ -104,7 +110,7 @@ export async function executeAdders<Args extends OptionDefinition>(
selectAddersToApply,
};

await executePlan(executionPlan, executingAdder, adderDetails, remoteControlOptions);
return await executePlan(executionPlan, executingAdder, adderDetails, remoteControlOptions);
} catch (e) {
if (e instanceof Error) cancel(e.message);
else cancel('Something went wrong.');
Expand Down Expand Up @@ -273,6 +279,13 @@ async function executePlan<Args extends OptionDefinition>(
displayNextSteps(adderDetails, isApplyingMultipleAdders, executionPlan);
endPrompts("You're all set!");
}

const executionResult: AddersExecutionResult = {
success: true,
changedFiles: filesToFormat,
outputDirectory: executionPlan.workingDirectory,
};
return executionResult;
}

async function processInlineAdder<Args extends OptionDefinition>(
Expand Down
41 changes: 7 additions & 34 deletions packages/testing-library/index.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,14 @@
import { rm } from 'node:fs/promises';
import { generateTestCases, runTestCases } from './utils/test-cases';
import { getTemplatesDirectory } from './utils/workspace';
import { downloadProjectTemplates } from './utils/create-project';
import { remoteControl } from '@svelte-add/core/internal';
import type { AdderWithoutExplicitArgs } from '@svelte-add/core/adder/config';
import {
generateTestCases,
runAdderEndToEndTests,
runAdderIntegrationTests,
} from './utils/test-cases';
import { prepareTests } from './utils/workspace';

export type TestOptions = {
headless: boolean;
pauseExecutionAfterBrowser: boolean;
outputDirectory: string;
};

export async function testAdder(adder: AdderWithoutExplicitArgs, options: TestOptions) {
await testAdders([adder], options);
}

export async function testAdders(adders: AdderWithoutExplicitArgs[], options: TestOptions) {
await prepareTests(options);

remoteControl.enable();
await executeTests(adders, options);
remoteControl.disable();
}

export async function executeTests(adders: AdderWithoutExplicitArgs[], options: TestOptions) {
console.log('generating test cases');
const testCases = generateTestCases(adders);

console.log('start testing');
await runTestCases(testCases, options);
}

async function prepareTests(options: TestOptions) {
console.log('deleting old files');
await rm(options.outputDirectory, { recursive: true, force: true });

console.log('downloading project templates');
const templatesOutputDirectory = getTemplatesDirectory(options);
await downloadProjectTemplates(templatesOutputDirectory);
}
export { generateTestCases, runAdderEndToEndTests, runAdderIntegrationTests, prepareTests };
7 changes: 4 additions & 3 deletions packages/testing-library/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
],
"dependencies": {
"@svelte-add/core": "workspace:^",
"playwright": "^1.44.1",
"create-svelte": "^6.3.4"
"create-svelte": "^6.3.4",
"playwright": "^1.44.1"
},
"devDependencies": {
"@vitest/ui": "^1.6.0",
"promise-parallel-throttle": "^3.5.0",
"terminate": "^2.6.1",
"uid": "^2.0.2"
"vitest": "^1.6.0"
},
"bugs": "https://github.com/svelte-add/svelte-add/issues",
"repository": {
Expand Down
10 changes: 9 additions & 1 deletion packages/testing-library/utils/adder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,19 @@ export async function runAdder(
adderOptions,
};

await executeAdder(
return await executeAdder(
{ config: adder.config, checks: adder.checks },
{ name: '@svelte-add/testing-library', version: 'latest' },
remoteControlOptions,
);
}

export async function runAdderAndPrepareTests(
adder: AdderWithoutExplicitArgs,
workingDirectory: string,
optionValues: OptionValues<Record<string, Question>>,
) {
await runAdder(adder, workingDirectory, optionValues);

const workspace = createEmptyWorkspace();
workspace.cwd = workingDirectory;
Expand Down
63 changes: 53 additions & 10 deletions packages/testing-library/utils/test-cases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@ import { join } from 'node:path';
import { mkdir } from 'node:fs/promises';
import { ProjectTypesList } from './create-project';
import { runTests } from './test';
import { uid } from 'uid';
import { startDevServer, stopDevServer } from './dev-server';
import { startBrowser, stopBrowser } from './browser-control';
import {
getTemplatesDirectory,
installDependencies,
prepareWorkspaceWithTemplate,
saveOptionsFile,
} from './workspace';
import { runAdder } from './adder';
import { prompts } from '@svelte-add/core/internal';
import { runAdder, runAdderAndPrepareTests } from './adder';
import { prompts, remoteControl } from '@svelte-add/core/internal';
import * as Throttle from 'promise-parallel-throttle';
import type { AdderWithoutExplicitArgs } from '@svelte-add/core/adder/config';
import type { TestOptions } from '..';
Expand Down Expand Up @@ -58,7 +56,7 @@ export function generateTestCases(adders: AdderWithoutExplicitArgs[]) {
return testCases;
}

export async function runAdderTests(
export async function runAdderEndToEndTests(
template: string,
adder: AdderWithoutExplicitArgs,
options: OptionValues<Record<string, Question>>,
Expand All @@ -69,17 +67,18 @@ export async function runAdderTests(
'The adder is not exporting any tests. Please make sure to properly define your tests while calling `defineAdder`',
);

const output = join(testOptions.outputDirectory, adder.config.metadata.id, template, uid());
remoteControl.enable();

const output = generateOutputDirectory(options, testOptions.outputDirectory, adder, template);
await mkdir(output, { recursive: true });

const workingDirectory = await prepareWorkspaceWithTemplate(
output,
template,
getTemplatesDirectory(testOptions),
getTemplatesDirectory(testOptions.outputDirectory),
);
await saveOptionsFile(workingDirectory, options);

await runAdder(adder, workingDirectory, options);
await runAdderAndPrepareTests(adder, workingDirectory, options);

await installDependencies(workingDirectory);

Expand All @@ -98,15 +97,54 @@ export async function runAdderTests(
} finally {
await stopBrowser(browser, page);
await stopDevServer(devServer);

remoteControl.disable();
}
}

export async function runAdderIntegrationTests(
testCase: TestCase,
outputDirectory: string,
adder: AdderWithoutExplicitArgs,
) {
const adderOutputDirectory = generateOutputDirectory(
testCase.options,
outputDirectory,
adder,
testCase.template,
);

const workingDirectory = await prepareWorkspaceWithTemplate(
adderOutputDirectory,
testCase.template,
getTemplatesDirectory(outputDirectory),
);

return await runAdder(adder, workingDirectory, testCase.options);
}

export type AdderError = {
adder: string;
template: string;
message: string;
} & Error;

export function generateOutputDirectory(
options: OptionValues<Record<string, Question>>,
outputDirectory: string,
adder: AdderWithoutExplicitArgs,
template: string,
) {
// generate a unique descriptive folder name if options are present
const optionsString = Object.entries(options)
.filter((data) => data[1]) // ensure value it not undefined
.map(([key, value]) => `${key}=${value as string}`)
.join('+');

const output = join(outputDirectory, adder.config.metadata.id, template, optionsString);
return output;
}

export async function runTestCases(testCases: Map<string, TestCase[]>, testOptions: TestOptions) {
const asyncTasks: Array<() => Promise<void>> = [];
const syncTasks: Array<() => Promise<void>> = [];
Expand All @@ -116,7 +154,12 @@ export async function runTestCases(testCases: Map<string, TestCase[]>, testOptio
for (const testCase of values) {
const taskExecutor = async () => {
try {
await runAdderTests(testCase.template, testCase.adder, testCase.options, testOptions);
await runAdderEndToEndTests(
testCase.template,
testCase.adder,
testCase.options,
testOptions,
);
} catch (e) {
const error = e as Error;
const adderError: AdderError = {
Expand Down
24 changes: 12 additions & 12 deletions packages/testing-library/utils/workspace.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import { join } from 'node:path';
import { cp, mkdir, writeFile } from 'node:fs/promises';
import { cp, mkdir, rm } from 'node:fs/promises';
import { executeCli } from '@svelte-add/core';
import type { TestOptions } from '..';
import type { OptionValues, Question } from '@svelte-add/core/adder/options';
import { downloadProjectTemplates } from './create-project';

const templatesDirectory = 'templates';

export function getTemplatesDirectory(options: TestOptions) {
return join(options.outputDirectory, templatesDirectory);
export function getTemplatesDirectory(outputDirectory: string) {
return join(outputDirectory, templatesDirectory);
}

export async function installDependencies(output: string) {
try {
// Since tests are executed and installed within this repo (packages/tests/.outputs),
// we need to add the `--ignore-workspace` flag so that our root lockfile isn't modified
await executeCli('pnpm', ['install', '--ignore-workspace'], output, { stdio: 'pipe' });
await executeCli('npm', ['install', '--ignore-workspace'], output, { stdio: 'pipe' });
} catch (error) {
const typedError = error as Error;
throw new Error('unable to install dependencies: ' + typedError.message);
Expand All @@ -33,10 +32,11 @@ export async function prepareWorkspaceWithTemplate(
return output;
}

export async function saveOptionsFile(
workingDirectory: string,
options: OptionValues<Record<string, Question>>,
) {
const json = JSON.stringify(options);
await writeFile(join(workingDirectory, 'options.json'), json);
export async function prepareTests(outputDirectory: string) {
console.log('deleting old files');
await rm(outputDirectory, { recursive: true, force: true });

console.log('downloading project templates');
const templatesOutputDirectory = getTemplatesDirectory(outputDirectory);
await downloadProjectTemplates(templatesOutputDirectory);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "test",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch"
},
"devDependencies": {
"@popperjs/core": "^2.11.8",
"@sveltejs/adapter-auto": "^3.0.0",
"@sveltejs/kit": "^2.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"bootstrap": "^5.3.3",
"svelte": "^4.2.7",
"svelte-check": "^3.6.0",
"typescript": "^5.0.0",
"vite": "^5.0.3"
},
"type": "module"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<script>import { browser } from "$app/environment";
import { onMount } from "svelte";
import "bootstrap/dist/css/bootstrap.css";

onMount(async () => {
if (!browser) return;

// this is enough for most components
await import("bootstrap");

// some components require a bootstrap instance, to fulfil their job. In that case, use this:
// const bootstrap = await import("bootstrap");
// sample usage:
// const toastBootstrap = bootstrap.Toast.getOrCreateInstance(toastLiveExample)
});</script><slot></slot>
<slot></slot>
Loading