Test with LiteralUnion.
",
- "examples": "tsfaker.literalUnionParamMethod(value: 'a' | 'b' | string, namedValue: AB | string, array: readonly Array<'a' | 'b' | string>, namedArray: readonly Array<AB | string>, mixed: 'a' | 'b' | string | readonly Array<'a' | 'b' | string>, namedMixed: AB | string | readonly Array<AB | string>): string
+ "examples": "tsfaker.literalUnionParamMethod(value: 'a' | 'b' | string, namedValue: 'a' | 'b' | string, array: readonly Array<'a' | 'b' | string>, namedArray: readonly Array<'a' | 'b' | string>, mixed: 'a' | 'b' | string | readonly Array<'a' | 'b' | string>, namedMixed: 'a' | 'b' | string | readonly Array<'a' | 'b' | string>): string
",
"name": "literalUnionParamMethod",
@@ -147,7 +147,7 @@ exports[`signature > analyzeSignature() > literalUnionParamMethod 1`] = `
"description": "'a'
or 'b'
.
",
"name": "namedValue",
- "type": "AB | string",
+ "type": "'a' | 'b' | string",
},
{
"default": undefined,
@@ -161,7 +161,7 @@ exports[`signature > analyzeSignature() > literalUnionParamMethod 1`] = `
"description": "Array of 'a'
or 'b'
.
",
"name": "namedArray",
- "type": "Array",
+ "type": "Array<'a' | 'b' | string>",
},
{
"default": undefined,
@@ -175,13 +175,13 @@ exports[`signature > analyzeSignature() > literalUnionParamMethod 1`] = `
"description": "Value 'a'
or 'b'
or an array thereof.
",
"name": "namedMixed",
- "type": "AB | string | Array",
+ "type": "'a' | 'b' | string | Array<'a' | 'b' | string>",
},
],
"returns": "string",
"seeAlsos": [],
"since": "",
- "sourcePath": "test/scripts/apidoc/signature.example.ts#L142",
+ "sourcePath": "test/scripts/apidoc/signature.example.ts#L155",
"title": "Literal Union Param Method",
}
`;
@@ -202,7 +202,7 @@ exports[`signature > analyzeSignature() > methodWithDeprecated 1`] = `
"test.apidoc.methodWithExample()",
],
"since": "",
- "sourcePath": "test/scripts/apidoc/signature.example.ts#L260",
+ "sourcePath": "test/scripts/apidoc/signature.example.ts#L273",
"title": "Method With Deprecated",
}
`;
@@ -255,7 +255,7 @@ exports[`signature > analyzeSignature() > methodWithDeprecatedOption 1`] = `
"returns": "number",
"seeAlsos": [],
"since": "",
- "sourcePath": "test/scripts/apidoc/signature.example.ts#L272",
+ "sourcePath": "test/scripts/apidoc/signature.example.ts#L285",
"title": "Method With Deprecated Option",
}
`;
@@ -274,7 +274,7 @@ exports[`signature > analyzeSignature() > methodWithExample 1`] = `
"returns": "number",
"seeAlsos": [],
"since": "",
- "sourcePath": "test/scripts/apidoc/signature.example.ts#L249",
+ "sourcePath": "test/scripts/apidoc/signature.example.ts#L262",
"title": "Method With Example",
}
`;
@@ -295,7 +295,7 @@ exports[`signature > analyzeSignature() > methodWithMultipleSeeMarkers 1`] = `
"test.apidoc.methodWithDeprecated()",
],
"since": "",
- "sourcePath": "test/scripts/apidoc/signature.example.ts#L299",
+ "sourcePath": "test/scripts/apidoc/signature.example.ts#L312",
"title": "Method With Multiple See Markers",
}
`;
@@ -316,7 +316,7 @@ exports[`signature > analyzeSignature() > methodWithMultipleSeeMarkersAndBacktic
"test.apidoc.methodWithDeprecated() with parameter bar
and baz
.",
],
"since": "",
- "sourcePath": "test/scripts/apidoc/signature.example.ts#L309",
+ "sourcePath": "test/scripts/apidoc/signature.example.ts#L322",
"title": "Method With Multiple See Markers And Backticks",
}
`;
@@ -334,7 +334,7 @@ exports[`signature > analyzeSignature() > methodWithSinceMarker 1`] = `
"returns": "number",
"seeAlsos": [],
"since": "1.0.0",
- "sourcePath": "test/scripts/apidoc/signature.example.ts#L318",
+ "sourcePath": "test/scripts/apidoc/signature.example.ts#L331",
"title": "Method With Since Marker",
}
`;
@@ -374,7 +374,7 @@ exports[`signature > analyzeSignature() > multiParamMethod 1`] = `
"returns": "number",
"seeAlsos": [],
"since": "",
- "sourcePath": "test/scripts/apidoc/signature.example.ts#L110",
+ "sourcePath": "test/scripts/apidoc/signature.example.ts#L112",
"title": "Multi Param Method",
}
`;
@@ -392,7 +392,7 @@ exports[`signature > analyzeSignature() > noParamMethod 1`] = `
"returns": "number",
"seeAlsos": [],
"since": "",
- "sourcePath": "test/scripts/apidoc/signature.example.ts#L72",
+ "sourcePath": "test/scripts/apidoc/signature.example.ts#L74",
"title": "No Param Method",
}
`;
@@ -418,7 +418,7 @@ exports[`signature > analyzeSignature() > optionalStringParamMethod 1`] = `
"returns": "number",
"seeAlsos": [],
"since": "",
- "sourcePath": "test/scripts/apidoc/signature.example.ts#L90",
+ "sourcePath": "test/scripts/apidoc/signature.example.ts#L92",
"title": "Optional String Param Method",
}
`;
@@ -487,7 +487,7 @@ It also has a more complex description.
"returns": "number",
"seeAlsos": [],
"since": "",
- "sourcePath": "test/scripts/apidoc/signature.example.ts#L199",
+ "sourcePath": "test/scripts/apidoc/signature.example.ts#L212",
"title": "Options Inline Param Method With Defaults",
}
`;
@@ -527,7 +527,7 @@ exports[`signature > analyzeSignature() > optionsInterfaceParamMethodWithDefault
"returns": "number",
"seeAlsos": [],
"since": "",
- "sourcePath": "test/scripts/apidoc/signature.example.ts#L235",
+ "sourcePath": "test/scripts/apidoc/signature.example.ts#L248",
"title": "Options Interface Param Method With Defaults",
}
`;
@@ -594,7 +594,7 @@ exports[`signature > analyzeSignature() > optionsParamMethod 1`] = `
"returns": "number",
"seeAlsos": [],
"since": "",
- "sourcePath": "test/scripts/apidoc/signature.example.ts#L169",
+ "sourcePath": "test/scripts/apidoc/signature.example.ts#L182",
"title": "Options Param Method",
}
`;
@@ -634,7 +634,7 @@ exports[`signature > analyzeSignature() > optionsTypeParamMethodWithDefaults 1`]
"returns": "number",
"seeAlsos": [],
"since": "",
- "sourcePath": "test/scripts/apidoc/signature.example.ts#L217",
+ "sourcePath": "test/scripts/apidoc/signature.example.ts#L230",
"title": "Options Type Param Method With Defaults",
}
`;
@@ -660,7 +660,7 @@ exports[`signature > analyzeSignature() > requiredNumberParamMethod 1`] = `
"returns": "number",
"seeAlsos": [],
"since": "",
- "sourcePath": "test/scripts/apidoc/signature.example.ts#L81",
+ "sourcePath": "test/scripts/apidoc/signature.example.ts#L83",
"title": "Required Number Param Method",
}
`;
@@ -670,7 +670,11 @@ exports[`signature > analyzeSignature() > stringUnionParamMethod 1`] = `
"deprecated": undefined,
"description": "Test with string union.
",
- "examples": "tsfaker.stringUnionParamMethod(value: 'a' | 'b'): string
+ "examples": "tsfaker.stringUnionParamMethod(value: 'a' | 'b', options?: {
+ casing: 'lower' | 'mixed' | 'upper',
+ excludes: readonly AlphaNumericChar[],
+ format: 'binary' | 'css' | 'decimal' | 'hex'
+}): string
",
"name": "stringUnionParamMethod",
@@ -682,11 +686,39 @@ exports[`signature > analyzeSignature() > stringUnionParamMethod 1`] = `
"name": "value",
"type": "'a' | 'b'",
},
+ {
+ "default": undefined,
+ "description": "The options parameter.
+",
+ "name": "options?",
+ "type": "{ ... }",
+ },
+ {
+ "default": undefined,
+ "description": "The casing parameter.
+",
+ "name": "options.casing?",
+ "type": "'lower' | 'mixed' | 'upper'",
+ },
+ {
+ "default": undefined,
+ "description": "The excludes parameter.
+",
+ "name": "options.excludes?",
+ "type": "readonly AlphaNumericChar[]",
+ },
+ {
+ "default": undefined,
+ "description": "The format parameter.
+",
+ "name": "options.format?",
+ "type": "'binary' | 'css' | 'decimal' | 'hex'",
+ },
],
"returns": "string",
"seeAlsos": [],
"since": "",
- "sourcePath": "test/scripts/apidoc/signature.example.ts#L128",
+ "sourcePath": "test/scripts/apidoc/signature.example.ts#L134",
"title": "String Union Param Method",
}
`;
diff --git a/test/scripts/apidoc/examplesAndDeprecations.spec.ts b/test/scripts/apidoc/examplesAndDeprecations.spec.ts
deleted file mode 100644
index 5ff635b202c..00000000000
--- 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/signature.example.ts b/test/scripts/apidoc/signature.example.ts
index 1013365f4eb..87bc331e07a 100644
--- a/test/scripts/apidoc/signature.example.ts
+++ b/test/scripts/apidoc/signature.example.ts
@@ -1,3 +1,5 @@
+import type { Casing, ColorFormat } from '../../../src';
+import type { AlphaNumericChar } from '../../../src/modules/string';
import type { LiteralUnion } from '../../../src/utils/types';
/**
@@ -124,9 +126,20 @@ export class SignatureTest {
* Test with string union.
*
* @param value `'a'` or `'b'`.
+ * @param options The options parameter.
+ * @param options.casing The casing parameter.
+ * @param options.format The format parameter.
+ * @param options.excludes The excludes parameter.
*/
- stringUnionParamMethod(value: 'a' | 'b'): string {
- return value;
+ stringUnionParamMethod(
+ value: 'a' | 'b',
+ options?: {
+ casing?: Casing;
+ format?: 'hex' | ColorFormat;
+ excludes?: ReadonlyArray;
+ }
+ ): string {
+ return value + options.format;
}
/**
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 00000000000..602864b13be
--- /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
+ );
+ });
+ }
+ );
+ });
+});