feat(runtime): Add runtime adapters, filename runtime parser and migration tool; integrate runtime selection into TsTest and add tests
This commit is contained in:
111
test/test.migration.node.ts
Normal file
111
test/test.migration.node.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import { expect, tap } from '../ts_tapbundle/index.js';
|
||||
import { Migration } from '../ts/tstest.classes.migration.js';
|
||||
import * as plugins from '../ts/tstest.plugins.js';
|
||||
import * as paths from '../ts/tstest.paths.js';
|
||||
|
||||
tap.test('Migration - can initialize', async () => {
|
||||
const migration = new Migration({
|
||||
baseDir: process.cwd(),
|
||||
dryRun: true,
|
||||
});
|
||||
|
||||
expect(migration).toBeInstanceOf(Migration);
|
||||
});
|
||||
|
||||
tap.test('Migration - findLegacyFiles returns empty for no legacy files', async () => {
|
||||
const migration = new Migration({
|
||||
baseDir: process.cwd(),
|
||||
pattern: 'test/test.migration.node.ts', // This file itself, not legacy
|
||||
dryRun: true,
|
||||
});
|
||||
|
||||
const legacyFiles = await migration.findLegacyFiles();
|
||||
expect(legacyFiles).toEqual([]);
|
||||
});
|
||||
|
||||
tap.test('Migration - generateReport works', async () => {
|
||||
const migration = new Migration({
|
||||
baseDir: process.cwd(),
|
||||
dryRun: true,
|
||||
});
|
||||
|
||||
const report = await migration.generateReport();
|
||||
expect(report).toBeTypeOf('string');
|
||||
expect(report).toContain('Test File Migration Report');
|
||||
});
|
||||
|
||||
tap.test('Migration - detects legacy files when they exist', async () => {
|
||||
// Create a temporary legacy test file
|
||||
const tempDir = plugins.path.join(process.cwd(), '.nogit', 'test_migration');
|
||||
await plugins.smartfile.fs.ensureEmptyDir(tempDir);
|
||||
|
||||
const legacyFile = plugins.path.join(tempDir, 'test.browser.ts');
|
||||
await plugins.smartfile.memory.toFs('// Legacy test file\nexport default Promise.resolve();', legacyFile);
|
||||
|
||||
const migration = new Migration({
|
||||
baseDir: tempDir,
|
||||
pattern: '**/*.ts',
|
||||
dryRun: true,
|
||||
});
|
||||
|
||||
const legacyFiles = await migration.findLegacyFiles();
|
||||
expect(legacyFiles.length).toEqual(1);
|
||||
expect(legacyFiles[0]).toContain('test.browser.ts');
|
||||
|
||||
// Clean up
|
||||
await plugins.smartfile.fs.removeSync(tempDir);
|
||||
});
|
||||
|
||||
tap.test('Migration - detects both legacy pattern', async () => {
|
||||
// Create temporary legacy files
|
||||
const tempDir = plugins.path.join(process.cwd(), '.nogit', 'test_migration_both');
|
||||
await plugins.smartfile.fs.ensureEmptyDir(tempDir);
|
||||
|
||||
const browserFile = plugins.path.join(tempDir, 'test.browser.ts');
|
||||
const bothFile = plugins.path.join(tempDir, 'test.both.ts');
|
||||
await plugins.smartfile.memory.toFs('// Browser test\nexport default Promise.resolve();', browserFile);
|
||||
await plugins.smartfile.memory.toFs('// Both test\nexport default Promise.resolve();', bothFile);
|
||||
|
||||
const migration = new Migration({
|
||||
baseDir: tempDir,
|
||||
pattern: '**/*.ts',
|
||||
dryRun: true,
|
||||
});
|
||||
|
||||
const legacyFiles = await migration.findLegacyFiles();
|
||||
expect(legacyFiles.length).toEqual(2);
|
||||
|
||||
// Clean up
|
||||
await plugins.smartfile.fs.removeSync(tempDir);
|
||||
});
|
||||
|
||||
tap.test('Migration - dry run does not modify files', async () => {
|
||||
// Create a temporary legacy test file
|
||||
const tempDir = plugins.path.join(process.cwd(), '.nogit', 'test_migration_dryrun');
|
||||
await plugins.smartfile.fs.ensureEmptyDir(tempDir);
|
||||
|
||||
const legacyFile = plugins.path.join(tempDir, 'test.browser.ts');
|
||||
await plugins.smartfile.memory.toFs('// Legacy test file\nexport default Promise.resolve();', legacyFile);
|
||||
|
||||
const migration = new Migration({
|
||||
baseDir: tempDir,
|
||||
pattern: '**/*.ts',
|
||||
dryRun: true,
|
||||
verbose: false,
|
||||
});
|
||||
|
||||
const summary = await migration.run();
|
||||
|
||||
expect(summary.dryRun).toEqual(true);
|
||||
expect(summary.totalLegacyFiles).toEqual(1);
|
||||
expect(summary.migratedCount).toEqual(1); // Dry run still counts as "would migrate"
|
||||
|
||||
// Verify original file still exists
|
||||
const fileExists = await plugins.smartfile.fs.fileExists(legacyFile);
|
||||
expect(fileExists).toEqual(true);
|
||||
|
||||
// Clean up
|
||||
await plugins.smartfile.fs.removeSync(tempDir);
|
||||
});
|
||||
|
||||
export default tap.start();
|
167
test/test.runtime.parser.node.ts
Normal file
167
test/test.runtime.parser.node.ts
Normal file
@@ -0,0 +1,167 @@
|
||||
import { expect, tap } from '../ts_tapbundle/index.js';
|
||||
import { parseTestFilename, isLegacyFilename, getLegacyMigrationTarget } from '../ts/tstest.classes.runtime.parser.js';
|
||||
|
||||
tap.test('parseTestFilename - single runtime', async () => {
|
||||
const parsed = parseTestFilename('test.node.ts');
|
||||
expect(parsed.baseName).toEqual('test');
|
||||
expect(parsed.runtimes).toEqual(['node']);
|
||||
expect(parsed.modifiers).toEqual([]);
|
||||
expect(parsed.extension).toEqual('ts');
|
||||
expect(parsed.isLegacy).toEqual(false);
|
||||
});
|
||||
|
||||
tap.test('parseTestFilename - chromium runtime', async () => {
|
||||
const parsed = parseTestFilename('test.chromium.ts');
|
||||
expect(parsed.baseName).toEqual('test');
|
||||
expect(parsed.runtimes).toEqual(['chromium']);
|
||||
expect(parsed.modifiers).toEqual([]);
|
||||
expect(parsed.extension).toEqual('ts');
|
||||
expect(parsed.isLegacy).toEqual(false);
|
||||
});
|
||||
|
||||
tap.test('parseTestFilename - multiple runtimes', async () => {
|
||||
const parsed = parseTestFilename('test.node+chromium.ts');
|
||||
expect(parsed.baseName).toEqual('test');
|
||||
expect(parsed.runtimes).toEqual(['node', 'chromium']);
|
||||
expect(parsed.modifiers).toEqual([]);
|
||||
expect(parsed.extension).toEqual('ts');
|
||||
expect(parsed.isLegacy).toEqual(false);
|
||||
});
|
||||
|
||||
tap.test('parseTestFilename - deno+bun runtime', async () => {
|
||||
const parsed = parseTestFilename('test.deno+bun.ts');
|
||||
expect(parsed.baseName).toEqual('test');
|
||||
expect(parsed.runtimes).toEqual(['deno', 'bun']);
|
||||
expect(parsed.modifiers).toEqual([]);
|
||||
expect(parsed.extension).toEqual('ts');
|
||||
expect(parsed.isLegacy).toEqual(false);
|
||||
});
|
||||
|
||||
tap.test('parseTestFilename - with nonci modifier', async () => {
|
||||
const parsed = parseTestFilename('test.chromium.nonci.ts');
|
||||
expect(parsed.baseName).toEqual('test');
|
||||
expect(parsed.runtimes).toEqual(['chromium']);
|
||||
expect(parsed.modifiers).toEqual(['nonci']);
|
||||
expect(parsed.extension).toEqual('ts');
|
||||
expect(parsed.isLegacy).toEqual(false);
|
||||
});
|
||||
|
||||
tap.test('parseTestFilename - multi-runtime with nonci', async () => {
|
||||
const parsed = parseTestFilename('test.node+chromium.nonci.ts');
|
||||
expect(parsed.baseName).toEqual('test');
|
||||
expect(parsed.runtimes).toEqual(['node', 'chromium']);
|
||||
expect(parsed.modifiers).toEqual(['nonci']);
|
||||
expect(parsed.extension).toEqual('ts');
|
||||
expect(parsed.isLegacy).toEqual(false);
|
||||
});
|
||||
|
||||
tap.test('parseTestFilename - legacy browser', async () => {
|
||||
const parsed = parseTestFilename('test.browser.ts');
|
||||
expect(parsed.baseName).toEqual('test');
|
||||
expect(parsed.runtimes).toEqual(['chromium']);
|
||||
expect(parsed.modifiers).toEqual([]);
|
||||
expect(parsed.extension).toEqual('ts');
|
||||
expect(parsed.isLegacy).toEqual(true);
|
||||
});
|
||||
|
||||
tap.test('parseTestFilename - legacy both', async () => {
|
||||
const parsed = parseTestFilename('test.both.ts');
|
||||
expect(parsed.baseName).toEqual('test');
|
||||
expect(parsed.runtimes).toEqual(['node', 'chromium']);
|
||||
expect(parsed.modifiers).toEqual([]);
|
||||
expect(parsed.extension).toEqual('ts');
|
||||
expect(parsed.isLegacy).toEqual(true);
|
||||
});
|
||||
|
||||
tap.test('parseTestFilename - legacy browser with nonci', async () => {
|
||||
const parsed = parseTestFilename('test.browser.nonci.ts');
|
||||
expect(parsed.baseName).toEqual('test');
|
||||
expect(parsed.runtimes).toEqual(['chromium']);
|
||||
expect(parsed.modifiers).toEqual(['nonci']);
|
||||
expect(parsed.extension).toEqual('ts');
|
||||
expect(parsed.isLegacy).toEqual(true);
|
||||
});
|
||||
|
||||
tap.test('parseTestFilename - complex basename', async () => {
|
||||
const parsed = parseTestFilename('test.some.feature.node.ts');
|
||||
expect(parsed.baseName).toEqual('test.some.feature');
|
||||
expect(parsed.runtimes).toEqual(['node']);
|
||||
expect(parsed.modifiers).toEqual([]);
|
||||
expect(parsed.extension).toEqual('ts');
|
||||
expect(parsed.isLegacy).toEqual(false);
|
||||
});
|
||||
|
||||
tap.test('parseTestFilename - default to node when no runtime', async () => {
|
||||
const parsed = parseTestFilename('test.ts');
|
||||
expect(parsed.baseName).toEqual('test');
|
||||
expect(parsed.runtimes).toEqual(['node']);
|
||||
expect(parsed.modifiers).toEqual([]);
|
||||
expect(parsed.extension).toEqual('ts');
|
||||
expect(parsed.isLegacy).toEqual(false);
|
||||
});
|
||||
|
||||
tap.test('parseTestFilename - tsx extension', async () => {
|
||||
const parsed = parseTestFilename('test.chromium.tsx');
|
||||
expect(parsed.baseName).toEqual('test');
|
||||
expect(parsed.runtimes).toEqual(['chromium']);
|
||||
expect(parsed.modifiers).toEqual([]);
|
||||
expect(parsed.extension).toEqual('tsx');
|
||||
expect(parsed.isLegacy).toEqual(false);
|
||||
});
|
||||
|
||||
tap.test('parseTestFilename - deduplicates runtime tokens', async () => {
|
||||
const parsed = parseTestFilename('test.node+node.ts');
|
||||
expect(parsed.baseName).toEqual('test');
|
||||
expect(parsed.runtimes).toEqual(['node']);
|
||||
expect(parsed.modifiers).toEqual([]);
|
||||
expect(parsed.extension).toEqual('ts');
|
||||
expect(parsed.isLegacy).toEqual(false);
|
||||
});
|
||||
|
||||
tap.test('isLegacyFilename - detects browser', async () => {
|
||||
expect(isLegacyFilename('test.browser.ts')).toEqual(true);
|
||||
});
|
||||
|
||||
tap.test('isLegacyFilename - detects both', async () => {
|
||||
expect(isLegacyFilename('test.both.ts')).toEqual(true);
|
||||
});
|
||||
|
||||
tap.test('isLegacyFilename - rejects new naming', async () => {
|
||||
expect(isLegacyFilename('test.node.ts')).toEqual(false);
|
||||
expect(isLegacyFilename('test.chromium.ts')).toEqual(false);
|
||||
expect(isLegacyFilename('test.node+chromium.ts')).toEqual(false);
|
||||
});
|
||||
|
||||
tap.test('getLegacyMigrationTarget - browser to chromium', async () => {
|
||||
const target = getLegacyMigrationTarget('test.browser.ts');
|
||||
expect(target).toEqual('test.chromium.ts');
|
||||
});
|
||||
|
||||
tap.test('getLegacyMigrationTarget - both to node+chromium', async () => {
|
||||
const target = getLegacyMigrationTarget('test.both.ts');
|
||||
expect(target).toEqual('test.node+chromium.ts');
|
||||
});
|
||||
|
||||
tap.test('getLegacyMigrationTarget - browser with nonci', async () => {
|
||||
const target = getLegacyMigrationTarget('test.browser.nonci.ts');
|
||||
expect(target).toEqual('test.chromium.nonci.ts');
|
||||
});
|
||||
|
||||
tap.test('getLegacyMigrationTarget - both with nonci', async () => {
|
||||
const target = getLegacyMigrationTarget('test.both.nonci.ts');
|
||||
expect(target).toEqual('test.node+chromium.nonci.ts');
|
||||
});
|
||||
|
||||
tap.test('getLegacyMigrationTarget - returns null for non-legacy', async () => {
|
||||
const target = getLegacyMigrationTarget('test.node.ts');
|
||||
expect(target).toEqual(null);
|
||||
});
|
||||
|
||||
tap.test('parseTestFilename - handles full paths', async () => {
|
||||
const parsed = parseTestFilename('/path/to/test.node+chromium.ts');
|
||||
expect(parsed.baseName).toEqual('test');
|
||||
expect(parsed.runtimes).toEqual(['node', 'chromium']);
|
||||
expect(parsed.original).toEqual('test.node+chromium.ts');
|
||||
});
|
||||
|
||||
export default tap.start();
|
Reference in New Issue
Block a user