Commit 70ef42c3 authored by Mario Nebl's avatar Mario Nebl Committed by Dan Abramov
Browse files

Add screencast task (#3816)

* Automate screencast recordings
* **screencast.js**: Automate screencast.sh, asciinema, svg-term-cli. Removes progress-bar, npm tree data from cast
* **screencast.sh**: Simulate user input, trigger demoed commands
* **screencast-start.js**: Start a shell command and end the process log patterns have been observed
parent 72c3d4eb
3 merge requests!12191Lim.Pisey.168:/Identified - We are currently investigating reports of missing build logs. The issue has been identified and a resolution is in progress. We will provide a further update when available.Mar 21, 09:02 UTC,!12853brikk,!5717Automatically extract project file structure from build bundle file
Showing with 173 additions and 2 deletions
+173 -2
......@@ -12,19 +12,23 @@
"postinstall": "cd packages/react-error-overlay/ && yarn build:prod",
"publish": "tasks/publish.sh",
"start": "cd packages/react-scripts && node bin/react-scripts.js start",
"screencast": "svg-term --cast hItN7sl5yfCPTHxvFg5glhhfp --out screencast.svg --window",
"screencast": "node ./tasks/screencast.js",
"test": "cd packages/react-scripts && node bin/react-scripts.js test --env=jsdom",
"format": "prettier --trailing-comma es5 --single-quote --write 'packages/*/*.js' 'packages/*/!(node_modules)/**/*.js'",
"precommit": "lint-staged"
},
"devDependencies": {
"eslint": "4.15.0",
"execa": "^0.9.0",
"husky": "^0.13.2",
"lerna": "2.6.0",
"lerna-changelog": "^0.6.0",
"lint-staged": "^3.3.1",
"meow": "^4.0.0",
"multimatch": "^2.1.0",
"prettier": "1.6.1",
"svg-term-cli": "^2.0.3"
"svg-term-cli": "^2.0.3",
"tempy": "^0.2.1"
},
"lint-staged": {
"*.js": [
......
#!/usr/bin/env node
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
const execa = require('execa');
const meow = require('meow');
const multimatch = require('multimatch');
main(meow());
function main(cli) {
let count = 0;
const start = Date.now();
const duration = parseInt(cli.flags.timeout, 10) * 1000;
const cp = execa.shell(cli.flags.command);
const target = parseInt(cli.flags.patternCount || '1', 10);
cp.stdout.on('data', data => {
process.stdout.write(data);
const matches = multimatch([String(data)], cli.flags.pattern);
const errMatches = multimatch([String(data)], cli.flags.errorPattern);
if (matches.length > 0) {
count++;
}
if (errMatches.length > 0) {
process.exit(1);
}
if (count >= target) {
setTimeout(() => {
process.exit(0);
}, duration);
}
});
cp.on('exit', e => {
const elapsed = Date.now() - start;
if (elapsed >= duration) {
return;
}
setTimeout(() => {
process.exit(e.code);
}, duration - elapsed);
});
}
#!/usr/bin/env node
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
'use strict';
const fs = require('fs');
const path = require('path');
const execa = require('execa');
const tempy = require('tempy');
main();
function main() {
const previous = process.cwd();
const cwd = tempy.directory();
const cast = path.join(cwd, 'screencast.json');
const script = path.join(__dirname, 'screencast.sh');
const out = path.join(previous, 'screencast.svg');
const resolveLine = l => l.indexOf('🔍 Resolving packages...') > -1;
const fetchLine = l => l.indexOf('🚚 Fetching packages...') > -1;
const countLine = l => l.match(/Saved [0-9]+ new dependencies/);
const doneLine = l => l.indexOf('✨ Done in') > -1;
try {
process.chdir(cwd);
console.log(`Recording screencast ...`);
execa.sync('asciinema', ['rec', '--command', `sh ${script}`, cast], {
cwd,
stdio: 'inherit',
});
console.log('Cleaning data ...');
const data = require(cast);
cut(data.stdout, { start: resolveLine, end: fetchLine });
cut(data.stdout, { start: countLine, end: doneLine });
replace(data.stdout, [{ in: cwd, out: '~' }]);
fs.writeFileSync(cast, JSON.stringify(data, null, ' '));
console.log('Rendering SVG ...');
execa.sync('svg-term', ['--window', '--in', cast, '--out', out]);
console.log(`Recorded screencast to ${cast}`);
console.log(`Rendered SVG to ${out}`);
} catch (err) {
throw err;
} finally {
process.chdir(previous);
}
}
function cut(frames, { start, end }) {
const si = frames.findIndex(([, l]) => start(l));
const ei = frames.findIndex(([, l]) => end(l));
if (si === -1 || ei === -1) {
return;
}
frames.splice(si + 1, ei - si - 1);
}
function replace(frames, replacements) {
frames.forEach(frame => {
replacements.forEach(r => (frame[1] = frame[1].split(r.in).join(r.out)));
});
}
#!/bin/zsh
# Copyright (c) 2015-present, Facebook, Inc.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.
# ******************************************************************************
# This is an end-to-end test intended to be run via screencast.js
# Dependencies: asciinema, pv, core-utils
# ******************************************************************************
set -e
printf '\e[32m%s\e[m' "λ "
echo "npx create-react-app my-app" | pv -qL $[10+(-2 + RANDOM%5)]
npx create-react-app my-app
printf '\e[32m%s\e[m' "λ "
sleep 1
echo "cd my-app" | pv -qL $[10+(-2 + RANDOM%5)]
cd my-app
printf '\e[32m%s\e[m' "λ "
sleep 1
echo "npm start" | pv -qL $[10+(-2 + RANDOM%5)]
BROWSER="none" node "$(dirname $0)/screencast-start.js" \
--command "npm start" \
--pattern="Compiled successfully*" \
--pattern-count 2 \
--error-pattern="*already running on port" \
--timeout 10
echo ""
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment