Merge pull request #8 from sveltejs/master

Sync Fork from Upstream Repo
pull/3941/head
Stefan Hagen 6 years ago committed by GitHub
commit 846c882665
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -96,6 +96,17 @@ Test samples are kept in `/test/xxx/samples` folder.
1. To run test, run `npm run test` 1. To run test, run `npm run test`
1. To run test for a specific feature, you can use the `-g` (aka `--grep`) option. For example, to only run test involving transitions, run `npm run test -- -g transition`. 1. To run test for a specific feature, you can use the `-g` (aka `--grep`) option. For example, to only run test involving transitions, run `npm run test -- -g transition`.
##### Running solo test
1. To run only one test, rename the test sample folder to end with `.solo`. For example, to run the `test/js/samples/action` only, rename it to `test/js/samples/action.solo`.
1. To run only one test suite, rename the test suite folder to end with `.solo`. For example, to run the `test/js` test suite only, rename it to `test/js.solo`.
1. Remember to rename the test folder back. The CI will fail if there's a solo test.
##### Updating `.expected` files
1. Tests suites like `css`, `js`, `server-side-rendering` asserts that the generated output has to match the content in the `.expected` file. For example, in the `js` test suites, the generated js code is compared against the content in `expected.js`.
1. To update the content of the `.expected` file, run the test with `--update` flag. (`npm run test --update`)
#### Breaking changes #### Breaking changes
When adding a new breaking change, follow this template in your pull request: When adding a new breaking change, follow this template in your pull request:

@ -2,18 +2,9 @@
<script> <script>
let people = [ let people = [
{ { first: 'Hans', last: 'Emil' },
first: 'Hans', { first: 'Max', last: 'Mustermann' },
last: 'Emil' { first: 'Roman', last: 'Tisch' }
},
{
first: 'Max',
last: 'Mustermann'
},
{
first: 'Roman',
last: 'Tisch'
}
]; ];
let prefix = ''; let prefix = '';
@ -39,7 +30,9 @@
} }
function update() { function update() {
people[i] = { first, last }; selected.first = first;
selected.last = last;
people = people;
} }
function remove() { function remove() {

@ -1291,17 +1291,23 @@
} }
}, },
"@sveltejs/svelte-repl": { "@sveltejs/svelte-repl": {
"version": "0.1.11", "version": "0.1.13",
"resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.1.11.tgz", "resolved": "https://registry.npmjs.org/@sveltejs/svelte-repl/-/svelte-repl-0.1.13.tgz",
"integrity": "sha512-z0Cv9fNggmL6C2bphYa2A5Bku91U3ukCmJTh9pFS68X0sJxDFJPsBgxAmWhrOfOe7NdGvm/s+fBEOo8cce66/w==", "integrity": "sha512-griMkrRRzAQq22awKaBN5cewGly4xeeo8qpDs8ZhQxmEk5TcX3dMhIGMLuPTSv3Yr0s2c6TDJXcN+ORJn//fpQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"codemirror": "^5.48.4", "codemirror": "^5.49.2",
"estree-walker": "^0.6.1", "estree-walker": "^0.9.0",
"sourcemap-codec": "^1.4.6", "sourcemap-codec": "^1.4.6",
"yootils": "0.0.16" "yootils": "0.0.16"
}, },
"dependencies": { "dependencies": {
"estree-walker": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.9.0.tgz",
"integrity": "sha512-12U47o7XHUX329+x3FzNVjCx3SHEzMF0nkDv7r/HnBzX/xNTKxajBk6gyygaxrAFtLj39219oMfbtxv4KpaOiA==",
"dev": true
},
"sourcemap-codec": { "sourcemap-codec": {
"version": "1.4.6", "version": "1.4.6",
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz",
@ -3368,12 +3374,6 @@
"requires": { "requires": {
"@babel/helper-module-imports": "^7.0.0", "@babel/helper-module-imports": "^7.0.0",
"rollup-pluginutils": "^2.8.1" "rollup-pluginutils": "^2.8.1"
},
"dependencies": {
"estree-walker": {
"version": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
"integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w=="
}
} }
}, },
"rollup-plugin-commonjs": { "rollup-plugin-commonjs": {
@ -3411,10 +3411,6 @@
"rollup-pluginutils": "^2.8.1" "rollup-pluginutils": "^2.8.1"
}, },
"dependencies": { "dependencies": {
"estree-walker": {
"version": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
"integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w=="
},
"resolve": { "resolve": {
"version": "1.11.1", "version": "1.11.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.1.tgz",
@ -3458,12 +3454,6 @@
"rollup-pluginutils": "^2.8.1", "rollup-pluginutils": "^2.8.1",
"serialize-javascript": "^1.7.0", "serialize-javascript": "^1.7.0",
"terser": "^4.1.0" "terser": "^4.1.0"
},
"dependencies": {
"estree-walker": {
"version": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
"integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w=="
}
} }
}, },
"rollup-pluginutils": { "rollup-pluginutils": {
@ -3473,14 +3463,6 @@
"dev": true, "dev": true,
"requires": { "requires": {
"estree-walker": "^0.6.1" "estree-walker": "^0.6.1"
},
"dependencies": {
"estree-walker": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",
"integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==",
"dev": true
}
} }
}, },
"safe-buffer": { "safe-buffer": {

@ -36,7 +36,7 @@
"@babel/runtime": "^7.6.0", "@babel/runtime": "^7.6.0",
"@sindresorhus/slugify": "^0.9.1", "@sindresorhus/slugify": "^0.9.1",
"@sveltejs/site-kit": "^1.1.4", "@sveltejs/site-kit": "^1.1.4",
"@sveltejs/svelte-repl": "^0.1.11", "@sveltejs/svelte-repl": "^0.1.13",
"degit": "^2.1.4", "degit": "^2.1.4",
"dotenv": "^8.1.0", "dotenv": "^8.1.0",
"esm": "^3.2.25", "esm": "^3.2.25",

@ -94,8 +94,12 @@ export default async function preprocess(
for (const fn of script) { for (const fn of script) {
source = await replace_async( source = await replace_async(
source, source,
/<script(\s[^]*?)?>([^]*?)<\/script>/gi, /<!--[^]*?-->|<script(\s[^]*?)?>([^]*?)<\/script>/gi,
async (match, attributes = '', content) => { async (match, attributes = '', content) => {
if (!attributes && !content) {
return match;
}
attributes = attributes || '';
const processed = await fn({ const processed = await fn({
content, content,
attributes: parse_attributes(attributes), attributes: parse_attributes(attributes),
@ -110,8 +114,11 @@ export default async function preprocess(
for (const fn of style) { for (const fn of style) {
source = await replace_async( source = await replace_async(
source, source,
/<style(\s[^]*?)?>([^]*?)<\/style>/gi, /<!--[^]*?-->|<style(\s[^]*?)?>([^]*?)<\/style>/gi,
async (match, attributes = '', content) => { async (match, attributes = '', content) => {
if (!attributes && !content) {
return match;
}
const processed: Processed = await fn({ const processed: Processed = await fn({
content, content,
attributes: parse_attributes(attributes), attributes: parse_attributes(attributes),

@ -1,19 +1,3 @@
declare module '*.svelte' { declare module '*.svelte' {
type Props = Record<string, any>; export { SvelteComponentDev as default } from 'svelte/internal';
export default class {
constructor(options: {
target: Element;
anchor?: Element;
props?: Props;
hydrate?: boolean;
intro?: boolean;
});
$set(props: Props): void;
$on<T = any>(event: string, callback: (event: CustomEvent<T>) => void): () => void;
$destroy(): void;
[accessor: string]: any;
}
} }

@ -8,5 +8,6 @@ export {
setContext, setContext,
getContext, getContext,
tick, tick,
createEventDispatcher createEventDispatcher,
SvelteComponentDev as SvelteComponent
} from 'svelte/internal'; } from 'svelte/internal';

@ -79,8 +79,24 @@ export function set_data_dev(text, data) {
text.data = data; text.data = data;
} }
type Props = Record<string, any>;
export interface SvelteComponentDev {
$set(props?: Props): void;
$on<T = any>(event: string, callback: (event: CustomEvent<T>) => void): () => void;
$destroy(): void;
[accessor: string]: any;
}
export class SvelteComponentDev extends SvelteComponent { export class SvelteComponentDev extends SvelteComponent {
constructor(options) { constructor(options: {
target: Element;
anchor?: Element;
props?: Props;
hydrate?: boolean;
intro?: boolean;
$$inline?: boolean;
}) {
if (!options || (!options.target && !options.$$inline)) { if (!options || (!options.target && !options.$$inline)) {
throw new Error(`'target' is a required option`); throw new Error(`'target' is a required option`);
} }

@ -1,6 +1,6 @@
import * as assert from 'assert'; import * as assert from 'assert';
import * as fs from 'fs'; import * as fs from 'fs';
import { env, normalizeHtml, svelte } from '../helpers.js'; import { env, svelte, setupHtmlEqual, shouldUpdateExpected } from '../helpers.js';
function try_require(file) { function try_require(file) {
try { try {
@ -37,6 +37,10 @@ function create(code) {
} }
describe('css', () => { describe('css', () => {
before(() => {
setupHtmlEqual();
});
fs.readdirSync(`${__dirname}/samples`).forEach(dir => { fs.readdirSync(`${__dirname}/samples`).forEach(dir => {
if (dir[0] === '.') return; if (dir[0] === '.') return;
@ -80,7 +84,17 @@ describe('css', () => {
css: read(`${__dirname}/samples/${dir}/expected.css`) css: read(`${__dirname}/samples/${dir}/expected.css`)
}; };
assert.equal(dom.css.code.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => $1 ? m : 'svelte-xyz'), expected.css); const actual_css = dom.css.code.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => $1 ? m : 'svelte-xyz');
try {
assert.equal(actual_css, expected.css);
} catch (error) {
if (shouldUpdateExpected()) {
fs.writeFileSync(`${__dirname}/samples/${dir}/expected.css`, actual_css);
console.log(`Updated ${dir}/expected.css.`);
} else {
throw error;
}
}
let ClientComponent; let ClientComponent;
let ServerComponent; let ServerComponent;
@ -114,10 +128,8 @@ describe('css', () => {
fs.writeFileSync(`${__dirname}/samples/${dir}/_actual.html`, html); fs.writeFileSync(`${__dirname}/samples/${dir}/_actual.html`, html);
assert.equal( const actual_html = html.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => $1 ? m : 'svelte-xyz');
normalizeHtml(window, html.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => $1 ? m : 'svelte-xyz')), assert.htmlEqual(actual_html, expected.html);
normalizeHtml(window, expected.html)
);
window.document.head.innerHTML = ''; // remove added styles window.document.head.innerHTML = ''; // remove added styles
} catch (err) { } catch (err) {
@ -127,13 +139,8 @@ describe('css', () => {
// ssr // ssr
try { try {
assert.equal( const actual_ssr = ServerComponent.render(config.props).html.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => $1 ? m : 'svelte-xyz');
normalizeHtml( assert.htmlEqual(actual_ssr, expected.html);
window,
ServerComponent.render(config.props).html.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => $1 ? m : 'svelte-xyz')
),
normalizeHtml(window, expected.html)
);
} catch (err) { } catch (err) {
console.log(ssr.js.code); console.log(ssr.js.code);
throw err; throw err;

@ -206,6 +206,10 @@ export function showOutput(cwd, options = {}, compile = svelte.compile) {
}); });
} }
export function shouldUpdateExpected() {
return process.argv.includes('--update');
}
export function spaces(i) { export function spaces(i) {
let result = ''; let result = '';
while (i--) result += ' '; while (i--) result += ' ';

@ -7,7 +7,8 @@ import {
loadConfig, loadConfig,
loadSvelte, loadSvelte,
env, env,
setupHtmlEqual setupHtmlEqual,
shouldUpdateExpected
} from '../helpers.js'; } from '../helpers.js';
let compileOptions = null; let compileOptions = null;
@ -76,7 +77,16 @@ describe('hydration', () => {
props: config.props props: config.props
}); });
assert.htmlEqual(target.innerHTML, fs.readFileSync(`${cwd}/_after.html`, 'utf-8')); 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 (config.test) { if (config.test) {
config.test(assert, target, snapshot, component, window); config.test(assert, target, snapshot, component, window);

@ -1,7 +1,8 @@
import * as assert from "assert"; import * as assert from "assert";
import * as fs from "fs"; import * as fs from "fs";
import * as path from "path"; import * as path from "path";
import { loadConfig, svelte } from "../helpers.js"; import * as colors from "kleur";
import { loadConfig, svelte, shouldUpdateExpected } from "../helpers.js";
describe("js", () => { describe("js", () => {
fs.readdirSync(`${__dirname}/samples`).forEach(dir => { fs.readdirSync(`${__dirname}/samples`).forEach(dir => {
@ -14,8 +15,14 @@ describe("js", () => {
throw new Error("Forgot to remove `solo: true` from test"); throw new Error("Forgot to remove `solo: true` from test");
} }
dir = path.resolve(`${__dirname}/samples`, dir);
if (!fs.existsSync(`${dir}/input.svelte`)) {
console.log(colors.red().bold(`Missing file ${dir}/input.svelte. If you recently switched branches you may need to delete this directory`));
return;
}
(solo ? it.only : it)(dir, () => { (solo ? it.only : it)(dir, () => {
dir = path.resolve(`${__dirname}/samples`, dir);
const config = loadConfig(`${dir}/_config.js`); const config = loadConfig(`${dir}/_config.js`);
const input = fs.readFileSync(`${dir}/input.svelte`, "utf-8").replace(/\s+$/, ""); const input = fs.readFileSync(`${dir}/input.svelte`, "utf-8").replace(/\s+$/, "");
@ -34,12 +41,32 @@ describe("js", () => {
const output = `${dir}/_actual.js`; const output = `${dir}/_actual.js`;
fs.writeFileSync(output, actual); fs.writeFileSync(output, actual);
const expected = fs.readFileSync(`${dir}/expected.js`, "utf-8"); const expectedPath = `${dir}/expected.js`;
let expected = '';
try {
expected = fs.readFileSync(expectedPath, "utf-8");
} catch (error) {
console.log(error);
if (error.code === 'ENOENT') {
// missing expected.js
fs.writeFileSync(expectedPath, actual);
}
}
assert.equal( try {
actual.trim().replace(/^[ \t]+$/gm, ""), assert.equal(
expected.trim().replace(/^[ \t]+$/gm, "") actual.trim().replace(/^[ \t]+$/gm, ""),
); expected.trim().replace(/^[ \t]+$/gm, "")
);
} catch (error) {
if (shouldUpdateExpected()) {
fs.writeFileSync(expectedPath, actual);
console.log(`Updated ${expectedPath}.`);
} else {
throw error;
}
}
}); });
}); });
}); });

@ -1,6 +1,6 @@
import * as assert from 'assert'; import * as assert from 'assert';
import * as fs from 'fs'; import * as fs from 'fs';
import { svelte, tryToLoadJson } from '../helpers.js'; import { svelte, tryToLoadJson, shouldUpdateExpected } from '../helpers.js';
describe('parse', () => { describe('parse', () => {
fs.readdirSync(`${__dirname}/samples`).forEach(dir => { fs.readdirSync(`${__dirname}/samples`).forEach(dir => {
@ -15,7 +15,9 @@ describe('parse', () => {
); );
} }
(solo ? it.only : it)(dir, () => { const skip = !fs.existsSync(`${__dirname}/samples/${dir}/input.svelte`);
(skip ? it.skip : solo ? it.only : it)(dir, () => {
const options = tryToLoadJson(`${__dirname}/samples/${dir}/options.json`) || {}; const options = tryToLoadJson(`${__dirname}/samples/${dir}/options.json`) || {};
const input = fs.readFileSync(`${__dirname}/samples/${dir}/input.svelte`, 'utf-8').replace(/\s+$/, ''); const input = fs.readFileSync(`${__dirname}/samples/${dir}/input.svelte`, 'utf-8').replace(/\s+$/, '');

@ -0,0 +1,8 @@
export default {
preprocess: [
{
script: ({ content }) => ({ code: content.replace(/one/g, 'two') }),
style: ({ content }) => ({ code: content.replace(/one/g, 'three') }),
},
],
};

@ -0,0 +1,25 @@
<style>
one
</style>
<script>
one
</script>
<!-- <style>
one
</style> -->
<!-- <script>
one
</script> -->
<style>
<!-- one -->
</style>
<script>
<!-- one -->
</script>

@ -0,0 +1,25 @@
<style>
three
</style>
<script>
two
</script>
<!-- <style>
one
</style> -->
<!-- <script>
one
</script> -->
<style>
<!-- three -->
</style>
<script>
<!-- two -->
</script>

@ -6,7 +6,8 @@ import {
showOutput, showOutput,
loadConfig, loadConfig,
setupHtmlEqual, setupHtmlEqual,
tryToLoadJson tryToLoadJson,
shouldUpdateExpected
} from "../helpers.js"; } from "../helpers.js";
function tryToReadFile(file) { function tryToReadFile(file) {
@ -58,18 +59,47 @@ describe("ssr", () => {
fs.writeFileSync(`${dir}/_actual.html`, html); fs.writeFileSync(`${dir}/_actual.html`, html);
if (css.code) fs.writeFileSync(`${dir}/_actual.css`, css.code); if (css.code) fs.writeFileSync(`${dir}/_actual.css`, css.code);
assert.htmlEqual(html, expectedHtml); try {
assert.equal( assert.htmlEqual(html, expectedHtml);
css.code.replace(/^\s+/gm, ""), } catch (error) {
expectedCss.replace(/^\s+/gm, "") if (shouldUpdateExpected()) {
); fs.writeFileSync(`${dir}/_expected.html`, html);
console.log(`Updated ${dir}/_expected.html.`);
} else {
throw error;
}
}
try {
assert.equal(
css.code.replace(/^\s+/gm, ""),
expectedCss.replace(/^\s+/gm, "")
);
} catch (error) {
if (shouldUpdateExpected()) {
fs.writeFileSync(`${dir}/_expected.css`, css.code);
console.log(`Updated ${dir}/_expected.css.`);
} else {
throw error;
}
}
if (fs.existsSync(`${dir}/_expected-head.html`)) { if (fs.existsSync(`${dir}/_expected-head.html`)) {
fs.writeFileSync(`${dir}/_actual-head.html`, head); fs.writeFileSync(`${dir}/_actual-head.html`, head);
assert.htmlEqual(
head, try {
fs.readFileSync(`${dir}/_expected-head.html`, 'utf-8') assert.htmlEqual(
); head,
fs.readFileSync(`${dir}/_expected-head.html`, 'utf-8')
);
} catch (error) {
if (shouldUpdateExpected()) {
fs.writeFileSync(`${dir}/_expected-head.html`, head);
console.log(`Updated ${dir}/_expected-head.html.`);
} else {
throw error;
}
}
} }
if (show) showOutput(dir, { generate: 'ssr', format: 'cjs' }); if (show) showOutput(dir, { generate: 'ssr', format: 'cjs' });

Loading…
Cancel
Save