diff --git a/package-lock.json b/package-lock.json index de8c5345685..8fe4eae9a29 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15772,7 +15772,6 @@ "version": "0.3.3", "resolved": "https://registry.npmjs.org/typedoc-plugin-resolve-crossmodule-references/-/typedoc-plugin-resolve-crossmodule-references-0.3.3.tgz", "integrity": "sha512-ZWWBy2WR8z9a6iXYGlyB3KrpV+JDdZv1mndYU6Eh6mInrfMCrQJi3Y5K9ihMBfuaBGB//le1nEmQLgzU3IO+dw==", - "dev": true, "engines": { "node": ">=14" }, @@ -17535,8 +17534,7 @@ "dependencies": { "handlebars": "4.7.7", "pluralize": "8.0.0", - "type-fest": "3.5.1", - "typedoc-plugin-markdown": "3.14.0" + "type-fest": "3.5.1" }, "engines": { "node": "^14.17.0 || ^16.13.0 || >=18.0.0", @@ -17544,7 +17542,10 @@ }, "peerDependencies": { "appium": "^2.0.0-beta.48", - "typedoc": ">=0.23.14" + "typedoc": "^0.23.14", + "typedoc-plugin-markdown": "^3.14.0", + "typedoc-plugin-resolve-crossmodule-references": "~0.3.3", + "typescript": "~4.7.0" } }, "packages/types": { diff --git a/package.json b/package.json index 605d9274adb..cefaa1a2424 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,7 @@ "lint:fix": "run-s \"lint -- --fix\"", "lint:commit": "commitlint", "lint:staged": "lint-staged", + "pack-all": "npm pack --workspaces --include-workspace-root", "prepublishOnly": "run-s rebuild", "reinstall": "run-s clean ci", "rebuild": "run-s clean:artifacts build:all", @@ -52,7 +53,7 @@ "sync-pkgs": "run-p sync-pkgs:*", "sync-pkgs:appium-readme": "sync-monorepo-packages --force --no-package-json --packages=packages/appium README.md", "sync-pkgs:common-fields": "sync-monorepo-packages --fields=author,license,bugs,homepage,engines", - "sync-pkgs:keywords": "sync-monorepo-packages --field=keywords --packages=\"packages/*\" --packages=\"!packages/eslint-config-appium\" --packages=\"!packages/types\"", + "sync-pkgs:keywords": "sync-monorepo-packages --field=keywords --packages=\"packages/*\" --packages=\"!packages/eslint-config-appium\" --packages=\"!packages/types\" --packages\"!packages/typedoc-plugin-appium\"", "sync-pkgs:license": "sync-monorepo-packages --force --no-package-json LICENSE", "stage-synced-pkgs": "git add -A packages/appium/README.md \"packages/*/package.json\"", "test": "npm-run-all -p lint build -s test:unit", diff --git a/packages/typedoc-plugin-appium/README.md b/packages/typedoc-plugin-appium/README.md index 50cb95e5e90..8645a1b4eeb 100644 --- a/packages/typedoc-plugin-appium/README.md +++ b/packages/typedoc-plugin-appium/README.md @@ -1,11 +1,64 @@ # `@appium/typedoc-plugin-appium` -> TypeDoc plugin for Appium & its extensions +> TypeDoc plugin for [Appium](https://appium.io) & its extensions -## Usage +## Overview + +This package leverages [TypeDoc](https://typedoc.org) to generate command documentation (HTTP endpoints, payload information, etc.) for Appium v2+ drivers and plugins. + +## Installation +```bash +npm install appium@next typedoc @appium/typedoc-plugin-appium --save-dev ``` -const typedocPluginAppium = require('@appium/typedoc-plugin-appium'); -// TODO: DEMONSTRATE API +`typedoc` and `appium` are peer dependencies of this package. Newer versions of `npm` will install these automatically (if possible). + +## Usage + +TypeDoc is configured via a `typedoc.json` or `typedoc.js` file ([read the docs](https://typedoc.org/guides/options/) for more information). + +An Appium extension author wishing to generate documentation for their extension will need to create a `typedoc.json`. At minimum, it should contain: + +> TODO: The plugin should be able to detect the entry points automatically, so this should not be necessary + +```json +{ + "entryPointStrategy": "packages", + "entryPoints": [ + "./node_modules/appium", + "./node_modules/@appium/base-driver", + "./node_modules/@appium/types", + "." + ], + "name": "", + "out": "" +} ``` + +Once this file is created, you can run `typedoc` to generate the documentation, and it will be output into the `out` directory as configured above. + +## Options + +This plugin supports all of the options from [typedoc-plugin-markdown](https://npm.im/typedoc-plugin-markdown), as well as the following: + +### `commandsDir` + +> TODO + +### `forceBreadcrumbs` + +> TODO + +### `outputBuiltinCommands` + +> TODO + +### `outputModules` + +> TODO + +## License + +Copyright © 2022 OpenJS Foundation. Licensed Apache-2.0 + diff --git a/packages/typedoc-plugin-appium/index.js b/packages/typedoc-plugin-appium/index.js index 90acd01aa4a..2441dc5a868 100644 --- a/packages/typedoc-plugin-appium/index.js +++ b/packages/typedoc-plugin-appium/index.js @@ -1 +1 @@ -module.exports = require('./build/lib/plugin.js'); +module.exports = require('./build/lib/index.js'); diff --git a/packages/typedoc-plugin-appium/lib/converter/builder.ts b/packages/typedoc-plugin-appium/lib/converter/builder.ts index 5ee1231cb25..5cf8c93bf4b 100644 --- a/packages/typedoc-plugin-appium/lib/converter/builder.ts +++ b/packages/typedoc-plugin-appium/lib/converter/builder.ts @@ -13,7 +13,7 @@ import { CommandData, ModuleCommands, CommandReflection, - CommandsReflection, + ExtensionReflection, ExecMethodData, ParentReflection, ProjectCommands, @@ -42,7 +42,7 @@ export function createCommandReflection( log: AppiumPluginLogger, ctx: Context, data: CommandData | ExecMethodData, - parent: CommandsReflection, + parent: ExtensionReflection, route?: Route ): void { const commandRefl = new CommandReflection(data, parent, route); @@ -52,7 +52,7 @@ export function createCommandReflection( } /** - * Create a new {@linkcode CommandsReflection} and all {@linkcode CommandReflection} children within + * Create a new {@linkcode ExtensionReflection} and all {@linkcode CommandReflection} children within * it. * * Note that the return value is mainly for informational purposes, since this method mutates @@ -63,27 +63,27 @@ export function createCommandReflection( * @param moduleCmds - Command information for `module` * @internal */ -export function createCommandsReflection( +export function createExtensionReflection( log: AppiumPluginLogger, ctx: Context, parent: ParentReflection, moduleCmds: ModuleCommands -): CommandsReflection { +): ExtensionReflection { // TODO: parent.name may not be right here - const commandsRefl = new CommandsReflection(parent.name, ctx.project, moduleCmds); + const extRefl = new ExtensionReflection(parent.name, parent, moduleCmds); /** * See note in {@link createCommandReflection} above about this call */ - ctx.postReflectionCreation(commandsRefl, undefined, undefined); + ctx.postReflectionCreation(extRefl, undefined, undefined); - const parentCtx = ctx.withScope(commandsRefl); + const parentCtx = ctx.withScope(extRefl); const {routeMap: routeMap, execMethodDataSet: execCommandsData} = moduleCmds; const sortedRouteMap = new Map([...routeMap].sort(([a], [b]) => a.localeCompare(b))); for (const [route, commandSet] of sortedRouteMap) { for (const data of commandSet) { - createCommandReflection(log, parentCtx, data, commandsRefl, route); + createCommandReflection(log, parentCtx, data, extRefl, route); } } @@ -92,11 +92,11 @@ export function createCommandsReflection( a.script.localeCompare(b.script) ); for (const data of sortedExecCommandsData) { - createCommandReflection(log, parentCtx, data, commandsRefl); + createCommandReflection(log, parentCtx, data, extRefl); } - ctx.finalizeDeclarationReflection(commandsRefl); - return commandsRefl; + ctx.finalizeDeclarationReflection(extRefl); + return extRefl; } /** @@ -106,18 +106,18 @@ export function createCommandsReflection( * @param ctx TypeDoc Context * @param parentLog Plugin logger * @param projectCmds Command info from converter; a map of parent reflections to parsed data - * @returns List of {@linkcode CommandsReflection} instances + * @returns List of {@linkcode ExtensionReflection} instances */ export function createReflections( ctx: Context, parentLog: AppiumPluginLogger, projectCmds: ProjectCommands -): CommandsReflection[] { +): ExtensionReflection[] { const log = parentLog.createChildLogger('builder'); const {project} = ctx; if (_.isEmpty(projectCmds)) { - log.error('No Appium commands found in the entire project!'); + log.warn('Nothing to do.'); return []; } @@ -127,7 +127,7 @@ export function createReflections( ? project : findChildByNameAndGuard(project, parentName, isParentReflection)!; - const cmdsRefl = createCommandsReflection(log, ctx, parentRefl, parentCmds); + const cmdsRefl = createExtensionReflection(log, ctx, parentRefl, parentCmds); log.info( '(%s) Created %d new command %s', diff --git a/packages/typedoc-plugin-appium/lib/converter/builtin-external-driver.ts b/packages/typedoc-plugin-appium/lib/converter/builtin-external-driver.ts index 05480d58d46..6364fc8ea76 100644 --- a/packages/typedoc-plugin-appium/lib/converter/builtin-external-driver.ts +++ b/packages/typedoc-plugin-appium/lib/converter/builtin-external-driver.ts @@ -1,19 +1,24 @@ -import {Context, ReflectionKind} from 'typedoc'; -import { - isAppiumTypesReflection, - isAsyncMethodDeclarationReflection, - isExternalDriverDeclarationReflection, -} from '../guards'; +import pluralize from 'pluralize'; +import {Context} from 'typedoc'; +import {isAppiumTypesReflection, isExternalDriverDeclarationReflection} from '../guards'; import {AppiumPluginLogger} from '../logger'; -import {deriveComment} from './comment'; import {BaseConverter} from './base-converter'; -import {AppiumTypesReflection, KnownMethodData, KnownMethods} from './types'; -import {findParentReflectionByName} from './utils'; +import {AppiumTypesReflection, KnownMethods} from './types'; +import {findAsyncMethodsInReflection, findParentReflectionByName} from './utils'; +/** + * Name of the module containing `ExternalDriver` + */ export const NAME_TYPES_MODULE = '@appium/types'; +/** + * Name of `ExternalDriver` interface + */ export const NAME_EXTERNAL_DRIVER = 'ExternalDriver'; +/** + * Converts `@appium/types` into a `KnownMethods`, if it can. + */ export class BuiltinExternalDriverConverter extends BaseConverter { /** * Creates a child logger for this instance @@ -24,7 +29,7 @@ export class BuiltinExternalDriverConverter extends BaseConverter super(ctx, log.createChildLogger('interfaces')); } - public convertMethodDeclarations(refl: AppiumTypesReflection): KnownMethods { + #convertMethodDeclarations(refl: AppiumTypesReflection): KnownMethods { const externalDriver = refl.getChildByName(NAME_EXTERNAL_DRIVER); let methods: KnownMethods = new Map(); @@ -32,46 +37,29 @@ export class BuiltinExternalDriverConverter extends BaseConverter this.log.warn('Could not find %s in %s', NAME_EXTERNAL_DRIVER, NAME_TYPES_MODULE); return methods; } - const methodRefs = externalDriver.getChildrenByKind(ReflectionKind.Method); - if (!methodRefs.length) { + methods = findAsyncMethodsInReflection(externalDriver); + + if (!methods.size) { this.log.warn('No methods found in %s', NAME_EXTERNAL_DRIVER); return methods; } - methods = new Map( - methodRefs.reduce((methods, method) => { - if (isAsyncMethodDeclarationReflection(method)) { - const commentData = deriveComment(method.name, undefined, method); - return [ - ...methods, - [ - method.name, - { - method, - comment: commentData?.comment, - commentSource: commentData?.commentSource, - }, - ], - ]; - } - this.log.verbose('(%s) Ignoring method %s', externalDriver.name, method.name); - return methods; - }, [] as [string, KnownMethodData][]) + this.log.verbose( + 'Found %s in %s', + pluralize('method declaration', methods.size, true), + NAME_EXTERNAL_DRIVER ); - this.log.verbose('Found %d method declarations in %s', methods.size, NAME_EXTERNAL_DRIVER); - return methods; } - public convert(): KnownMethods { + public override convert(): KnownMethods { const {project} = this.ctx; let methods: KnownMethods = new Map(); - const typesModule = findParentReflectionByName(project, NAME_TYPES_MODULE); if (!isAppiumTypesReflection(typesModule)) { - this.log.warn('Invalid or missing %s', NAME_TYPES_MODULE); + this.log.error('Could not find %s', NAME_TYPES_MODULE); return methods; } @@ -81,6 +69,6 @@ export class BuiltinExternalDriverConverter extends BaseConverter NAME_EXTERNAL_DRIVER ); - return this.convertMethodDeclarations(typesModule); + return this.#convertMethodDeclarations(typesModule); } } diff --git a/packages/typedoc-plugin-appium/lib/converter/builtin-method-map.ts b/packages/typedoc-plugin-appium/lib/converter/builtin-method-map.ts index 0cf377887c8..932ab68cf7b 100644 --- a/packages/typedoc-plugin-appium/lib/converter/builtin-method-map.ts +++ b/packages/typedoc-plugin-appium/lib/converter/builtin-method-map.ts @@ -12,7 +12,7 @@ import {convertMethodMap} from './method-map'; import {KnownMethods} from './types'; import { findChildByNameAndGuard, - findMethodsInClassReflection, + findAsyncMethodsInReflection, findParentReflectionByName, } from './utils'; @@ -85,7 +85,7 @@ export class BuiltinMethodMapConverter extends BaseConverter { const classReflections = filterChildrenByGuard(parentRefl, isClassDeclarationReflection); for (const classRefl of classReflections) { - const methods = findMethodsInClassReflection(classRefl, this.knownMethods); + const methods = findAsyncMethodsInReflection(classRefl, this.knownMethods); if (!methods.size) { this.log.warn('(%s) No async methods found', classRefl.name); diff --git a/packages/typedoc-plugin-appium/lib/converter/index.ts b/packages/typedoc-plugin-appium/lib/converter/index.ts index d1e81107e2e..13ca3990402 100644 --- a/packages/typedoc-plugin-appium/lib/converter/index.ts +++ b/packages/typedoc-plugin-appium/lib/converter/index.ts @@ -14,9 +14,13 @@ * @module */ -import {Context} from 'typedoc'; +import {Context, ProjectReflection, ReflectionKind} from 'typedoc'; import {AppiumPluginLogger} from '../logger'; -import {ProjectCommands} from '../model'; +import { + AppiumPluginReflectionKind, + AppiumPluginReflectionKindGroupTitles, + ProjectCommands, +} from '../model'; import {BuiltinExternalDriverConverter} from './builtin-external-driver'; import {BuiltinMethodMapConverter} from './builtin-method-map'; import {ExternalConverter} from './external'; @@ -49,6 +53,36 @@ export function convertCommands(ctx: Context, parentLog: AppiumPluginLogger): Pr return new ProjectCommands(allCommands); } +/** + * Removes any reflection _not_ created by this plugin from the TypeDoc project _except_ the main + * project and its module children (if any). + * + * This includes removal of groups from the main project. + * @param project - Current TypeDoc project + * @returns Project w/o the stuff in it. It is mutated in place. + */ +export function omitDefaultReflections(project: ProjectReflection): ProjectReflection { + // find all modules under the project, then anything not created by this plugin, and remove it + for (const module of project.getChildrenByKind(ReflectionKind.Module)) { + for (const child of module.getChildrenByKind(~(AppiumPluginReflectionKind.Extension as any))) { + project.removeReflection(child); + } + } + // find anything under the project itself not created by this plugin (except modules) and remove it + for (const child of project.getChildrenByKind( + ~(AppiumPluginReflectionKind.Extension as any) & ~ReflectionKind.Module + )) { + project.removeReflection(child); + } + + /// remove all groups except those created for the ReflectionKinds in this plugin + project.groups = project.groups?.filter((group) => + AppiumPluginReflectionKindGroupTitles.has(group.title) + ); + + return project; +} + export * from './base-converter'; export * from './builder'; export * from '../model/builtin-commands'; diff --git a/packages/typedoc-plugin-appium/lib/converter/utils.ts b/packages/typedoc-plugin-appium/lib/converter/utils.ts index fdaf8f15f0d..5189e713443 100644 --- a/packages/typedoc-plugin-appium/lib/converter/utils.ts +++ b/packages/typedoc-plugin-appium/lib/converter/utils.ts @@ -11,6 +11,7 @@ import {NAME_OPTIONAL, NAME_REQUIRED} from './external'; import { ClassDeclarationReflection, Guard, + InterfaceDeclarationReflection, KnownMethods, ParamsPropDeclarationReflection, } from './types'; @@ -19,9 +20,7 @@ export function findParentReflectionByName( project: ProjectReflection, name: string ): ParentReflection | undefined { - return project.name === name - ? project - : findChildByNameAndGuard(project, name, isParentReflection); + return project.name === name ? project : (project.getChildByName(name) as ParentReflection); } /** @@ -101,16 +100,17 @@ export function filterChildrenByKind( } /** - * Finds _all_ async methods in a class - * @param classRefl Class reflection + * Finds _all_ async methods in a class or interface + * @param refl Class reflection + * @param knownMethods Known methods (if any) * @returns Map of method names to method reflections */ -export function findMethodsInClassReflection( - classRefl: ClassDeclarationReflection, - knownMethods: KnownMethods +export function findAsyncMethodsInReflection( + refl: ClassDeclarationReflection | InterfaceDeclarationReflection, + knownMethods?: KnownMethods ): KnownMethods { return new Map( - filterChildrenByGuard(classRefl, isAsyncMethodDeclarationReflection).map((method) => { + filterChildrenByGuard(refl, isAsyncMethodDeclarationReflection).map((method) => { const commentData = deriveComment(method.name, knownMethods, method); const knownMethodData = {method, comment: commentData?.comment}; return [method.name, knownMethodData]; diff --git a/packages/typedoc-plugin-appium/lib/index.ts b/packages/typedoc-plugin-appium/lib/index.ts new file mode 100644 index 00000000000..7efe7775a93 --- /dev/null +++ b/packages/typedoc-plugin-appium/lib/index.ts @@ -0,0 +1,46 @@ +import {Application, Context, Converter} from 'typedoc'; +import {convertCommands, createReflections, omitDefaultReflections} from './converter'; +import {AppiumPluginLogger, AppiumPluginParentLogger} from './logger'; +import {NS} from './model'; +import {configureOptions, declarations} from './options'; +import {AppiumTheme, THEME_NAME} from './theme'; + +/** + * Loads the Appium TypeDoc plugin + * @param app - TypeDoc Application + */ +export function load(app: Application) { + // register our custom theme. the user still has to choose it + app.renderer.defineTheme(THEME_NAME, AppiumTheme); + + configureOptions(app); + + app.converter + .on(Converter.EVENT_RESOLVE_BEGIN, (ctx: Context) => { + // we don't want to do this work if we're not using the custom theme! + const log = new AppiumPluginLogger(app.logger, NS); + + // this should not be necessary given the `AppiumPluginOptionsReader` forces the issue, but + // it's a safeguard nonetheless. + if (app.renderer.themeName === THEME_NAME) { + // this queries the declarations created by TypeDoc and extracts command information + const moduleCommands = convertCommands(ctx, log); + + // this creates new custom reflections from the data we gathered and registers them + // with TypeDoc + createReflections(ctx, log, moduleCommands); + } else { + log.warn('Not using the Appium theme; skipping command reflection creation'); + } + }) + .on(Converter.EVENT_RESOLVE_END, (ctx: Context) => { + // if the `outputModules` option is false, then we want to remove all the usual TypeDoc reflections. + if (!app.options.getValue(declarations.outputModules.name)) { + omitDefaultReflections(ctx.project); + } + }); +} + +export * from './options'; +export * from './theme'; +export type {AppiumPluginLogger, AppiumPluginParentLogger}; diff --git a/packages/typedoc-plugin-appium/lib/logger.ts b/packages/typedoc-plugin-appium/lib/logger.ts index bd241d06db9..77164af1172 100644 --- a/packages/typedoc-plugin-appium/lib/logger.ts +++ b/packages/typedoc-plugin-appium/lib/logger.ts @@ -47,6 +47,22 @@ export class AppiumPluginLogger extends Logger { this.#logThroughParent = logThroughParent; } + /** + * Create a new {@link AppiumPluginLogger} for the given context. + * + * @param ns - New sub-namespace; will be appended to the current namespace. + * @returns the new logger. + */ + public createChildLogger(ns: string) { + const newLogger = new AppiumPluginLogger( + this.#parent, + `${this.ns}:${ns}`, + this.#logThrough.bind(this) + ); + newLogger.level = this.level; + return newLogger; + } + /** * Log the given error message. * @@ -77,22 +93,6 @@ export class AppiumPluginLogger extends Logger { this.#log(level, text); } - /** - * Create a new {@link AppiumPluginLogger} for the given context. - * - * @param ns - New sub-namespace; will be appended to the current namespace. - * @returns the new logger. - */ - public createChildLogger(ns: string) { - const newLogger = new AppiumPluginLogger( - this.#parent, - `${this.ns}:${ns}`, - this.#logThrough.bind(this) - ); - newLogger.level = this.level; - return newLogger; - } - /** * Log the given verbose message. * diff --git a/packages/typedoc-plugin-appium/lib/model/index.ts b/packages/typedoc-plugin-appium/lib/model/index.ts index 619a10ffed9..cf732c24c5e 100644 --- a/packages/typedoc-plugin-appium/lib/model/index.ts +++ b/packages/typedoc-plugin-appium/lib/model/index.ts @@ -3,3 +3,8 @@ export * from './reflection'; export * from './module-commands'; export * from './command-data'; export * from './project-commands'; + +/** + * Namespace for whatever we need namespaces for. + */ +export const NS = 'appium'; diff --git a/packages/typedoc-plugin-appium/lib/model/reflection/command.ts b/packages/typedoc-plugin-appium/lib/model/reflection/command.ts index 2cbb599aa81..b84de4300dd 100644 --- a/packages/typedoc-plugin-appium/lib/model/reflection/command.ts +++ b/packages/typedoc-plugin-appium/lib/model/reflection/command.ts @@ -3,7 +3,7 @@ import {AsyncMethodDeclarationReflection, CommentSourceType} from '../../convert import {isExecMethodData} from '../../guards'; import {CommandData, ExecMethodData} from '../command-data'; import {AllowedHttpMethod, Route} from '../types'; -import {CommandsReflection} from './commands'; +import {ExtensionReflection} from './extension'; import {AppiumPluginReflectionKind} from './kind'; /** @@ -60,12 +60,12 @@ export class CommandReflection extends DeclarationReflection { /** * Sets props depending on type of `data` * @param data Command or execute method data - * @param parent Always a {@linkcode CommandsReflection} + * @param parent Always a {@linkcode ExtensionReflection} * @param route Route, if not an execute method */ constructor( readonly data: CommandData | ExecMethodData, - parent: CommandsReflection, + parent: ExtensionReflection, route?: Route ) { let name: string; @@ -86,7 +86,7 @@ export class CommandReflection extends DeclarationReflection { // kind-specific data if (isExecMethodData(data)) { script = name = data.script; - kind = AppiumPluginReflectionKind.EXECUTE_METHOD; + kind = AppiumPluginReflectionKind.ExecuteMethod; route = NAME_EXECUTE_ROUTE; httpMethod = HTTP_METHOD_EXECUTE; } else { @@ -94,7 +94,7 @@ export class CommandReflection extends DeclarationReflection { throw new TypeError('"route" arg is required for a non-execute-method command'); } name = route; - kind = AppiumPluginReflectionKind.COMMAND; + kind = AppiumPluginReflectionKind.Command; httpMethod = data.httpMethod; } @@ -129,6 +129,6 @@ export class CommandReflection extends DeclarationReflection { * If `true`, this command contains data about an execute method */ public get isExecuteMethod(): boolean { - return this.kindOf(AppiumPluginReflectionKind.EXECUTE_METHOD as any); + return this.kindOf(AppiumPluginReflectionKind.ExecuteMethod as any); } } diff --git a/packages/typedoc-plugin-appium/lib/model/reflection/commands.ts b/packages/typedoc-plugin-appium/lib/model/reflection/extension.ts similarity index 64% rename from packages/typedoc-plugin-appium/lib/model/reflection/commands.ts rename to packages/typedoc-plugin-appium/lib/model/reflection/extension.ts index 9fd8ffd6c30..1499913b1bf 100644 --- a/packages/typedoc-plugin-appium/lib/model/reflection/commands.ts +++ b/packages/typedoc-plugin-appium/lib/model/reflection/extension.ts @@ -8,7 +8,7 @@ import {AppiumPluginReflectionKind} from './kind'; * * Methods may be invoked directly by Handlebars templates. */ -export class CommandsReflection extends DeclarationReflection { +export class ExtensionReflection extends DeclarationReflection { /** * Info about execute methods */ @@ -18,12 +18,23 @@ export class CommandsReflection extends DeclarationReflection { */ public readonly routeMap: RouteMap; - constructor( - name: string, - parent: ParentReflection, - {routeMap, execMethodDataSet}: ModuleCommands - ) { - super(name, AppiumPluginReflectionKind.COMMANDS as any, parent); + /** + * + * @param name Name of module containing commands + * @param parent Module containing commands + * @param moduleCommands Data containing commands and execute methods + * @todo Determine the kind by inspecting `package.json` or smth + */ + constructor(name: string, parent: ParentReflection, moduleCommands: ModuleCommands) { + const {routeMap, execMethodDataSet} = moduleCommands; + const kind = ( + name.includes('driver') + ? AppiumPluginReflectionKind.Driver + : name.includes('plugin') + ? AppiumPluginReflectionKind.Plugin + : AppiumPluginReflectionKind.Extension + ) as any; + super(name, kind, parent); this.parent = parent; this.routeMap = routeMap; this.execMethodDataSet = execMethodDataSet; diff --git a/packages/typedoc-plugin-appium/lib/model/reflection/index.ts b/packages/typedoc-plugin-appium/lib/model/reflection/index.ts index 2f722e35fcf..db721228332 100644 --- a/packages/typedoc-plugin-appium/lib/model/reflection/index.ts +++ b/packages/typedoc-plugin-appium/lib/model/reflection/index.ts @@ -1,3 +1,3 @@ export * from './command'; -export * from './commands'; +export * from './extension'; export * from './kind'; diff --git a/packages/typedoc-plugin-appium/lib/model/reflection/kind.ts b/packages/typedoc-plugin-appium/lib/model/reflection/kind.ts index ce517db870e..e745973d01d 100644 --- a/packages/typedoc-plugin-appium/lib/model/reflection/kind.ts +++ b/packages/typedoc-plugin-appium/lib/model/reflection/kind.ts @@ -4,23 +4,32 @@ * A "kind" is a way for TypeDoc to understand how to document something. Mostly, these have a 1:1 relationship with some sort of TypeScript concept. This is unsuitable for our purposes, since there's no notion of a "command" or "execute method" in TypeScript. To that end, we must create new ones. * * Note that _creating new `ReflectionKind`s is a hack_ and is not supported by TypeDoc. This is the reason you will see `as any` wherever a {@linkcode AppiumPluginReflectionKind} is used. + * + * @module */ import {addReflectionKind} from './utils'; -/** - * Namespace for our reflection kinds. - * - * The only reason we use a namespace is to avoid conflicts with TypeDoc or other plugins monkeying around in the "kind" system. - */ -export const NS = 'appium'; - /** * Extends the TypeDoc's `ReflectionKind` to add namespaced kinds */ export enum AppiumPluginReflectionKind { - COMMANDS = addReflectionKind(NS, 'Commands'), - COMMAND = addReflectionKind(NS, 'Command'), - EXECUTE_METHOD = addReflectionKind(NS, 'ExecuteMethod'), - ANY = addReflectionKind(NS, 'Any', COMMAND | EXECUTE_METHOD | COMMANDS), + Driver = addReflectionKind('Driver'), + Plugin = addReflectionKind('Plugin'), + Command = addReflectionKind('Command'), + ExecuteMethod = addReflectionKind('ExecuteMethod'), + Extension = addReflectionKind('Extension', Driver | Plugin), + Any = addReflectionKind('Any', Command | ExecuteMethod | Driver | Plugin), } + +/** + * The values here are internally computed by TypeDoc, but we need to use them to filter on + * "groups" for display (since there's no direct relationship from a `ReflectionGroup` back to a `ReflectionKind`). + */ +export const AppiumPluginReflectionKindGroupTitles = new Set([ + 'Drivers', + 'Plugins', + 'Extensions', + 'Execute methods', + 'Commands', +]); diff --git a/packages/typedoc-plugin-appium/lib/model/reflection/utils.ts b/packages/typedoc-plugin-appium/lib/model/reflection/utils.ts index 15fb72abaa9..4947e6241b4 100644 --- a/packages/typedoc-plugin-appium/lib/model/reflection/utils.ts +++ b/packages/typedoc-plugin-appium/lib/model/reflection/utils.ts @@ -17,16 +17,14 @@ const getHigherBitMask = () => .filter((v) => v.match(/^0*10*$/)) .map((v) => parseInt(v, 2)) ); -export const addReflectionKind = (ns: string, name: string, value?: number | null) => { - const fullName = `${ns}:${name}`; - +export const addReflectionKind = (name: string, value?: number | null) => { const kindAny = ReflectionKind as any; - const existingValue = kindAny[fullName]; + const existingValue = kindAny[name]; if (existingValue !== null && existingValue !== undefined) { return existingValue; } const defaultedValue = value ?? getHigherBitMask() * 2; - kindAny[fullName] = defaultedValue; - kindAny[defaultedValue] = fullName; + kindAny[name] = defaultedValue; + kindAny[defaultedValue] = name; return defaultedValue; }; diff --git a/packages/typedoc-plugin-appium/lib/model/types.ts b/packages/typedoc-plugin-appium/lib/model/types.ts index f9a2657f098..080720f17b3 100644 --- a/packages/typedoc-plugin-appium/lib/model/types.ts +++ b/packages/typedoc-plugin-appium/lib/model/types.ts @@ -28,7 +28,7 @@ export type Command = string; export type CommandSet = Set; /** - * A reflection which can be the parent of a {@linkcode CommandsReflection} + * A reflection which can be the parent of a {@linkcode ExtensionReflection} */ export type ParentReflection = DeclarationReflection | ProjectReflection; diff --git a/packages/typedoc-plugin-appium/lib/options/declarations.ts b/packages/typedoc-plugin-appium/lib/options/declarations.ts new file mode 100644 index 00000000000..4ba2d8f8a0b --- /dev/null +++ b/packages/typedoc-plugin-appium/lib/options/declarations.ts @@ -0,0 +1,33 @@ +import {DeclarationOption, ParameterType} from 'typedoc'; +import {NS} from '../model'; + +/** + * List of options for the plugin + * @internal + */ +export const declarations = { + commandsDir: { + defaultValue: 'commands', + help: `(${NS}) Name of "commands" directory under the TypeDoc output directory. Not a full path`, + name: 'commandsDir', + type: ParameterType.String, + } as DeclarationOption, + forceBreadcrumbs: { + defaultValue: false, + help: `(${NS}) Force breadcrumbs to be shown; overrides "hideBreadcrumbs"`, + name: 'forceBreadcrumbs', + type: ParameterType.Boolean, + } as DeclarationOption, + outputBuiltinCommands: { + defaultValue: false, + help: `(${NS}) Output builtin commands`, + name: 'outputBuiltinCommands', + type: ParameterType.Boolean, + } as DeclarationOption, + outputModules: { + defaultValue: true, + help: `(${NS}) Output modules APIs in addition to commands. This is needed for complete typing information`, + name: 'outputModules', + type: ParameterType.Boolean, + } as DeclarationOption, +} as const; diff --git a/packages/typedoc-plugin-appium/lib/options/index.ts b/packages/typedoc-plugin-appium/lib/options/index.ts new file mode 100644 index 00000000000..67b95407b79 --- /dev/null +++ b/packages/typedoc-plugin-appium/lib/options/index.ts @@ -0,0 +1,28 @@ +import {Application, ParameterType} from 'typedoc'; +import {AppiumPluginOptionsReader} from './reader'; +import {declarations} from './declarations'; + +export * from './reader'; +export {declarations}; + +/** + * Configures how this plugin handles TypeDoc options. + * @param app TypeDoc Application + */ +export function configureOptions(app: Application) { + // for evil + app.options.addReader(new AppiumPluginOptionsReader()); + + // add our custom options + for (const declaration of Object.values(declarations)) { + app.options.addDeclaration(declaration); + } +} + +export type AppiumPluginOptions = { + [O in keyof typeof declarations]: typeof declarations[O]['type'] extends ParameterType.Boolean + ? boolean + : typeof declarations[O]['type'] extends ParameterType.String + ? string + : unknown; +}; diff --git a/packages/typedoc-plugin-appium/lib/options/reader.ts b/packages/typedoc-plugin-appium/lib/options/reader.ts new file mode 100644 index 00000000000..39e58e79318 --- /dev/null +++ b/packages/typedoc-plugin-appium/lib/options/reader.ts @@ -0,0 +1,124 @@ +import path from 'node:path'; +import {EntryPointStrategy, Options, OptionsReader, Logger} from 'typedoc'; +import {AppiumPluginLogger} from '../logger'; +import {NS} from '../model'; +import {THEME_NAME} from '../theme'; + +/** + * List of theme names to override. + * + * `default` is what happens if the user does not specify a theme. The markdown plugin, + * if loaded, will overwrite `default` with `markdown`, so we'll have to overwrite it again. + * + * @internal + */ +const OVERRIDE_THEME_NAMES: Readonly> = new Set(['default', 'markdown']); + +/** + * These packages must be resolvable for the plugin to work at all. + * @internal + */ +const REQUIRED_PACKAGES: Readonly> = new Set(['@appium/base-driver', '@appium/types']); + +/** + * This befouls the options. + * + * It can do what has been undone and undo what has been done. It can make real your dreams... or nightmares. + */ +export class AppiumPluginOptionsReader implements OptionsReader { + /** + * I don't know the point of `name`, but the interface requires it, so here. + */ + public name = 'naughty-appium-options-reader'; + /** + * This needs to be higher than the value in `MarkdownOptionsReader`. + */ + public priority = 2000; + + /** + * Forces the theme to be {@linkcode THEME_NAME} + * @param container Options + * @param log Logger + */ + #configureTheme(container: Options, log: AppiumPluginLogger) { + if (OVERRIDE_THEME_NAMES.has(container.getValue('theme'))) { + container.setValue('theme', THEME_NAME); + log.verbose('Set option "theme" to "appium"'); + } + } + + /** + * Forces the `entryPointStrategy` option to be {@linkcode EntryPointStrategy.Packages} + * @param container Options + * @param log Logger + */ + #configureEntryPointStrategy(container: Options, log: AppiumPluginLogger) { + const entryPointStrategy = container.getValue('entryPointStrategy'); + if (entryPointStrategy !== EntryPointStrategy.Packages) { + container.setValue('entryPointStrategy', EntryPointStrategy.Packages); + log.verbose('Set option "entryPointStrategy" to "%s"', EntryPointStrategy.Packages); + } + } + + /** + * Adds required packages to the `entryPoints` option. + * + * If the `entryPoints` option already contains something that _looks like_ a + * {@linkcode REQUIRED_PACKAGES required package}, then it is validated via + * `require.resolve`. If this fails, it is replaced with the proper package path. + * + * If a required package cannot be resolved, an error occurs + * @param container Options + * @param log Logger + */ + #configureEntryPoints(container: Options, log: AppiumPluginLogger) { + const entryPoints = container.getValue('entryPoints'); + const newEntryPoints: Set = new Set(entryPoints); + + const addEntryPoint = (entryPoint: string) => { + try { + const entryPointPath = path.dirname(require.resolve(`${entryPoint}/package.json`)); + newEntryPoints.add(entryPointPath); + log.verbose('Added %s to "entryPoint" option', entryPointPath); + } catch (err) { + log.error('Could not find required package "%s"', entryPoint); + } + }; + + for (const reqdEntryPoint of REQUIRED_PACKAGES) { + const foundReqdEP = entryPoints.find((entryPoint) => entryPoint.includes(reqdEntryPoint)); + if (foundReqdEP) { + try { + require.resolve(foundReqdEP); + log.verbose('entryPoint %s already exists (%s)', reqdEntryPoint, foundReqdEP); + } catch { + newEntryPoints.delete(foundReqdEP); + addEntryPoint(reqdEntryPoint); + log.warn( + '"entryPoint" option item matching required package "%s" is invalid or missing (%s); it was replaced', + reqdEntryPoint, + foundReqdEP + ); + } + } else { + addEntryPoint(reqdEntryPoint); + } + } + + container.setValue('entryPoints', [...newEntryPoints]); + log.verbose('Final value of "entryPoints" option: %O', container.getValue('entryPoints')); + } + + /** + * Calls various private methods to override option values or provide defaults. + * @param container - Options container + * @param logger - Logger + */ + public read(container: Options, logger: Logger) { + const log = new AppiumPluginLogger(logger, `${NS}:options-reader`); + + this.#configureTheme(container, log); + this.#configureEntryPointStrategy(container, log); + this.#configureEntryPoints(container, log); + } +} diff --git a/packages/typedoc-plugin-appium/lib/theme/helpers.ts b/packages/typedoc-plugin-appium/lib/theme/helpers.ts index e91e6fbc22e..ee9a2c86ffc 100644 --- a/packages/typedoc-plugin-appium/lib/theme/helpers.ts +++ b/packages/typedoc-plugin-appium/lib/theme/helpers.ts @@ -16,8 +16,10 @@ import plural from 'pluralize'; function reflectionPath(this: PageEvent) { if (this.model) { if (this.model.kind && this.model.kind !== ReflectionKind.Module) { - if (this.model.kind === (AppiumPluginReflectionKind.COMMANDS as any)) { - return `${this.model.name} Commands`; + if (this.model.kind === (AppiumPluginReflectionKind.Driver as any)) { + return `${this.model.name} Driver`; + } else if (this.model.kind === (AppiumPluginReflectionKind.Plugin as any)) { + return `${this.model.name} Plugin`; } const title: string[] = []; if (this.model.parent && this.model.parent.parent) { diff --git a/packages/typedoc-plugin-appium/lib/theme/index.ts b/packages/typedoc-plugin-appium/lib/theme/index.ts index 43ec06d8fb8..b4d84bc4c8c 100644 --- a/packages/typedoc-plugin-appium/lib/theme/index.ts +++ b/packages/typedoc-plugin-appium/lib/theme/index.ts @@ -2,6 +2,7 @@ import {ContainerReflection, PageEvent, ReflectionKind, Renderer} from 'typedoc' import {MarkdownTheme} from 'typedoc-plugin-markdown'; import {AppiumPluginLogger} from '../logger'; import {AppiumPluginReflectionKind, NS} from '../model'; +import {AppiumPluginOptions, declarations} from '../options'; import {registerHelpers} from './helpers'; import {AppiumThemeTemplate, compileTemplate} from './template'; @@ -10,50 +11,68 @@ import {AppiumThemeTemplate, compileTemplate} from './template'; */ export const THEME_NAME = 'appium'; +/** + * This theme uses everything from `MarkdownTheme` and adds a new section for commands. + */ export class AppiumTheme extends MarkdownTheme { /** * A template renderer for `CommandReflection`s */ - #commandsTemplateRenderer: TemplateRenderer; + #extensionTemplateRenderer: TemplateRenderer; /** * Custom logger. This is not the same as the one created by the plugin loader. */ #log: AppiumPluginLogger; + /** + * Options specific to this plugin + */ + #opts: AppiumPluginOptions; + /** * Creates template renderers and registers all {@linkcode Handlebars} helpers. * @param renderer - TypeDoc renderer * - * @todo Make `hideBreadcrumbs` configurable + * @todo Use declaration merging to add an instance of `AppiumPluginLogger` to `Application`, + * which we can then reference here. */ constructor(renderer: Renderer) { super(renderer); - // ideally, this would be a child of the logger created by the `load()` function, - // but I don't know how to get at it. this.#log = new AppiumPluginLogger(renderer.owner.logger, `${NS}:theme`); - this.#commandsTemplateRenderer = this.#createTemplateRenderer(AppiumThemeTemplate.Commands); + this.#extensionTemplateRenderer = this.#createTemplateRenderer(AppiumThemeTemplate.Extension); + + this.#opts = Object.keys(declarations).reduce((opts, name) => { + opts[name] = this.application.options.getValue(name); + return opts; + }, {} as AppiumPluginOptions); - // the intent is to have mkdocs render breadcrumbs - this.hideBreadcrumbs = true; + /** + * We do not want to show breadcrumbs by default, but `MarkdownTheme` does. We cannot override + * default value of the `hideBreadcrumbs` option, but we can add a new one, which is what we've done; + * if the `forceBreadcrumbs` option is not truthy, then we will hide breadcrumbs. + */ + this.hideBreadcrumbs = !this.#opts.forceBreadcrumbs; // this ensures we can overwrite MarkdownTheme's Handlebars helpers registerHelpers(); } /** - * This is essentially a lookup of {@linkcode ReflectionKind}s to templates. It also controls in which directory the output files live. + * A lookup of {@linkcode ReflectionKind}s to templates. It also controls in which directory the output files live. + * + * This is part of {@linkcode MarkdownTheme} and adds a new template. * * If `isLeaf` is `false`, the model gets its own document. */ public override get mappings(): TemplateMapping[] { return [ { - kind: [AppiumPluginReflectionKind.COMMANDS as any], + kind: [AppiumPluginReflectionKind.Extension as any], isLeaf: false, - directory: 'commands', - template: this.#commandsTemplateRenderer, + directory: this.application.options.getValue(declarations.commandsDir.name) as string, + template: this.#extensionTemplateRenderer, }, ...super.mappings, ]; diff --git a/packages/typedoc-plugin-appium/lib/theme/resources/templates/commands.hbs b/packages/typedoc-plugin-appium/lib/theme/resources/templates/extension.hbs similarity index 100% rename from packages/typedoc-plugin-appium/lib/theme/resources/templates/commands.hbs rename to packages/typedoc-plugin-appium/lib/theme/resources/templates/extension.hbs diff --git a/packages/typedoc-plugin-appium/lib/theme/template.ts b/packages/typedoc-plugin-appium/lib/theme/template.ts index b4edcfab5b5..3dad632d5f0 100644 --- a/packages/typedoc-plugin-appium/lib/theme/template.ts +++ b/packages/typedoc-plugin-appium/lib/theme/template.ts @@ -38,7 +38,7 @@ export enum AppiumThemeTemplate { /** * Template to render a list of commands */ - Commands = 'commands.hbs', + Extension = 'extension.hbs', } /** diff --git a/packages/typedoc-plugin-appium/package.json b/packages/typedoc-plugin-appium/package.json index 899149ba6c4..2c0d7a53096 100644 --- a/packages/typedoc-plugin-appium/package.json +++ b/packages/typedoc-plugin-appium/package.json @@ -14,17 +14,14 @@ "directory": "packages/typedoc-plugin-appium" }, "keywords": [ - "automation", - "javascript", - "selenium", - "webdriver", - "ios", - "android", - "firefoxos", - "testing" + "typedoc-plugin", + "typedocplugin", + "typedoc-theme", + "appium", + "markdown" ], "author": "https://github.com/appium", - "types": "./build/lib/plugin.d.ts", + "types": "./build/lib/index.d.ts", "scripts": { "build": "cpy lib/theme/resources build", "clean": "npx rimraf build/lib/theme/resources", @@ -53,16 +50,18 @@ "npm": ">=8" }, "typedoc": { - "entryPoint": "./lib/plugin.ts" + "entryPoint": "./lib/index.ts" }, "peerDependencies": { "appium": "^2.0.0-beta.48", - "typedoc": ">=0.23.14" + "typedoc": "^0.23.14", + "typescript": "~4.7.0", + "typedoc-plugin-markdown": "^3.14.0", + "typedoc-plugin-resolve-crossmodule-references": "~0.3.3" }, "dependencies": { "handlebars": "4.7.7", "pluralize": "8.0.0", - "type-fest": "3.5.1", - "typedoc-plugin-markdown": "3.14.0" + "type-fest": "3.5.1" } } diff --git a/packages/typedoc-plugin-appium/test/unit/converter/builder.spec.ts b/packages/typedoc-plugin-appium/test/unit/converter/builder.spec.ts index 3a7eed515c9..e4d9e4301da 100644 --- a/packages/typedoc-plugin-appium/test/unit/converter/builder.spec.ts +++ b/packages/typedoc-plugin-appium/test/unit/converter/builder.spec.ts @@ -13,7 +13,7 @@ import {AppiumPluginLogger} from '../../../lib/logger'; import { AppiumPluginReflectionKind, CommandReflection, - CommandsReflection, + ExtensionReflection, ProjectCommands, } from '../../../lib/model'; import {initAppForPkgs, NAME_FAKE_DRIVER_MODULE, ROOT_TSCONFIG} from '../helpers'; @@ -34,7 +34,7 @@ describe('command data builder', function () { let moduleCommands: ProjectCommands; let ctx: Context; let log: AppiumPluginLogger; - let cmdsRefls!: CommandsReflection[]; + let cmdsRefls!: ExtensionReflection[]; before(async function () { const app = await initAppForPkgs( @@ -76,7 +76,7 @@ describe('command data builder', function () { for (const cmdsRefl of cmdsRefls) { let lastRoute = ''; for (const cmdRefl of cmdsRefl.getChildrenByKind( - AppiumPluginReflectionKind.COMMAND as any + AppiumPluginReflectionKind.Command as any ) as CommandReflection[]) { if (lastRoute) { expect(cmdRefl.route.localeCompare(lastRoute)).to.greaterThanOrEqual(0); @@ -90,7 +90,7 @@ describe('command data builder', function () { for (const cmdsRefl of cmdsRefls) { let lastScript = ''; for (const cmdRefl of cmdsRefl.getChildrenByKind( - AppiumPluginReflectionKind.EXECUTE_METHOD as any + AppiumPluginReflectionKind.ExecuteMethod as any ) as CommandReflection[]) { if (lastScript) { expect(cmdRefl.script!.localeCompare(lastScript)).to.greaterThanOrEqual(0); diff --git a/packages/typedoc-plugin-appium/test/unit/converter/builtin-external-driver.spec.ts b/packages/typedoc-plugin-appium/test/unit/converter/builtin-external-driver.spec.ts index 9491b24d0c8..9ef4a2df617 100644 --- a/packages/typedoc-plugin-appium/test/unit/converter/builtin-external-driver.spec.ts +++ b/packages/typedoc-plugin-appium/test/unit/converter/builtin-external-driver.spec.ts @@ -4,6 +4,7 @@ import {Context} from 'typedoc'; import { BuiltinExternalDriverConverter, KnownMethods, + NAME_EXTERNAL_DRIVER, NAME_TYPES_MODULE, } from '../../../lib/converter'; import {AppiumPluginLogger} from '../../../lib/logger'; @@ -40,7 +41,7 @@ describe('BuiltinExternalDriverConverter', function () { knownMethods = converter.convert(); }); - it(`should find ExternalDriver's method declarations in ${NAME_TYPES_MODULE}`, async function () { + it(`should find ${NAME_EXTERNAL_DRIVER}'s method declarations in ${NAME_TYPES_MODULE}`, async function () { expect(knownMethods.size).to.be.above(0); }); @@ -52,10 +53,10 @@ describe('BuiltinExternalDriverConverter', function () { expect(badConverter.convert()).to.be.empty; }); - it('should contain methods in ExternalDriver', async function () { + it(`should contain methods in ${NAME_EXTERNAL_DRIVER}`, async function () { converter = await initConverter(BuiltinExternalDriverConverter, NAME_TYPES_MODULE); knownMethods = converter.convert(); - + expect(knownMethods.size).to.be.above(0); let {method, comment} = knownMethods.get('createSession')!; expect(method).to.exist; expect(comment).to.exist; diff --git a/packages/typedoc-plugin-appium/test/unit/converter/external.spec.ts b/packages/typedoc-plugin-appium/test/unit/converter/external.spec.ts index a087bdfd8cd..151876824ef 100644 --- a/packages/typedoc-plugin-appium/test/unit/converter/external.spec.ts +++ b/packages/typedoc-plugin-appium/test/unit/converter/external.spec.ts @@ -12,7 +12,7 @@ import { import {BuiltinCommands} from '../../../lib/model/builtin-commands'; import {isCallSignatureReflectionWithParams} from '../../../lib/guards'; import {AppiumPluginLogger} from '../../../lib/logger'; -import {ModuleCommands, ProjectCommands} from '../../../lib/model'; +import {CommandSet, ModuleCommands, ProjectCommands} from '../../../lib/model'; import {initConverter, NAME_FAKE_DRIVER_MODULE} from '../helpers'; describe('ExternalConverter', function () { @@ -55,6 +55,9 @@ describe('ExternalConverter', function () { describe('when run against an Appium extension', function () { let driverCmds: ProjectCommands; + let fakeDriverCmds: ModuleCommands; + let sessionCmdSet: CommandSet; + beforeEach(async function () { const converter = await initConverter(ExternalConverter, NAME_FAKE_DRIVER_MODULE, { extraArgs: [externalDriverMethods, builtinCmdSrc.moduleCmds], @@ -64,26 +67,23 @@ describe('ExternalConverter', function () { it('should find commands', function () { expect(driverCmds).not.to.be.empty; + fakeDriverCmds = driverCmds.get(NAME_FAKE_DRIVER_MODULE)!; + expect(fakeDriverCmds).to.exist; + sessionCmdSet = fakeDriverCmds.routeMap.get('/session')!; + expect(sessionCmdSet).to.exist; }); it('should find commands from the new method map', function () { - expect( - driverCmds.get(NAME_FAKE_DRIVER_MODULE)!.routeMap.get('/session/:sessionId/fakedriver') - ).to.have.lengthOf(2); + expect(fakeDriverCmds.routeMap.get('/session/:sessionId/fakedriver')).to.have.lengthOf(2); }); it('should find commands in the execute method map', function () { - const execCmds = [...driverCmds.get(NAME_FAKE_DRIVER_MODULE)!.execMethodDataSet]; - + const execCmds = [...fakeDriverCmds.execMethodDataSet]; expect(execCmds.find((cmd) => cmd.script === 'fake: getThing')).to.exist; }); it('should use the summary from the driver instead of from builtins', function () { - const commandData = [ - ...driverCmds.get(NAME_FAKE_DRIVER_MODULE)!.routeMap.get('/session')!, - ]; - - const postRoute = commandData.find((cmdData) => cmdData.httpMethod === 'POST')!; + const postRoute = [...sessionCmdSet].find((cmdData) => cmdData.httpMethod === 'POST')!; expect(Comment.combineDisplayParts(postRoute.comment!.summary)).to.equal( 'Comment for `createSession` in `FakeDriver`' @@ -91,11 +91,7 @@ describe('ExternalConverter', function () { }); it('should prefer method map parameters over method parameters', function () { - const commandData = [ - ...driverCmds.get(NAME_FAKE_DRIVER_MODULE)!.routeMap.get('/session')!, - ]; - - const postRoute = commandData.find((cmdData) => cmdData.httpMethod === 'POST')!; + const postRoute = [...sessionCmdSet].find((cmdData) => cmdData.httpMethod === 'POST')!; const pRefls = postRoute.methodRefl!.signatures!.find( isCallSignatureReflectionWithParams diff --git a/typedoc.json b/typedoc.json index 985b49dc0a3..ae884e9b90d 100644 --- a/typedoc.json +++ b/typedoc.json @@ -11,15 +11,7 @@ "./packages/fake-driver", "./packages/typedoc-plugin-appium" ], - "excludeInternal": true, - "includeVersion": false, "name": "Appium", "out": "typedoc-docs", - "plugin": [ - "typedoc-plugin-resolve-crossmodule-references", - "typedoc-plugin-markdown", - "./packages/typedoc-plugin-appium" - ], - "theme": "appium", - "tsconfig": "./tsconfig.json" + "outputBuiltinCommands": true }