UNPKG

@analogjs/vitest-angular

Version:

Vitest Builder for Angular

197 lines 26.8 kB
import { createBuilder } from '@angular-devkit/architect'; import * as path from 'path'; import { globSync } from 'tinyglobby'; import { createAngularMemoryPlugin } from './plugins/angular-memory-plugin'; import { esbuildDownlevelPlugin } from './plugins/esbuild-downlevel-plugin'; import { getBuildApplicationFunction } from './devkit'; export var ResultKind; (function (ResultKind) { ResultKind[ResultKind["Failure"] = 0] = "Failure"; ResultKind[ResultKind["Full"] = 1] = "Full"; ResultKind[ResultKind["Incremental"] = 2] = "Incremental"; ResultKind[ResultKind["ComponentUpdate"] = 3] = "ComponentUpdate"; })(ResultKind || (ResultKind = {})); process.env['VITE_CJS_IGNORE_WARNING'] = 'true'; async function* vitestApplicationBuilder(options, context) { process.env['TEST'] = 'true'; process.env['VITEST'] = 'true'; const { buildApplicationInternal, angularVersion } = await getBuildApplicationFunction(); const { startVitest } = await Function('return import("vitest/node")')(); const projectConfig = await context.getProjectMetadata(context.target); const extraArgs = await getExtraArgs(options); const workspaceRoot = context.workspaceRoot; const projectRoot = projectConfig['root']; const setupFile = path.relative(projectRoot, options.setupFile); const config = { root: `${projectRoot || '.'}`, watch: options.watch === true, config: options.configFile, setupFiles: [setupFile], globals: true, pool: 'vmThreads', reporters: ['default'], environment: 'jsdom', exclude: options?.exclude || [], ...extraArgs, }; const includes = findIncludes({ workspaceRoot, projectRoot, include: options.include, exclude: options.exclude || [], }); const testFiles = [ path.relative(workspaceRoot, options.setupFile), ...includes.map((inc) => path.relative(workspaceRoot, inc)), ]; const entryPoints = generateEntryPoints({ projectRoot: projectRoot, testFiles, context, angularVersion, }); const outputFiles = new Map(); const viteConfig = { plugins: [ (await createAngularMemoryPlugin({ angularVersion, workspaceRoot, outputFiles, })), await esbuildDownlevelPlugin(), ], }; let server; for await (const buildOutput of buildApplicationInternal({ aot: false, index: false, progress: false, prerender: false, optimization: false, outputPath: `.angular/.vitest/${projectConfig['name']}`, outExtension: 'mjs', outputHashing: 2, // None tsConfig: path.relative(workspaceRoot, options.tsConfig), watch: options.watch === true, entryPoints, allowedCommonJsDependencies: ['@analogjs/vitest-angular/setup-zone'], sourceMap: { scripts: true, styles: false, vendor: false, }, }, context)) { if (buildOutput.kind === ResultKind.Failure) { return { success: false }; } else if (buildOutput.kind === ResultKind.Incremental || buildOutput.kind === ResultKind.Full) { if (buildOutput.kind === ResultKind.Full) { outputFiles.clear(); Object.keys(buildOutput.files).forEach((key) => { outputFiles.set(key, buildOutput.files[key]); }); } else { Object.keys(buildOutput.files).forEach((key) => { outputFiles.set(key, buildOutput.files[key]); }); } } if (options.watch) { if (!server) { server = await startVitest('test', [], config, viteConfig); } else { await server.start([]); } yield { success: true }; } else { server = await startVitest('test', [], config, viteConfig); const success = server?.state.getCountOfFailedTests() === 0; yield { success }; } } yield { success: true }; } export async function getExtraArgs(options) { // support passing extra args to Vitest CLI const schema = await import('./schema.json', { with: { type: 'json' } }); const extraArgs = {}; for (const key of Object.keys(options)) { if (!schema.default.properties[key]) { extraArgs[key] = options[key]; } } return extraArgs; } /** * Finds test files to include in the Vitest run using tinyglobby pattern matching. * * This function: * 1. Normalizes the project root path to ensure consistent path separators * 2. Constructs glob patterns by prepending the project root to each include pattern * 3. Uses globSync from tinyglobby to find all files matching the patterns while respecting exclusions * * @param options Configuration object containing workspace and project paths, include/exclude patterns * @returns Array of absolute file paths that match the include patterns * * Sample output paths: * - /workspace/apps/my-app/src/app/app.component.spec.ts * - /workspace/apps/my-app/src/app/services/data.service.spec.ts * - /workspace/apps/my-app/src/app/components/header/header.component.test.ts * - /workspace/apps/my-app/src/app/utils/helpers.spec.ts * * tinyglobby vs fast-glob comparison: * - Both support the same glob patterns and ignore functionality * - Both are fast and efficient for file matching * - tinyglobby is a lighter alternative with similar API * - tinyglobby's globSync returns absolute paths by default when absolute: true is set * - tinyglobby has fewer dependencies and smaller bundle size * * globSync options explained: * - dot: true - Includes files/directories that start with a dot (e.g., .env.test) * - absolute: true - Returns absolute file paths instead of relative paths * - ignore: options.exclude - Excludes files matching the exclude patterns */ function findIncludes(options) { const { normalizePath } = require('vite'); // Normalize project root path to ensure consistent path separators across platforms const projectRoot = normalizePath(path.resolve(options.workspaceRoot, options.projectRoot)); // Construct glob patterns by prepending project root to each include pattern // Example: if include=['**/*.spec.ts'] and projectRoot='/workspace/apps/my-app' // Result: ['/workspace/apps/my-app/**/*.spec.ts'] const globs = [...options.include.map((glob) => `${projectRoot}/${glob}`)]; // Use globSync from tinyglobby to find all files matching the patterns // Returns absolute file paths that match the include patterns while respecting exclusions return globSync(globs, { dot: true, // Include files/directories starting with dot (e.g., .env.test) absolute: true, // Return absolute file paths ignore: options.exclude, // Exclude files matching these patterns }); } function generateEntryPoints({ projectRoot, testFiles, context, angularVersion, }) { if (angularVersion < 19) { return testFiles; } const seen = new Set(); return new Map(Array.from(testFiles, (testFile) => { const relativePath = path .relative(testFile.startsWith(projectRoot) ? projectRoot : context.workspaceRoot, testFile) .replace(/^[./]+/, '_') .replace(/\//g, '-'); let uniqueName = `spec-${path.basename(relativePath, path.extname(relativePath))}`; let suffix = 2; while (seen.has(uniqueName)) { uniqueName = `${relativePath}-${suffix}`; ++suffix; } seen.add(uniqueName); return [uniqueName, testFile]; })); } export default createBuilder(vitestApplicationBuilder); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidml0ZXN0LmltcGwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy92aXRlc3QtYW5ndWxhci9zcmMvbGliL2J1aWxkZXJzL2J1aWxkL3ZpdGVzdC5pbXBsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUMxRCxPQUFPLEtBQUssSUFBSSxNQUFNLE1BQU0sQ0FBQztBQUk3QixPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBR3RDLE9BQU8sRUFBRSx5QkFBeUIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzVFLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLG9DQUFvQyxDQUFDO0FBQzVFLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUV2RCxNQUFNLENBQU4sSUFBWSxVQUtYO0FBTEQsV0FBWSxVQUFVO0lBQ3BCLGlEQUFPLENBQUE7SUFDUCwyQ0FBSSxDQUFBO0lBQ0oseURBQVcsQ0FBQTtJQUNYLGlFQUFlLENBQUE7QUFDakIsQ0FBQyxFQUxXLFVBQVUsS0FBVixVQUFVLFFBS3JCO0FBRUQsT0FBTyxDQUFDLEdBQUcsQ0FBQyx5QkFBeUIsQ0FBQyxHQUFHLE1BQU0sQ0FBQztBQUVoRCxLQUFLLFNBQVMsQ0FBQyxDQUFDLHdCQUF3QixDQUN0QyxPQUFxQixFQUNyQixPQUFZO0lBRVosT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxNQUFNLENBQUM7SUFDN0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsR0FBRyxNQUFNLENBQUM7SUFFL0IsTUFBTSxFQUFFLHdCQUF3QixFQUFFLGNBQWMsRUFBRSxHQUNoRCxNQUFNLDJCQUEyQixFQUFFLENBQUM7SUFDdEMsTUFBTSxFQUFFLFdBQVcsRUFBRSxHQUFHLE1BQU8sUUFBUSxDQUNyQyw4QkFBOEIsQ0FD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QUFHLFFBQVEsSUFBSSxDQUFDLFFBQVEsQ0FDcEMsWUFBWSxFQUNaLElBQUksQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQzNCLEVBQUUsQ0FBQztRQUNKLElBQUksTUFBTSxHQUFHLENBQUMsQ0FBQztRQUNmLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsRUFBRSxDQUFDO1lBQzVCLFVBQVUsR0FBRyxHQUFHLFlBQVksSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUN6QyxFQUFFLE1BQU0sQ0FBQztRQUNYLENBQUM7UUFDRCxJQUFJLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBRXJCLE9BQU8sQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLENBQUM7SUFDaEMsQ0FBQyxDQUFDLENBQ0gsQ0FBQztBQUNKLENBQUM7QUFFRCxlQUFlLGFBQWEsQ0FBQyx3QkFBd0IsQ0FBWSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3JlYXRlQnVpbGRlciB9IGZyb20gJ0Bhbmd1bGFyLWRldmtpdC9hcmNoaXRlY3QnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCB0eXBlIHsgVml0ZXN0IH0gZnJvbSAndml0ZXN0L25vZGUnO1xuaW1wb3J0IHR5cGUgeyBQbHVnaW4sIFVzZXJDb25maWcgfSBmcm9tICd2aXRlJztcbmltcG9ydCB0eXBlIHsgVGVzdFVzZXJDb25maWcgYXMgVml0ZXN0Q29uZmlnIH0gZnJvbSAndml0ZXN0L25vZGUnO1xuaW1wb3J0IHsgZ2xvYlN5bmMgfSBmcm9tICd0aW55Z2xvYmJ5JztcblxuaW1wb3J0IHsgVml0ZXN0U2NoZW1hIH0gZnJvbSAnLi9zY2hlbWEnO1xuaW1wb3J0IHsgY3JlYXRlQW5ndWxhck1lbW9yeVBsdWdpbiB9IGZyb20gJy4vcGx1Z2lucy9hbmd1bGFyLW1lbW9yeS1wbHVnaW4nO1xuaW1wb3J0IHsgZXNidWlsZERvd25sZXZlbFBsdWdpbiB9IGZyb20gJy4vcGx1Z2lucy9lc2J1aWxkLWRvd25sZXZlbC1wbHVnaW4nO1xuaW1wb3J0IHsgZ2V0QnVpbGRBcHBsaWNhdGlvbkZ1bmN0aW9uIH0gZnJvbSAnLi9kZXZraXQnO1xuXG5leHBvcnQgZW51bSBSZXN1bHRLaW5kIHtcbiAgRmFpbHVyZSxcbiAgRnVsbCxcbiAgSW5jcmVtZW50YWwsXG4gIENvbXBvbmVudFVwZGF0ZSxcbn1cblxucHJvY2Vzcy5lbnZbJ1ZJVEVfQ0pTX0lHTk9SRV9XQVJOSU5HJ10gPSAndHJ1ZSc7XG5cbmFzeW5jIGZ1bmN0aW9uKiB2aXRlc3RBcHBsaWNhdGlvbkJ1aWxkZXIoXG4gIG9wdGlvbnM6IFZpdGVzdFNjaGVtYSxcbiAgY29udGV4dDogYW55LFxuKTogQXN5bmNJdGVyYWJsZTx7IHN1Y2Nlc3M6IGJvb2xlYW4gfT4ge1xuICBwcm9jZXNzLmVudlsnVEVTVCddID0gJ3RydWUnO1xuICBwcm9jZXNzLmVudlsnVklURVNUJ10gPSAndHJ1ZSc7XG5cbiAgY29uc3QgeyBidWlsZEFwcGxpY2F0aW9uSW50ZXJuYWwsIGFuZ3VsYXJWZXJzaW9uIH0gPVxuICAgIGF3YWl0IGdldEJ1aWxkQXBwbGljYXRpb25GdW5jdGlvbigpO1xuICBjb25zdCB7IHN0YXJ0Vml0ZXN0IH0gPSBhd2FpdCAoRnVuY3Rpb24oXG4gICAgJ3JldHVybiBpbXBvcnQoXCJ2aXRlc3Qvbm9kZVwiKScsXG4gICkoKSBhcyBQcm9taXNlPHR5cGVvZiBpbXBvcnQoJ3ZpdGVzdC9ub2RlJyk+KTtcblxuICBjb25zdCBwcm9qZWN0Q29uZmlnID0gYXdhaXQgY29udGV4dC5nZXRQcm9qZWN0TWV0YWRhdGEoY29udGV4dC50YXJnZXQpO1xuICBjb25zdCBleHRyYUFyZ3MgPSBhd2FpdCBnZXRFeHRyYUFyZ3Mob3B0aW9ucyk7XG4gIGNvbnN0IHdvcmtzcGFjZVJvb3QgPSBjb250ZXh0LndvcmtzcGFjZVJvb3Q7XG4gIGNvbnN0IHByb2plY3RSb290ID0gcHJvamVjdENvbmZpZ1sncm9vdCddO1xuICBjb25zdCBzZXR1cEZpbGUgPSBwYXRoLnJlbGF0aXZlKHByb2plY3RSb290LCBvcHRpb25zLnNldHVwRmlsZSk7XG5cbiAgY29uc3QgY29uZmlnOiBWaXRlc3RDb25maWcgPSB7XG4gICAgcm9vdDogYCR7cHJvamVjdFJvb3QgfHwgJy4nfWAsXG4gICAgd2F0Y2g6IG9wdGlvbnMud2F0Y2ggPT09IHRydWUsXG4gICAgY29uZmlnOiBvcHRpb25zLmNvbmZpZ0ZpbGUsXG4gICAgc2V0dXBGaWxlczogW3NldHVwRmlsZV0sXG4gICAgZ2xvYmFsczogdHJ1ZSxcbiAgICBwb29sOiAndm1UaHJlYWRzJyxcbiAgICByZXBvcnRlcnM6IFsnZGVmYXVsdCddLFxuICAgIGVudmlyb25tZW50OiAnanNkb20nLFxuICAgIGV4Y2x1ZGU6IG9wdGlvbnM/LmV4Y2x1ZGUgfHwgW10sXG4gICAgLi4uZXh0cmFBcmdzLFxuICB9O1xuXG4gIGNvbnN0IGluY2x1ZGVzOiBzdHJpbmdbXSA9IGZpbmRJbmNsdWRlcyh7XG4gICAgd29ya3NwYWNlUm9vdCxcbiAgICBwcm9qZWN0Um9vdCxcbiAgICBpbmNsdWRlOiBvcHRpb25zLmluY2x1ZGUsXG4gICAgZXhjbHVkZTogb3B0aW9ucy5leGNsdWRlIHx8IFtdLFxuICB9KTtcblxuICBjb25zdCB0ZXN0RmlsZXMgPSBbXG4gICAgcGF0aC5yZWxhdGl2ZSh3b3Jrc3BhY2VSb290LCBvcHRpb25zLnNldHVwRmlsZSksXG4gICAgLi4uaW5jbHVkZXMubWFwKChpbmMpID0+IHBhdGgucmVsYXRpdmUod29ya3NwYWNlUm9vdCwgaW5jKSksXG4gIF07XG5cbiAgY29uc3QgZW50cnlQb2ludHMgPSBnZW5lcmF0ZUVudHJ5UG9pbnRzKHtcbiAgICBwcm9qZWN0Um9vdDogcHJvamVjdFJvb3QsXG4gICAgdGVzdEZpbGVzLFxuICAgIGNvbnRleHQsXG4gICAgYW5ndWxhclZlcnNpb24sXG4gIH0pO1xuXG4gIGNvbnN0IG91dHB1dEZpbGVzID0gbmV3IE1hcCgpO1xuXG4gIGNvbnN0IHZpdGVDb25maWc6IGFueSA9IHtcbiAgICBwbHVnaW5zOiBbXG4gICAgICAoYXdhaXQgY3JlYXRlQW5ndWxhck1lbW9yeVBsdWdpbih7XG4gICAgICAgIGFuZ3VsYXJWZXJzaW9uLFxuICAgICAgICB3b3Jrc3BhY2VSb290LFxuICAgICAgICBvdXRwdXRGaWxlcyxcbiAgICAgIH0pKSBhcyBQbHVnaW4sXG4gICAgICBhd2FpdCBlc2J1aWxkRG93bmxldmVsUGx1Z2luKCksXG4gICAgXSxcbiAgfTtcblxuICBsZXQgc2VydmVyOiBWaXRlc3QgfCB1bmRlZmluZWQ7XG4gIGZvciBhd2FpdCAoY29uc3QgYnVpbGRPdXRwdXQgb2YgYnVpbGRBcHBsaWNhdGlvbkludGVybmFsKFxuICAgIHtcbiAgICAgIGFvdDogZmFsc2UsXG4gICAgICBpbmRleDogZmFsc2UsXG4gICAgICBwcm9ncmVzczogZmFsc2UsXG4gICAgICBwcmVyZW5kZXI6IGZhbHNlLFxuICAgICAgb3B0aW1pemF0aW9uOiBmYWxzZSxcbiAgICAgIG91dHB1dFBhdGg6IGAuYW5ndWxhci8udml0ZXN0LyR7cHJvamVjdENvbmZpZ1snbmFtZSddfWAsXG4gICAgICBvdXRFeHRlbnNpb246ICdtanMnLFxuICAgICAgb3V0cHV0SGFzaGluZzogMiwgLy8gTm9uZVxuICAgICAgdHNDb25maWc6IHBhdGgucmVsYXRpdmUod29ya3NwYWNlUm9vdCwgb3B0aW9ucy50c0NvbmZpZyksXG4gICAgICB3YXRjaDogb3B0aW9ucy53YXRjaCA9PT0gdHJ1ZSxcbiAgICAgIGVudHJ5UG9pbnRzLFxuICAgICAgYWxsb3dlZENvbW1vbkpzRGVwZW5kZW5jaWVzOiBbJ0BhbmFsb2dqcy92aXRlc3QtYW5ndWxhci9zZXR1cC16b25lJ10sXG4gICAgICBzb3VyY2VNYXA6IHtcbiAgICAgICAgc2NyaXB0czogdHJ1ZSxcbiAgICAgICAgc3R5bGVzOiBmYWxzZSxcbiAgICAgICAgdmVuZG9yOiBmYWxzZSxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBjb250ZXh0LFxuICApKSB7XG4gICAgaWYgKGJ1aWxkT3V0cHV0LmtpbmQgPT09IFJlc3VsdEtpbmQuRmFpbHVyZSkge1xuICAgICAgcmV0dXJuIHsgc3VjY2VzczogZmFsc2UgfTtcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgYnVpbGRPdXRwdXQua2luZCA9PT0gUmVzdWx0S2luZC5JbmNyZW1lbnRhbCB8fFxuICAgICAgYnVpbGRPdXRwdXQua2luZCA9PT0gUmVzdWx0S2luZC5GdWxsXG4gICAgKSB7XG4gICAgICBpZiAoYnVpbGRPdXRwdXQua2luZCA9PT0gUmVzdWx0S2luZC5GdWxsKSB7XG4gICAgICAgIG91dHB1dEZpbGVzLmNsZWFyKCk7XG4gICAgICAgIE9iamVjdC5rZXlzKGJ1aWxkT3V0cHV0LmZpbGVzKS5mb3JFYWNoKChrZXkpID0+IHtcbiAgICAgICAgICBvdXRwdXRGaWxlcy5zZXQoa2V5LCBidWlsZE91dHB1dC5maWxlc1trZXldKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBPYmplY3Qua2V5cyhidWlsZE91dHB1dC5maWxlcykuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgICAgICAgb3V0cHV0RmlsZXMuc2V0KGtleSwgYnVpbGRPdXRwdXQuZmlsZXNba2V5XSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChvcHRpb25zLndhdGNoKSB7XG4gICAgICBpZiAoIXNlcnZlcikge1xuICAgICAgICBzZXJ2ZXIgPSBhd2FpdCBzdGFydFZpdGVzdCgndGVzdCcsIFtdLCBjb25maWcsIHZpdGVDb25maWcpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgYXdhaXQgc2VydmVyLnN0YXJ0KFtdKTtcbiAgICAgIH1cblxuICAgICAgeWllbGQgeyBzdWNjZXNzOiB0cnVlIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIHNlcnZlciA9IGF3YWl0IHN0YXJ0Vml0ZXN0KCd0ZXN0JywgW10sIGNvbmZpZywgdml0ZUNvbmZpZyk7XG5cbiAgICAgIGNvbnN0IHN1Y2Nlc3MgPSBzZXJ2ZXI/LnN0YXRlLmdldENvdW50T2ZGYWlsZWRUZXN0cygpID09PSAwO1xuXG4gICAgICB5aWVsZCB7IHN1Y2Nlc3MgfTtcbiAgICB9XG4gIH1cblxuICB5aWVsZCB7IHN1Y2Nlc3M6IHRydWUgfTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldEV4dHJhQXJncyhcbiAgb3B0aW9uczogVml0ZXN0U2NoZW1hLFxuKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gIC8vIHN1cHBvcnQgcGFzc2luZyBleHRyYSBhcmdzIHRvIFZpdGVzdCBDTElcbiAgY29uc3Qgc2NoZW1hID0gYXdhaXQgaW1wb3J0KCcuL3NjaGVtYS5qc29uJywgeyB3aXRoOiB7IHR5cGU6ICdqc29uJyB9IH0pO1xuICBjb25zdCBleHRyYUFyZ3M6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fTtcbiAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMob3B0aW9ucykpIHtcbiAgICBpZiAoIShzY2hlbWEgYXMgYW55KS5kZWZhdWx0LnByb3BlcnRpZXNba2V5XSkge1xuICAgICAgZXh0cmFBcmdzW2tleV0gPSAob3B0aW9ucyBhcyBhbnkpW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGV4dHJhQXJncztcbn1cblxuLyoqXG4gKiBGaW5kcyB0ZXN0IGZpbGVzIHRvIGluY2x1ZGUgaW4gdGhlIFZpdGVzdCBydW4gdXNpbmcgdGlueWdsb2JieSBwYXR0ZXJuIG1hdGNoaW5nLlxuICpcbiAqIFRoaXMgZnVuY3Rpb246XG4gKiAxLiBOb3JtYWxpemVzIHRoZSBwcm9qZWN0IHJvb3QgcGF0aCB0byBlbnN1cmUgY29uc2lzdGVudCBwYXRoIHNlcGFyYXRvcnNcbiAqIDIuIENvbnN0cnVjdHMgZ2xvYiBwYXR0ZXJucyBieSBwcmVwZW5kaW5nIHRoZSBwcm9qZWN0IHJvb3QgdG8gZWFjaCBpbmNsdWRlIHBhdHRlcm5cbiAqIDMuIFVzZXMgZ2xvYlN5bmMgZnJvbSB0aW55Z2xvYmJ5IHRvIGZpbmQgYWxsIGZpbGVzIG1hdGNoaW5nIHRoZSBwYXR0ZXJucyB3aGlsZSByZXNwZWN0aW5nIGV4Y2x1c2lvbnNcbiAqXG4gKiBAcGFyYW0gb3B0aW9ucyBDb25maWd1cmF0aW9uIG9iamVjdCBjb250YWluaW5nIHdvcmtzcGFjZSBhbmQgcHJvamVjdCBwYXRocywgaW5jbHVkZS9leGNsdWRlIHBhdHRlcm5zXG4gKiBAcmV0dXJucyBBcnJheSBvZiBhYnNvbHV0ZSBmaWxlIHBhdGhzIHRoYXQgbWF0Y2ggdGhlIGluY2x1ZGUgcGF0dGVybnNcbiAqXG4gKiBTYW1wbGUgb3V0cHV0IHBhdGhzOlxuICogLSAvd29ya3NwYWNlL2FwcHMvbXktYXBwL3NyYy9hcHAvYXBwLmNvbXBvbmVudC5zcGVjLnRzXG4gKiAtIC93b3Jrc3BhY2UvYXBwcy9teS1hcHAvc3JjL2FwcC9zZXJ2aWNlcy9kYXRhLnNlcnZpY2Uuc3BlYy50c1xuICogLSAvd29ya3NwYWNlL2FwcHMvbXktYXBwL3NyYy9hcHAvY29tcG9uZW50cy9oZWFkZXIvaGVhZGVyLmNvbXBvbmVudC50ZXN0LnRzXG4gKiAtIC93b3Jrc3BhY2UvYXBwcy9teS1hcHAvc3JjL2FwcC91dGlscy9oZWxwZXJzLnNwZWMudHNcbiAqXG4gKiB0aW55Z2xvYmJ5IHZzIGZhc3QtZ2xvYiBjb21wYXJpc29uOlxuICogLSBCb3RoIHN1cHBvcnQgdGhlIHNhbWUgZ2xvYiBwYXR0ZXJucyBhbmQgaWdub3JlIGZ1bmN0aW9uYWxpdHlcbiAqIC0gQm90aCBhcmUgZmFzdCBhbmQgZWZmaWNpZW50IGZvciBmaWxlIG1hdGNoaW5nXG4gKiAtIHRpbnlnbG9iYnkgaXMgYSBsaWdodGVyIGFsdGVybmF0aXZlIHdpdGggc2ltaWxhciBBUElcbiAqIC0gdGlueWdsb2JieSdzIGdsb2JTeW5jIHJldHVybnMgYWJzb2x1dGUgcGF0aHMgYnkgZGVmYXVsdCB3aGVuIGFic29sdXRlOiB0cnVlIGlzIHNldFxuICogLSB0aW55Z2xvYmJ5IGhhcyBmZXdlciBkZXBlbmRlbmNpZXMgYW5kIHNtYWxsZXIgYnVuZGxlIHNpemVcbiAqXG4gKiBnbG9iU3luYyBvcHRpb25zIGV4cGxhaW5lZDpcbiAqIC0gZG90OiB0cnVlIC0gSW5jbHVkZXMgZmlsZXMvZGlyZWN0b3JpZXMgdGhhdCBzdGFydCB3aXRoIGEgZG90IChlLmcuLCAuZW52LnRlc3QpXG4gKiAtIGFic29sdXRlOiB0cnVlIC0gUmV0dXJucyBhYnNvbHV0ZSBmaWxlIHBhdGhzIGluc3RlYWQgb2YgcmVsYXRpdmUgcGF0aHNcbiAqIC0gaWdub3JlOiBvcHRpb25zLmV4Y2x1ZGUgLSBFeGNsdWRlcyBmaWxlcyBtYXRjaGluZyB0aGUgZXhjbHVkZSBwYXR0ZXJuc1xuICovXG5mdW5jdGlvbiBmaW5kSW5jbHVkZXMob3B0aW9uczoge1xuICB3b3Jrc3BhY2VSb290OiBzdHJpbmc7XG4gIHByb2plY3RSb290OiBzdHJpbmc7XG4gIGluY2x1ZGU6IHN0cmluZ1tdO1xuICBleGNsdWRlOiBzdHJpbmdbXTtcbn0pIHtcbiAgY29uc3QgeyBub3JtYWxpemVQYXRoIH0gPSByZXF1aXJlKCd2aXRlJyk7XG5cbiAgLy8gTm9ybWFsaXplIHByb2plY3Qgcm9vdCBwYXRoIHRvIGVuc3VyZSBjb25zaXN0ZW50IHBhdGggc2VwYXJhdG9ycyBhY3Jvc3MgcGxhdGZvcm1zXG4gIGNvbnN0IHByb2plY3RSb290ID0gbm9ybWFsaXplUGF0aChcbiAgICBwYXRoLnJlc29sdmUob3B0aW9ucy53b3Jrc3BhY2VSb290LCBvcHRpb25zLnByb2plY3RSb290KSxcbiAgKTtcblxuICAvLyBDb25zdHJ1Y3QgZ2xvYiBwYXR0ZXJucyBieSBwcmVwZW5kaW5nIHByb2plY3Qgcm9vdCB0byBlYWNoIGluY2x1ZGUgcGF0dGVyblxuICAvLyBFeGFtcGxlOiBpZiBpbmNsdWRlPVsnKiovKi5zcGVjLnRzJ10gYW5kIHByb2plY3RSb290PScvd29ya3NwYWNlL2FwcHMvbXktYXBwJ1xuICAvLyBSZXN1bHQ6IFsnL3dvcmtzcGFjZS9hcHBzL215LWFwcC8qKi8qLnNwZWMudHMnXVxuICBjb25zdCBnbG9icyA9IFsuLi5vcHRpb25zLmluY2x1ZGUubWFwKChnbG9iKSA9PiBgJHtwcm9qZWN0Um9vdH0vJHtnbG9ifWApXTtcblxuICAvLyBVc2UgZ2xvYlN5bmMgZnJvbSB0aW55Z2xvYmJ5IHRvIGZpbmQgYWxsIGZpbGVzIG1hdGNoaW5nIHRoZSBwYXR0ZXJuc1xuICAvLyBSZXR1cm5zIGFic29sdXRlIGZpbGUgcGF0aHMgdGhhdCBtYXRjaCB0aGUgaW5jbHVkZSBwYXR0ZXJucyB3aGlsZSByZXNwZWN0aW5nIGV4Y2x1c2lvbnNcbiAgcmV0dXJuIGdsb2JTeW5jKGdsb2JzLCB7XG4gICAgZG90OiB0cnVlLCAvLyBJbmNsdWRlIGZpbGVzL2RpcmVjdG9yaWVzIHN0YXJ0aW5nIHdpdGggZG90IChlLmcuLCAuZW52LnRlc3QpXG4gICAgYWJzb2x1dGU6IHRydWUsIC8vIFJldHVybiBhYnNvbHV0ZSBmaWxlIHBhdGhzXG4gICAgaWdub3JlOiBvcHRpb25zLmV4Y2x1ZGUsIC8vIEV4Y2x1ZGUgZmlsZXMgbWF0Y2hpbmcgdGhlc2UgcGF0dGVybnNcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIGdlbmVyYXRlRW50cnlQb2ludHMoe1xuICBwcm9qZWN0Um9vdCxcbiAgdGVzdEZpbGVzLFxuICBjb250ZXh0LFxuICBhbmd1bGFyVmVyc2lvbixcbn06IHtcbiAgcHJvamVjdFJvb3Q6IHN0cmluZztcbiAgdGVzdEZpbGVzOiBzdHJpbmdbXTtcbiAgY29udGV4dDogYW55O1xuICBhbmd1bGFyVmVyc2lvbjogbnVtYmVyO1xufSkge1xuICBpZiAoYW5ndWxhclZlcnNpb24gPCAxOSkge1xuICAgIHJldHVybiB0ZXN0RmlsZXM7XG4gIH1cblxuICBjb25zdCBzZWVuID0gbmV3IFNldCgpO1xuXG4gIHJldHVybiBuZXcgTWFwKFxuICAgIEFycmF5LmZyb20odGVzdEZpbGVzLCAodGVzdEZpbGUpID0+IHtcbiAgICAgIGNvbnN0IHJlbGF0aXZlUGF0aCA9IHBhdGhcbiAgICAgICAgLnJlbGF0aXZlKFxuICAgICAgICAgIHRlc3RGaWxlLnN0YXJ0c1dpdGgocHJvamVjdFJvb3QpXG4gICAgICAgICAgICA/IHByb2plY3RSb290XG4gICAgICAgICAgICA6IGNvbnRleHQud29ya3NwYWNlUm9vdCxcbiAgICAgICAgICB0ZXN0RmlsZSxcbiAgICAgICAgKVxuICAgICAgICAucmVwbGFjZSgvXlsuL10rLywgJ18nKVxuICAgICAgICAucmVwbGFjZSgvXFwvL2csICctJyk7XG5cbiAgICAgIGxldCB1bmlxdWVOYW1lID0gYHNwZWMtJHtwYXRoLmJhc2VuYW1lKFxuICAgICAgICByZWxhdGl2ZVBhdGgsXG4gICAgICAgIHBhdGguZXh0bmFtZShyZWxhdGl2ZVBhdGgpLFxuICAgICAgKX1gO1xuICAgICAgbGV0IHN1ZmZpeCA9IDI7XG4gICAgICB3aGlsZSAoc2Vlbi5oYXModW5pcXVlTmFtZSkpIHtcbiAgICAgICAgdW5pcXVlTmFtZSA9IGAke3JlbGF0aXZlUGF0aH0tJHtzdWZmaXh9YDtcbiAgICAgICAgKytzdWZmaXg7XG4gICAgICB9XG4gICAgICBzZWVuLmFkZCh1bmlxdWVOYW1lKTtcblxuICAgICAgcmV0dXJuIFt1bmlxdWVOYW1lLCB0ZXN0RmlsZV07XG4gICAgfSksXG4gICk7XG59XG5cbmV4cG9ydCBkZWZhdWx0IGNyZWF0ZUJ1aWxkZXIodml0ZXN0QXBwbGljYXRpb25CdWlsZGVyKSBhcyB1bmtub3duO1xuIl19