@elastic/synthetics
Version:
Elastic synthetic monitoring agent
175 lines (164 loc) • 4.81 kB
text/typescript
/**
* MIT License
*
* Copyright (c) 2020-present, Elastic NV
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
import { stdin, cwd } from 'process';
import { extname, resolve } from 'path';
import { CliArgs } from './common_types';
import { step, journey } from './core';
import { log } from './core/logger';
import { expect } from './core/expect';
import * as mfa from './core/mfa';
import {
isDepInstalled,
isDirectory,
totalist,
findPkgJsonByTraversing,
} from './helpers';
import { installTransform } from './core/transform';
const resolvedCwd = cwd();
const JOURNEY_EXTENSIONS = ['.js', '.ts', '.mjs', '.cjs'];
/**
* Perform global setup process required for running the test suites
* and also for bundling the monitors. The process includes
* - Transpiling the TS/JS test files
* - Loading these files for running test suites
*/
export async function globalSetup(options: CliArgs, args: string[]) {
const revert = installTransform();
await loadTestFiles(options, args);
return () => {
revert();
};
}
export async function loadTestFiles(options: CliArgs, args: string[]) {
/**
* Preload modules before running the tests
*/
const modules = [].concat(options.require || []).filter(Boolean);
for (const name of modules) {
if (isDepInstalled(name)) {
require(name);
} else {
throw new Error(`cannot find module '${name}'`);
}
}
if (options.inline) {
const source = await readStdin();
loadInlineScript(source);
return;
}
/**
* Handle piped files by reading the STDIN
* ex: ls example/suites/*.js | npx @elastic/synthetics
*/
const files =
args.length > 0 ? args : (await readStdin()).split('\n').filter(Boolean);
const suites = await prepareSuites(files, options.pattern);
requireSuites(suites);
}
const loadInlineScript = source => {
const scriptFn = new Function(
'step',
'page',
'context',
'browser',
'params',
'expect',
'request',
'mfa',
source
);
journey('inline', ({ page, context, browser, params, request }) => {
scriptFn.apply(null, [
step,
page,
context,
browser,
params,
expect,
request,
mfa,
]);
});
};
/**
* Read the input from STDIN and run it as inline journey
*/
async function readStdin() {
const chunks = [];
stdin.resume();
stdin.setEncoding('utf-8');
for await (const chunk of stdin) {
chunks.push(chunk);
}
return chunks.join();
}
function requireSuites(suites: Iterable<string>) {
for (const suite of suites) {
require(suite);
}
}
/**
* Handle both directory and files that are passed through TTY
* and add them to suites
*/
async function prepareSuites(inputs: string[], filePattern?: string) {
const suites = new Set<string>();
const addSuite = absPath => {
if (!JOURNEY_EXTENSIONS.includes(extname(absPath))) {
return;
}
log(`Processing file: ${absPath}`);
suites.add(require.resolve(absPath));
};
/**
* Match all files inside the directory with the
* .journey.{mjs|cjs|js|ts) extensions
*/
const pattern = filePattern
? new RegExp(filePattern, 'i')
: /.+\.journey\.([mc]js|[jt]s?)$/;
/**
* Ignore node_modules by default when running suites
*/
const ignored = /node_modules/i;
for (const input of inputs) {
const absPath = resolve(resolvedCwd, input);
/**
* Validate for package.json file before running
* the suites
*/
findPkgJsonByTraversing(absPath, resolvedCwd);
if (isDirectory(absPath)) {
await totalist(absPath, (rel, abs) => {
if (pattern.test(rel) && !ignored.test(rel)) {
addSuite(abs);
}
});
} else {
addSuite(absPath);
}
}
return suites.values();
}