fusion-cli
Version:
335 lines (305 loc) • 10 kB
JavaScript
// @flow
/* eslint-env node */
const t = require('assert');
const path = require('path');
const {promisify} = require('util');
const fs = require('fs');
const getPort = require('get-port');
const puppeteer = require('puppeteer');
const readdir = promisify(fs.readdir);
const exists = promisify(fs.exists);
const {cmd, dev, run, start} = require('../utils.js');
const dir = path.resolve(__dirname, './fixture');
test('`fusion dev --dir` works w/ relative dir', async () => {
const entryPath = `.fusion/dist/development/server/server-main.js`;
const entry = path.resolve(dir, entryPath);
// $FlowFixMe
const {proc, promise} = await dev(`--dir=${dir}`, {
stdio: ['inherit', 'inherit', 'pipe'],
});
await new Promise(resolve => setTimeout(resolve, 1000));
t.ok(await exists(entry), 'Entry file gets compiled');
promise.then(({stderr}) => {
t.ok(!stderr.match(/Error/), 'does not error');
});
proc.stderr.destroy(); // disconnect the piped socket to prevent the Node process from hanging
proc.kill();
}, 100000);
test('`fusion dev` works', async () => {
const entryPath = `.fusion/dist/development/server/server-main.js`;
const entry = path.resolve(dir, entryPath);
const {proc} = await dev(`--dir=${dir}`);
await new Promise(resolve => setTimeout(resolve, 1000));
t.ok(await exists(entry), 'Entry file gets compiled');
proc.kill();
});
test('`fusion build` works', async () => {
const serverEntryPath = path.resolve(
dir,
`.fusion/dist/development/server/server-main.js`
);
const serverMapPath = path.resolve(
dir,
`.fusion/dist/development/server/server-main.js.map`
);
const clientMain = path.resolve(
dir,
`.fusion/dist/development/client/client-main.js`
);
const clientMainMap = path.resolve(
dir,
`.fusion/dist/development/client/client-main.js.map`
);
const clientMainVendor = path.resolve(
dir,
`.fusion/dist/development/client/client-vendor.js`
);
const clientMainVendorMap = path.resolve(
dir,
`.fusion/dist/development/client/client-vendor.js.map`
);
await cmd(`build --dir=${dir}`);
t.ok(await exists(serverEntryPath), 'Server Entry file gets compiled');
t.ok(
await exists(serverMapPath),
'Server Entry file sourcemap gets compiled'
);
t.ok(await exists(clientMain), 'Client Entry file gets compiled');
t.ok(
await exists(clientMainMap),
'Client Entry file sourcemap gets compiled'
);
t.ok(await exists(clientMainVendor), 'Client vendor file gets compiled');
t.ok(
await exists(clientMainVendorMap),
'Client vendor file sourcemap gets compiled'
);
}, 100000);
test('`fusion build` works in production with a CDN_URL', async () => {
const serverEntryPath = path.resolve(
dir,
`.fusion/dist/production/server/server-main.js`
);
const serverMapPath = path.resolve(
dir,
`.fusion/dist/production/server/server-main.js.map`
);
await cmd(`build --dir=${dir} --production`);
const clientFiles = await readdir(
path.resolve(dir, '.fusion/dist/production/client')
);
t.ok(
clientFiles.some(f => /client-main-(.*?).js$/.test(f)),
'includes a versioned client-main.js file'
);
t.ok(
clientFiles.some(f => /client-vendor-(.*?).js$/.test(f)),
'includes a versioned client-vendor.js file'
);
t.ok(await exists(serverEntryPath), 'Server Entry file gets compiled');
t.ok(
await exists(serverMapPath),
'Server Entry file sourcemap gets compiled'
);
const {res, proc} = await start(`--dir=${dir}`, {
env: Object.assign({}, process.env, {
CDN_URL: 'https://cdn.com/test',
NODE_ENV: 'production',
}),
});
t.ok(
res.includes('https://cdn.com/test/client-legacy-main'),
'includes a reference to client-legacy-main'
);
t.ok(
res.includes('https://cdn.com/test/client-legacy-vendor'),
'includes a reference to client-legacy-vendor'
);
proc.kill();
}, 100000);
test('`fusion build` works in production with default asset path and supplied ROUTE_PREFIX', async () => {
const serverEntryPath = path.resolve(
dir,
`.fusion/dist/production/server/server-main.js`
);
const serverMapPath = path.resolve(
dir,
`.fusion/dist/production/server/server-main.js.map`
);
await cmd(`build --dir=${dir} --production`);
const clientFiles = await readdir(
path.resolve(dir, '.fusion/dist/production/client')
);
t.ok(
clientFiles.some(f => /client-main-(.*?).js$/.test(f)),
'includes a versioned client-main.js file'
);
t.ok(
clientFiles.some(f => /client-vendor-(.*?).js$/.test(f)),
'includes a versioned client-vendor.js file'
);
t.ok(await exists(serverEntryPath), 'Server Entry file gets compiled');
t.ok(
await exists(serverMapPath),
'Server Entry file sourcemap gets compiled'
);
const {res, proc} = await start(`--dir=${dir}`, {
env: Object.assign({}, process.env, {
ROUTE_PREFIX: '/test-prefix',
NODE_ENV: 'production',
}),
});
t.ok(
res.includes('/test-prefix/_static/client-legacy-main'),
'includes a reference to client-legacy-main'
);
t.ok(
res.includes('/test-prefix/_static/client-legacy-vendor'),
'includes a reference to client-legacy-vendor'
);
proc.kill();
}, 100000);
test('`fusion start` does not throw error on client when using route prefix', async () => {
await cmd(`build --dir=${dir} --production`);
const {proc, port} = await start(`--dir=${dir}`, {
env: Object.assign({}, process.env, {
ROUTE_PREFIX: '/test-prefix',
NODE_ENV: 'production',
}),
});
const browser = await puppeteer.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
const page = await browser.newPage();
page.on('error', err => {
// $FlowFixMe
t.fail(`Client-side error: ${err}`);
});
page.on('pageerror', err => {
// $FlowFixMe
t.fail(`Client-side error: ${err}`);
});
await page.goto(`http://localhost:${port}/test-prefix/`, {
waitUntil: 'networkidle0',
});
t.ok('did not error');
browser.close();
proc.kill();
}, 100000);
test('`fusion build` works in production', async () => {
const serverEntryPath = path.resolve(
dir,
`.fusion/dist/production/server/server-main.js`
);
const serverMapPath = path.resolve(
dir,
`.fusion/dist/production/server/server-main.js.map`
);
await cmd(`build --dir=${dir} --production`);
const clientFiles = await readdir(
path.resolve(dir, '.fusion/dist/production/client')
);
t.ok(
clientFiles.some(f => /client-main-(.*?).js$/.test(f)),
'includes a versioned client-main.js file'
);
t.ok(
clientFiles.some(f => /client-vendor-(.*?).js$/.test(f)),
'includes a versioned client-vendor.js file'
);
t.ok(await exists(serverEntryPath), 'Server Entry file gets compiled');
t.ok(
await exists(serverMapPath),
'Server Entry file sourcemap gets compiled'
);
const {res, proc} = await start(`--dir=${dir}`, {
env: Object.assign({}, process.env, {
NODE_ENV: 'production',
}),
});
t.ok(
res.includes('/_static/client-legacy-main'),
'includes a reference to client-legacy-main'
);
t.ok(
res.includes('/_static/client-legacy-vendor'),
'includes a reference to client-legacy-vendor'
);
clientFiles.forEach(file => {
if (file.endsWith('.map')) {
t.ok(
clientFiles.includes(path.basename(file, '.map')),
'source map filename has same base as regular file'
);
}
});
proc.kill();
}, 100000);
test('production works', async () => {
await cmd(`build --dir=${dir} --production`, {
env: {...process.env, NODE_ENV: 'production'},
});
const entryPath = `.fusion/dist/production/server/server-main.js`;
const entry = path.resolve(dir, entryPath);
t.ok(await exists(entry), 'Entry file gets compiled');
t.ok(await exists(entry + '.map'), 'Source map gets compiled');
const clientDir = path.resolve(dir, `.fusion/dist/production/client`);
const assets = await readdir(clientDir);
t.ok(assets.find(a => a.match(/^client-main.+\.js$/)), 'main .js');
t.ok(assets.find(a => a.match(/^client-main.+\.js.map$/)), 'main .map');
//t.ok(assets.find(a => a.match(/^client-main.+\.js.gz$/)), 'main .gz');
t.ok(assets.find(a => a.match(/^client-main.+\.js.br$/)), 'main .br');
t.ok(assets.find(a => a.match(/^client-vendor.+\.js$/)), 'vendor .js');
t.ok(assets.find(a => a.match(/^client-vendor.+\.js.map$/)), 'vendor .map');
//t.ok(assets.find(a => a.match(/^client-vendor.+\.js.gz$/)), 'vendor .gz');
t.ok(assets.find(a => a.match(/^client-vendor.+\.js.br$/)), 'vendor .br');
const command = `
const assert = require('assert');
const app = require('${entry}');
assert.equal(typeof app.start, 'function', 'Entry has start function');
app
.start({port: ${await getPort()}})
.then(server => {
server.close();
})
.catch(e => {
setImmediate(() => {
throw e;
});
});
`;
await run(['-e', command], {
env: Object.assign({}, process.env, {
NODE_ENV: 'production',
}),
stdio: 'pipe',
});
}, 100000);
test('dev works', async () => {
await cmd(`build --dir=${dir}`, {
env: {...process.env, NODE_ENV: 'development'},
});
const entryPath = `.fusion/dist/development/server/server-main.js`;
const entry = path.resolve(dir, entryPath);
t.ok(await exists(entry), 'Entry file gets compiled');
t.ok(await exists(entry + '.map'), 'Source map gets compiled');
const command = `
const assert = require('assert');
const app = require('${entry}');
assert.equal(typeof app.start, 'function', 'Entry has start function');
(async () => {
const server = await app.start({port: ${await getPort()}});
server.close();
})().catch(e => {
setImmediate(() => {
throw e;
});
});
`;
await run(['-e', command], {
env: Object.assign({}, process.env, {
NODE_ENV: 'development',
}),
stdio: 'pipe',
});
}, 100000);