 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>
		
			
				
	
	
		
			240 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			240 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| "use strict";
 | |
| Object.defineProperty(exports, "__esModule", { value: true });
 | |
| exports.isNpm = isNpm;
 | |
| exports.isPnp = isPnp;
 | |
| exports.checkAndPreparePackage = checkAndPreparePackage;
 | |
| const node_child_process_1 = require("node:child_process");
 | |
| const fs = require("node:fs");
 | |
| const https = require("node:https");
 | |
| const path = require("node:path");
 | |
| const zlib = require("node:zlib");
 | |
| const constants_js_1 = require("./constants.js");
 | |
| const helpers_js_1 = require("./helpers.js");
 | |
| const REDIRECT_STATUS_CODES = new Set([301, 302, 307, 308]);
 | |
| function fetch(url) {
 | |
|     return new Promise((resolve, reject) => {
 | |
|         https
 | |
|             .get(url, res => {
 | |
|             if (REDIRECT_STATUS_CODES.has(res.statusCode) &&
 | |
|                 res.headers.location) {
 | |
|                 fetch(res.headers.location).then(resolve, reject);
 | |
|                 return;
 | |
|             }
 | |
|             if (res.statusCode !== 200) {
 | |
|                 return reject(new Error(`Server responded with ${res.statusCode}`));
 | |
|             }
 | |
|             const chunks = [];
 | |
|             res.on('data', (chunk) => chunks.push(chunk));
 | |
|             res.on('end', () => resolve(Buffer.concat(chunks)));
 | |
|         })
 | |
|             .on('error', reject);
 | |
|     });
 | |
| }
 | |
| function extractFileFromTarGzip(buffer, subpath) {
 | |
|     try {
 | |
|         buffer = zlib.unzipSync(buffer);
 | |
|     }
 | |
|     catch (err) {
 | |
|         throw new Error((0, helpers_js_1.errorMessage)(`Invalid gzip data in archive`, (0, helpers_js_1.getErrorMessage)(err)));
 | |
|     }
 | |
|     const str = (i, n) => String.fromCodePoint(...buffer.subarray(i, i + n)).replace(/\0.*$/, '');
 | |
|     let offset = 0;
 | |
|     subpath = `package/${subpath}`;
 | |
|     while (offset < buffer.length) {
 | |
|         const name = str(offset, 100);
 | |
|         const size = Number.parseInt(str(offset + 124, 12), 8);
 | |
|         offset += 512;
 | |
|         if (!Number.isNaN(size)) {
 | |
|             if (name === subpath) {
 | |
|                 return buffer.subarray(offset, offset + size);
 | |
|             }
 | |
|             offset += (size + 511) & ~511;
 | |
|         }
 | |
|     }
 | |
|     throw new Error((0, helpers_js_1.errorMessage)(`Could not find \`${subpath}\` in archive`));
 | |
| }
 | |
| function isNpm() {
 | |
|     return process.env.npm_config_user_agent?.startsWith('npm/');
 | |
| }
 | |
| function isPnp() {
 | |
|     return !!process.versions.pnp;
 | |
| }
 | |
