Skip to content

Commit 0bb868b

Browse files
committed
CCM-12896: Add unit tests for typescript-schema-generator
1 parent f7f51fc commit 0bb868b

File tree

11 files changed

+289
-43
lines changed

11 files changed

+289
-43
lines changed

package-lock.json

Lines changed: 90 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/config/sonar-scanner.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ sonar.tests=tests/, src/asyncapigenerator/tests, src/cloudeventjekylldocs/tests,
88
sonar.test.inclusions=tests/**, src/**/tests/**, src/**/__tests__/**, lambdas/**/src/__tests__/**, utils/utils/src/__tests__/**
99
sonar.terraform.provider.aws.version=5.54.1
1010
sonar.cpd.exclusions=**.test.*
11-
sonar.coverage.exclusions=tests/**, src/**/tests/**, src/**/__tests__/**, **/*.dev.*, lambdas/**/src/__tests__/**, **/jest.config.ts, **/jest.config.cjs, scripts/**/*.*, docs/**/*.*, utils/utils/src/__tests__/**, src/asyncapigenerator/example_usage.py, src/asyncapigenerator/test_generator.py, src/eventcatalogasyncapiimporter/examples.py, src/typescript-schema-generator/**
11+
sonar.coverage.exclusions=tests/**, src/**/tests/**, src/**/__tests__/**, **/*.dev.*, lambdas/**/src/__tests__/**, **/jest.config.ts, **/jest.config.cjs, scripts/**/*.*, docs/**/*.*, utils/utils/src/__tests__/**, src/asyncapigenerator/example_usage.py, src/asyncapigenerator/test_generator.py, src/eventcatalogasyncapiimporter/examples.py
1212

1313
sonar.python.coverage.reportPaths=src/asyncapigenerator/coverage.xml,src/cloudeventjekylldocs/coverage.xml,src/eventcatalogasyncapiimporter/coverage.xml
1414
sonar.javascript.lcov.reportPaths=lcov.info,src/cloudevents/coverage/lcov.info
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { baseJestConfig } from '../../jest.config.base';
2+
3+
const config = {
4+
...baseJestConfig,
5+
coveragePathIgnorePatterns: [
6+
...(baseJestConfig.coveragePathIgnorePatterns ?? []),
7+
'src/generate-types-cli.ts',
8+
'src/generate-validators-cli.ts',
9+
],
10+
};
11+
12+
export default config;

src/typescript-schema-generator/package.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,12 @@
66
},
77
"description": "Generate Typescript types and standalone validator functions for the application's event schemas.",
88
"devDependencies": {
9+
"@types/jest": "^29.5.14",
10+
"@types/mock-fs": "^4.13.4",
11+
"cross-env": "^10.1.0",
912
"eslint": "^9.39.1",
13+
"jest": "^29.7.0",
14+
"mock-fs": "^5.5.0",
1015
"rimraf": "^5.0.10",
1116
"tsx": "^4.20.6"
1217
},
@@ -23,11 +28,11 @@
2328
"scripts": {
2429
"clean": "rimraf types validators",
2530
"generate-dependencies": "npm run generate-types && npm run generate-validators",
26-
"generate-types": "tsx src/generate-types.ts",
27-
"generate-validators": "tsx src/generate-validators.ts",
31+
"generate-types": "tsx src/generate-types-cli.ts",
32+
"generate-validators": "tsx src/generate-validators-cli.ts",
2833
"lint": "eslint src",
2934
"lint:fix": "eslint src --fix",
30-
"test:unit": "echo \"No unit tests configured\"",
35+
"test:unit": "cross-env NODE_OPTIONS=\"$NODE_OPTIONS --experimental-vm-modules\" jest",
3136
"typecheck": "tsc --noEmit"
3237
},
3338
"version": "0.0.1"
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/* eslint-disable security/detect-non-literal-fs-filename */
2+
3+
import { eventSchemasDir } from 'file-utils';
4+
import { generateTypes } from 'generate-types';
5+
import { compile } from 'json-schema-to-typescript';
6+
import mockFs from 'mock-fs';
7+
import { readFileSync, readdirSync } from 'node:fs';
8+
import path from 'node:path';
9+
10+
jest.mock('json-schema-to-typescript');
11+
12+
describe('generate-types', () => {
13+
const outputDir = path.resolve(__dirname, '..', '..', 'types');
14+
15+
beforeEach(() => {
16+
mockFs({
17+
[eventSchemasDir]: {
18+
'one.flattened.schema.json': '{"title": "One"}',
19+
'two.flattened.schema.json': '{"title": "Two"}',
20+
'three.flattened.schema.json': '{"title": "Three"}',
21+
},
22+
});
23+
24+
jest.mocked(compile).mockResolvedValue('Some TS code');
25+
26+
jest.spyOn(console, 'log').mockImplementation(() => {});
27+
jest.spyOn(console, 'group').mockImplementation(() => {});
28+
});
29+
30+
afterEach(() => {
31+
mockFs.restore();
32+
});
33+
34+
it('should generate a type declaration file for each schema', async () => {
35+
await generateTypes();
36+
37+
const typeDeclarationFiles = readdirSync(outputDir);
38+
39+
expect(typeDeclarationFiles.length).toBe(4); // 3 schemas + 1 index file
40+
expect(typeDeclarationFiles).toEqual(
41+
expect.arrayContaining(['One.d.ts', 'Two.d.ts', 'Three.d.ts']),
42+
);
43+
});
44+
45+
it('should create an index file exporting all generated types', async () => {
46+
await generateTypes();
47+
48+
const indexFileContents = readFileSync(
49+
path.join(outputDir, 'index.d.ts'),
50+
'utf8',
51+
);
52+
expect(indexFileContents).toContain("export * from './One';");
53+
expect(indexFileContents).toContain("export * from './Two';");
54+
expect(indexFileContents).toContain("export * from './Three';");
55+
});
56+
});
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/* eslint-disable security/detect-non-literal-fs-filename */
2+
import standaloneCode from 'ajv/dist/standalone';
3+
import { eventSchemasDir } from 'file-utils';
4+
import { generateValidators } from 'generate-validators';
5+
import mockFs from 'mock-fs';
6+
import { readFileSync, readdirSync } from 'node:fs';
7+
import path from 'node:path';
8+
9+
jest.mock('ajv/dist/2020');
10+
jest.mock('ajv/dist/standalone');
11+
12+
describe('generate-validators', () => {
13+
const outputDir = path.resolve(__dirname, '..', '..', 'validators');
14+
15+
beforeEach(() => {
16+
mockFs({
17+
[eventSchemasDir]: {
18+
'one.flattened.schema.json': '{"title": "One"}',
19+
'two.flattened.schema.json': '{"title": "Two"}',
20+
'three.flattened.schema.json': '{"title": "Three"}',
21+
},
22+
});
23+
24+
jest.mocked(standaloneCode).mockReturnValue('Some validator code');
25+
26+
jest.spyOn(console, 'log').mockImplementation(() => {});
27+
jest.spyOn(console, 'group').mockImplementation(() => {});
28+
});
29+
30+
afterEach(() => {
31+
mockFs.restore();
32+
});
33+
34+
it('should generate a validator function file for each schema', () => {
35+
generateValidators();
36+
37+
const validatorFunctionFiles = readdirSync(outputDir);
38+
39+
expect(validatorFunctionFiles.length).toBe(4); // 3 schemas + 1 index file
40+
expect(validatorFunctionFiles).toEqual(
41+
expect.arrayContaining(['One.js', 'Two.js', 'Three.js']),
42+
);
43+
});
44+
45+
it('should create an index file declaring modules for all generated files', () => {
46+
generateValidators();
47+
48+
const indexFileContents = readFileSync(
49+
path.join(outputDir, 'index.d.ts'),
50+
'utf8',
51+
);
52+
expect(indexFileContents).toContain(
53+
"declare module 'typescript-schema-generator/One.js';",
54+
);
55+
expect(indexFileContents).toContain(
56+
"declare module 'typescript-schema-generator/Two.js';",
57+
);
58+
expect(indexFileContents).toContain(
59+
"declare module 'typescript-schema-generator/Three.js';",
60+
);
61+
});
62+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/* eslint-disable no-console */
2+
3+
import { generateTypes } from 'generate-types';
4+
5+
generateTypes().catch((error) => {
6+
console.error('Error generating types:', error);
7+
throw error;
8+
});

src/typescript-schema-generator/src/generate-types.ts

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ import {
1010
writeTypesIndex,
1111
} from 'file-utils';
1212

13-
const eventSchemaFilenames = listEventSchemas();
14-
const outputDir = createOutputDir('types');
13+
export async function generateTypes() {
14+
const eventSchemaFilenames = listEventSchemas();
15+
const outputDir = createOutputDir('types');
16+
console.log(`Output directory created at ${outputDir}`);
1517

16-
async function generateTypes() {
18+
console.group('Writing type declaration files:');
1719
const indexLines: string[] = [];
1820
for (const eventSchemaFilename of eventSchemaFilenames) {
1921
const eventSchemaPath = path.join(eventSchemasDir, eventSchemaFilename);
@@ -25,16 +27,15 @@ async function generateTypes() {
2527
});
2628

2729
// Write a .d.ts file named after the schema title or file.
28-
writeFile(outputDir, `${typeName}.d.ts`, eventTs);
30+
const typeDeclarationFilename = `${typeName}.d.ts`;
31+
writeFile(outputDir, typeDeclarationFilename, eventTs);
32+
console.log(typeDeclarationFilename);
2933

3034
// Also create an export statement for this type.
3135
indexLines.push(`export * from './${typeName}';`);
3236
}
37+
console.groupEnd();
3338

3439
writeTypesIndex(outputDir, indexLines);
40+
console.log('index.d.ts file written');
3541
}
36-
37-
generateTypes().catch((error) => {
38-
console.error('Error generating types:', error);
39-
throw error;
40-
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { generateValidators } from 'generate-validators';
2+
3+
generateValidators();

0 commit comments

Comments
 (0)