Skip to content

Commit 591800c

Browse files
committed
chore: update-tests
update to make tests more robust for package-generator
1 parent c367164 commit 591800c

File tree

5 files changed

+274
-98
lines changed

5 files changed

+274
-98
lines changed

tools/create-package/src/generators/create-package-generator.spec.ts

Lines changed: 0 additions & 79 deletions
This file was deleted.
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
2+
import { Tree, installPackagesTask, formatFiles } from '@nx/devkit';
3+
import { createPackageGeneratorGenerator } from './create-package-generator';
4+
import { CreatePackageGeneratorGeneratorSchema } from './schema';
5+
import { beforeEach, describe, expect, it, vi } from 'vitest';
6+
7+
// Mock installPackagesTask and formatFiles
8+
vi.mock('@nx/devkit', async () => {
9+
const actual = await vi.importActual('@nx/devkit');
10+
return {
11+
...actual,
12+
installPackagesTask: vi.fn(),
13+
formatFiles: vi.fn(),
14+
};
15+
});
16+
17+
describe('create-package-generator generator', () => {
18+
let tree: Tree;
19+
let options: CreatePackageGeneratorGeneratorSchema = { name: 'test' };
20+
21+
beforeEach(() => {
22+
tree = createTreeWithEmptyWorkspace();
23+
vi.clearAllMocks();
24+
});
25+
26+
const getJson = (path: string) => {
27+
const contents = tree.read(path) ?? new Buffer('');
28+
const value = Buffer.from(contents).toString();
29+
30+
return JSON.parse(value);
31+
};
32+
33+
it('should run successfully', async () => {
34+
options = {
35+
name: 'test-package',
36+
packageScope: 'test',
37+
description: 'I have written some code',
38+
sideEffects: false,
39+
outputDir: './dist',
40+
moduleType: 'module',
41+
};
42+
const returnedFn = await createPackageGeneratorGenerator(tree, options);
43+
44+
expect(tree.exists('packages/test-package/package.json')).toBeTruthy();
45+
46+
const packageJson = getJson('packages/test-package/package.json');
47+
48+
expect(packageJson.name).toBe('@test/test-package');
49+
expect(packageJson.sideEffects).toBe(false);
50+
expect(packageJson.type).toBe('module');
51+
expect(packageJson.description).toBe('I have written some code');
52+
expect(packageJson.module).toBe('./dist/index.js');
53+
expect(packageJson.exports).toEqual({
54+
'.': './dist/index.js',
55+
'./package.json': './package.json',
56+
});
57+
expect(packageJson.dependencies).toEqual({});
58+
expect(packageJson.devDependencies).toEqual({});
59+
expect(packageJson.version).toBe('0.0.0');
60+
expect(packageJson.private).toBe(true);
61+
expect(packageJson.main).toBe('./dist/index.js');
62+
63+
expect(tree.exists('packages/test-package/src/index.ts')).toBe(true);
64+
expect(tree.exists('packages/test-package/src/lib/index.ts')).toBe(true);
65+
expect(tree.exists('packages/test-package/LICENSE')).toBe(true);
66+
67+
expect(typeof returnedFn).toBe('function');
68+
69+
returnedFn();
70+
expect(installPackagesTask).toHaveBeenCalledTimes(1);
71+
expect(installPackagesTask).toHaveBeenCalledWith(tree, true);
72+
});
73+
74+
it('should have defaults that work', async () => {
75+
options = {
76+
name: 'test-package',
77+
};
78+
const installer = await createPackageGeneratorGenerator(tree, options);
79+
80+
expect(tree.exists('packages/test-package/package.json')).toBeTruthy();
81+
82+
const packageJson = getJson('packages/test-package/package.json');
83+
84+
expect(packageJson.name).toBe('@forgerock/test-package');
85+
expect(packageJson.sideEffects).toBe(false);
86+
expect(packageJson.type).toBe('module');
87+
expect(packageJson.description).toBe('');
88+
expect(packageJson.module).toBe('./dist/index.js');
89+
expect(packageJson.exports).toEqual({
90+
'.': './dist/index.js',
91+
'./package.json': './package.json',
92+
});
93+
expect(packageJson.dependencies).toEqual({});
94+
expect(packageJson.devDependencies).toEqual({});
95+
expect(packageJson.version).toBe('0.0.0');
96+
expect(packageJson.private).toBe(true);
97+
expect(packageJson.main).toBe('./dist/index.js');
98+
99+
expect(tree.exists('packages/test-package/src/index.ts')).toBe(true);
100+
expect(tree.exists('packages/test-package/src/lib/index.ts')).toBe(true);
101+
expect(tree.exists('packages/test-package/LICENSE')).toBe(true);
102+
103+
installer();
104+
expect(installPackagesTask).toHaveBeenCalledWith(tree, true);
105+
});
106+
107+
describe('installer function', () => {
108+
it('should handle installation errors', async () => {
109+
vi.mocked(installPackagesTask).mockImplementationOnce(() => {
110+
throw new Error('Installation failed');
111+
});
112+
113+
const installer = await createPackageGeneratorGenerator(tree, { name: 'test-package' });
114+
expect(() => installer()).toThrow('Installation failed');
115+
});
116+
117+
it('should handle multiple installations', async () => {
118+
const installer = await createPackageGeneratorGenerator(tree, { name: 'test-package' });
119+
120+
installer();
121+
installer();
122+
123+
expect(installPackagesTask).toHaveBeenCalledTimes(2);
124+
expect(installPackagesTask).toHaveBeenNthCalledWith(1, tree, true);
125+
expect(installPackagesTask).toHaveBeenNthCalledWith(2, tree, true);
126+
});
127+
});
128+
129+
describe('file content validation', () => {
130+
it('should generate correct index.ts content', async () => {
131+
await createPackageGeneratorGenerator(tree, { name: 'test-package' });
132+
133+
const indexContent = tree.read('packages/test-package/src/index.ts')?.toString();
134+
expect(indexContent).toContain('import testPackage from "./lib/index.ts"');
135+
});
136+
137+
it('should generate correct lib/index.ts content', async () => {
138+
await createPackageGeneratorGenerator(tree, { name: 'test-package' });
139+
140+
const libContent = tree.read('packages/test-package/src/lib/index.ts')?.toString();
141+
expect(libContent).toBeDefined();
142+
expect(libContent).not.toBe('');
143+
});
144+
145+
it('should include correct license content', async () => {
146+
await createPackageGeneratorGenerator(tree, { name: 'test-package' });
147+
148+
const licenseContent = tree.read('packages/test-package/LICENSE')?.toString();
149+
expect(licenseContent).toBeDefined();
150+
expect(licenseContent).toContain('MIT License');
151+
});
152+
});
153+
154+
describe('package.json edge cases', () => {
155+
it('should sanitize package names properly', async () => {
156+
await createPackageGeneratorGenerator(tree, {
157+
name: 'test-package-with-special',
158+
packageScope: 'test-scope',
159+
});
160+
161+
const packageJson = getJson('packages/test-package-with-special/package.json');
162+
expect(packageJson.name).toBe('@test-scope/test-package-with-special');
163+
});
164+
165+
it('should handle very long descriptions', async () => {
166+
const longDescription = 'a'.repeat(1000);
167+
await createPackageGeneratorGenerator(tree, {
168+
name: 'test-package-long-desc',
169+
description: longDescription,
170+
});
171+
172+
const packageJson = getJson('packages/test-package-long-desc/package.json');
173+
expect(packageJson.description).toBe(longDescription);
174+
});
175+
});
176+
177+
describe('file formatting', () => {
178+
it('should call formatFiles after generating files', async () => {
179+
await createPackageGeneratorGenerator(tree, { name: 'test-package' });
180+
expect(formatFiles).toHaveBeenCalledTimes(1);
181+
expect(formatFiles).toHaveBeenCalledWith(tree);
182+
});
183+
184+
it('should still create files if formatFiles fails', async () => {
185+
vi.mocked(formatFiles).mockRejectedValueOnce(new Error('Format failed'));
186+
187+
await expect(createPackageGeneratorGenerator(tree, { name: 'test-package' })).rejects.toThrow(
188+
'Format failed',
189+
);
190+
191+
expect(tree.exists('packages/test-package/package.json')).toBe(true);
192+
});
193+
});
194+
195+
it('should error if no name is passed', async () => {
196+
const options = {};
197+
// @ts-expect-error options is purposefully invalid
198+
await expect(createPackageGeneratorGenerator(tree, options)).rejects.toThrowError(
199+
'Invalid name provided. Please provide a name',
200+
);
201+
});
202+
203+
it('should error when no moduleType is provided or its invalid', async () => {
204+
const options = {
205+
name: 'test-package',
206+
moduleType: 'invalid moduleType',
207+
};
208+
209+
// @ts-expect-error options is purposefully invalid
210+
await expect(createPackageGeneratorGenerator(tree, options)).rejects.toThrowError(
211+
'Invalid moduleType provided. Please provide a valid moduleType',
212+
);
213+
});
214+
});

tools/create-package/src/generators/files/package.json.template

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,13 @@
1010
"sideEffects": <%= sideEffects %>,
1111
"exports": {
1212
".": "./dist/index.js",
13-
"./package.json": "./package.json",
13+
"./package.json": "./package.json"
1414
},
1515
"files": ["<%= outputDir %>"],
1616
"dependencies": {},
1717
"devDependencies": {},
1818
"scripts": {
19-
"build": "tsc --project ./tsconfig.lib.json ",
19+
"build": "nx exec -- vite build",
2020
"lint": "nx exec -- eslint **/*.ts --fix",
2121
"test": "vitest",
2222
"test:watch": "vitest --watch",
Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,67 @@
11
import { defineConfig } from 'vite';
2+
import dts from 'vite-plugin-dts';
3+
import * as path from 'path';
4+
import * as pkg from './package.json';
5+
import { codecovVitePlugin } from '@codecov/vite-plugin';
26

3-
export default defineConfig(() => ({
4-
cacheDir: '../../node_modules/.vite/<%= name %>',
7+
export default defineConfig({
8+
root: __dirname,
9+
cacheDir: '../../node_modules/.vite/packages/<%= name %>',
10+
11+
plugins: [
12+
dts({
13+
rollupTypes: false,
14+
insertTypesEntry: false,
15+
entryRoot: 'src',
16+
tsconfigPath: path.join(__dirname, 'tsconfig.lib.json'),
17+
}),
18+
/**
19+
* This is specifically for tracking bundle sizes
20+
* and will only run in CI when the CODECOV_TOKEN
21+
* is available
22+
**/
23+
codecovVitePlugin({
24+
enableBundleAnalysis: process.env['CODECOV_TOKEN'] !== undefined,
25+
bundleName: '<%= name %>',
26+
uploadToken: process.env['CODECOV_TOKEN'],
27+
}),
28+
],
29+
build: {
30+
outDir: './dist',
31+
target: ['esnext', 'es2020'],
32+
rollupOptions: {
33+
output: {
34+
// This is the directory your library will be compiled to.
35+
dir: '<%= outputDir %>',
36+
preserveModules: true,
37+
preserveModulesRoot: 'src',
38+
},
39+
external: Array.from(Object.keys(pkg.dependencies) || []).concat([
40+
'./src/lib/mock-data',
41+
'@reduxjs/toolkit/query',
42+
]),
43+
},
44+
lib: {
45+
entry: 'src/index.ts',
46+
name: '<%= name %>',
47+
formats: ['es'],
48+
},
49+
reportCompressedSize: true,
50+
commonjsOptions: { transformMixedEsModules: true },
51+
},
552
test: {
6-
reporters: ['default'],
53+
cache: {
54+
dir: '../../node_modules/.vitest',
55+
},
756
globals: true,
8-
passWithNoTests: true,
9-
watch: !process.env['CI'],
57+
environment: 'jsdom',
58+
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
59+
reporters: ['default'],
1060
coverage: {
11-
enabled: Boolean(process.env['CI']),
1261
reporter: ['text', 'json', 'html'],
62+
enabled: Boolean(process.env['CI']),
1363
reportsDirectory: './coverage',
1464
provider: 'v8',
1565
},
16-
deps: {
17-
optimizer: {
18-
web: {
19-
include: ['vitest-canvas-mock'],
20-
},
21-
},
22-
},
23-
environment: 'jsdom',
24-
include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'],
2566
},
26-
}));
67+
});

0 commit comments

Comments
 (0)