| function installUsingNPM(hostPkg, pkg, version, target, subpath, nodePath) {
 | |
|     const isWasm32Wasi = target === constants_js_1.WASM32_WASI;
 | |
|     const env = { ...process.env, npm_config_global: undefined };
 | |
|     const pkgDir = path.dirname(require.resolve(hostPkg + `/${constants_js_1.PACKAGE_JSON}`));
 | |
|     const installDir = path.join(pkgDir, 'npm-install');
 | |
|     try {
 | |
|         fs.mkdirSync(installDir, { recursive: true });
 | |
|     }
 | |
|     catch (err) {
 | |
|         const error = err;
 | |
|         if (error.code === 'EROFS') {
 | |
|             (0, helpers_js_1.errorLog)(`Failed to create the temporary directory on read-only location: ${error.message}`);
 | |
|             (0, helpers_js_1.errorLog)(`You have to install \`${pkg}\` manually in this case.`);
 | |
|             return;
 | |
|         }
 | |
|         throw err;
 | |
|     }
 | |
|     try {
 | |
|         const packageJsonPath = path.join(installDir, constants_js_1.PACKAGE_JSON);
 | |
|         fs.writeFileSync(packageJsonPath, '{}');
 | |
|         (0, node_child_process_1.execSync)(`npm install --loglevel=error --prefer-offline --no-audit --progress=false${isWasm32Wasi ? ` --cpu=${constants_js_1.WASM32} --force` : ''} ${pkg}@${version}`, { cwd: installDir, stdio: 'pipe', env });
 | |
|         if (isWasm32Wasi) {
 | |
|             fs.unlinkSync(packageJsonPath);
 | |
|         }
 | |
|         const nodeModulesDir = path.join(installDir, 'node_modules');
 | |
|         try {
 | |
|             if (isWasm32Wasi) {
 | |
|                 const newNodeModulesDir = path.resolve(installDir, '../node_modules');
 | |
|                 const dirs = fs.readdirSync(nodeModulesDir);
 | |
|                 for (const dir of dirs) {
 | |
|                     if (dir.startsWith('@')) {
 | |
|                         const newPath = path.join(newNodeModulesDir, dir);
 | |
|                         fs.mkdirSync(newPath, { recursive: true });
 | |
|                         const subdir = path.join(nodeModulesDir, dir);
 | |
|                         const nestedDirs = fs.readdirSync(subdir);
 | |
|                         for (const nestedDir of nestedDirs) {
 | |
|                             try {
 | |
|                                 fs.renameSync(path.join(subdir, nestedDir), path.join(newPath, nestedDir));
 | |
|                             }
 | |
|                             catch {
 | |
|                             }
 | |
|                         }
 | |
|                     }
 | |
|                     else {
 | |
|                         try {
 | |
|                             fs.renameSync(path.join(nodeModulesDir, dir), path.join(newNodeModulesDir, dir));
 | |
|                         }
 | |
|                         catch {
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             else {
 | |
|                 const newPath = path.resolve(pkgDir, hostPkg
 | |
|                     .split('/')
 | |
|                     .map(() => '..')
 | |
|                     .join('/'), pkg);
 | |
|                 fs.mkdirSync(newPath, { recursive: true });
 | |
|                 fs.renameSync(path.join(nodeModulesDir, pkg), newPath);
 | |
|             }
 | |
|         }
 | |
|         catch {
 | |
|             fs.renameSync(path.join(nodeModulesDir, pkg, subpath), nodePath);
 | |
|         }
 | |
|     }
 | |
|     finally {
 | |
|         try {
 | |
|             (0, helpers_js_1.removeRecursive)(installDir);
 | |
|         }
 | |
|         catch {
 | |
|         }
 | |
|     }
 | |
| }
 | |
| async function downloadDirectlyFromNPM(pkg, version, subpath, nodePath) {
 | |
|     const url = `${(0, helpers_js_1.getGlobalNpmRegistry)()}${pkg}/-/${pkg.startsWith('@') ? pkg.split('/')[1] : pkg}-${version}.tgz`;
 | |
|     (0, helpers_js_1.errorLog)(`Trying to download ${JSON.stringify(url)}`);
 | |
|     try {
 | |
|         fs.writeFileSync(nodePath, extractFileFromTarGzip(await fetch(url), subpath));
 | |
|     }
 | |
|     catch (err) {
 | |
|         (0, helpers_js_1.errorLog)(`Failed to download ${JSON.stringify(url)}`, (0, helpers_js_1.getErrorMessage)(err));
 | |
|         throw err;
 | |
|     }
 | |
| }
 | |
| async function checkAndPreparePackage(packageNameOrPackageJson, versionOrCheckVersion, checkVersion) {
 | |
|     let packageJson;
 | |
|     if (typeof packageNameOrPackageJson === 'string') {
 | |
|         try {
 | |
|             packageJson = require(packageNameOrPackageJson + `/${constants_js_1.PACKAGE_JSON}`);
 | |
|         }
 | |
|         catch {
 | |
|             if (typeof versionOrCheckVersion !== 'string') {
 | |
|                 throw new TypeError((0, helpers_js_1.errorMessage)(`Failed to load \`${constants_js_1.PACKAGE_JSON}\` from \`${packageNameOrPackageJson}\`, please provide a version.`));
 | |
|             }
 | |
|             const pkg = packageNameOrPackageJson;
 | |
|             const packageJsonBuffer = await fetch(`${(0, helpers_js_1.getGlobalNpmRegistry)()}${pkg}/${versionOrCheckVersion}`);
 | |
|             packageJson = JSON.parse(packageJsonBuffer.toString('utf8'));
 | |
|         }
 | |
|     }
 | |
|     else {
 | |
|         packageJson = packageNameOrPackageJson;
 | |
|         if (checkVersion === undefined &&
 | |
|             typeof versionOrCheckVersion === 'boolean') {
 | |
|             checkVersion = versionOrCheckVersion;
 | |
|         }
 | |
|     }
 | |
|     const { name, version: pkgVersion, optionalDependencies } = packageJson;
 | |
|     const { napi, version = pkgVersion } = (0, helpers_js_1.getNapiInfoFromPackageJson)(packageJson, checkVersion);
 | |
|     if (checkVersion && pkgVersion !== version) {
 | |
|         throw new Error((0, helpers_js_1.errorMessage)(`Inconsistent package versions found for \`${name}\` v${pkgVersion} vs \`${napi.packageName}\` v${version}.`));
 | |
|     }
 | |
|     const targets = (0, helpers_js_1.getNapiNativeTargets)();
 | |
|     for (const target of targets) {
 | |
|         const pkg = `${napi.packageName}-${target}`;
 | |
|         if (!optionalDependencies?.[pkg]) {
 | |
|             continue;
 | |
|         }
 | |
|         const isWasm32Wasi = target === constants_js_1.WASM32_WASI;
 | |
|         const binaryPrefix = napi.binaryName ? `${napi.binaryName}.` : '';
 | |
|         const subpath = `${binaryPrefix}${target}.${isWasm32Wasi ? 'wasm' : 'node'}`;
 | |
|         try {
 | |
|             require.resolve(`${pkg}/${subpath}`);
 | |
|             break;
 | |
|         }
 | |
|         catch {
 | |
|             try {
 | |
|                 require.resolve(`${name}/${subpath}`);
 | |
|                 break;
 | |
|             }
 | |
|             catch { }
 | |
|             if (isPnp()) {
 | |
|                 if (isWasm32Wasi) {
 | |
|                     try {
 | |
|                         (0, node_child_process_1.execSync)(`yarn add -D ${pkg}@${version}`);
 | |
|                     }
 | |
|                     catch (err) {
 | |
|                         (0, helpers_js_1.errorLog)(`Failed to install package \`${pkg}\` automatically in the yarn P'n'P environment`, (0, helpers_js_1.getErrorMessage)(err));
 | |
|                         (0, helpers_js_1.errorLog)("You'll have to install it manually in this case.");
 | |
|                     }
 | |
|                 }
 | |
|                 return;
 | |
|             }
 | |
|             if (!isNpm()) {
 | |
|                 (0, helpers_js_1.errorLog)(`Failed to find package "${pkg}" on the file system
 | |
| 
 | |
| This can happen if you use the "--no-optional" flag. The "optionalDependencies"
 | |
| ${constants_js_1.PACKAGE_JSON} feature is used by ${name} to install the correct napi binary
 | |
| for your current platform. This install script will now attempt to work around
 | |
| this. If that fails, you need to remove the "--no-optional" flag to use ${name}.
 | |
| `);
 | |
|             }
 | |
|             let nodePath;
 | |
|             try {
 | |
|                 nodePath = (0, helpers_js_1.downloadedNodePath)(name, subpath);
 | |
|             }
 | |
|             catch {
 | |
|                 const nodeModulesDir = path.resolve(require.resolve(constants_js_1.meta.name + `/${constants_js_1.PACKAGE_JSON}`), '../..');
 | |
|                 nodePath = path.join(nodeModulesDir, name, subpath);
 | |
|                 fs.mkdirSync(path.dirname(nodePath), { recursive: true });
 | |
|             }
 | |
|             try {
 | |
|                 (0, helpers_js_1.errorLog)(`Trying to install package "${pkg}" using npm`);
 | |
|                 installUsingNPM(name, pkg, version, target, subpath, nodePath);
 | |
|                 break;
 | |
|             }
 | |
|             catch (err) {
 | |
|                 (0, helpers_js_1.errorLog)(`Failed to install package "${pkg}" using npm`, (0, helpers_js_1.getErrorMessage)(err));
 | |
|                 try {
 | |
|                     await downloadDirectlyFromNPM(pkg, version, subpath, nodePath);
 | |
|                     break;
 | |
|                 }
 | |
|                 catch (err) {
 | |
|                     throw new Error((0, helpers_js_1.errorMessage)(`Failed to install package "${pkg}"`, (0, helpers_js_1.getErrorMessage)(err)));
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| //# sourceMappingURL=index.js.map
 |