Skip to content

Commit b35609d

Browse files
committed
validator test coverage
1 parent 041d88e commit b35609d

File tree

3 files changed

+236
-15
lines changed

3 files changed

+236
-15
lines changed

.changeset/gentle-mugs-nail.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@codeshift/validator': patch
3+
---
4+
5+
Adds additional test coverage to the validator package

packages/validator/src/index.spec.ts

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
jest.mock('fs-extra');
2+
3+
import fs from 'fs-extra';
4+
import path from 'path';
5+
6+
import {
7+
isValidPackageName,
8+
isValidConfig,
9+
isValidConfigAtPath,
10+
isValidPackageJson,
11+
} from '.';
12+
13+
describe('validator', () => {
14+
describe('isValidPackageName', () => {
15+
it('should detect a valid package name', () => {
16+
expect(isValidPackageName('foobar')).toEqual(true);
17+
expect(isValidPackageName('123123')).toEqual(true);
18+
expect(isValidPackageName('yo~')).toEqual(true);
19+
expect(isValidPackageName('yo-')).toEqual(true);
20+
expect(isValidPackageName('@foo__bar')).toEqual(true);
21+
expect(isValidPackageName('@foo__bar1111')).toEqual(true);
22+
expect(isValidPackageName('@foo11__bar1111')).toEqual(true);
23+
});
24+
25+
it('should detect a invalid package names', () => {
26+
expect(isValidPackageName('foo bar')).toEqual(false);
27+
expect(isValidPackageName('#foo#')).toEqual(false);
28+
expect(isValidPackageName('@foo/bar')).toEqual(false);
29+
expect(isValidPackageName('@foo/bar1111')).toEqual(false);
30+
expect(isValidPackageName('@foo11/bar1111')).toEqual(false);
31+
});
32+
});
33+
34+
describe('isValidConfig', () => {
35+
it('should validate config with transforms & presets', () => {
36+
expect(
37+
isValidConfig({
38+
transforms: {
39+
'10.0.0': 'codemod.js',
40+
},
41+
presets: {
42+
'sort-imports': 'codemod.js',
43+
},
44+
}),
45+
).toEqual(true);
46+
});
47+
48+
it('should validate config with empty transforms & presets', () => {
49+
expect(
50+
isValidConfig({
51+
transforms: {},
52+
presets: {},
53+
}),
54+
).toEqual(true);
55+
56+
expect(isValidConfig({ transforms: {} })).toEqual(true);
57+
expect(isValidConfig({ presets: {} })).toEqual(true);
58+
});
59+
60+
it('should validate config transforms', () => {
61+
expect(
62+
isValidConfig({
63+
transforms: {
64+
'10.0.0': 'codemod.js',
65+
'11.0.0': 'codemod.js',
66+
'0.0.1': 'codemod.js',
67+
'1110.0.1': 'codemod.js',
68+
},
69+
}),
70+
).toEqual(true);
71+
72+
expect(
73+
isValidConfig({
74+
transforms: {
75+
'10.0': 'codemod.js',
76+
},
77+
}),
78+
).toEqual(false);
79+
80+
expect(
81+
isValidConfig({
82+
transforms: {
83+
'hello-10.0.0': 'codemod.js',
84+
},
85+
}),
86+
).toEqual(false);
87+
});
88+
89+
it('should validate config presets', () => {
90+
expect(
91+
isValidConfig({
92+
presets: {
93+
foobar: 'codemod.js',
94+
'foo-bar': 'codemod.js',
95+
},
96+
}),
97+
).toEqual(true);
98+
99+
expect(
100+
isValidConfig({
101+
presets: {
102+
'foo bar': 'codemod.js',
103+
},
104+
}),
105+
).toEqual(false);
106+
});
107+
});
108+
109+
describe('isValidConfigAtPath', () => {
110+
afterEach(() => {
111+
jest.restoreAllMocks();
112+
jest.resetModules();
113+
});
114+
115+
it('should validate config', () => {
116+
jest.mock(
117+
path.join(__dirname, 'path', 'to', 'codeshift.config.js'),
118+
() => ({
119+
__esModule: true,
120+
default: {
121+
transforms: {
122+
'10.0.0': 'path/to/transform.js',
123+
},
124+
},
125+
}),
126+
{ virtual: true },
127+
);
128+
129+
expect(isValidConfigAtPath('path/to/')).toEqual(true);
130+
});
131+
132+
it('should error if config contains invalid transforms', () => {
133+
jest.mock(
134+
path.join(__dirname, 'path', 'to', 'codeshift.config.js'),
135+
() => ({
136+
__esModule: true,
137+
default: {
138+
transforms: {
139+
hello: '',
140+
},
141+
},
142+
}),
143+
{ virtual: true },
144+
);
145+
146+
expect(() => isValidConfigAtPath('path/to/')).toThrowError(
147+
`Invalid transform ids found for config at "path/to/".
148+
Please make sure all transforms are identified by a valid semver version. ie 10.0.0`,
149+
);
150+
});
151+
152+
it('should error if config contains invalid presets', () => {
153+
jest.mock(
154+
path.join(__dirname, 'path', 'to', 'codeshift.config.js'),
155+
() => ({
156+
__esModule: true,
157+
default: {
158+
presets: {
159+
'foo bar': '',
160+
},
161+
},
162+
}),
163+
{ virtual: true },
164+
);
165+
166+
expect(() => isValidConfigAtPath('path/to/')).toThrowError(
167+
`Invalid preset ids found for config at "path/to/".
168+
Please make sure all presets are kebab case and contain no spaces or special characters. ie sort-imports-by-scope`,
169+
);
170+
});
171+
});
172+
173+
describe('isValidPackageJson', () => {
174+
afterEach(() => jest.resetAllMocks());
175+
176+
it('should detect valid package.json', async () => {
177+
(fs.readFile as jest.Mock).mockReturnValue(`{
178+
"name": "codeshift-package",
179+
"main": "dist/index.js",
180+
"version": "0.0.1"
181+
}`);
182+
183+
const result = await isValidPackageJson('path/to/');
184+
expect(result).toEqual(true);
185+
expect(fs.readFile).toHaveBeenCalledWith('path/to/package.json', 'utf8');
186+
});
187+
188+
it('should detect invalid package.json', async () => {
189+
expect.assertions(2);
190+
191+
{
192+
(fs.readFile as jest.Mock).mockReturnValue(`{
193+
"name": "codeshift-package"
194+
}`);
195+
196+
try {
197+
await isValidPackageJson('path/to/');
198+
} catch (error) {
199+
expect(error.message).toMatch(
200+
'No main entrypoint provided in package.json',
201+
);
202+
}
203+
}
204+
205+
{
206+
(fs.readFile as jest.Mock).mockReturnValue(`{
207+
"main": "dist/index.js"
208+
}`);
209+
210+
try {
211+
await isValidPackageJson('path/to/');
212+
} catch (error) {
213+
expect(error.message).toMatch(
214+
'No package name provided in package.json',
215+
);
216+
}
217+
}
218+
});
219+
});
220+
});

