UNPKG

skutter

Version:

Skutter: Opinionated BDD Browser based test framework

123 lines (122 loc) 6.36 kB
"use strict"; const Lazy = require("lazy.js"); const executor_proxy_factory_1 = require("../services/executor-proxy-factory"); const executor_message_listener_1 = require("./executor-message-listener"); const even_distributor_1 = require("../services/even-distributor"); const file_checker_1 = require("../services/file-checker"); const result_aggregator_1 = require("../result-aggregator/result-aggregator"); const feature_result_factory_1 = require("../services/feature-result-factory"); const feature_info_provider_1 = require("../services/feature-info-provider"); const just_filter_1 = require("./filters/just-filter"); const exclude_filter_1 = require("./filters/exclude-filter"); const only_filter_1 = require("./filters/only-filter"); const exit_codes_1 = require("../exit-codes"); const ireporter_registration_context_1 = require("../reporters/ireporter-registration-context"); const threadCompletionDelay = 500; class Orchestrator { constructor(config) { if (!config) { throw new Error("config is not specified."); } this.config = config; this.results = []; } start(features, reporters = []) { if (!features || features.length === 0) { throw new Error("No features to run."); } if (!reporters || reporters.length === 0) { throw new Error("No reporters specified."); } if (just_filter_1.JustFilter.apply(features)) { console.log("@Just tag discovered."); if (this.config.failAtJustRuns) { let exitCode = exit_codes_1.ExitCodes.AtJustViolation; console.log(`Exiting with code: ${exitCode}, @just applied to an executable feature and this is explicitly disallowed by the failAtJust config value.`); process.exit(exitCode); return; } } if (exclude_filter_1.ExcludeFilter.apply(this.config.filters, features)) { console.log("Features reduced due to exclude filters."); } if (only_filter_1.OnlyFilter.apply(this.config.filters, features)) { console.log("Features reduced due to only filters."); } let queuedFeatures = Lazy(features).where((feature) => { return feature.queued; }).size(); if (queuedFeatures === 0) { let exitCode = exit_codes_1.ExitCodes.NothingToRun; console.log(`Exiting with code: ${exitCode}, No features are queued to be executed. This may indicate an unrequired filter is set.`); process.exit(exitCode); return; } let executorCount = Math.min(queuedFeatures, this.config.numExecutors); console.log(`${executorCount} executor${executorCount > 1 ? "s" : ""} processing ${queuedFeatures} feature${queuedFeatures > 1 ? "s" : ""}.`); let executorBootstrapScript = `${__dirname}\\..\\executor\\executor-bootstrap.js`; if (!file_checker_1.FileChecker.exists(executorBootstrapScript)) { throw new Error(`The required file 'executor-bootstrap.js' was not found at the expected location '${executorBootstrapScript}'.`); } let weightExtractorFn = (feature) => { return 1; }; let featureBuckets = even_distributor_1.EvenDistributor.distributeBasedOnContent(Lazy(features).where((feature) => { return feature.queued; }).toArray(), weightExtractorFn, executorCount); let executors = []; let executionPromises = []; let reporterRegistrationContext = new ireporter_registration_context_1.ReporterRegistrationContext(); reporterRegistrationContext.executorsCount = executorCount; reporters = Lazy(reporters).reject((reporter) => { return reporter.selfUnregister(reporterRegistrationContext); }).toArray(); let featureInfoProvider = new feature_info_provider_1.FeatureInfoProvider(features); let featureResultProvider = new feature_result_factory_1.FeatureResultFactory(); let resultAggregator = new result_aggregator_1.ResultAggregator(featureInfoProvider, featureResultProvider, reporters); let executorMessageListener = new executor_message_listener_1.ExecutorMessageListener(resultAggregator); let executorProxyFactory = new executor_proxy_factory_1.ExecutorProxyFactory(executorMessageListener, this.config.executor, this.config.outputRootPath); for (let reporter of reporters) { try { reporter.runStarting(); } catch (exception) { console.log("Errored during runStarting call. " + exception.message); } } let debugPort = this.config.debugPort || 5999; let nodeStartOpts = { silent: true, execArgv: executorCount === 1 ? [`--debug=${debugPort}`] : undefined }; if (executorCount === 1) { console.log(`Single thread debugging enabled on port ${debugPort}`); } for (let executorIndex = 0; executorIndex < executorCount; executorIndex++) { let executorFeatures = featureBuckets[executorIndex]; let executor = executorProxyFactory.create(executorBootstrapScript, nodeStartOpts); let executionPromise = executor.start(executorFeatures); executionPromises.push(executionPromise); executors.push(executor); } Promise.all(executionPromises) .then(() => { setTimeout(() => { let runResults = resultAggregator.getResults(); let runErrors = resultAggregator.getErrors(); for (let reporter of reporters) { try { reporter.runCompleted(runResults, runErrors); } catch (exception) { console.log("Errored during runCompleted call. " + exception.message); } } }, threadCompletionDelay); }, (error) => { for (let reporter of reporters) { try { reporter.fatalError(error); } catch (exception) { console.log("Errored during fatalError call. " + exception.message); } } }); } } exports.Orchestrator = Orchestrator;