 aacb45156b
			
		
	
	aacb45156b
	
	
	
		
			
			- Install Jest for unit testing with React Testing Library - Install Playwright for end-to-end testing - Configure Jest with proper TypeScript support and module mapping - Create test setup files and utilities for both unit and e2e tests Components: * Jest configuration with coverage thresholds * Playwright configuration with browser automation * Unit tests for LoginForm, AuthContext, and useSocketIO hook * E2E tests for authentication, dashboard, and agents workflows * GitHub Actions workflow for automated testing * Mock data and API utilities for consistent testing * Test documentation with best practices Testing features: - Unit tests with 70% coverage threshold - E2E tests with API mocking and user journey testing - CI/CD integration for automated test runs - Cross-browser testing support with Playwright - Authentication system testing end-to-end 🚀 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			450 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			450 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import { assertNotStrictEqual, } from './typings/common-types.js';
 | |
| import { isPromise } from './utils/is-promise.js';
 | |
| import { applyMiddleware, commandMiddlewareFactory, } from './middleware.js';
 | |
| import { parseCommand } from './parse-command.js';
 | |
| import { isYargsInstance, } from './yargs-factory.js';
 | |
| import { maybeAsyncResult } from './utils/maybe-async-result.js';
 | |
| import whichModule from './utils/which-module.js';
 | |
| const DEFAULT_MARKER = /(^\*)|(^\$0)/;
 | |