packages/validator/src/index.ts

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,21 @@ import path from 'path';
44
import { CodeshiftConfig } from '@codeshift/types';
55

66
function getConfigFromPath(filePath: string): CodeshiftConfig {
7-
const configPath = path.join(process.cwd(), filePath, 'codeshift.config.js');
7+
const configPath = path.join(__dirname, filePath, 'codeshift.config.js');
88
// eslint-disable-next-line @typescript-eslint/no-var-requires
99
const config = require(configPath);
1010

1111
return !!config.default ? config.default : config;
1212
}
1313

1414
function hasValidTransforms(transforms?: Record<string, string>) {
15-
if (!transforms || !Object.keys(transforms).length) return false;
15+
if (!transforms) return true;
1616

1717
return Object.entries(transforms).every(([key]) => semver.valid(key));
1818
}
1919

2020
function hasValidPresets(presets?: Record<string, string>): boolean {
21-
if (!presets || !Object.keys(presets).length) return false;
21+
if (!presets) return true;
2222

2323
return Object.entries(presets).every(([key]) =>
2424
key.match(/^[0-9a-zA-Z\-]+$/),
@@ -31,22 +31,13 @@ export function isValidPackageName(dir: string): boolean {
3131

3232
export function isValidConfig(config: CodeshiftConfig) {
3333
return (
34-
hasValidTransforms(config.transforms) || hasValidPresets(config.presets)
34+
hasValidTransforms(config.transforms) && hasValidPresets(config.presets)
3535
);
3636
}
3737

3838
export function isValidConfigAtPath(filePath: string) {
3939
const config = getConfigFromPath(filePath);
4040

41-
if (
42-
!hasValidTransforms(config.transforms) &&
43-
!hasValidPresets(config.presets)
44-
) {
45-
throw new Error(
46-
`At least one transform should be specified for config at "${filePath}"`,
47-
);
48-
}
49-
5041
if (!hasValidTransforms(config.transforms)) {
5142
throw new Error(`Invalid transform ids found for config at "${filePath}".
5243
Please make sure all transforms are identified by a valid semver version. ie 10.0.0`);
@@ -56,10 +47,15 @@ Please make sure all transforms are identified by a valid semver version. ie 10.
5647
throw new Error(`Invalid preset ids found for config at "${filePath}".
5748
Please make sure all presets are kebab case and contain no spaces or special characters. ie sort-imports-by-scope`);
5849
}
50+
51+
return true;
5952
}
6053

61-
export async function isValidPackageJson(path: string) {
62-
const packageJsonRaw = await fs.readFile(path + '/package.json', 'utf8');
54+
export async function isValidPackageJson(targetPath: string) {
55+
const packageJsonRaw = await fs.readFile(
56+
path.join(targetPath, 'package.json'),
57+
'utf8',
58+
);
6359
const packageJson = JSON.parse(packageJsonRaw);
6460

6561
if (!packageJson.name) {

0 commit comments

Comments
 (0)