 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>
		
			
				
	
	
		
			298 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			298 lines
		
	
	
		
			7.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /*
 | |
|  * Jake JavaScript build tool
 | |
|  * Copyright 2112 Matthew Eernisse (mde@fleegix.org)
 | |
|  *
 | |
|  * Licensed under the Apache License, Version 2.0 (the "License");
 | |
|  * you may not use this file except in compliance with the License.
 | |
|  * You may obtain a copy of the License at
 | |
|  *
 | |
|  *         http://www.apache.org/licenses/LICENSE-2.0
 | |
|  *
 | |
|  * Unless required by applicable law or agreed to in writing, software
 | |
|  * distributed under the License is distributed on an "AS IS" BASIS,
 | |
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|  * See the License for the specific language governing permissions and
 | |
|  * limitations under the License.
 | |
|  *
 | |
| */
 | |
| 
 | |
| 
 | |
| let util = require('util'); // Native Node util module
 | |
| let spawn = require('child_process').spawn;
 | |
| let EventEmitter = require('events').EventEmitter;
 | |
| let logger = require('./logger');
 | |
| let file = require('./file');
 | |
| let Exec;
 | |
| 
 | |
| const _UUID_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
 | |
| 
 | |
| let parseArgs = function (argumentsObj) {
 | |
|   let args;
 | |
|   let arg;
 | |
|   let cmds;
 | |
|   let callback;
 | |
|   let opts = {
 | |
|     interactive: false,
 | |
|     printStdout: false,
 | |
|     printStderr: false,
 | |
|     breakOnError: true
 | |
|   };
 | |
| 
 | |
|   args = Array.prototype.slice.call(argumentsObj);
 | |
| 
 | |
|   cmds = args.shift();
 | |
|   // Arrayize if passed a single string command
 | |
|   if (typeof cmds == 'string') {
 | |
|     cmds = [cmds];
 | |
|   }
 | |
|   // Make a copy if it's an actual list
 | |
|   else {
 | |
|     cmds = cmds.slice();
 | |
|   }
 | |
| 
 | |
|   // Get optional callback or opts
 | |
|   while((arg = args.shift())) {
 | |
|     if (typeof arg == 'function') {
 | |
|       callback = arg;
 | |
|     }
 | |
|     else if (typeof arg == 'object') {
 | |
|       opts = Object.assign(opts, arg);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // Backward-compat shim
 | |
|   if (typeof opts.stdout != 'undefined') {
 | |
|     opts.printStdout = opts.stdout;
 | |
|     delete opts.stdout;
 | |
|   }
 | |
|   if (typeof opts.stderr != 'undefined') {
 | |
|     opts.printStderr = opts.stderr;
 | |
|     delete opts.stderr;
 | |
|   }
 | |
| 
 | |
|   return {
 | |
|     cmds: cmds,
 | |
|     opts: opts,
 | |
|     callback: callback
 | |
|   };
 | |
| };
 | |
| 
 | |
| /**
 | |
|   @name jake
 | |
|   @namespace jake
 | |
| */
 | |
| let utils = new (function () {
 | |
|   /**
 | |
|     @name jake.exec
 | |
|     @static
 | |
|     @function
 | |
|     @description Executes shell-commands asynchronously with an optional
 | |
|     final callback.
 | |
|     `
 | |
|     @param {String[]} cmds The list of shell-commands to execute
 | |
|     @param {Object} [opts]
 | |
|       @param {Boolean} [opts.printStdout=false] Print stdout from each command
 | |
|       @param {Boolean} [opts.printStderr=false] Print stderr from each command
 | |
|       @param {Boolean} [opts.breakOnError=true] Stop further execution on
 | |
|       the first error.
 | |
|       @param {Boolean} [opts.windowsVerbatimArguments=false] Don't translate
 | |
|       arguments on Windows.
 | |
|     @param {Function} [callback] Callback to run after executing  the
 | |
|     commands
 | |
| 
 | |
|     @example
 | |
|     let cmds = [
 | |
|           'echo "showing directories"'
 | |
|         , 'ls -al | grep ^d'
 | |
|         , 'echo "moving up a directory"'
 | |
|         , 'cd ../'
 | |
|         ]
 | |
|       , callback = function () {
 | |
|           console.log('Finished running commands.');
 | |
|         }
 | |
|     jake.exec(cmds, {stdout: true}, callback);
 | |
|    */
 | |
|   this.exec = function (a, b, c) {
 | |
|     let parsed = parseArgs(arguments);
 | |
|     let cmds = parsed.cmds;
 | |
|     let opts = parsed.opts;
 | |
|     let callback = parsed.callback;
 | |
| 
 | |
|     let ex = new Exec(cmds, opts, callback);
 | |
| 
 | |
|     ex.addListener('error', function (msg, code) {
 | |
|       if (opts.breakOnError) {
 | |
|         fail(msg, code);
 | |
|       }
 | |
|     });
 | |
|     ex.run();
 | |
| 
 | |
|     return ex;
 | |
|   };
 | |
| 
 | |
|   this.createExec = function (a, b, c) {
 | |
|     return new Exec(a, b, c);
 | |
|   };
 | |
| 
 | |
|   // From Math.uuid.js, https://github.com/broofa/node-uuid
 | |
|   // Robert Kieffer (robert@broofa.com), MIT license
 | |
|   this.uuid = function (length, radix) {
 | |
|     var chars = _UUID_CHARS
 | |
|       , uuid = []
 | |
|       , r
 | |
|       , i;
 | |
| 
 | |
|     radix = radix || chars.length;
 | |
| 
 | |
|     if (length) {
 | |
|       // Compact form
 | |
|       i = -1;
 | |
|       while (++i < length) {
 | |
|         uuid[i] = chars[0 | Math.random()*radix];
 | |
|       }
 | |
|     } else {
 | |
|       // rfc4122, version 4 form
 | |
| 
 | |
|       // rfc4122 requires these characters
 | |
|       uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
 | |
|       uuid[14] = '4';
 | |
| 
 | |
|       // Fill in random data.  At i==19 set the high bits of clock sequence as
 | |
|       // per rfc4122, sec. 4.1.5
 | |
|       i = -1;
 | |
|       while (++i < 36) {
 | |
|         if (!uuid[i]) {
 | |
|           r = 0 | Math.random()*16;
 | |
|           uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return uuid.join('');
 | |
|   };
 | |
| 
 | |
| })();
 | |
| 
 | |
| Exec = function () {
 | |
|   let parsed = parseArgs(arguments);
 | |
|   let cmds = parsed.cmds;
 | |
|   let opts = parsed.opts;
 | |
|   let callback = parsed.callback;
 | |
| 
 | |
|   this._cmds = cmds;
 | |
|   this._callback = callback;
 | |
|   this._config = opts;
 | |
| };
 | |
| 
 | |
| util.inherits(Exec, EventEmitter);
 | |
| 
 | |
| Object.assign(Exec.prototype, new (function () {
 | |
| 
 | |
|   let _run = function () {
 | |
|     let self = this;
 | |
|     let sh;
 | |
|     let cmd;
 | |
|     let args;
 | |
|     let next = this._cmds.shift();
 | |
|     let config = this._config;
 | |
|     let errData = '';
 | |
|     let shStdio;
 | |
|     let handleStdoutData = function (data) {
 | |
|       self.emit('stdout', data);
 | |
|     };
 | |
|     let handleStderrData = function (data) {
 | |
|       let d = data.toString();
 | |
|       self.emit('stderr', data);
 | |
|       // Accumulate the error-data so we can use it as the
 | |
|       // stack if the process exits with an error
 | |
|       errData += d;
 | |
|     };
 | |
| 
 | |
|     // Keep running as long as there are commands in the array
 | |
|     if (next) {
 | |
|       let spawnOpts = {};
 | |
|       this.emit('cmdStart', next);
 | |
| 
 | |
|       // Ganking part of Node's child_process.exec to get cmdline args parsed
 | |
|       if (process.platform == 'win32') {
 | |
|         cmd = 'cmd';
 | |
|         args = ['/c', next];
 | |
|         if (config.windowsVerbatimArguments) {
 | |
|           spawnOpts.windowsVerbatimArguments = true;
 | |
|         }
 | |
|       }
 | |
|       else {
 | |
|         cmd = '/bin/sh';
 | |
|         args = ['-c', next];
 | |
|       }
 | |
| 
 | |
|       if (config.interactive) {
 | |
|         spawnOpts.stdio = 'inherit';
 | |
|         sh = spawn(cmd, args, spawnOpts);
 | |
|       }
 | |
|       else {
 | |
|         shStdio = [
 | |
|           process.stdin
 | |
|         ];
 | |
|         if (config.printStdout) {
 | |
|           shStdio.push(process.stdout);
 | |
|         }
 | |
|         else {
 | |
|           shStdio.push('pipe');
 | |
|         }
 | |
|         if (config.printStderr) {
 | |
|           shStdio.push(process.stderr);
 | |
|         }
 | |
|         else {
 | |
|           shStdio.push('pipe');
 | |
|         }
 | |
|         spawnOpts.stdio = shStdio;
 | |
|         sh = spawn(cmd, args, spawnOpts);
 | |
|         if (!config.printStdout) {
 | |
|           sh.stdout.addListener('data', handleStdoutData);
 | |
|         }
 | |
|         if (!config.printStderr) {
 | |
|           sh.stderr.addListener('data', handleStderrData);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       // Exit, handle err or run next
 | |
|       sh.on('exit', function (code) {
 | |
|         let msg;
 | |
|         if (code !== 0) {
 | |
|           msg = errData || 'Process exited with error.';
 | |
|           msg = msg.trim();
 | |
|           self.emit('error', msg, code);
 | |
|         }
 | |
|         if (code === 0 || !config.breakOnError) {
 | |
|           self.emit('cmdEnd', next);
 | |
|           setTimeout(function () { _run.call(self); }, 0);
 | |
|         }
 | |
|       });
 | |
| 
 | |
|     }
 | |
|     else {
 | |
|       self.emit('end');
 | |
|       if (typeof self._callback == 'function') {
 | |
|         self._callback();
 | |
|       }
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   this.append = function (cmd) {
 | |
|     this._cmds.push(cmd);
 | |
|   };
 | |
| 
 | |
|   this.run = function () {
 | |
|     _run.call(this);
 | |
|   };
 | |
| 
 | |
| })());
 | |
| 
 | |
| utils.Exec = Exec;
 | |
| utils.file = file;
 | |
| utils.logger = logger;
 | |
| 
 | |
| module.exports = utils;
 | |
| 
 |