| export class CommandInstance {
 | |
|     constructor(usage, validation, globalMiddleware, shim) {
 | |
|         this.requireCache = new Set();
 | |
|         this.handlers = {};
 | |
|         this.aliasMap = {};
 | |
|         this.frozens = [];
 | |
|         this.shim = shim;
 | |
|         this.usage = usage;
 | |
|         this.globalMiddleware = globalMiddleware;
 | |
|         this.validation = validation;
 | |
|     }
 | |
|     addDirectory(dir, req, callerFile, opts) {
 | |
|         opts = opts || {};
 | |
|         if (typeof opts.recurse !== 'boolean')
 | |
|             opts.recurse = false;
 | |
|         if (!Array.isArray(opts.extensions))
 | |
|             opts.extensions = ['js'];
 | |
|         const parentVisit = typeof opts.visit === 'function' ? opts.visit : (o) => o;
 | |
|         opts.visit = (obj, joined, filename) => {
 | |
|             const visited = parentVisit(obj, joined, filename);
 | |
|             if (visited) {
 | |
|                 if (this.requireCache.has(joined))
 | |
|                     return visited;
 | |
|                 else
 | |
|                     this.requireCache.add(joined);
 | |
|                 this.addHandler(visited);
 | |
|             }
 | |
|             return visited;
 | |
|         };
 | |
|         this.shim.requireDirectory({ require: req, filename: callerFile }, dir, opts);
 | |
|     }
 | |
|     addHandler(cmd, description, builder, handler, commandMiddleware, deprecated) {
 | |
|         let aliases = [];
 | |
|         const middlewares = commandMiddlewareFactory(commandMiddleware);
 | |
|         handler = handler || (() => { });
 | |
|         if (Array.isArray(cmd)) {
 | |
|             if (isCommandAndAliases(cmd)) {
 | |
|                 [cmd, ...aliases] = cmd;
 | |
|             }
 | |
|             else {
 | |
|                 for (const command of cmd) {
 | |
|                     this.addHandler(command);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         else if (isCommandHandlerDefinition(cmd)) {
 | |
|             let command = Array.isArray(cmd.command) || typeof cmd.command === 'string'
 | |
|                 ? cmd.command
 | |
|                 : this.moduleName(cmd);
 | |
|             if (cmd.aliases)
 | |
|                 command = [].concat(command).concat(cmd.aliases);
 | |
|             this.addHandler(command, this.extractDesc(cmd), cmd.builder, cmd.handler, cmd.middlewares, cmd.deprecated);
 | |
|             return;
 | |
|         }
 | |
|         else if (isCommandBuilderDefinition(builder)) {
 | |
|             this.addHandler([cmd].concat(aliases), description, builder.builder, builder.handler, builder.middlewares, builder.deprecated);
 | |
|             return;
 | |
|         }
 | |
|         if (typeof cmd === 'string') {
 | |
|             const parsedCommand = parseCommand(cmd);
 | |
|             aliases = aliases.map(alias => parseCommand(alias).cmd);
 | |
|             let isDefault = false;
 | |
|             const parsedAliases = [parsedCommand.cmd].concat(aliases).filter(c => {
 | |
|                 if (DEFAULT_MARKER.test(c)) {
 | |
|                     isDefault = true;
 | |
|                     return false;
 | |
|                 }
 | |
|                 return true;
 | |
|             });
 | |
|             if (parsedAliases.length === 0 && isDefault)
 | |
|                 parsedAliases.push('$0');
 | |
|             if (isDefault) {
 | |
|                 parsedCommand.cmd = parsedAliases[0];
 | |
|                 aliases = parsedAliases.slice(1);
 | |
|                 cmd = cmd.replace(DEFAULT_MARKER, parsedCommand.cmd);
 | |
|             }
 | |
|             aliases.forEach(alias => {
 | |
|                 this.aliasMap[alias] = parsedCommand.cmd;
 | |
|             });
 | |
|             if (description !== false) {
 | |
|                 this.usage.command(cmd, description, isDefault, aliases, deprecated);
 | |
|             }
 | |
|             this.handlers[parsedCommand.cmd] = {
 | |
|                 original: cmd,
 | |
|                 description,
 | |
|                 handler,
 | |
|                 builder: builder || {},
 | |
|                 middlewares,
 | |
|                 deprecated,
 | |
|                 demanded: parsedCommand.demanded,
 | |
|                 optional: parsedCommand.optional,
 | |
|             };
 | |
|             if (isDefault)
 | |
|                 this.defaultCommand = this.handlers[parsedCommand.cmd];
 | |
|         }
 | |
|     }
 | |
|     getCommandHandlers() {
 | |
|         return this.handlers;
 | |
|     }
 | |
|     getCommands() {
 | |
|         return Object.keys(this.handlers).concat(Object.keys(this.aliasMap));
 | |
|     }
 | |
|     hasDefaultCommand() {
 | |
|         return !!this.defaultCommand;
 | |
|     }
 | |
|     runCommand(command, yargs, parsed, commandIndex, helpOnly, helpOrVersionSet) {
 | |
|         const commandHandler = this.handlers[command] ||
 | |
|             this.handlers[this.aliasMap[command]] ||
 | |
|             this.defaultCommand;
 | |
|         const currentContext = yargs.getInternalMethods().getContext();
 | |
|         const parentCommands = currentContext.commands.slice();
 | |
|         const isDefaultCommand = !command;
 | |
|         if (command) {
 | |
|             currentContext.commands.push(command);
 | |
|             currentContext.fullCommands.push(commandHandler.original);
 | |
|         }
 | |
|         const builderResult = this.applyBuilderUpdateUsageAndParse(isDefaultCommand, commandHandler, yargs, parsed.aliases, parentCommands, commandIndex, helpOnly, helpOrVersionSet);
 | |
|         return isPromise(builderResult)
 | |
|             ? builderResult.then(result => this.applyMiddlewareAndGetResult(isDefaultCommand, commandHandler, result.innerArgv, currentContext, helpOnly, result.aliases, yargs))
 | |
|             : this.applyMiddlewareAndGetResult(isDefaultCommand, commandHandler, builderResult.innerArgv, currentContext, helpOnly, builderResult.aliases, yargs);
 | |
|     }
 | |
|     applyBuilderUpdateUsageAndParse(isDefaultCommand, commandHandler, yargs, aliases, parentCommands, commandIndex, helpOnly, helpOrVersionSet) {
 | |
|         const builder = commandHandler.builder;
 | |
|         let innerYargs = yargs;
 | |
|         if (isCommandBuilderCallback(builder)) {
 | |
|             yargs.getInternalMethods().getUsageInstance().freeze();
 | |
|             const builderOutput = builder(yargs.getInternalMethods().reset(aliases), helpOrVersionSet);
 | |
|             if (isPromise(builderOutput)) {
 | |
|                 return builderOutput.then(output => {
 | |
|                     innerYargs = isYargsInstance(output) ? output : yargs;
 | |
|                     return this.parseAndUpdateUsage(isDefaultCommand, commandHandler, innerYargs, parentCommands, commandIndex, helpOnly);
 | |
|                 });
 | |
|             }
 | |
|         }
 | |
|         else if (isCommandBuilderOptionDefinitions(builder)) {
 | |
|             yargs.getInternalMethods().getUsageInstance().freeze();
 | |
|             innerYargs = yargs.getInternalMethods().reset(aliases);
 | |
|             Object.keys(commandHandler.builder).forEach(key => {
 | |
|                 innerYargs.option(key, builder[key]);
 | |
|             });
 | |
|         }
 | |
|         return this.parseAndUpdateUsage(isDefaultCommand, commandHandler, innerYargs, parentCommands, commandIndex, helpOnly);
 | |
|     }
 | |
|     parseAndUpdateUsage(isDefaultCommand, commandHandler, innerYargs, parentCommands, commandIndex, helpOnly) {
 | |
|         if (isDefaultCommand)
 | |
|             innerYargs.getInternalMethods().getUsageInstance().unfreeze(true);
 | |
|         if (this.shouldUpdateUsage(innerYargs)) {
 | |
|             innerYargs
 | |
|                 .getInternalMethods()
 | |
|                 .getUsageInstance()
 | |
|                 .usage(this.usageFromParentCommandsCommandHandler(parentCommands, commandHandler), commandHandler.description);
 | |
|         }
 | |
|         const innerArgv = innerYargs
 | |
|             .getInternalMethods()
 | |
|             .runYargsParserAndExecuteCommands(null, undefined, true, commandIndex, helpOnly);
 | |
|         return isPromise(innerArgv)
 | |
|             ? innerArgv.then(argv => ({
 | |
|                 aliases: innerYargs.parsed.aliases,
 | |
|                 innerArgv: argv,
 | |
|             }))
 | |
|             : {
 | |
|                 aliases: innerYargs.parsed.aliases,
 | |
|                 innerArgv: innerArgv,
 | |
|             };
 | |
|     }
 | |
|     shouldUpdateUsage(yargs) {
 | |
|         return (!yargs.getInternalMethods().getUsageInstance().getUsageDisabled() &&
 | |
|             yargs.getInternalMethods().getUsageInstance().getUsage().length === 0);
 | |
|     }
 | |
|     usageFromParentCommandsCommandHandler(parentCommands, commandHandler) {
 | |
|         const c = DEFAULT_MARKER.test(commandHandler.original)
 | |
|             ? commandHandler.original.replace(DEFAULT_MARKER, '').trim()
 | |
|             : commandHandler.original;
 | |
|         const pc = parentCommands.filter(c => {
 | |
|             return !DEFAULT_MARKER.test(c);
 | |
|         });
 | |
|         pc.push(c);
 | |
|         return `$0 ${pc.join(' ')}`;
 | |
|     }
 | |
|     handleValidationAndGetResult(isDefaultCommand, commandHandler, innerArgv, currentContext, aliases, yargs, middlewares, positionalMap) {
 | |
|         if (!yargs.getInternalMethods().getHasOutput()) {
 | |
|             const validation = yargs
 | |
|                 .getInternalMethods()
 | |
|                 .runValidation(aliases, positionalMap, yargs.parsed.error, isDefaultCommand);
 | |
|             innerArgv = maybeAsyncResult(innerArgv, result => {
 | |
|                 validation(result);
 | |
|                 return result;
 | |
|             });
 | |
|         }
 | |
|         if (commandHandler.handler && !yargs.getInternalMethods().getHasOutput()) {
 | |
|             yargs.getInternalMethods().setHasOutput();
 | |
|             const populateDoubleDash = !!yargs.getOptions().configuration['populate--'];
 | |
|             yargs
 | |
|                 .getInternalMethods()
 | |
|                 .postProcess(innerArgv, populateDoubleDash, false, false);
 | |
|             innerArgv = applyMiddleware(innerArgv, yargs, middlewares, false);
 | |
|             innerArgv = maybeAsyncResult(innerArgv, result => {
 | |
|                 const handlerResult = commandHandler.handler(result);
 | |
|                 return isPromise(handlerResult)
 | |
|                     ? handlerResult.then(() => result)
 | |
|                     : result;
 | |
|             });
 | |
|             if (!isDefaultCommand) {
 | |
|                 yargs.getInternalMethods().getUsageInstance().cacheHelpMessage();
 | |
|             }
 | |
|             if (isPromise(innerArgv) &&
 | |
|                 !yargs.getInternalMethods().hasParseCallback()) {
 | |
|                 innerArgv.catch(error => {
 | |
|                     try {
 | |
|                         yargs.getInternalMethods().getUsageInstance().fail(null, error);
 | |
|                     }
 | |
|                     catch (_err) {
 | |
|                     }
 | |
|                 });
 | |
|             }
 | |
|         }
 | |
|         if (!isDefaultCommand) {
 | |
|             currentContext.commands.pop();
 | |
|             currentContext.fullCommands.pop();
 | |
|         }
 | |
|         return innerArgv;
 | |
|     }
 | |
|     applyMiddlewareAndGetResult(isDefaultCommand, commandHandler, innerArgv, currentContext, helpOnly, aliases, yargs) {
 | |
|         let positionalMap = {};
 | |
|         if (helpOnly)
 | |
|             return innerArgv;
 | |
|         if (!yargs.getInternalMethods().getHasOutput()) {
 | |
|             positionalMap = this.populatePositionals(commandHandler, innerArgv, currentContext, yargs);
 | |
|         }
 | |
|         const middlewares = this.globalMiddleware
 | |
|             .getMiddleware()
 | |
|             .slice(0)
 | |
|             .concat(commandHandler.middlewares);
 | |
|         const maybePromiseArgv = applyMiddleware(innerArgv, yargs, middlewares, true);
 | |
|         return isPromise(maybePromiseArgv)
 | |
|             ? maybePromiseArgv.then(resolvedInnerArgv => this.handleValidationAndGetResult(isDefaultCommand, commandHandler, resolvedInnerArgv, currentContext, aliases, yargs, middlewares, positionalMap))
 | |
|             : this.handleValidationAndGetResult(isDefaultCommand, commandHandler, maybePromiseArgv, currentContext, aliases, yargs, middlewares, positionalMap);
 | |
|     }
 | |
|     populatePositionals(commandHandler, argv, context, yargs) {
 | |
|         argv._ = argv._.slice(context.commands.length);
 | |
|         const demanded = commandHandler.demanded.slice(0);
 | |
|         const optional = commandHandler.optional.slice(0);
 | |
|         const positionalMap = {};
 | |
|         this.validation.positionalCount(demanded.length, argv._.length);
 | |
|         while (demanded.length) {
 | |
|             const demand = demanded.shift();
 | |
|             this.populatePositional(demand, argv, positionalMap);
 | |
|         }
 | |
|         while (optional.length) {
 | |
|             const maybe = optional.shift();
 | |
|             this.populatePositional(maybe, argv, positionalMap);
 | |
|         }
 | |
|         argv._ = context.commands.concat(argv._.map(a => '' + a));
 | |
|         this.postProcessPositionals(argv, positionalMap, this.cmdToParseOptions(commandHandler.original), yargs);
 | |
|         return positionalMap;
 | |
|     }
 | |
|     populatePositional(positional, argv, positionalMap) {
 | |
|         const cmd = positional.cmd[0];
 | |
|         if (positional.variadic) {
 | |
|             positionalMap[cmd] = argv._.splice(0).map(String);
 | |
|         }
 | |
|         else {
 | |
|             if (argv._.length)
 | |
|                 positionalMap[cmd] = [String(argv._.shift())];
 | |
|         }
 | |
|     }
 | |
|     cmdToParseOptions(cmdString) {
 | |
|         const parseOptions = {
 | |
|             array: [],
 | |
|             default: {},
 | |
|             alias: {},
 | |
|             demand: {},
 | |
|         };
 | |
|         const parsed = parseCommand(cmdString);
 | |
|         parsed.demanded.forEach(d => {
 | |
|             const [cmd, ...aliases] = d.cmd;
 | |
|             if (d.variadic) {
 | |
|                 parseOptions.array.push(cmd);
 | |
|                 parseOptions.default[cmd] = [];
 | |
|             }
 | |
|             parseOptions.alias[cmd] = aliases;
 | |
|             parseOptions.demand[cmd] = true;
 | |
|         });
 | |
|         parsed.optional.forEach(o => {
 | |
|             const [cmd, ...aliases] = o.cmd;
 | |
|             if (o.variadic) {
 | |
|                 parseOptions.array.push(cmd);
 | |
|                 parseOptions.default[cmd] = [];
 | |
|             }
 | |
|             parseOptions.alias[cmd] = aliases;
 | |
|         });
 | |
|         return parseOptions;
 | |
|     }
 | |
|     postProcessPositionals(argv, positionalMap, parseOptions, yargs) {
 | |
|         const options = Object.assign({}, yargs.getOptions());
 | |
|         options.default = Object.assign(parseOptions.default, options.default);
 | |
|         for (const key of Object.keys(parseOptions.alias)) {
 | |
|             options.alias[key] = (options.alias[key] || []).concat(parseOptions.alias[key]);
 | |
|         }
 | |
|         options.array = options.array.concat(parseOptions.array);
 | |
|         options.config = {};
 | |
|         const unparsed = [];
 | |
|         Object.keys(positionalMap).forEach(key => {
 | |
|             positionalMap[key].map(value => {
 | |
|                 if (options.configuration['unknown-options-as-args'])
 | |
|                     options.key[key] = true;
 | |
|                 unparsed.push(`--${key}`);
 | |
|                 unparsed.push(value);
 | |
|             });
 | |
|         });
 | |
|         if (!unparsed.length)
 | |
|             return;
 | |
|         const config = Object.assign({}, options.configuration, {
 | |
|             'populate--': false,
 | |
|         });
 | |
|         const parsed = this.shim.Parser.detailed(unparsed, Object.assign({}, options, {
 | |
|             configuration: config,
 | |
|         }));
 | |
|         if (parsed.error) {
 | |
|             yargs
 | |
|                 .getInternalMethods()
 | |
|                 .getUsageInstance()
 | |
|                 .fail(parsed.error.message, parsed.error);
 | |
|         }
 | |
|         else {
 | |
|             const positionalKeys = Object.keys(positionalMap);
 | |
|             Object.keys(positionalMap).forEach(key => {
 | |
|                 positionalKeys.push(...parsed.aliases[key]);
 | |
|             });
 | |
|             Object.keys(parsed.argv).forEach(key => {
 | |
|                 if (positionalKeys.includes(key)) {
 | |
|                     if (!positionalMap[key])
 | |
|                         positionalMap[key] = parsed.argv[key];
 | |
|                     if (!this.isInConfigs(yargs, key) &&
 | |
|                         !this.isDefaulted(yargs, key) &&
 | |
|                         Object.prototype.hasOwnProperty.call(argv, key) &&
 | |
|                         Object.prototype.hasOwnProperty.call(parsed.argv, key) &&
 | |
|                         (Array.isArray(argv[key]) || Array.isArray(parsed.argv[key]))) {
 | |
|                         argv[key] = [].concat(argv[key], parsed.argv[key]);
 | |
|                     }
 | |
|                     else {
 | |
|                         argv[key] = parsed.argv[key];
 | |
|                     }
 | |
|                 }
 | |
|             });
 | |
|         }
 | |
|     }
 | |
|     isDefaulted(yargs, key) {
 | |
|         const { default: defaults } = yargs.getOptions();
 | |
|         return (Object.prototype.hasOwnProperty.call(defaults, key) ||
 | |
|             Object.prototype.hasOwnProperty.call(defaults, this.shim.Parser.camelCase(key)));
 | |
|     }
 | |
|     isInConfigs(yargs, key) {
 | |
|         const { configObjects } = yargs.getOptions();
 | |
|         return (configObjects.some(c => Object.prototype.hasOwnProperty.call(c, key)) ||
 | |
|             configObjects.some(c => Object.prototype.hasOwnProperty.call(c, this.shim.Parser.camelCase(key))));
 | |
|     }
 | |
|     runDefaultBuilderOn(yargs) {
 | |
|         if (!this.defaultCommand)
 | |
|             return;
 | |
|         if (this.shouldUpdateUsage(yargs)) {
 | |
|             const commandString = DEFAULT_MARKER.test(this.defaultCommand.original)
 | |
|                 ? this.defaultCommand.original
 | |
|                 : this.defaultCommand.original.replace(/^[^[\]<>]*/, '$0 ');
 | |
|             yargs
 | |
|                 .getInternalMethods()
 | |
|                 .getUsageInstance()
 | |
|                 .usage(commandString, this.defaultCommand.description);
 | |
|         }
 | |
|         const builder = this.defaultCommand.builder;
 | |
|         if (isCommandBuilderCallback(builder)) {
 | |
|             return builder(yargs, true);
 | |
|         }
 | |
|         else if (!isCommandBuilderDefinition(builder)) {
 | |
|             Object.keys(builder).forEach(key => {
 | |
|                 yargs.option(key, builder[key]);
 | |
|             });
 | |
|         }
 | |
|         return undefined;
 | |
|     }
 | |
|     moduleName(obj) {
 | |
|         const mod = whichModule(obj);
 | |
|         if (!mod)
 | |
|             throw new Error(`No command name given for module: ${this.shim.inspect(obj)}`);
 | |
|         return this.commandFromFilename(mod.filename);
 | |
|     }
 | |
|     commandFromFilename(filename) {
 | |
|         return this.shim.path.basename(filename, this.shim.path.extname(filename));
 | |
|     }
 | |
|     extractDesc({ describe, description, desc }) {
 | |
|         for (const test of [describe, description, desc]) {
 | |
|             if (typeof test === 'string' || test === false)
 | |
|                 return test;
 | |
|             assertNotStrictEqual(test, true, this.shim);
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
|     freeze() {
 | |
|         this.frozens.push({
 | |
|             handlers: this.handlers,
 | |
|             aliasMap: this.aliasMap,
 | |
|             defaultCommand: this.defaultCommand,
 | |
|         });
 | |
|     }
 | |
|     unfreeze() {
 | |
|         const frozen = this.frozens.pop();
 | |
|         assertNotStrictEqual(frozen, undefined, this.shim);
 | |
|         ({
 | |
|             handlers: this.handlers,
 | |
|             aliasMap: this.aliasMap,
 | |
|             defaultCommand: this.defaultCommand,
 | |
|         } = frozen);
 | |
|     }
 | |
|     reset() {
 | |
|         this.handlers = {};
 | |
|         this.aliasMap = {};
 | |
|         this.defaultCommand = undefined;
 | |
|         this.requireCache = new Set();
 | |
|         return this;
 | |
|     }
 | |
| }
 | |
| export function command(usage, validation, globalMiddleware, shim) {
 | |
|     return new CommandInstance(usage, validation, globalMiddleware, shim);
 | |
| }
 | |
| export function isCommandBuilderDefinition(builder) {
 | |
|     return (typeof builder === 'object' &&
 | |
|         !!builder.builder &&
 | |
|         typeof builder.handler === 'function');
 | |
| }
 | |
| function isCommandAndAliases(cmd) {
 | |
|     return cmd.every(c => typeof c === 'string');
 | |
| }
 | |
| export function isCommandBuilderCallback(builder) {
 | |
|     return typeof builder === 'function';
 | |
| }
 | |
| function isCommandBuilderOptionDefinitions(builder) {
 | |
|     return typeof builder === 'object';
 | |
| }
 | |
| export function isCommandHandlerDefinition(cmd) {
 | |
|     return typeof cmd === 'object' && !Array.isArray(cmd);
 | |
| }
 |