Skip to content
Open
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
6 changes: 3 additions & 3 deletions documentation/docs/30-add-ons/99-community.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,10 +134,10 @@ export default defineConfig({
And the global test setup script `tests/setup/global.js`:

```js
import { fileURLToPath } from 'node:url';
import path from 'node:path';
import { setupGlobal } from 'sv/testing';

const TEST_DIR = fileURLToPath(new URL('../../.test-output/', import.meta.url));
// test projects are scaffolded into `<project-root>/.test-output`
const TEST_DIR = path.resolve(import.meta.dirname, '..', '..', '.test-output');

export default setupGlobal({ TEST_DIR });
```
Expand Down
5 changes: 2 additions & 3 deletions packages/sv-utils/src/tests/css/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import fs from 'node:fs';
import { join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { join } from 'node:path';
import { format } from 'oxfmt';
import { describe, expect, test } from 'vitest';
import oxfmtConfig from '../../../../../oxfmt.config.ts';
import { parseCss, serializeCss } from '../../tooling/index.ts';

const baseDir = resolve(fileURLToPath(import.meta.url), '..');
const baseDir = import.meta.dirname;
const categoryDirectories = getDirectoryNames(baseDir);

for (const categoryDirectory of categoryDirectories) {
Expand Down
5 changes: 2 additions & 3 deletions packages/sv-utils/src/tests/html/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import fs from 'node:fs';
import { join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { join } from 'node:path';
import { format } from 'oxfmt';
import { describe, expect, test } from 'vitest';
import oxfmtConfig from '../../../../../oxfmt.config.ts';
import { parseHtml, serializeHtml } from '../../tooling/index.ts';

const baseDir = resolve(fileURLToPath(import.meta.url), '..');
const baseDir = import.meta.dirname;
const categoryDirectories = getDirectoryNames(baseDir);

for (const categoryDirectory of categoryDirectories) {
Expand Down
5 changes: 2 additions & 3 deletions packages/sv-utils/src/tests/js/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import fs from 'node:fs';
import { join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { join } from 'node:path';
import { describe, expect, test } from 'vitest';
import { parseScript, serializeScript } from '../../tooling/index.ts';

const baseDir = resolve(fileURLToPath(import.meta.url), '..');
const baseDir = import.meta.dirname;
const categoryDirectories = getDirectoryNames(baseDir);

for (const categoryDirectory of categoryDirectories) {
Expand Down
5 changes: 2 additions & 3 deletions packages/sv-utils/src/tests/svelte/svelte/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import fs from 'node:fs';
import { join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { join } from 'node:path';
import { describe, expect, test } from 'vitest';
import { parseSvelte, serializeSvelte } from '../../../../src/tooling/index.ts';

const baseDir = resolve(fileURLToPath(import.meta.url), '..');
const baseDir = import.meta.dirname;
const categoryDirectories = getDirectoryNames(baseDir);

for (const categoryDirectory of categoryDirectories) {
Expand Down
7 changes: 5 additions & 2 deletions packages/sv/src/addons/tests/_setup/global.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import path from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
import * as find from 'empathic/find';
import { setupGlobal } from 'sv/testing';
import { exec } from 'tinyexec';

const TEST_DIR = fileURLToPath(new URL('../../../../.test-output/addons/', import.meta.url));
const ROOT = path.dirname(find.up('pnpm-workspace.yaml', { cwd: import.meta.dirname })!);
const TEST_DIR = path.resolve(ROOT, 'packages', 'sv', '.test-output', 'addons');

const CI = Boolean(process.env.CI);

export default setupGlobal({
Expand Down
3 changes: 1 addition & 2 deletions packages/sv/src/addons/tests/drizzle/test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import fs from 'node:fs';
import path from 'node:path';
import process from 'node:process';
import { fileURLToPath } from 'node:url';
import { execSync } from 'tinyexec';
import { beforeAll, expect } from 'vitest';
import drizzle from '../../drizzle.ts';
Expand Down Expand Up @@ -39,7 +38,7 @@ const { test, testCases, prepareServer } = setupTest(

beforeAll(() => {
if (!MUST_HAVE_DOCKER) return;
const cwd = path.dirname(fileURLToPath(import.meta.url));
const cwd = import.meta.dirname;

try {
execSync('docker', ['--version'], { nodeOptions: { cwd }, throwOnError: true });
Expand Down
40 changes: 19 additions & 21 deletions packages/sv/src/cli/tests/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ import fs from 'node:fs';
import path from 'node:path';
import process from 'node:process';
import { parse } from '@sveltejs/sv-utils';
import * as find from 'empathic/find';
import { exec } from 'tinyexec';
import { beforeAll, describe, expect, it } from 'vitest';

/** Matches `sv@1.2.3`, `sv@0.0.0-next.0`, `sv@1.0.0-rc.1+build.5`. */
const SV_VERSION_REGEX = /sv@\d+\.\d+\.\d+(?:-[\w.-]+)?(?:\+[\w.-]+)?/g;

const monoRepoPath = path.resolve(__dirname, '..', '..', '..', '..', '..');
const svBinPath = path.resolve(monoRepoPath, 'packages', 'sv', 'dist', 'bin.mjs');
const testOutputCliPath = path.resolve(monoRepoPath, 'packages', 'sv', '.test-output', 'cli');
const ROOT = path.dirname(find.up('pnpm-workspace.yaml', { cwd: import.meta.dirname })!);
const SV_BIN_PATH = path.resolve(ROOT, 'packages', 'sv', 'dist', 'bin.mjs');
const TEST_DIR = path.resolve(ROOT, 'packages', 'sv', '.test-output', 'cli');

beforeAll(() => {
if (fs.existsSync(testOutputCliPath)) {
fs.rmSync(testOutputCliPath, { force: true, recursive: true });
if (fs.existsSync(TEST_DIR)) {
fs.rmSync(TEST_DIR, { force: true, recursive: true });
}
});

Expand Down Expand Up @@ -72,15 +73,12 @@ describe('cli', () => {
snapshot?: boolean;
};

const testOutputPath = path.relative(
monoRepoPath,
path.resolve(testOutputCliPath, projectName)
);
const projectPath = path.relative(ROOT, path.resolve(TEST_DIR, projectName));

const allArgs = [
svBinPath,
SV_BIN_PATH,
'create',
testOutputPath,
projectPath,
'--template',
template,
...(template === 'addon' ? [] : ['--types', 'ts']),
Expand All @@ -89,12 +87,12 @@ describe('cli', () => {
];

/**
* Same as `exec`. but `cwd` defaults to `testOutputPath`
* Same as `exec`. but `cwd` defaults to `projectPath`
*/
const run = (...params: Parameters<typeof exec>) => {
const [command, args, options = {}] = params;
options.nodeOptions ??= {};
options.nodeOptions.cwd ??= testOutputPath;
options.nodeOptions.cwd ??= projectPath;
return exec(command, args, options);
};

Expand All @@ -108,15 +106,15 @@ describe('cli', () => {
`Error with cli:\n cmd: node ${allArgs.join(' ')}\n stdout: ${result.stdout}\n stderr: ${result.stderr}`
).toBe(0);
// test output path exists
expect(fs.existsSync(testOutputPath)).toBe(true);
expect(fs.existsSync(projectPath)).toBe(true);

// package.json has a name
const packageJsonPath = path.resolve(testOutputPath, 'package.json');
const packageJsonPath = path.resolve(projectPath, 'package.json');
const { data: packageJson } = parse.json(fs.readFileSync(packageJsonPath, 'utf-8'));
expect(packageJson.name).toBe(projectName);

const snapPath = path.resolve(
monoRepoPath,
ROOT,
'packages',
'sv',
'src',
Expand All @@ -126,7 +124,7 @@ describe('cli', () => {
projectName
);
const relativeFiles = snapshot
? (fs.readdirSync(testOutputPath, { recursive: true }) as string[])
? (fs.readdirSync(projectPath, { recursive: true }) as string[])
: [];

// Files from ai-tools repo (skills, agents) change independently -
Expand All @@ -135,7 +133,7 @@ describe('cli', () => {
const aiToolsPattern = /[\\/](skills|agents)[\\/]/;

for (const relativeFile of relativeFiles) {
if (!fs.statSync(path.resolve(testOutputPath, relativeFile)).isFile()) continue;
if (!fs.statSync(path.resolve(projectPath, relativeFile)).isFile()) continue;
if (['.svg', '.env'].some((ext) => relativeFile.endsWith(ext))) continue;

const normalized = relativeFile.replace(/\\/g, '/');
Expand All @@ -151,7 +149,7 @@ describe('cli', () => {
continue;
}

let generated = fs.readFileSync(path.resolve(testOutputPath, relativeFile), 'utf-8');
let generated = fs.readFileSync(path.resolve(projectPath, relativeFile), 'utf-8');
if (relativeFile === 'package.json') {
const { data: generatedPackageJson } = parse.json(generated);
// remove @types/node from generated package.json as we test on different node versions
Expand Down Expand Up @@ -220,7 +218,7 @@ describe('cli', () => {
}

if (projectName === 'create-experimental') {
const read = (p: string) => fs.readFileSync(path.resolve(testOutputPath, p), 'utf-8');
const read = (p: string) => fs.readFileSync(path.resolve(projectPath, p), 'utf-8');
const envFile = read('src/env.ts');
expect(envFile).toContain('defineEnvVars');
expect(envFile).toContain('DATABASE_URL');
Expand All @@ -231,7 +229,7 @@ describe('cli', () => {

if (template === 'addon') {
// replace sv and sv-utils versions in package.json for tests
const packageJsonPath = path.resolve(testOutputPath, 'package.json');
const packageJsonPath = path.resolve(projectPath, 'package.json');
const { data: packageJson } = parse.json(fs.readFileSync(packageJsonPath, 'utf-8'));
packageJson.peerDependencies['sv'] = 'file:../../../..';
packageJson.devDependencies['sv'] = 'file:../../../..';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { fileURLToPath } from 'node:url';
import path from 'node:path';
import { setupGlobal } from 'sv/testing';

const TEST_DIR = fileURLToPath(new URL('../../.test-output/', import.meta.url));
const TEST_DIR = path.resolve(import.meta.dirname, '..', '..', '.test-output');

export default setupGlobal({
TEST_DIR,
Expand Down
3 changes: 1 addition & 2 deletions packages/sv/src/core/fetch-packages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import fs from 'node:fs';
import { platform } from 'node:os';
import path from 'node:path';
import { pipeline } from 'node:stream/promises';
import { fileURLToPath } from 'node:url';
import { createGunzip } from 'node:zlib';
import { color, coerceVersion, downloadJson } from '@sveltejs/sv-utils';
import { unpackTar } from 'modern-tar/fs';
Expand All @@ -13,7 +12,7 @@ import { PackageJSONSchema, type PackageJSON } from './common.ts';
import type { AddonDefinition, AddonReference } from './config.ts';

// path to the `node_modules` directory of `sv`
const NODE_MODULES = fileURLToPath(new URL('../../node_modules', import.meta.url));
const NODE_MODULES = path.resolve(import.meta.dirname, '..', '..', 'node_modules');

type PackageBlocklist = { npm_names: string[] };

Expand Down
3 changes: 1 addition & 2 deletions packages/sv/src/create/scripts/build-templates.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import fs from 'node:fs';
import { createRequire } from 'node:module';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import parser from 'gitignore-parser';
import { format } from 'oxfmt';
import { transform } from 'sucrase';
Expand All @@ -11,7 +10,7 @@ import oxfmtConfig from '../../../../../oxfmt.config.ts';

/** @import { File, LanguageType } from '../index.ts' */

const pkgRoot = path.resolve(fileURLToPath(import.meta.url), '..', '..');
const pkgRoot = path.resolve(import.meta.dirname, '..');
const require = createRequire(import.meta.url);
const createVitePath = path.dirname(require.resolve('create-vite/package.json'));

Expand Down
4 changes: 2 additions & 2 deletions packages/sv/src/create/templates/addon/tests/setup/global.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { fileURLToPath } from 'node:url';
import path from 'node:path';
import { setupGlobal } from 'sv/testing';

const TEST_DIR = fileURLToPath(new URL('../../.test-output/', import.meta.url));
const TEST_DIR = path.resolve(import.meta.dirname, '..', '..', '.test-output');

export default setupGlobal({
TEST_DIR,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import * as find from 'empathic/find';
import { exec, type Result } from 'tinyexec';
import { beforeAll, describe, expect, test } from 'vitest';
import { add, officialAddons } from '../../../../sv/src/index.ts';
import { createProject } from '../../cli/create.ts';
import { type LanguageType, type TemplateType, create } from '../index.ts';

// Resolve the given path relative to the current file
const resolve_path = (path: string) => fileURLToPath(new URL(path, import.meta.url));

// use a directory outside of packages to ensure it isn't added to the pnpm workspace
const test_workspace_dir = resolve_path('../../../../../.test-output/create/');
const ROOT = path.dirname(find.up('pnpm-workspace.yaml', { cwd: import.meta.dirname })!);
const TEMPLATES_DIR = path.resolve(ROOT, 'packages', 'sv', 'src', 'create', 'templates');
const TEST_DIR = path.resolve(ROOT, 'packages', 'sv', '.test-output', 'create');

// prepare test pnpm workspace
fs.rmSync(test_workspace_dir, { recursive: true, force: true });
fs.mkdirSync(test_workspace_dir, { recursive: true });
fs.rmSync(TEST_DIR, { recursive: true, force: true });
fs.mkdirSync(TEST_DIR, { recursive: true });

fs.writeFileSync(path.join(test_workspace_dir, 'pnpm-workspace.yaml'), 'packages:\n - ./*\n');
fs.writeFileSync(path.join(TEST_DIR, 'pnpm-workspace.yaml'), 'packages:\n - ./*\n');

beforeAll(async () => {
const install = await exec('pnpm', ['install', '--no-frozen-lockfile'], {
nodeOptions: { cwd: test_workspace_dir }
nodeOptions: { cwd: TEST_DIR }
});
if (install.exitCode !== 0) {
throw new Error(
`pnpm install failed in ${test_workspace_dir}\n stdout: ${install.stdout}\n stderr: ${install.stderr}`
`pnpm install failed in ${TEST_DIR}\n stdout: ${install.stdout}\n stderr: ${install.stderr}`
);
}
}, 60000);
Expand All @@ -36,13 +34,13 @@ beforeAll(async () => {
*/
const script_test_map = new Map<string, Array<[string, () => Result]>>();

const templates = fs.readdirSync(resolve_path('../templates/')) as TemplateType[];
const templates = fs.readdirSync(TEMPLATES_DIR) as TemplateType[];

for (const template of templates.filter((t) => t !== 'addon')) {
if (template[0] === '.') continue;

for (const types of ['checkjs', 'typescript', 'none'] as LanguageType[]) {
const cwd = path.join(test_workspace_dir, `${template}-${types}`);
const cwd = path.join(TEST_DIR, `${template}-${types}`);
fs.rmSync(cwd, { recursive: true, force: true });

if (template === 'demo' && types === 'typescript') {
Expand Down
18 changes: 9 additions & 9 deletions packages/sv/src/create/tests/playground.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import * as find from 'empathic/find';
import { expect, test } from 'vitest';
import { create } from '../index.ts';
import {
Expand All @@ -11,8 +11,8 @@ import {
validatePlaygroundUrl
} from '../playground.ts';

const resolvePath = (path: string) => fileURLToPath(new URL(path, import.meta.url));
const testWorkspaceDir = resolvePath('../../../.test-output/create/');
const ROOT = path.dirname(find.up('pnpm-workspace.yaml', { cwd: import.meta.dirname })!);
const TEST_DIR = path.resolve(ROOT, 'packages', 'sv', '.test-output', 'playground');

test.for([
{ input: 'https://svelte.dev/playground/628f435d787a465f9c1f1854134d6f70/', valid: true },
Expand Down Expand Up @@ -147,15 +147,15 @@ test('detect dependencies from playground files', () => {
expect(Array.from(dependencies.keys()).length).toBe(3);
});

test('real world download and convert playground async', async () => {
const directory = path.join(testWorkspaceDir, 'real-world-playground');
test('download and convert playground e2e (svelte async)', async () => {
const directory = path.join(TEST_DIR, 'playground-e2e-svelte-async');
if (fs.existsSync(directory)) {
fs.rmSync(directory, { recursive: true });
}

create({
cwd: directory,
name: 'real-world-playground',
name: 'playground-e2e-svelte-async',
template: 'minimal',
types: 'typescript'
});
Expand Down Expand Up @@ -199,15 +199,15 @@ test('real world download and convert playground async', async () => {
expect(viteConfigContent).toContain('experimental: { async: true }');
});

test('real world download and convert playground without async', async () => {
const directory = path.join(testWorkspaceDir, 'real-world-playground-old');
test('download and convert playground e2e (pre svelte async)', async () => {
const directory = path.join(TEST_DIR, 'playground-e2e-pre-svelte-async');
if (fs.existsSync(directory)) {
fs.rmSync(directory, { recursive: true });
}

create({
cwd: directory,
name: 'real-world-playground-old',
name: 'playground-e2e-pre-svelte-async',
template: 'minimal',
types: 'typescript'
});
Expand Down
Loading