Skip to content

Commit

Permalink
test: ensure working examples and no console spam (#908)
Browse files Browse the repository at this point in the history
  • Loading branch information
ST-DDT authored May 4, 2022
1 parent 39b74c0 commit f1dba1b
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 1 deletion.
1 change: 1 addition & 0 deletions test/scripts/apidoc/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
*.actuals.json
temp/
111 changes: 111 additions & 0 deletions test/scripts/apidoc/examplesAndDeprecations.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { mkdirSync, writeFileSync } from 'node:fs';
import { resolve } from 'node:path';
import type { DeclarationReflection, SignatureReflection } from 'typedoc';
import { ReflectionKind } from 'typedoc';
import type { SpyInstance } from 'vitest';
import { afterAll, beforeEach, describe, expect, it, vi } from 'vitest';
import { faker } from '../../../src';
import { loadProject } from './utils';

/*
* This test ensures, that every method
* - has working examples
* - and running these does not log anything, unless the method is deprecated
*/

const locales: Record<string, string> = {
GH: 'en_GH',
US: 'en_US',
};

describe('examples and deprecations', () => {
const project = loadProject();

const directs: DeclarationReflection[] = project
.getChildrenByKind(ReflectionKind.Class)
.filter((ref) => ref.name === 'Faker')[0]
.getChildrenByKind(ReflectionKind.Property)
.filter((ref) => ['fake', 'unique'].includes(ref.name));

const modules: Record<string, DeclarationReflection[]> = project
.getChildrenByKind(ReflectionKind.Namespace)[0]
.getChildrenByKind(ReflectionKind.Class)
.filter((ref) => faker[ref.name.toLowerCase()] && ref.name !== 'Mersenne')
.reduce(
(a, v) => ({
...a,
[v.name]: v.getChildrenByKind(ReflectionKind.Method),
}),
{ directs }
);

const consoleSpies: Array<SpyInstance> = Object.keys(console)
.filter((key) => typeof console[key] === 'function')
.map((methodName) => vi.spyOn(console, methodName as keyof typeof console));

afterAll(() => {
faker.locale = 'en';
for (const spy of consoleSpies) {
spy.mockRestore();
}
});

describe.each(Object.entries(modules))('%s', (moduleName, methods) => {
const methodsByName: Record<string, DeclarationReflection> = methods.reduce(
(a, v) => ({ ...a, [v.name]: v }),
{}
);

beforeEach(() => {
faker.locale = 'en';
for (const spy of consoleSpies) {
spy.mockReset();
}
});

// eslint-disable-next-line @typescript-eslint/no-misused-promises
it.each(Object.entries(methodsByName))('%s', async (methodName, method) => {
const signatures: SignatureReflection[] =
method.signatures || method.type['declaration'].signatures;
const signature = signatures[signatures.length - 1];

// Extract examples and make them runnable
let examples =
signature?.comment?.tags
.filter((tag) => tag.tagName === 'example')
.map((tag) => tag.text.trimEnd())
.join('')
.trim() ?? '';
examples = examples.replace(
/faker([A-Z]{2})\./g,
(_, locale: string) => `faker.locale = '${locales[locale]}';\nfaker.`
);

expect(examples, `${moduleName}.${methodName} to have examples`).not.toBe(
''
);

// Save examples to a file to run it
const dir = resolve(__dirname, 'temp', moduleName);
mkdirSync(dir, { recursive: true });
const path = resolve(dir, `${methodName}.ts`);
writeFileSync(
path,
`import { faker } from '../../../../../src';\n${examples}`
);

// Run the examples
await import(path);

// Verify logging
const deprecatedFlag = signature.comment?.hasTag('deprecated') ?? false;
if (deprecatedFlag) {
expect(consoleSpies[1]).toHaveBeenCalled();
} else {
for (const spy of consoleSpies) {
expect(spy).not.toHaveBeenCalled();
}
}
});
});
});
19 changes: 18 additions & 1 deletion test/scripts/apidoc/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { DeclarationReflection } from 'typedoc';
import type { DeclarationReflection, ProjectReflection } from 'typedoc';
import { ReflectionKind } from 'typedoc';
import { newTypeDocApp, patchProject } from '../../../scripts/apidoc/utils';

Expand All @@ -24,3 +24,20 @@ export function loadExampleMethods(): Record<string, DeclarationReflection> {

return methods;
}

/**
* Loads the project using TypeDoc.
*/
export function loadProject(): ProjectReflection {
const app = newTypeDocApp();

app.bootstrap({
entryPoints: ['src/index.ts'],
});

const project = app.convert();

patchProject(project);

return project;
}

0 comments on commit f1dba1b

Please sign in to comment.