mirror of
https://github.com/kevin-DL/sapper.git
synced 2026-01-14 20:14:39 +00:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6390ba692b | ||
|
|
0e131cc81e | ||
|
|
bd3d5713cb | ||
|
|
9ec23c47ad | ||
|
|
b7bb69925e | ||
|
|
25124f6ee7 | ||
|
|
73d491cd19 | ||
|
|
e25fceb4b8 | ||
|
|
3807147c57 | ||
|
|
a523ba58ff | ||
|
|
fe03fd3a52 | ||
|
|
89c430a0cb | ||
|
|
8ef312849c | ||
|
|
4200446684 | ||
|
|
681ed005b8 | ||
|
|
d457af8d51 | ||
|
|
0c158b9e1f | ||
|
|
50011e2077 | ||
|
|
f27b7973e3 | ||
|
|
2af2ab3cb9 | ||
|
|
6a4dc1901c | ||
|
|
fbbc0e9e19 | ||
|
|
1213c3da46 | ||
|
|
4cc2104088 | ||
|
|
d6dda371ca | ||
|
|
304c06085e | ||
|
|
33b6450e34 | ||
|
|
9ea4137b87 | ||
|
|
7588911108 | ||
|
|
fc8280adea | ||
|
|
d08f9eb5a4 | ||
|
|
30ddb3dd7e | ||
|
|
0c891ba79e |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -2,4 +2,5 @@
|
|||||||
node_modules
|
node_modules
|
||||||
cypress/screenshots
|
cypress/screenshots
|
||||||
test/app/.sapper
|
test/app/.sapper
|
||||||
runtime.js
|
runtime.js
|
||||||
|
yarn.lock
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
# sapper changelog
|
# sapper changelog
|
||||||
|
|
||||||
|
## 0.5.0
|
||||||
|
|
||||||
|
* Experimental support for `sapper export` ([#9](https://github.com/sveltejs/sapper/issues/9))
|
||||||
|
* Lazily load chokidar, for faster startup ([#64](https://github.com/sveltejs/sapper/pull/64))
|
||||||
|
|
||||||
## 0.4.0
|
## 0.4.0
|
||||||
|
|
||||||
* `%sapper.main%` has been replaced with `%sapper.scripts%` ([#86](https://github.com/sveltejs/sapper/issues/86))
|
* `%sapper.main%` has been replaced with `%sapper.scripts%` ([#86](https://github.com/sveltejs/sapper/issues/86))
|
||||||
|
|||||||
27
cli/index.js
27
cli/index.js
@@ -1,8 +1,29 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const build = require('../lib/build.js');
|
||||||
|
|
||||||
const cmd = process.argv[2];
|
const cmd = process.argv[2];
|
||||||
|
const start = Date.now();
|
||||||
|
|
||||||
if (cmd === 'build') {
|
if (cmd === 'build') {
|
||||||
process.env.NODE_ENV = 'production';
|
build()
|
||||||
require('../lib/build.js')();
|
.then(() => {
|
||||||
}
|
const elapsed = Date.now() - start;
|
||||||
|
console.error(`built in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds'
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err ? err.details || err.stack || err.message || err : 'Unknown error');
|
||||||
|
});
|
||||||
|
} else if (cmd === 'export') {
|
||||||
|
const start = Date.now();
|
||||||
|
|
||||||
|
build()
|
||||||
|
.then(() => require('../lib/utils/export.js')())
|
||||||
|
.then(() => {
|
||||||
|
const elapsed = Date.now() - start;
|
||||||
|
console.error(`extracted in ${elapsed}ms`); // TODO beautify this, e.g. 'built in 4.7 seconds'
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err ? err.details || err.stack || err.message || err : 'Unknown error');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
45
lib/build.js
45
lib/build.js
@@ -1,3 +1,5 @@
|
|||||||
|
process.env.NODE_ENV = 'production';
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const mkdirp = require('mkdirp');
|
const mkdirp = require('mkdirp');
|
||||||
@@ -14,29 +16,32 @@ module.exports = () => {
|
|||||||
// create main.js and server-routes.js
|
// create main.js and server-routes.js
|
||||||
create_app();
|
create_app();
|
||||||
|
|
||||||
function handleErrors(err, stats) {
|
return new Promise((fulfil, reject) => {
|
||||||
if (err) {
|
function handleErrors(err, stats) {
|
||||||
console.error(err ? err.details || err.stack || err.message || err : 'Unknown error');
|
if (err) {
|
||||||
process.exit(1);
|
reject(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stats.hasErrors()) {
|
||||||
|
console.error(stats.toString({ colors: true }));
|
||||||
|
reject(new Error(`Encountered errors while building app`));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stats.hasErrors()) {
|
client.run((err, clientStats) => {
|
||||||
console.log(stats.toString({ colors: true }));
|
handleErrors(err, clientStats);
|
||||||
process.exit(1);
|
const clientInfo = clientStats.toJson();
|
||||||
}
|
fs.writeFileSync(path.join(dest, 'stats.client.json'), JSON.stringify(clientInfo, null, ' '));
|
||||||
}
|
|
||||||
|
|
||||||
client.run((err, clientStats) => {
|
server.run((err, serverStats) => {
|
||||||
handleErrors(err, clientStats);
|
handleErrors(err, serverStats);
|
||||||
const clientInfo = clientStats.toJson();
|
const serverInfo = serverStats.toJson();
|
||||||
fs.writeFileSync(path.join(dest, 'stats.client.json'), JSON.stringify(clientInfo, null, ' '));
|
fs.writeFileSync(path.join(dest, 'stats.server.json'), JSON.stringify(serverInfo, null, ' '));
|
||||||
|
|
||||||
server.run((err, serverStats) => {
|
generate_asset_cache(clientInfo, serverInfo);
|
||||||
handleErrors(err, serverStats);
|
fulfil();
|
||||||
const serverInfo = serverStats.toJson();
|
});
|
||||||
fs.writeFileSync(path.join(dest, 'stats.server.json'), JSON.stringify(serverInfo, null, ' '));
|
|
||||||
|
|
||||||
generate_asset_cache(clientInfo, serverInfo);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
const glob = require('glob');
|
const glob = require('glob');
|
||||||
const chokidar = require('chokidar');
|
|
||||||
const create_routes = require('./utils/create_routes.js');
|
const create_routes = require('./utils/create_routes.js');
|
||||||
const { src, dev } = require('./config.js');
|
const { src, dev } = require('./config.js');
|
||||||
|
|
||||||
@@ -20,7 +19,7 @@ function update() {
|
|||||||
update();
|
update();
|
||||||
|
|
||||||
if (dev) {
|
if (dev) {
|
||||||
const watcher = chokidar.watch(`${src}/**/*.+(html|js|mjs)`, {
|
const watcher = require('chokidar').watch(`${src}/**/*.+(html|js|mjs)`, {
|
||||||
ignoreInitial: true,
|
ignoreInitial: true,
|
||||||
persistent: false
|
persistent: false
|
||||||
});
|
});
|
||||||
@@ -28,4 +27,4 @@ if (dev) {
|
|||||||
watcher.on('add', update);
|
watcher.on('add', update);
|
||||||
watcher.on('change', update);
|
watcher.on('change', update);
|
||||||
watcher.on('unlink', update);
|
watcher.on('unlink', update);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const glob = require('glob');
|
const glob = require('glob');
|
||||||
const chalk = require('chalk');
|
const chalk = require('chalk');
|
||||||
const chokidar = require('chokidar');
|
|
||||||
const framer = require('code-frame');
|
const framer = require('code-frame');
|
||||||
const { locate } = require('locate-character');
|
const { locate } = require('locate-character');
|
||||||
const { dev } = require('./config.js');
|
const { dev } = require('./config.js');
|
||||||
@@ -103,7 +102,7 @@ function create_templates() {
|
|||||||
create_templates();
|
create_templates();
|
||||||
|
|
||||||
if (dev) {
|
if (dev) {
|
||||||
const watcher = chokidar.watch('templates/**.html', {
|
const watcher = require('chokidar').watch('templates/**.html', {
|
||||||
ignoreInitial: true,
|
ignoreInitial: true,
|
||||||
persistent: false
|
persistent: false
|
||||||
});
|
});
|
||||||
@@ -125,4 +124,4 @@ exports.stream = (res, status, data) => {
|
|||||||
if (template) return template.stream(res, data);
|
if (template) return template.stream(res, data);
|
||||||
|
|
||||||
return `Missing template for status code ${status}`;
|
return `Missing template for status code ${status}`;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
const chokidar = require('chokidar');
|
|
||||||
const route_manager = require('../route_manager.js');
|
const route_manager = require('../route_manager.js');
|
||||||
const { src, entry, dev } = require('../config.js');
|
const { src, entry, dev } = require('../config.js');
|
||||||
|
|
||||||
@@ -70,7 +69,7 @@ function create_app() {
|
|||||||
if (dev) {
|
if (dev) {
|
||||||
route_manager.onchange(create_app);
|
route_manager.onchange(create_app);
|
||||||
|
|
||||||
const watcher = chokidar.watch(`templates/main.js`, {
|
const watcher = require('chokidar').watch(`templates/main.js`, {
|
||||||
ignoreInitial: true,
|
ignoreInitial: true,
|
||||||
persistent: false
|
persistent: false
|
||||||
});
|
});
|
||||||
@@ -80,4 +79,4 @@ if (dev) {
|
|||||||
watcher.on('unlink', create_app);
|
watcher.on('unlink', create_app);
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = create_app;
|
module.exports = create_app;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ module.exports = function create_matchers(files) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const pattern = new RegExp(`^${pattern_string || '\\/'}$`);
|
const pattern = new RegExp(`^${pattern_string}\\/?$`);
|
||||||
|
|
||||||
const test = url => pattern.test(url);
|
const test = url => pattern.test(url);
|
||||||
|
|
||||||
|
|||||||
87
lib/utils/export.js
Normal file
87
lib/utils/export.js
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
const sander = require('sander');
|
||||||
|
const app = require('express')();
|
||||||
|
const cheerio = require('cheerio');
|
||||||
|
const fetch = require('node-fetch');
|
||||||
|
const URL = require('url-parse');
|
||||||
|
const sapper = require('../index.js');
|
||||||
|
|
||||||
|
const { PORT = 3000, OUTPUT_DIR = 'dist' } = process.env;
|
||||||
|
const { dest } = require('../config.js');
|
||||||
|
|
||||||
|
const origin = `http://localhost:${PORT}`;
|
||||||
|
|
||||||
|
module.exports = function() {
|
||||||
|
// Prep output directory
|
||||||
|
sander.rimrafSync(OUTPUT_DIR);
|
||||||
|
|
||||||
|
sander.copydirSync('assets').to(OUTPUT_DIR);
|
||||||
|
sander.copydirSync(`${dest}/client`).to(`${OUTPUT_DIR}/client`);
|
||||||
|
sander.copyFileSync(`${dest}/service-worker.js`).to(`${OUTPUT_DIR}/service-worker.js`);
|
||||||
|
|
||||||
|
// Intercept server route fetches
|
||||||
|
function save(res) {
|
||||||
|
res = res.clone();
|
||||||
|
|
||||||
|
return res.text().then(body => {
|
||||||
|
const { pathname } = new URL(res.url);
|
||||||
|
let dest = OUTPUT_DIR + pathname;
|
||||||
|
|
||||||
|
const type = res.headers.get('Content-Type');
|
||||||
|
if (type.startsWith('text/html;')) dest += '/index.html';
|
||||||
|
|
||||||
|
sander.writeFileSync(dest, body);
|
||||||
|
|
||||||
|
return body;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
global.fetch = (url, opts) => {
|
||||||
|
if (url[0] === '/') {
|
||||||
|
url = `http://localhost:${PORT}${url}`;
|
||||||
|
|
||||||
|
return fetch(url, opts)
|
||||||
|
.then(r => {
|
||||||
|
save(r);
|
||||||
|
return r;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetch(url, opts);
|
||||||
|
};
|
||||||
|
|
||||||
|
app.use(sapper());
|
||||||
|
const server = app.listen(PORT);
|
||||||
|
|
||||||
|
const seen = new Set();
|
||||||
|
|
||||||
|
function handle(url) {
|
||||||
|
if (url.origin !== origin) return;
|
||||||
|
|
||||||
|
if (seen.has(url.pathname)) return;
|
||||||
|
seen.add(url.pathname);
|
||||||
|
|
||||||
|
return fetch(url.href)
|
||||||
|
.then(r => {
|
||||||
|
save(r);
|
||||||
|
return r.text();
|
||||||
|
})
|
||||||
|
.then(body => {
|
||||||
|
const $ = cheerio.load(body);
|
||||||
|
const hrefs = [];
|
||||||
|
|
||||||
|
$('a[href]').each((i, $a) => {
|
||||||
|
hrefs.push($a.attribs.href);
|
||||||
|
});
|
||||||
|
|
||||||
|
return hrefs.reduce((promise, href) => {
|
||||||
|
return promise.then(() => handle(new URL(href, url.href)));
|
||||||
|
}, Promise.resolve());
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(`Error rendering ${url.pathname}: ${err.message}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return handle(new URL(origin)) // TODO all static routes
|
||||||
|
.then(() => server.close());
|
||||||
|
};
|
||||||
@@ -3,7 +3,7 @@ const path = require('path');
|
|||||||
const glob = require('glob');
|
const glob = require('glob');
|
||||||
const templates = require('../templates.js');
|
const templates = require('../templates.js');
|
||||||
const route_manager = require('../route_manager.js');
|
const route_manager = require('../route_manager.js');
|
||||||
const { dest, dev } = require('../config.js');
|
const { dest } = require('../config.js');
|
||||||
|
|
||||||
function ensure_array(thing) {
|
function ensure_array(thing) {
|
||||||
return Array.isArray(thing) ? thing : [thing]; // omg webpack what the HELL are you doing
|
return Array.isArray(thing) ? thing : [thing]; // omg webpack what the HELL are you doing
|
||||||
@@ -17,10 +17,8 @@ module.exports = function generate_asset_cache(clientInfo, serverInfo) {
|
|||||||
const service_worker = generate_service_worker(chunk_files);
|
const service_worker = generate_service_worker(chunk_files);
|
||||||
const index = generate_index(main_file);
|
const index = generate_index(main_file);
|
||||||
|
|
||||||
if (dev) {
|
fs.writeFileSync(path.join(dest, 'service-worker.js'), service_worker);
|
||||||
fs.writeFileSync(path.join(dest, 'service-worker.js'), service_worker);
|
fs.writeFileSync(path.join(dest, 'index.html'), index);
|
||||||
fs.writeFileSync(path.join(dest, 'index.html'), index);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
client: {
|
client: {
|
||||||
|
|||||||
755
package-lock.json
generated
755
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "sapper",
|
"name": "sapper",
|
||||||
"version": "0.4.0",
|
"version": "0.5.0",
|
||||||
"description": "Military-grade apps, engineered by Svelte",
|
"description": "Military-grade apps, engineered by Svelte",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chalk": "^2.3.0",
|
"chalk": "^2.3.0",
|
||||||
|
"cheerio": "^1.0.0-rc.2",
|
||||||
"chokidar": "^1.7.0",
|
"chokidar": "^1.7.0",
|
||||||
"code-frame": "^5.0.0",
|
"code-frame": "^5.0.0",
|
||||||
"escape-html": "^1.0.3",
|
"escape-html": "^1.0.3",
|
||||||
@@ -26,7 +27,10 @@
|
|||||||
"relative": "^3.0.2",
|
"relative": "^3.0.2",
|
||||||
"require-relative": "^0.8.7",
|
"require-relative": "^0.8.7",
|
||||||
"rimraf": "^2.6.2",
|
"rimraf": "^2.6.2",
|
||||||
|
"sander": "^0.6.0",
|
||||||
"serialize-javascript": "^1.4.0",
|
"serialize-javascript": "^1.4.0",
|
||||||
|
"url-parse": "^1.2.0",
|
||||||
|
"walk-sync": "^0.3.2",
|
||||||
"webpack": "^3.10.0",
|
"webpack": "^3.10.0",
|
||||||
"webpack-hot-middleware": "^2.21.0"
|
"webpack-hot-middleware": "^2.21.0"
|
||||||
},
|
},
|
||||||
|
|||||||
3
test/app/.gitignore
vendored
3
test/app/.gitignore
vendored
@@ -3,4 +3,5 @@ node_modules
|
|||||||
.sapper
|
.sapper
|
||||||
yarn.lock
|
yarn.lock
|
||||||
cypress/screenshots
|
cypress/screenshots
|
||||||
templates/.*
|
templates/.*
|
||||||
|
dist
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
preload({ params, query }) {
|
preload({ params, query }) {
|
||||||
return fetch(`/api/blog`).then(r => r.json()).then(posts => {
|
return fetch(`/api/blog/contents`).then(r => r.json()).then(posts => {
|
||||||
return { posts };
|
return { posts };
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ const serve = require('serve-static');
|
|||||||
const Nightmare = require('nightmare');
|
const Nightmare = require('nightmare');
|
||||||
const getPort = require('get-port');
|
const getPort = require('get-port');
|
||||||
const fetch = require('node-fetch');
|
const fetch = require('node-fetch');
|
||||||
|
const walkSync = require('walk-sync');
|
||||||
|
|
||||||
run('production');
|
run('production');
|
||||||
run('development');
|
run('development');
|
||||||
@@ -78,7 +79,7 @@ function run(env) {
|
|||||||
|
|
||||||
if (env === 'production') {
|
if (env === 'production') {
|
||||||
const cli = path.resolve(__dirname, '../../cli/index.js');
|
const cli = path.resolve(__dirname, '../../cli/index.js');
|
||||||
exec_promise = exec(`${cli} build`);
|
exec_promise = exec(`${cli} build`).then(() => exec(`${cli} export`));
|
||||||
}
|
}
|
||||||
|
|
||||||
return exec_promise.then(() => {
|
return exec_promise.then(() => {
|
||||||
@@ -295,6 +296,18 @@ function run(env) {
|
|||||||
assert.equal(html, `URL is /show-url`);
|
assert.equal(html, `URL is /show-url`);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('calls a delete handler', () => {
|
||||||
|
return nightmare
|
||||||
|
.goto(`${base}/delete-test`)
|
||||||
|
.wait(() => window.READY)
|
||||||
|
.click('.del')
|
||||||
|
.wait(() => window.deleted)
|
||||||
|
.evaluate(() => window.deleted.id)
|
||||||
|
.then(id => {
|
||||||
|
assert.equal(id, 42);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('headers', () => {
|
describe('headers', () => {
|
||||||
@@ -312,20 +325,92 @@ function run(env) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (env === 'production') {
|
||||||
|
describe('export', () => {
|
||||||
|
it('export all pages', () => {
|
||||||
|
const dest = path.resolve(__dirname, '../app/dist');
|
||||||
|
|
||||||
|
// Pages that should show up in the extraction directory.
|
||||||
|
const expectedPages = [
|
||||||
|
'index.html',
|
||||||
|
'about/index.html',
|
||||||
|
'slow-preload/index.html',
|
||||||
|
|
||||||
|
'blog/index.html',
|
||||||
|
'blog/a-very-long-post/index.html',
|
||||||
|
'blog/how-can-i-get-involved/index.html',
|
||||||
|
'blog/how-is-sapper-different-from-next/index.html',
|
||||||
|
'blog/how-to-use-sapper/index.html',
|
||||||
|
'blog/what-is-sapper/index.html',
|
||||||
|
'blog/why-the-name/index.html',
|
||||||
|
|
||||||
|
'api/blog/contents',
|
||||||
|
'api/blog/a-very-long-post',
|
||||||
|
'api/blog/how-can-i-get-involved',
|
||||||
|
'api/blog/how-is-sapper-different-from-next',
|
||||||
|
'api/blog/how-to-use-sapper',
|
||||||
|
'api/blog/what-is-sapper',
|
||||||
|
'api/blog/why-the-name',
|
||||||
|
|
||||||
|
'favicon.png',
|
||||||
|
'global.css',
|
||||||
|
'great-success.png',
|
||||||
|
'manifest.json',
|
||||||
|
'service-worker.js',
|
||||||
|
'svelte-logo-192.png',
|
||||||
|
'svelte-logo-512.png',
|
||||||
|
];
|
||||||
|
// Client scripts that should show up in the extraction directory.
|
||||||
|
const expectedClientRegexes = [
|
||||||
|
/client\/_\..*?\.js/,
|
||||||
|
/client\/about\..*?\.js/,
|
||||||
|
/client\/blog_\$slug\$\..*?\.js/,
|
||||||
|
/client\/blog\..*?\.js/,
|
||||||
|
/client\/main\..*?\.js/,
|
||||||
|
/client\/show_url\..*?\.js/,
|
||||||
|
/client\/slow_preload\..*?\.js/,
|
||||||
|
];
|
||||||
|
const allPages = walkSync(dest);
|
||||||
|
|
||||||
|
expectedPages.forEach((expectedPage) => {
|
||||||
|
assert.ok(allPages.includes(expectedPage),
|
||||||
|
`Could not find page matching ${expectedPage}`);
|
||||||
|
});
|
||||||
|
expectedClientRegexes.forEach((expectedRegex) => {
|
||||||
|
// Ensure each client page regular expression matches at least one
|
||||||
|
// generated page.
|
||||||
|
let matched = false;
|
||||||
|
for (const page of allPages) {
|
||||||
|
if (expectedRegex.test(page)) {
|
||||||
|
matched = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert.ok(matched,
|
||||||
|
`Could not find client page matching ${expectedRegex}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function exec(cmd) {
|
function exec(cmd) {
|
||||||
return new Promise((fulfil, reject) => {
|
return new Promise((fulfil, reject) => {
|
||||||
require('child_process').exec(cmd, (err, stdout, stderr) => {
|
const parts = cmd.split(' ');
|
||||||
if (err) {
|
const proc = require('child_process').spawn(parts.shift(), parts);
|
||||||
process.stdout.write(stdout);
|
|
||||||
process.stderr.write(stderr);
|
|
||||||
|
|
||||||
return reject(err);
|
proc.stdout.on('data', data => {
|
||||||
}
|
process.stdout.write(data);
|
||||||
|
|
||||||
fulfil();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
proc.stderr.on('data', data => {
|
||||||
|
process.stderr.write(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
proc.on('error', reject);
|
||||||
|
|
||||||
|
proc.on('close', () => fulfil());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user