aboutsummaryrefslogtreecommitdiff
path: root/test/scripts
diff options
context:
space:
mode:
authorShinigami <[email protected]>2023-03-30 17:02:32 +0200
committerGitHub <[email protected]>2023-03-30 17:02:32 +0200
commit063ba6e264ec44f797531c7612b814bd331c5f59 (patch)
treefb104a3a5587e5802d72a5fe3393f840fee6f7c7 /test/scripts
parent3562e872530b3610d95be71aa6f4f7fdfef7134f (diff)
downloadfaker-063ba6e264ec44f797531c7612b814bd331c5f59.tar.xz
faker-063ba6e264ec44f797531c7612b814bd331c5f59.zip
test: separate jsdoc tag tests (#1969)
Diffstat (limited to 'test/scripts')
-rw-r--r--test/scripts/apidoc/examplesAndDeprecations.spec.ts124
-rw-r--r--test/scripts/apidoc/verify-jsdoc-tags.spec.ts150
2 files changed, 150 insertions, 124 deletions
diff --git a/test/scripts/apidoc/examplesAndDeprecations.spec.ts b/test/scripts/apidoc/examplesAndDeprecations.spec.ts
deleted file mode 100644
index 5ff635b2..00000000
--- a/test/scripts/apidoc/examplesAndDeprecations.spec.ts
+++ /dev/null
@@ -1,124 +0,0 @@
-import { mkdirSync, writeFileSync } from 'node:fs';
-import { resolve } from 'node:path';
-import type { SpyInstance } from 'vitest';
-import {
- afterAll,
- beforeAll,
- beforeEach,
- describe,
- expect,
- it,
- vi,
-} from 'vitest';
-import {
- analyzeSignature,
- initMarkdownRenderer,
-} from '../../../scripts/apidoc/signature';
-import {
- extractDeprecated,
- extractRawExamples,
- extractSeeAlsos,
- extractSince,
- extractTagContent,
-} from '../../../scripts/apidoc/typedoc';
-import { loadProjectModules } from './utils';
-
-/*
- * This test ensures, that every method
- * - has working examples
- * - and running these do not log anything, unless the method is deprecated
- */
-
-beforeAll(initMarkdownRenderer);
-
-describe('examples and deprecations', () => {
- const modules = loadProjectModules();
-
- const consoleSpies: SpyInstance[] = Object.keys(console)
- .filter((key) => typeof console[key] === 'function')
- .map((methodName) => vi.spyOn(console, methodName as keyof typeof console));
-
- afterAll(() => {
- for (const spy of consoleSpies) {
- spy.mockRestore();
- }
- });
-
- describe.each(Object.entries(modules))('%s', (moduleName, methodsByName) => {
- beforeEach(() => {
- for (const spy of consoleSpies) {
- spy.mockReset();
- }
- });
-
- // eslint-disable-next-line @typescript-eslint/no-misused-promises
- it.each(Object.entries(methodsByName))(
- '%s',
- async (methodName, signature) => {
- // Extract examples and make them runnable
- const examples = extractRawExamples(signature).join('').trim();
-
- 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`);
- const imports = [...new Set(examples.match(/faker[^\.]*(?=\.)/g))];
- writeFileSync(
- path,
- `import { ${imports.join(
- ', '
- )} } from '../../../../../src';\n\n${examples}`
- );
-
- // Run the examples
- await import(path);
-
- // Verify logging
- const deprecatedFlag = extractDeprecated(signature) !== undefined;
- if (deprecatedFlag) {
- expect(consoleSpies[1]).toHaveBeenCalled();
- expect(
- extractTagContent('@deprecated', signature).join(''),
- '@deprecated tag without message'
- ).not.toBe('');
- } else {
- for (const spy of consoleSpies) {
- expect(spy).not.toHaveBeenCalled();
- }
- }
-
- // Verify @param tags
- analyzeSignature(signature, moduleName, methodName).parameters.forEach(
- (param) => {
- const { name, description } = param;
- const plainDescription = description.replace(/<[^>]+>/g, '').trim();
- expect(
- plainDescription,
- `Expect param ${name} to have a description`
- ).not.toBe('Missing');
- }
- );
-
- // Verify @see tag
- extractSeeAlsos(signature).forEach((link) => {
- if (link.startsWith('faker.')) {
- // Expected @see faker.xxx.yyy()
- expect(link, 'Expect method reference to contain ()').toContain(
- '('
- );
- expect(link, 'Expect method reference to contain ()').toContain(
- ')'
- );
- }
- });
-
- expect(extractSince(signature), '@since to be present').toBeTruthy();
- }
- );
- });
-});
diff --git a/test/scripts/apidoc/verify-jsdoc-tags.spec.ts b/test/scripts/apidoc/verify-jsdoc-tags.spec.ts
new file mode 100644
index 00000000..602864b1
--- /dev/null
+++ b/test/scripts/apidoc/verify-jsdoc-tags.spec.ts
@@ -0,0 +1,150 @@
+import { mkdirSync, rmdirSync, writeFileSync } from 'node:fs';
+import { resolve } from 'node:path';
+import validator from 'validator';
+import { afterAll, beforeAll, describe, expect, it, vi } from 'vitest';
+import {
+ analyzeSignature,
+ initMarkdownRenderer,
+ MISSING_DESCRIPTION,
+} from '../../../scripts/apidoc/signature';
+import {
+ extractDeprecated,
+ extractRawExamples,
+ extractSeeAlsos,
+ extractSince,
+ extractTagContent,
+} from '../../../scripts/apidoc/typedoc';
+import { loadProjectModules } from './utils';
+
+// This test ensures, that every method
+// - has working examples
+// - running these do not log anything, unless the method is deprecated
+
+beforeAll(initMarkdownRenderer);
+
+const tempDir = resolve(__dirname, 'temp');
+
+afterAll(() => {
+ // Remove temp folder
+ rmdirSync(tempDir, { recursive: true });
+});
+
+describe('verify JSDoc tags', () => {
+ const modules = loadProjectModules();
+
+ function resolveDirToModule(moduleName: string): string {
+ return resolve(tempDir, moduleName);
+ }
+
+ function resolvePathToMethodFile(
+ moduleName: string,
+ methodName: string
+ ): string {
+ const dir = resolveDirToModule(moduleName);
+ return resolve(dir, `${methodName}.ts`);
+ }
+
+ describe.each(Object.entries(modules))('%s', (moduleName, methodsByName) => {
+ describe.each(Object.entries(methodsByName))(
+ '%s',
+ (methodName, signature) => {
+ beforeAll(() => {
+ // Write temp files to disk
+
+ // Extract examples and make them runnable
+ const examples = extractRawExamples(signature).join('').trim();
+
+ // Save examples to a file to run them later in the specific tests
+ const dir = resolveDirToModule(moduleName);
+ mkdirSync(dir, { recursive: true });
+
+ const path = resolvePathToMethodFile(moduleName, methodName);
+ const imports = [...new Set(examples.match(/faker[^\.]*(?=\.)/g))];
+ writeFileSync(
+ path,
+ `import { ${imports.join(
+ ', '
+ )} } from '../../../../../src';\n\n${examples}`
+ );
+ });
+
+ it('verify @example tag', async () => {
+ // Extract the examples
+ const examples = extractRawExamples(signature).join('').trim();
+
+ expect(
+ examples,
+ `${moduleName}.${methodName} to have examples`
+ ).not.toBe('');
+
+ // Grab path to example file
+ const path = resolvePathToMethodFile(moduleName, methodName);
+
+ // Executing the examples should not throw
+ await expect(import(`${path}?scope=example`)).resolves.toBeDefined();
+ });
+
+ // This only checks whether the whole method is deprecated or not
+ // It does not check whether the method is deprecated for a specific set of arguments
+ it('verify @deprecated tag', async () => {
+ // Grab path to example file
+ const path = resolvePathToMethodFile(moduleName, methodName);
+
+ const consoleWarnSpy = vi.spyOn(console, 'warn');
+
+ // Run the examples
+ await import(`${path}?scope=deprecated`);
+
+ // Verify that deprecated methods log a warning
+ const deprecatedFlag = extractDeprecated(signature) !== undefined;
+ if (deprecatedFlag) {
+ expect(consoleWarnSpy).toHaveBeenCalled();
+ expect(
+ extractTagContent('@deprecated', signature).join(''),
+ '@deprecated tag without message'
+ ).not.toBe('');
+ } else {
+ expect(consoleWarnSpy).not.toHaveBeenCalled();
+ }
+ });
+
+ it('verify @param tags', () => {
+ analyzeSignature(
+ signature,
+ moduleName,
+ methodName
+ ).parameters.forEach((param) => {
+ const { name, description } = param;
+ const plainDescription = description.replace(/<[^>]+>/g, '').trim();
+ expect(
+ plainDescription,
+ `Expect param ${name} to have a description`
+ ).not.toBe(MISSING_DESCRIPTION);
+ });
+ });
+
+ it('verify @see tags', () => {
+ extractSeeAlsos(signature).forEach((link) => {
+ if (link.startsWith('faker.')) {
+ // Expected @see faker.xxx.yyy()
+ expect(link, 'Expect method reference to contain ()').toContain(
+ '('
+ );
+ expect(link, 'Expect method reference to contain ()').toContain(
+ ')'
+ );
+ }
+ });
+ });
+
+ it('verify @since tag', () => {
+ const since = extractSince(signature);
+ expect(since, '@since to be present').toBeTruthy();
+ expect(since, '@since to be a valid semver').toSatisfy(
+ validator.isSemVer
+ );
+ });
+ }
+ );
+ });
+});