Merge pull request #223 from spotify/rugvip/e2e-cli-test
added scripts dir with test for making sure serve and plugin scaffolding works
This commit is contained in:
@@ -37,3 +37,8 @@ jobs:
|
||||
yarn test
|
||||
env:
|
||||
CI: true
|
||||
# This creates a new plugin and pollutes the workspace, so it should be run last.
|
||||
- name: verify app serve and plugin creation
|
||||
run: |
|
||||
sudo sysctl fs.inotify.max_user_watches=524288
|
||||
node scripts/cli-e2e-test.js
|
||||
|
||||
+2
-1
@@ -19,7 +19,8 @@
|
||||
"cross-env": "^7.0.0",
|
||||
"lerna": "^3.20.2",
|
||||
"prettier": "^1.19.1",
|
||||
"typescript": "^3.7.5"
|
||||
"typescript": "^3.7.5",
|
||||
"zombie": "^6.1.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/classnames": "^2.2.9",
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
const { resolve: resolvePath } = require('path');
|
||||
const childProcess = require('child_process');
|
||||
const { spawn } = childProcess;
|
||||
const Browser = require('zombie');
|
||||
|
||||
Browser.localhost('localhost', 3000);
|
||||
|
||||
async function main() {
|
||||
process.env.CI = 'true';
|
||||
|
||||
const projectDir = resolvePath(__dirname, '..');
|
||||
process.chdir(projectDir);
|
||||
|
||||
const start = spawnPiped(['yarn', 'start']);
|
||||
|
||||
try {
|
||||
const browser = new Browser();
|
||||
|
||||
await waitForPageWithText(browser, '/', 'Welcome to Backstage');
|
||||
print('Backstage loaded correctly, creating plugin');
|
||||
|
||||
const createPlugin = spawnPiped(['yarn', 'create-plugin']);
|
||||
createPlugin.stdin.write('test-plugin\n');
|
||||
|
||||
print('Waiting for plugin create script to be done');
|
||||
await waitForExit(createPlugin);
|
||||
|
||||
print('Plugin create script is done, waiting for plugin page to load');
|
||||
await waitForPageWithText(
|
||||
browser,
|
||||
'/test-plugin',
|
||||
'Welcome to test-plugin!',
|
||||
);
|
||||
|
||||
print('Test plugin loaded correctly, exiting');
|
||||
} finally {
|
||||
start.kill();
|
||||
}
|
||||
await waitForExit(start);
|
||||
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
function print(msg) {
|
||||
return process.stdout.write(`${msg}\n`);
|
||||
}
|
||||
|
||||
async function waitForExit(child) {
|
||||
await new Promise((resolve, reject) =>
|
||||
child.once('exit', code => {
|
||||
if (code) {
|
||||
reject(new Error(`Child exited with code ${code}`));
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
function spawnPiped(cmd, options) {
|
||||
function pipeWithPrefix(stream, prefix = '') {
|
||||
return data => {
|
||||
const prefixedMsg = data
|
||||
.toString('utf8')
|
||||
.trimRight()
|
||||
.replace(/^/gm, prefix);
|
||||
stream.write(`${prefixedMsg}\n`, 'utf8');
|
||||
};
|
||||
}
|
||||
|
||||
const child = spawn(cmd[0], cmd.slice(1), { stdio: 'pipe', ...options });
|
||||
child.on('error', handleError);
|
||||
child.on('exit', code => {
|
||||
if (code) {
|
||||
print(`Child '${cmd.join(' ')}' exited with code ${code}`);
|
||||
process.exit(code);
|
||||
}
|
||||
});
|
||||
child.stdout.on(
|
||||
'data',
|
||||
pipeWithPrefix(process.stdout, `[${cmd.join(' ')}].out: `),
|
||||
);
|
||||
child.stderr.on(
|
||||
'data',
|
||||
pipeWithPrefix(process.stderr, `[${cmd.join(' ')}].err: `),
|
||||
);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
async function waitForPageWithText(
|
||||
browser,
|
||||
path,
|
||||
text,
|
||||
{ intervalMs = 1000, maxAttempts = 60 } = {},
|
||||
) {
|
||||
let attempts = 0;
|
||||
for (;;) {
|
||||
try {
|
||||
await new Promise(resolve => setTimeout(resolve, intervalMs));
|
||||
await browser.visit(path);
|
||||
|
||||
break;
|
||||
} catch (error) {
|
||||
attempts++;
|
||||
if (attempts > maxAttempts) {
|
||||
throw new Error(
|
||||
`Failed to load page '${path}', max number of attempts reached`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const escapedText = text.replace(/"/g, '\\"');
|
||||
browser.assert.evaluate(
|
||||
`Array.from(document.querySelectorAll("*")).some(el => el.textContent === "${escapedText}")`,
|
||||
true,
|
||||
`expected to find text ${text}`,
|
||||
);
|
||||
}
|
||||
|
||||
function handleError(err) {
|
||||
process.stdout.write(`${err.name}: ${err.message}\n`);
|
||||
if (typeof err.code === 'number') {
|
||||
process.exit(err.code);
|
||||
} else {
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
process.on('unhandledRejection', handleError);
|
||||
main(process.argv.slice(2)).catch(handleError);
|
||||
@@ -4236,7 +4236,7 @@ babel-preset-react-app@^9.1.1:
|
||||
babel-plugin-macros "2.8.0"
|
||||
babel-plugin-transform-react-remove-prop-types "0.4.24"
|
||||
|
||||
babel-runtime@6.x, babel-runtime@^6.23.0, babel-runtime@^6.26.0:
|
||||
babel-runtime@6.26.0, babel-runtime@6.x, babel-runtime@^6.23.0, babel-runtime@^6.26.0:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
|
||||
integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4=
|
||||
@@ -6937,7 +6937,7 @@ events@^3.0.0:
|
||||
resolved "https://registry.npmjs.org/events/-/events-3.1.0.tgz#84279af1b34cb75aa88bf5ff291f6d0bd9b31a59"
|
||||
integrity sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==
|
||||
|
||||
eventsource@^1.0.7:
|
||||
eventsource@^1.0.5, eventsource@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.npmjs.org/eventsource/-/eventsource-1.0.7.tgz#8fbc72c93fcd34088090bc0a4e64f4b5cee6d8d0"
|
||||
integrity sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ==
|
||||
@@ -8456,7 +8456,7 @@ hyphenate-style-name@^1.0.2, hyphenate-style-name@^1.0.3:
|
||||
resolved "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.0.3.tgz#097bb7fa0b8f1a9cf0bd5c734cf95899981a9b48"
|
||||
integrity sha512-EcuixamT82oplpoJ2XU4pDtKGWQ7b00CD9f1ug9IaQ3p1bkHMiKCZ9ut9QDI6qsa6cpUuB+A/I+zLtdNK4n2DQ==
|
||||
|
||||
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13:
|
||||
iconv-lite@0.4.24, iconv-lite@^0.4.21, iconv-lite@^0.4.24, iconv-lite@~0.4.13:
|
||||
version "0.4.24"
|
||||
resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
|
||||
@@ -10102,7 +10102,7 @@ jsbn@~0.1.0:
|
||||
resolved "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
|
||||
integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
|
||||
|
||||
jsdom@^11.5.1:
|
||||
jsdom@11.12.0, jsdom@^11.5.1:
|
||||
version "11.12.0"
|
||||
resolved "https://registry.npmjs.org/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8"
|
||||
integrity sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw==
|
||||
@@ -10944,7 +10944,7 @@ lodash.without@~4.4.0:
|
||||
resolved "https://registry.npmjs.org/lodash.without/-/lodash.without-4.4.0.tgz#3cd4574a00b67bae373a94b748772640507b7aac"
|
||||
integrity sha1-PNRXSgC2e643OpS3SHcmQFB7eqw=
|
||||
|
||||
lodash@4.17.15, "lodash@>=3.5 <5", lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1:
|
||||
lodash@4.17.15, "lodash@>=3.5 <5", lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.3, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1:
|
||||
version "4.17.15"
|
||||
resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
|
||||
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
|
||||
@@ -11341,7 +11341,7 @@ mime@1.6.0:
|
||||
resolved "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
|
||||
|
||||
mime@^2.4.3, mime@^2.4.4:
|
||||
mime@^2.3.1, mime@^2.4.3, mime@^2.4.4:
|
||||
version "2.4.4"
|
||||
resolved "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5"
|
||||
integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA==
|
||||
@@ -14604,7 +14604,7 @@ request-promise-native@^1.0.5, request-promise-native@^1.0.7:
|
||||
stealthy-require "^1.1.1"
|
||||
tough-cookie "^2.3.3"
|
||||
|
||||
request@^2.87.0, request@^2.88.0:
|
||||
request@^2.85.0, request@^2.87.0, request@^2.88.0:
|
||||
version "2.88.2"
|
||||
resolved "https://registry.npmjs.org/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3"
|
||||
integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==
|
||||
@@ -17672,3 +17672,21 @@ zen-observable@^0.8.15:
|
||||
version "0.8.15"
|
||||
resolved "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15"
|
||||
integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==
|
||||
|
||||
zombie@^6.1.4:
|
||||
version "6.1.4"
|
||||
resolved "https://registry.npmjs.org/zombie/-/zombie-6.1.4.tgz#9f0f53f3d9a032beb7f3fe5b382146a3475a4d47"
|
||||
integrity sha512-yxNvKtyz3PP8lkr31AYh7vdbBD4is9hYXiOQKPp+k/7GiDiFQXX1Ex+peCl4ttodu/bHZcIluJ8lxMla5XefBQ==
|
||||
dependencies:
|
||||
babel-runtime "6.26.0"
|
||||
bluebird "^3.5.1"
|
||||
debug "^4.1.0"
|
||||
eventsource "^1.0.5"
|
||||
iconv-lite "^0.4.21"
|
||||
jsdom "11.12.0"
|
||||
lodash "^4.17.10"
|
||||
mime "^2.3.1"
|
||||
ms "^2.1.1"
|
||||
request "^2.85.0"
|
||||
tough-cookie "^2.3.4"
|
||||
ws "^6.1.2"
|
||||
|
||||
Reference in New Issue
Block a user