diff --git a/test/helpers.ts b/test/helpers.ts index 1ea0b19880..fab3b4ca29 100644 --- a/test/helpers.ts +++ b/test/helpers.ts @@ -1,6 +1,5 @@ import * as assert$1 from 'assert'; import * as jsdom from 'jsdom'; -import glob from 'tiny-glob/sync'; import * as path from 'path'; import * as fs from 'fs'; import * as colors from 'kleur'; @@ -206,27 +205,6 @@ export function addLineNumbers(code) { .join('\n'); } -export function showOutput(cwd, options = {}, compile = svelte.compile) { - glob('**/*.svelte', { cwd }).forEach(file => { - if (file[0] === '_') return; - - try { - const { js } = compile( - fs.readFileSync(`${cwd}/${file}`, 'utf-8'), - Object.assign(options, { - filename: file - }) - ); - - console.log( // eslint-disable-line no-console - `\n>> ${colors.cyan().bold(file)}\n${addLineNumbers(js.code)}\n<< ${colors.cyan().bold(file)}` - ); - } catch (err) { - console.log(`failed to generate output: ${err.message}`); - } - }); -} - export function shouldUpdateExpected() { return process.argv.includes('--update'); } diff --git a/test/hydration/index.ts b/test/hydration/index.ts index f3e2c9ea0a..01edbc6bbb 100644 --- a/test/hydration/index.ts +++ b/test/hydration/index.ts @@ -1,9 +1,9 @@ import * as path from 'path'; import * as fs from 'fs'; +import * as register from '../register'; import { assert, - showOutput, loadConfig, loadSvelte, env, @@ -11,34 +11,16 @@ import { shouldUpdateExpected } from '../helpers'; -let compileOptions = null; - -const sveltePath = process.cwd(); +let svelte; describe('hydration', () => { before(() => { - const svelte = loadSvelte(); - - require.extensions['.svelte'] = function(module, filename) { - const options = Object.assign( - { - filename, - hydratable: true, - format: 'cjs', - sveltePath - }, - compileOptions - ); - - const { js } = svelte.compile(fs.readFileSync(filename, 'utf-8'), options); - - return module._compile(js.code, filename); - }; + svelte = loadSvelte(); return setupHtmlEqual(); }); - function runTest(dir) { + function runTest(dir: string) { if (dir[0] === '.') return; const config = loadConfig(`./hydration/samples/${dir}/_config.js`); @@ -51,83 +33,75 @@ describe('hydration', () => { (config.skip ? it.skip : solo ? it.only : it)(dir, () => { const cwd = path.resolve(`${__dirname}/samples/${dir}`); - compileOptions = config.compileOptions || {}; - compileOptions.accessors = 'accessors' in config ? config.accessors : true; + register.setCompileOptions({ + ...config.compileOptions, + accessors: 'accessors' in config ? config.accessors : true, + hydratable: true + }); + register.setCompile(svelte.compile); + register.setOutputFolderName('hydratable'); const window = env(); - try { - global.window = window; + global.window = window; - const SvelteComponent = require(`${cwd}/main.svelte`).default; + const SvelteComponent = require(`${cwd}/main.svelte`).default; - const target = window.document.body; - const head = window.document.head; + const target = window.document.body; + const head = window.document.head; - target.innerHTML = fs.readFileSync(`${cwd}/_before.html`, 'utf-8'); + target.innerHTML = fs.readFileSync(`${cwd}/_before.html`, 'utf-8'); - let before_head; - try { - before_head = fs.readFileSync(`${cwd}/_before_head.html`, 'utf-8'); - head.innerHTML = before_head; - } catch (err) { - // continue regardless of error - } + let before_head; + try { + before_head = fs.readFileSync(`${cwd}/_before_head.html`, 'utf-8'); + head.innerHTML = before_head; + } catch (err) { + // continue regardless of error + } + + const snapshot = config.snapshot ? config.snapshot(target) : {}; - const snapshot = config.snapshot ? config.snapshot(target) : {}; + const component = new SvelteComponent({ + target, + hydrate: true, + props: config.props + }); - const component = new SvelteComponent({ - target, - hydrate: true, - props: config.props - }); + try { + assert.htmlEqual(target.innerHTML, fs.readFileSync(`${cwd}/_after.html`, 'utf-8')); + } catch (error) { + if (shouldUpdateExpected()) { + fs.writeFileSync(`${cwd}/_after.html`, target.innerHTML); + console.log(`Updated ${cwd}/_after.html.`); + } else { + throw error; + } + } + if (before_head) { try { - assert.htmlEqual(target.innerHTML, fs.readFileSync(`${cwd}/_after.html`, 'utf-8')); + assert.htmlEqual(head.innerHTML, fs.readFileSync(`${cwd}/_after_head.html`, 'utf-8')); } catch (error) { if (shouldUpdateExpected()) { - fs.writeFileSync(`${cwd}/_after.html`, target.innerHTML); - console.log(`Updated ${cwd}/_after.html.`); + fs.writeFileSync(`${cwd}/_after_head.html`, head.innerHTML); + console.log(`Updated ${cwd}/_after_head.html.`); } else { throw error; } } - - if (before_head) { - try { - assert.htmlEqual(head.innerHTML, fs.readFileSync(`${cwd}/_after_head.html`, 'utf-8')); - } catch (error) { - if (shouldUpdateExpected()) { - fs.writeFileSync(`${cwd}/_after_head.html`, head.innerHTML); - console.log(`Updated ${cwd}/_after_head.html.`); - } else { - throw error; - } - } - } - - if (config.test) { - config.test(assert, target, snapshot, component, window); - } else { - component.$destroy(); - assert.equal(target.innerHTML, ''); - } - } catch (err) { - showOutput(cwd, { - hydratable: true - }); - throw err; } - if (config.show) { - showOutput(cwd, { - hydratable: true - }); + if (config.test) { + config.test(assert, target, snapshot, component, window); + } else { + component.$destroy(); + assert.equal(target.innerHTML, ''); } }); } fs.readdirSync(`${__dirname}/samples`).forEach(dir => { - runTest(dir, null); + runTest(dir); }); }); diff --git a/test/register.ts b/test/register.ts new file mode 100644 index 0000000000..3aa165782a --- /dev/null +++ b/test/register.ts @@ -0,0 +1,77 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import { mkdirp } from './helpers'; +import * as svelte from 'svelte/compiler'; + +type Compile = typeof svelte.compile; +type CompileOptions = Parameters[1]; + +const extensions = ['.svelte', '.html']; +let compileOptions = {}; +let compile; +let folderName = 'normal'; + +const sveltePath = process.cwd().split('\\').join('/'); + +function capitalise(name: string) { + return name[0].toUpperCase() + name.slice(1); +} + +export function setCompileOptions(_compileOptions: CompileOptions) { + compileOptions = _compileOptions; +} + +export function setCompile(_compile: Compile) { + compile = _compile; +} + +export function setOutputFolderName(_folderName: string) { + folderName = _folderName; +} + +export function clearRequireCache() { + Object.keys(require.cache) + .filter(x => x.endsWith('.svelte')) + .forEach(file => { + delete require.cache[file]; + }); +} + +function registerExtension(extension: string) { + require.extensions[extension] = function(module, filename) { + const name = path + .parse(filename) + .name.replace(/^\d/, '_$&') + .replace(/[^a-zA-Z0-9_$]/g, ''); + + const options = Object.assign({}, compileOptions, { + filename, + sveltePath, + name: capitalise(name), + format: 'cjs' + }); + + const { + js: { code } + } = compile(fs.readFileSync(filename, 'utf-8'), options); + + if (!process.env.CI) { + saveGeneratedOutput(code, filename); + } + + return module._compile(code, filename); + }; +} + +function saveGeneratedOutput(code: string, filename: string) { + filename = filename.split('\\').join('/'); + filename = filename.replace( + /samples\/([^/]+)\/(.*)\.svelte$/, + `samples/$1/_output/${folderName}/$2.js` + ); + + mkdirp(path.dirname(filename)); + fs.writeFileSync(filename, code, 'utf8'); +} + +extensions.forEach(registerExtension); diff --git a/test/runtime/index.ts b/test/runtime/index.ts index f3c962f1d9..772441a686 100644 --- a/test/runtime/index.ts +++ b/test/runtime/index.ts @@ -2,28 +2,21 @@ import * as path from 'path'; import * as fs from 'fs'; import { rollup } from 'rollup'; import virtual from '@rollup/plugin-virtual'; -import glob from 'tiny-glob/sync.js'; import { clear_loops, flush, set_now, set_raf } from '../../internal'; +import * as register from '../register'; import { assert, - showOutput, loadConfig, loadSvelte, cleanRequireCache, env, - setupHtmlEqual, - mkdirp + setupHtmlEqual } from '../helpers'; let svelte$; let svelte; -let compileOptions = null; -let compile = null; - -const sveltePath = process.cwd().split('\\').join('/'); - let unhandled_rejection = false; function unhandledRejection_handler(err) { unhandled_rejection = err; @@ -35,16 +28,6 @@ describe('runtime', () => { svelte = loadSvelte(false); svelte$ = loadSvelte(true); - require.extensions['.svelte'] = function(module, filename) { - const options = Object.assign({ - filename - }, compileOptions); - - const { js: { code } } = compile(fs.readFileSync(filename, 'utf-8').replace(/\r/g, ''), options); - - return module._compile(code, filename); - }; - return setupHtmlEqual(); }); after(() => process.removeListener('unhandledRejection', unhandledRejection_handler)); @@ -73,18 +56,19 @@ describe('runtime', () => { unhandled_rejection = null; - compile = (config.preserveIdentifiers ? svelte : svelte$).compile; - const cwd = path.resolve(`${__dirname}/samples/${dir}`); - - compileOptions = config.compileOptions || {}; - compileOptions.format = 'cjs'; - compileOptions.sveltePath = sveltePath; - compileOptions.hydratable = hydrate; - compileOptions.immutable = config.immutable; - compileOptions.accessors = 'accessors' in config ? config.accessors : true; - - cleanRequireCache(); + + const compileOptions = { + ...config.compileOptions, + hydratable: hydrate, + immutable: config.immutable, + accessors: 'accessors' in config ? config.accessors : true + }; + + register.clearRequireCache(); + register.setCompile((config.preserveIdentifiers ? svelte : svelte$).compile); + register.setCompileOptions(compileOptions); + register.setOutputFolderName(hydrate ? 'hydratable' : 'normal'); let mod; let SvelteComponent; @@ -93,34 +77,7 @@ describe('runtime', () => { const window = env(); - glob('**/*.svelte', { cwd }).forEach(file => { - if (file[0] === '_') return; - - const dir = `${cwd}/_output/${hydrate ? 'hydratable' : 'normal'}`; - const out = `${dir}/${file.replace(/\.svelte$/, '.js')}`; - - if (fs.existsSync(out)) { - fs.unlinkSync(out); - } - - mkdirp(dir); - - try { - const { js } = compile( - fs.readFileSync(`${cwd}/${file}`, 'utf-8').replace(/\r/g, ''), - { - ...compileOptions, - filename: file - } - ); - - fs.writeFileSync(out, js.code); - } catch (err) { - // do nothing - } - }); - - Promise.resolve() + return Promise.resolve() .then(() => { // hack to support transition tests clear_loops(); @@ -142,13 +99,8 @@ describe('runtime', () => { }; }); - try { - mod = require(`./samples/${dir}/main.svelte`); - SvelteComponent = mod.default; - } catch (err) { - showOutput(cwd, compileOptions, compile); // eslint-disable-line no-console - throw err; - } + mod = require(`./samples/${dir}/main.svelte`); + SvelteComponent = mod.default; // Put things we need on window for testing window.SvelteComponent = SvelteComponent; @@ -239,7 +191,6 @@ describe('runtime', () => { } }).catch(err => { failed.add(dir); - showOutput(cwd, compileOptions, compile); // eslint-disable-line no-console throw err; }) .catch(err => { @@ -249,10 +200,6 @@ describe('runtime', () => { throw err; }) .then(() => { - if (config.show) { - showOutput(cwd, compileOptions, compile); - } - flush(); if (config.after_test) config.after_test(); diff --git a/test/server-side-rendering/index.ts b/test/server-side-rendering/index.ts index 2a4e0596e7..619d8af374 100644 --- a/test/server-side-rendering/index.ts +++ b/test/server-side-rendering/index.ts @@ -1,17 +1,15 @@ import * as fs from 'fs'; import * as path from 'path'; -import glob from 'tiny-glob/sync.js'; +import * as register from '../register'; import { assert, - showOutput, loadConfig, loadSvelte, setupHtmlEqual, tryToLoadJson, cleanRequireCache, - shouldUpdateExpected, - mkdirp + shouldUpdateExpected } from '../helpers'; import { set_current_component } from '../../internal'; @@ -25,11 +23,14 @@ function tryToReadFile(file) { } const sveltePath = process.cwd().split('\\').join('/'); -let compile = null; describe('ssr', () => { before(() => { - compile = loadSvelte(true).compile; + register.setCompileOptions({ + generate: 'ssr' + }); + register.setCompile(loadSvelte(true).compile); + register.setOutputFolderName('ssr'); return setupHtmlEqual(); }); @@ -46,7 +47,6 @@ describe('ssr', () => { // add .solo to a sample directory name to only run that test, or // .show to always show the output. or both const solo = config.solo || /\.solo/.test(dir); - const show = /\.show/.test(dir); if (solo && process.env.CI) { throw new Error('Forgot to remove `solo: true` from test'); @@ -131,10 +131,8 @@ describe('ssr', () => { } } - if (show) showOutput(dir, { generate: 'ssr', format: 'cjs' }); done(); } catch (err) { - showOutput(dir, { generate: 'ssr', format: 'cjs' }); err.stack += `\n\ncmd-click: ${path.relative(process.cwd(), dir)}/main.svelte`; done(err); } finally { @@ -163,46 +161,17 @@ describe('ssr', () => { (config.skip ? it.skip : solo ? it.only : it)(dir, () => { const cwd = path.resolve(`test/${suite}/samples`, dir); - cleanRequireCache(); - delete global.window; - - const compileOptions = { + register.clearRequireCache(); + register.setCompileOptions({ sveltePath, ...config.compileOptions, generate: 'ssr', format: 'cjs' - }; - - require('../../register')(compileOptions); - - glob('**/*.svelte', { cwd }).forEach(file => { - if (file[0] === '_') return; - - const dir = `${cwd}/_output/ssr`; - const out = `${dir}/${file.replace(/\.svelte$/, '.js')}`; - - if (fs.existsSync(out)) { - fs.unlinkSync(out); - } - - mkdirp(dir); - - try { - const { js } = compile( - fs.readFileSync(`${cwd}/${file}`, 'utf-8'), - { - ...compileOptions, - filename: file - } - ); - - fs.writeFileSync(out, js.code); - } catch (err) { - // do nothing - } }); + register.setOutputFolderName('ssr'); + try { if (config.before_test) config.before_test(); @@ -222,10 +191,6 @@ describe('ssr', () => { } if (config.after_test) config.after_test(); - - if (config.show) { - showOutput(cwd, compileOptions); - } } catch (err) { err.stack += `\n\ncmd-click: ${path.relative(process.cwd(), cwd)}/main.svelte`; @@ -236,7 +201,6 @@ describe('ssr', () => { assert.equal(err.message, config.error); } } else { - showOutput(cwd, compileOptions); throw err; } } finally {