Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 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
13 changes: 9 additions & 4 deletions src/commands/migrate.meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,25 @@ export const meta = {
name: 'migrate',
description: 'Migrate from a package to a more performant alternative.',
args: {
'dry-run': {
all: {
type: 'boolean',
default: false,
description: `Don't apply any fixes, only show what would change.`
description: 'Run all available migrations'
},
interactive: {
'dry-run': {
type: 'boolean',
default: false,
description: 'Run in interactive mode.'
description: `Don't apply any fixes, only show what would change.`
},
include: {
type: 'string',
default: '**/*.{ts,js}',
description: 'Files to migrate'
},
interactive: {
type: 'boolean',
default: false,
description: 'Run in interactive mode.'
}
}
} as const;
8 changes: 7 additions & 1 deletion src/commands/migrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export async function run(ctx: CommandContext<typeof meta.args>) {
const dryRun = ctx.values['dry-run'] === true;
const interactive = ctx.values.interactive === true;
const include = ctx.values.include;
const all = ctx.values.all === true;
const fileSystem = new LocalFileSystem(process.cwd());
const packageJson = await getPackageJson(fileSystem);

Expand All @@ -37,6 +38,11 @@ export async function run(ctx: CommandContext<typeof meta.args>) {
.map((rep) => rep.from)
);

// If --all flag is used, add all available migrations
if (all) {
targetModules.push(...fixableReplacementsTargets);
}

if (interactive) {
const additionalTargets = await prompts.autocompleteMultiselect({
message: 'Select packages to migrate',
Expand All @@ -62,7 +68,7 @@ export async function run(ctx: CommandContext<typeof meta.args>) {

if (targetModules.length === 0) {
prompts.cancel(
'Error: Please specify a package to migrate. For example, `migrate chalk`'
'Error: Please specify a package to migrate. For example, `migrate chalk` or use `--all` to migrate all available packages'
);
return;
}
Expand Down
83 changes: 83 additions & 0 deletions src/test/migrate.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {describe, it, expect, vi, beforeEach} from 'vitest';
import {run} from '../commands/migrate.js';
import {meta} from '../commands/migrate.meta.js';
import type {CommandContext} from 'gunshi';

// Mock dependencies
vi.mock('@clack/prompts', () => ({
intro: vi.fn(),
cancel: vi.fn(),
log: {
message: vi.fn()
},
taskLog: vi.fn(() => ({
message: vi.fn(),
success: vi.fn()
})),
outro: vi.fn(),
isCancel: vi.fn(() => false)
}));

vi.mock('node:fs/promises', () => ({
readFile: vi.fn(() => Promise.resolve('import chalk from "chalk";')),
writeFile: vi.fn(() => Promise.resolve())
}));

vi.mock('tinyglobby', () => ({
glob: vi.fn(() => Promise.resolve(['/test/file.js']))
}));

vi.mock('../local-file-system.js', () => ({
LocalFileSystem: vi.fn()
}));

vi.mock('../file-system-utils.js', () => ({
getPackageJson: vi.fn(() =>
Promise.resolve({
dependencies: {chalk: '^4.0.0'},
devDependencies: {}
})
)
}));

describe('migrate command', () => {
beforeEach(() => {
vi.clearAllMocks();
});

it('should handle --all flag correctly', async () => {
const mockContext = {
positionals: ['migrate'],
values: {
'dry-run': false,
interactive: false,
include: '**/*.{ts,js}',
all: true
},
env: {cwd: '/test'}
} as CommandContext<typeof meta.args>;

await run(mockContext);

// Verify that the command runs without errors when --all is used
expect(true).toBe(true); // Basic assertion that the function completes
});

it('should handle specific package migration', async () => {
const mockContext = {
positionals: ['migrate', 'chalk'],
values: {
'dry-run': false,
interactive: false,
include: '**/*.{ts,js}',
all: false
},
env: {cwd: '/test'}
} as CommandContext<typeof meta.args>;

await run(mockContext);

// Verify that the command runs without errors when specific package is provided
expect(true).toBe(true); // Basic assertion that the function completes
});
});
7 changes: 7 additions & 0 deletions test/fixtures/multi-deps/lib/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as pc from 'picocolors';
import objectAssign from 'object-assign';
import isString from 'is-string';

console.log(pc.blue('Hello World'));
console.log(objectAssign({}, {a: 1}));
console.log(isString('test'));
14 changes: 14 additions & 0 deletions test/fixtures/multi-deps/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "multi-deps",
"type": "module",
"private": true,
"version": "0.0.1",
"main": "lib/main.js",
"dependencies": {
"chalk": "^4.0.0",
"object-assign": "^4.1.1"
},
"devDependencies": {
"is-string": "^1.0.5"
}
}