diff --git a/test/runtime/samples/globals-not-overwritten-by-bindings/main.html b/test/runtime/samples/globals-not-overwritten-by-bindings/main.html
index ca6c6ccb35..a8b873211c 100644
--- a/test/runtime/samples/globals-not-overwritten-by-bindings/main.html
+++ b/test/runtime/samples/globals-not-overwritten-by-bindings/main.html
@@ -1,6 +1,6 @@
-{{#each Object.keys(todos) as key}}
-
+{#each Object.keys(todos) as key}
+
-{{/each}}
\ No newline at end of file
+{/each}
\ No newline at end of file
diff --git a/test/runtime/samples/globals-shadowed-by-data/main.html b/test/runtime/samples/globals-shadowed-by-data/main.html
index 73fd9437af..7e3b408331 100644
--- a/test/runtime/samples/globals-shadowed-by-data/main.html
+++ b/test/runtime/samples/globals-shadowed-by-data/main.html
@@ -1,4 +1,4 @@
-{{Math.min(x, 5)}}
+{Math.min(x, 5)}
\ No newline at end of file
diff --git a/test/runtime/samples/if-block-else-in-each/main.html b/test/runtime/samples/if-block-else-in-each/main.html
index 81cd07273f..4df229b2e8 100644
--- a/test/runtime/samples/if-block-else-in-each/main.html
+++ b/test/runtime/samples/if-block-else-in-each/main.html
@@ -1,7 +1,7 @@
-{{#each array as item}}
- {{#if item}}
+{#each array as item}
+ {#if item}
foo
- {{else}}
+ {:else}
bar
- {{/if}}
-{{/each}}
+ {/if}
+{/each}
diff --git a/test/runtime/samples/if-block-else/main.html b/test/runtime/samples/if-block-else/main.html
index 5a211aa840..997f503e98 100644
--- a/test/runtime/samples/if-block-else/main.html
+++ b/test/runtime/samples/if-block-else/main.html
@@ -1,11 +1,11 @@
-{{#if foo}}
+{#if foo}
foo
-{{else}}
+{:else}
not foo
-{{/if}}
+{/if}
-{{#if bar}}
+{#if bar}
bar
-{{else}}
+{:else}
not bar
-{{/if}}
+{/if}
diff --git a/test/runtime/samples/if-block-elseif-text/main.html b/test/runtime/samples/if-block-elseif-text/main.html
index 42fc0ca46f..43ac545677 100644
--- a/test/runtime/samples/if-block-elseif-text/main.html
+++ b/test/runtime/samples/if-block-elseif-text/main.html
@@ -1 +1 @@
-before-{{#if x > 10}}if{{elseif x < 5}}elseif{{else}}else{{/if}}-after
+before-{#if x > 10}if{:elseif x < 5}elseif{:else}else{/if}-after
diff --git a/test/runtime/samples/if-block-elseif/main.html b/test/runtime/samples/if-block-elseif/main.html
index 254d7a2202..ffa5879943 100644
--- a/test/runtime/samples/if-block-elseif/main.html
+++ b/test/runtime/samples/if-block-elseif/main.html
@@ -1,7 +1,7 @@
-{{#if x > 10}}
+{#if x > 10}
x is greater than 10
-{{elseif x < 5}}
+{:elseif x < 5}
x is less than 5
-{{else}}
+{:else}
x is between 5 and 10
-{{/if}}
+{/if}
diff --git a/test/runtime/samples/if-block-expression/main.html b/test/runtime/samples/if-block-expression/main.html
index 31b8bc6392..10d2c7b74f 100644
--- a/test/runtime/samples/if-block-expression/main.html
+++ b/test/runtime/samples/if-block-expression/main.html
@@ -1,3 +1,3 @@
-{{#if 2 > 1}}
+{#if 2 > 1}
two is greater than one
-{{/if}}
+{/if}
diff --git a/test/runtime/samples/if-block-or/main.html b/test/runtime/samples/if-block-or/main.html
index 68d6158688..8f3713bffb 100644
--- a/test/runtime/samples/if-block-or/main.html
+++ b/test/runtime/samples/if-block-or/main.html
@@ -1,3 +1,3 @@
-{{#if a || b}}
+{#if a || b}
i am visible
-{{/if}}
+{/if}
diff --git a/test/runtime/samples/if-block-widget/main.html b/test/runtime/samples/if-block-widget/main.html
index 5e2a3859b4..cd73d020a6 100644
--- a/test/runtime/samples/if-block-widget/main.html
+++ b/test/runtime/samples/if-block-widget/main.html
@@ -1,7 +1,7 @@
before
-{{#if visible}}
+{#if visible}
-{{/if}}
+{/if}
after
\ No newline at end of file
diff --git a/test/runtime/samples/immutable-mutable/_config.js b/test/runtime/samples/immutable-mutable/_config.js
index 5dab0f239b..d7381a38a2 100644
--- a/test/runtime/samples/immutable-mutable/_config.js
+++ b/test/runtime/samples/immutable-mutable/_config.js
@@ -4,13 +4,15 @@ export default {
test(assert, component, target, window) {
var nested = component.refs.nested;
- nested.observe('foo', foo => {
- nested.set({ count: nested.get('count') + 1 });
+ nested.on('state', ({ changed }) => {
+ if (changed.foo) {
+ nested.set({ count: nested.get().count + 1 });
+ }
});
- assert.htmlEqual(target.innerHTML, `
Called 1 times.
`);
+ assert.htmlEqual(target.innerHTML, `
Called 0 times.
`);
- nested.set({ foo: nested.get('foo') });
- assert.htmlEqual(target.innerHTML, `
Called 2 times.
`);
+ nested.set({ foo: nested.get().foo });
+ assert.htmlEqual(target.innerHTML, `
Called 1 times.
`);
}
};
diff --git a/test/runtime/samples/immutable-nested/Nested.html b/test/runtime/samples/immutable-nested/Nested.html
index 05eb9f3fdf..1f3d808d63 100644
--- a/test/runtime/samples/immutable-nested/Nested.html
+++ b/test/runtime/samples/immutable-nested/Nested.html
@@ -1,4 +1,4 @@
-
Called {{count}} times.
+
Called {count} times.
diff --git a/test/runtime/samples/inline-expressions/main.html b/test/runtime/samples/inline-expressions/main.html
index 93c55f37e3..e5da1ff551 100644
--- a/test/runtime/samples/inline-expressions/main.html
+++ b/test/runtime/samples/inline-expressions/main.html
@@ -1 +1 @@
-
{{a}} + {{b}} = {{a + b}}
+
{a} + {b} = {a + b}
diff --git a/test/runtime/samples/lifecycle-events/_config.js b/test/runtime/samples/lifecycle-events/_config.js
index 07af44c2dc..c82af470e0 100644
--- a/test/runtime/samples/lifecycle-events/_config.js
+++ b/test/runtime/samples/lifecycle-events/_config.js
@@ -2,10 +2,11 @@ export default {
test(assert, component) {
const nested = component.refs.nested;
+
assert.deepEqual(component.events, ['create']);
assert.deepEqual(nested.events, { create: false });
component.destroy();
- assert.deepEqual(component.events, ['create', 'destroy', 'unmount']);
- assert.deepEqual(nested.events, { create: false, unmount: false, destroy: true });
+ assert.deepEqual(component.events, ['create', 'unmount', 'destroy']);
+ assert.deepEqual(nested.events, { create: false, unmount: false, destroy: false });
}
};
diff --git a/test/runtime/samples/names-deconflicted-nested/main.html b/test/runtime/samples/names-deconflicted-nested/main.html
index 7de2cf204d..4d0b8ae1b6 100644
--- a/test/runtime/samples/names-deconflicted-nested/main.html
+++ b/test/runtime/samples/names-deconflicted-nested/main.html
@@ -1,7 +1,7 @@
-{{#each array as row, i}}
+{#each array as row, i}
- {{#each row as cell, j}}
- [ {{i}}, {{j}} ]
- {{/each}}
+ {#each row as cell, j}
+ [ {i}, {j} ]
+ {/each}
-{{/each}}
+{/each}
diff --git a/test/runtime/samples/names-deconflicted/Widget.html b/test/runtime/samples/names-deconflicted/Widget.html
index 9a6074567b..a004758196 100644
--- a/test/runtime/samples/names-deconflicted/Widget.html
+++ b/test/runtime/samples/names-deconflicted/Widget.html
@@ -1 +1 @@
-
{{index + 1}}: {{widget.name}}
+
{index + 1}: {widget.name}
diff --git a/test/runtime/samples/names-deconflicted/main.html b/test/runtime/samples/names-deconflicted/main.html
index ca6eac71db..282c438267 100644
--- a/test/runtime/samples/names-deconflicted/main.html
+++ b/test/runtime/samples/names-deconflicted/main.html
@@ -1,6 +1,6 @@
-{{#each widgets as widget, i}}
-
-{{/each}}
+{#each widgets as widget, i}
+
+{/each}
\ No newline at end of file
diff --git a/test/runtime/samples/ondestroy-before-cleanup/main.html b/test/runtime/samples/ondestroy-before-cleanup/main.html
index c4b7ac879f..cce0356f6a 100644
--- a/test/runtime/samples/ondestroy-before-cleanup/main.html
+++ b/test/runtime/samples/ondestroy-before-cleanup/main.html
@@ -1,6 +1,6 @@
-{{#if visible}}
+{#if visible}
-{{/if}}
+{/if}
+
\ No newline at end of file
diff --git a/test/runtime/samples/onrender-chain/List.html b/test/runtime/samples/onrender-chain/List.html
index 5bf8f12cd8..513c62b2e6 100644
--- a/test/runtime/samples/onrender-chain/List.html
+++ b/test/runtime/samples/onrender-chain/List.html
@@ -1,6 +1,6 @@
-{{#each items as item}}
-
-{{/each}}
+{#each items as item}
+
+{/each}
\ No newline at end of file
diff --git a/test/runtime/samples/onstate-event/_config.js b/test/runtime/samples/onstate-event/_config.js
new file mode 100644
index 0000000000..d3f24376f9
--- /dev/null
+++ b/test/runtime/samples/onstate-event/_config.js
@@ -0,0 +1,49 @@
+export default {
+ 'skip-ssr': true,
+
+ data: {
+ foo: 'woo!'
+ },
+
+ html: `
+
woo!
+
undefined
+ `,
+
+ test(assert, component, target) {
+ const history = [];
+
+ component.on('state', ({ changed, current, previous }) => {
+ history.push({ changed, current, previous });
+ component.set({ bar: current.foo.toUpperCase() });
+ });
+
+ component.set({ foo: 'yeah!' });
+ assert.htmlEqual(target.innerHTML, `
+
yeah!
+
YEAH!
+ `);
+
+ component.set({ unused: 'x' });
+
+ assert.deepEqual(history, [
+ {
+ changed: { foo: true },
+ current: { foo: 'yeah!' },
+ previous: { foo: 'woo!' }
+ },
+ // this is NOT received, because Svelte will not allow
+ // an event handler to trigger itself recursively
+ // {
+ // changed: { bar: true },
+ // current: { foo: 'yeah!', bar: 'YEAH!' },
+ // previous: { foo: 'yeah!' }
+ // },
+ {
+ changed: { unused: true },
+ current: { foo: 'yeah!', bar: 'YEAH!', unused: 'x' },
+ previous: { foo: 'yeah!', bar: 'YEAH!' }
+ }
+ ]);
+ }
+};
diff --git a/test/runtime/samples/onstate-event/main.html b/test/runtime/samples/onstate-event/main.html
new file mode 100644
index 0000000000..fbcc02f2f8
--- /dev/null
+++ b/test/runtime/samples/onstate-event/main.html
@@ -0,0 +1,2 @@
+
{foo}
+
{bar}
\ No newline at end of file
diff --git a/test/runtime/samples/onstate-no-template/_config.js b/test/runtime/samples/onstate-no-template/_config.js
new file mode 100644
index 0000000000..87d7c599ce
--- /dev/null
+++ b/test/runtime/samples/onstate-no-template/_config.js
@@ -0,0 +1,11 @@
+export default {
+ 'skip-ssr': true,
+
+ data: {
+ foo: 'woo!'
+ },
+
+ test(assert, component) {
+ assert.deepEqual(component.changed, { foo: 1 });
+ }
+};
diff --git a/test/runtime/samples/onstate-no-template/main.html b/test/runtime/samples/onstate-no-template/main.html
new file mode 100644
index 0000000000..a3c59f99be
--- /dev/null
+++ b/test/runtime/samples/onstate-no-template/main.html
@@ -0,0 +1,7 @@
+
diff --git a/test/runtime/samples/onstate/_config.js b/test/runtime/samples/onstate/_config.js
new file mode 100644
index 0000000000..48712bb41f
--- /dev/null
+++ b/test/runtime/samples/onstate/_config.js
@@ -0,0 +1,20 @@
+export default {
+ 'skip-ssr': true,
+
+ data: {
+ foo: 'woo!'
+ },
+
+ html: `
+
woo!
+
WOO!
+ `,
+
+ test(assert, component, target) {
+ component.set({ foo: 'yeah!' });
+ assert.htmlEqual(target.innerHTML, `
+
yeah!
+
YEAH!
+ `);
+ }
+};
diff --git a/test/runtime/samples/onstate/main.html b/test/runtime/samples/onstate/main.html
new file mode 100644
index 0000000000..f35c64cd74
--- /dev/null
+++ b/test/runtime/samples/onstate/main.html
@@ -0,0 +1,10 @@
+
{foo}
+
{bar}
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/onupdate/_config.js b/test/runtime/samples/onupdate/_config.js
new file mode 100644
index 0000000000..41e6041937
--- /dev/null
+++ b/test/runtime/samples/onupdate/_config.js
@@ -0,0 +1,20 @@
+export default {
+ 'skip-ssr': true,
+
+ data: {
+ value: 'hello!'
+ },
+
+ html: `
+
hello!
+
hello!
+ `,
+
+ test(assert, component, target) {
+ component.set({ value: 'goodbye!' });
+ assert.htmlEqual(target.innerHTML, `
+
goodbye!
+
goodbye!
+ `);
+ }
+};
diff --git a/test/runtime/samples/onupdate/main.html b/test/runtime/samples/onupdate/main.html
new file mode 100644
index 0000000000..49afda13e5
--- /dev/null
+++ b/test/runtime/samples/onupdate/main.html
@@ -0,0 +1,12 @@
+
{value}
+
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/option-without-select/main.html b/test/runtime/samples/option-without-select/main.html
index 36c101d13d..b0156e95c5 100644
--- a/test/runtime/samples/option-without-select/main.html
+++ b/test/runtime/samples/option-without-select/main.html
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/test/runtime/samples/options/main.html b/test/runtime/samples/options/main.html
index 2cd6339235..1053bc4c0a 100644
--- a/test/runtime/samples/options/main.html
+++ b/test/runtime/samples/options/main.html
@@ -1,4 +1,4 @@
-
{{text}}
+
{text}
\ No newline at end of file
diff --git a/test/runtime/samples/set-in-observe-dedupes-renders/Widget.html b/test/runtime/samples/set-in-observe-dedupes-renders/Widget.html
deleted file mode 100644
index 3d414dd204..0000000000
--- a/test/runtime/samples/set-in-observe-dedupes-renders/Widget.html
+++ /dev/null
@@ -1,17 +0,0 @@
-
{{foo.x}}
-
-
diff --git a/test/runtime/samples/set-in-observe/main.html b/test/runtime/samples/set-in-observe/main.html
deleted file mode 100644
index d07607f5fe..0000000000
--- a/test/runtime/samples/set-in-observe/main.html
+++ /dev/null
@@ -1,16 +0,0 @@
-
{{foo}}
-
{{bar}}
-
-
diff --git a/test/runtime/samples/set-in-oncreate/main.html b/test/runtime/samples/set-in-oncreate/main.html
index 8e71ec5905..77633574f1 100644
--- a/test/runtime/samples/set-in-oncreate/main.html
+++ b/test/runtime/samples/set-in-oncreate/main.html
@@ -1,4 +1,4 @@
-
{{foo}}
+
{foo}
\ No newline at end of file
diff --git a/test/runtime/samples/set-in-observe-dedupes-renders/_config.js b/test/runtime/samples/set-in-onstate-dedupes-renders/_config.js
similarity index 100%
rename from test/runtime/samples/set-in-observe-dedupes-renders/_config.js
rename to test/runtime/samples/set-in-onstate-dedupes-renders/_config.js
diff --git a/test/runtime/samples/set-in-observe-dedupes-renders/main.html b/test/runtime/samples/set-in-onstate-dedupes-renders/main.html
similarity index 58%
rename from test/runtime/samples/set-in-observe-dedupes-renders/main.html
rename to test/runtime/samples/set-in-onstate-dedupes-renders/main.html
index f62940a473..6813463ec1 100644
--- a/test/runtime/samples/set-in-observe-dedupes-renders/main.html
+++ b/test/runtime/samples/set-in-onstate-dedupes-renders/main.html
@@ -1,4 +1,4 @@
-
+
diff --git a/test/runtime/samples/set-mutated-data/main.html b/test/runtime/samples/set-mutated-data/main.html
index 24369f73a4..e076ac55f8 100644
--- a/test/runtime/samples/set-mutated-data/main.html
+++ b/test/runtime/samples/set-mutated-data/main.html
@@ -1 +1 @@
-{{foo}}
\ No newline at end of file
+{foo}
\ No newline at end of file
diff --git a/test/runtime/samples/set-prevents-loop/main.html b/test/runtime/samples/set-prevents-loop/main.html
index becfe053fe..685bfeaa14 100644
--- a/test/runtime/samples/set-prevents-loop/main.html
+++ b/test/runtime/samples/set-prevents-loop/main.html
@@ -1,8 +1,8 @@
-{{#if visible}}
+{#if visible}
-{{else}}
+{:else}
-{{/if}}
+{/if}
\ No newline at end of file
diff --git a/test/runtime/samples/spread-component-with-bind/Widget.html b/test/runtime/samples/spread-component-with-bind/Widget.html
new file mode 100644
index 0000000000..7d9b108a1a
--- /dev/null
+++ b/test/runtime/samples/spread-component-with-bind/Widget.html
@@ -0,0 +1,2 @@
+
{value}
+
\ No newline at end of file
diff --git a/test/runtime/samples/spread-component-with-bind/_config.js b/test/runtime/samples/spread-component-with-bind/_config.js
new file mode 100644
index 0000000000..12a400b755
--- /dev/null
+++ b/test/runtime/samples/spread-component-with-bind/_config.js
@@ -0,0 +1,18 @@
+export default {
+ html: `
+
foo
+
+ `,
+
+ test (assert, component, target, window) {
+ const input = target.querySelector('input');
+
+ input.value = 'bar';
+ input.dispatchEvent(new window.Event('input'));
+
+ assert.htmlEqual(target.innerHTML, `
+
bar
+
+ `);
+ }
+};
diff --git a/test/runtime/samples/spread-component-with-bind/main.html b/test/runtime/samples/spread-component-with-bind/main.html
new file mode 100644
index 0000000000..97ad6f7e44
--- /dev/null
+++ b/test/runtime/samples/spread-component-with-bind/main.html
@@ -0,0 +1,15 @@
+
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/spread-component/Widget.html b/test/runtime/samples/spread-component/Widget.html
new file mode 100644
index 0000000000..a60afb741c
--- /dev/null
+++ b/test/runtime/samples/spread-component/Widget.html
@@ -0,0 +1,4 @@
+
foo: {foo}
+
baz: {baz} ({typeof baz})
+
qux: {qux}
+
quux: {quux}
diff --git a/test/runtime/samples/spread-component/_config.js b/test/runtime/samples/spread-component/_config.js
new file mode 100644
index 0000000000..06acc4906d
--- /dev/null
+++ b/test/runtime/samples/spread-component/_config.js
@@ -0,0 +1,25 @@
+export default {
+ data: {
+ props: {
+ foo: 'lol',
+ baz: 40 + 2,
+ qux: `this is a ${'piece of'} string`,
+ quux: 'core'
+ }
+ },
+
+ html: `
foo: lol
\n
baz: 42 (number)
\n
qux: named
\n
quux: core
`,
+
+ test ( assert, component, target ) {
+ component.set({
+ props: {
+ foo: 'wut',
+ baz: 40 + 3,
+ qux: `this is a ${'rather boring'} string`,
+ quux: 'heart'
+ }
+ });
+
+ assert.equal( target.innerHTML, `
foo: wut
\n
baz: 43 (number)
\n
qux: named
\n
quux: heart
` );
+ }
+};
diff --git a/test/server-side-rendering/samples/component-data-static/main.html b/test/runtime/samples/spread-component/main.html
similarity index 77%
rename from test/server-side-rendering/samples/component-data-static/main.html
rename to test/runtime/samples/spread-component/main.html
index 0df72c1465..ea7e0a812c 100644
--- a/test/server-side-rendering/samples/component-data-static/main.html
+++ b/test/runtime/samples/spread-component/main.html
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/test/runtime/samples/spread-each-element/_config.js b/test/runtime/samples/spread-each-element/_config.js
new file mode 100644
index 0000000000..913a7cc865
--- /dev/null
+++ b/test/runtime/samples/spread-each-element/_config.js
@@ -0,0 +1,26 @@
+export default {
+ html: `
+
+
+ `,
+
+ data: {
+ things: [
+ { 'data-a': 1, 'data-b': 2 },
+ { 'data-c': 3, 'data-d': 4 }
+ ]
+ },
+
+ test(assert, component, target) {
+ const { things } = component.get();
+
+ component.set({
+ things: things.reverse()
+ });
+
+ assert.htmlEqual(target.innerHTML, `
+
+
+ `);
+ },
+};
diff --git a/test/runtime/samples/spread-each-element/main.html b/test/runtime/samples/spread-each-element/main.html
new file mode 100644
index 0000000000..99ae4eeece
--- /dev/null
+++ b/test/runtime/samples/spread-each-element/main.html
@@ -0,0 +1,3 @@
+{#each things as thing}
+
+{/each}
\ No newline at end of file
diff --git a/test/runtime/samples/spread-element-boolean/_config.js b/test/runtime/samples/spread-element-boolean/_config.js
new file mode 100644
index 0000000000..83a1590f29
--- /dev/null
+++ b/test/runtime/samples/spread-element-boolean/_config.js
@@ -0,0 +1,27 @@
+export default {
+ data: {
+ props: {
+ disabled: true
+ }
+ },
+
+ html: `
+
+ `,
+
+ test(assert, component, target) {
+ const button = target.querySelector('button');
+
+ assert.ok(button.disabled);
+
+ component.set({
+ props: { disabled: false }
+ });
+
+ assert.htmlEqual(
+ target.innerHTML,
+ `
`
+ );
+ assert.ok(!button.disabled);
+ },
+};
diff --git a/test/runtime/samples/spread-element-boolean/main.html b/test/runtime/samples/spread-element-boolean/main.html
new file mode 100644
index 0000000000..5cd4df8766
--- /dev/null
+++ b/test/runtime/samples/spread-element-boolean/main.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/runtime/samples/spread-element-input/_config.js b/test/runtime/samples/spread-element-input/_config.js
new file mode 100644
index 0000000000..26f6d9cec2
--- /dev/null
+++ b/test/runtime/samples/spread-element-input/_config.js
@@ -0,0 +1,9 @@
+export default {
+ data: {
+ props: {
+ 'data-foo': 'bar'
+ }
+ },
+
+ html: `
`
+};
diff --git a/test/runtime/samples/spread-element-input/main.html b/test/runtime/samples/spread-element-input/main.html
new file mode 100644
index 0000000000..736444749b
--- /dev/null
+++ b/test/runtime/samples/spread-element-input/main.html
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/test/runtime/samples/spread-element-multiple/_config.js b/test/runtime/samples/spread-element-multiple/_config.js
new file mode 100644
index 0000000000..4a1aae2d83
--- /dev/null
+++ b/test/runtime/samples/spread-element-multiple/_config.js
@@ -0,0 +1,33 @@
+export default {
+ data: {
+ a: {
+ 'data-one': 1,
+ 'data-two': 2,
+ },
+ c: {
+ 'data-b': 'overridden',
+ },
+ d: 'deeeeee',
+ },
+
+ html: `
+
test
+ `,
+
+ test(assert, component, target) {
+ component.set({
+ a: {
+ 'data-one': 10
+ },
+ c: {
+ 'data-c': 'new'
+ },
+ d: 'DEEEEEE'
+ });
+
+ assert.htmlEqual(
+ target.innerHTML,
+ `
test
`
+ );
+ },
+};
diff --git a/test/runtime/samples/spread-element-multiple/main.html b/test/runtime/samples/spread-element-multiple/main.html
new file mode 100644
index 0000000000..97272e6946
--- /dev/null
+++ b/test/runtime/samples/spread-element-multiple/main.html
@@ -0,0 +1 @@
+
test
\ No newline at end of file
diff --git a/test/runtime/samples/spread-element/_config.js b/test/runtime/samples/spread-element/_config.js
new file mode 100644
index 0000000000..bd6c0b891e
--- /dev/null
+++ b/test/runtime/samples/spread-element/_config.js
@@ -0,0 +1,19 @@
+export default {
+ html: `
red
`,
+
+ test ( assert, component, target ) {
+ const div = target.querySelector( 'div' );
+
+ assert.equal( div.dataset.foo, 'bar' );
+ assert.equal( div.dataset.named, 'value' );
+
+ component.set({ color: 'blue', props: { 'data-foo': 'baz', 'data-named': 'qux' } });
+ assert.htmlEqual( target.innerHTML, `
blue
` );
+ assert.equal( div.dataset.foo, 'baz' );
+ assert.equal( div.dataset.named, 'value' );
+
+ component.set({ color: 'blue', props: {} });
+ assert.htmlEqual( target.innerHTML, `
blue
` );
+ assert.equal( div.dataset.foo, undefined );
+ }
+};
diff --git a/test/runtime/samples/spread-element/main.html b/test/runtime/samples/spread-element/main.html
new file mode 100644
index 0000000000..391566826f
--- /dev/null
+++ b/test/runtime/samples/spread-element/main.html
@@ -0,0 +1,13 @@
+
{color}
+
+
diff --git a/test/runtime/samples/state-deconflicted/main.html b/test/runtime/samples/state-deconflicted/main.html
index b5ce111cae..12ff80a0ed 100644
--- a/test/runtime/samples/state-deconflicted/main.html
+++ b/test/runtime/samples/state-deconflicted/main.html
@@ -1,7 +1,7 @@
-
Current state: {{state}}
+
Current state: {state}
- {{#each states as state}}
- - {{state}}
- {{/each}}
+ {#each states as state}
+ - {state}
+ {/each}
\ No newline at end of file
diff --git a/test/runtime/samples/store-binding/_config.js b/test/runtime/samples/store-binding/_config.js
index aefc4ec652..7839a9e3ea 100644
--- a/test/runtime/samples/store-binding/_config.js
+++ b/test/runtime/samples/store-binding/_config.js
@@ -19,7 +19,7 @@ export default {
input.value = 'everybody';
input.dispatchEvent(event);
- assert.equal(store.get('name'), 'everybody');
+ assert.equal(store.get().name, 'everybody');
assert.htmlEqual(target.innerHTML, `
Hello everybody!
diff --git a/test/runtime/samples/store-binding/main.html b/test/runtime/samples/store-binding/main.html
index 06410ea770..0f9e902bf3 100644
--- a/test/runtime/samples/store-binding/main.html
+++ b/test/runtime/samples/store-binding/main.html
@@ -1,4 +1,4 @@
-
Hello {{$name}}!
+
Hello {$name}!
\ No newline at end of file
diff --git a/test/runtime/samples/store-computed/Todo.html b/test/runtime/samples/store-computed/Todo.html
index 2ad67420ca..c665d86d32 100644
--- a/test/runtime/samples/store-computed/Todo.html
+++ b/test/runtime/samples/store-computed/Todo.html
@@ -1,11 +1,11 @@
-{{#if isVisible}}
-
{{todo.description}}
-{{/if}}
+{#if isVisible}
+
{todo.description}
+{/if}
diff --git a/test/runtime/samples/svg-child-component-declared-namespace-backtick-string/_config.js b/test/runtime/samples/svg-child-component-declared-namespace-backtick-string/_config.js
new file mode 100644
index 0000000000..b4a0da70db
--- /dev/null
+++ b/test/runtime/samples/svg-child-component-declared-namespace-backtick-string/_config.js
@@ -0,0 +1,21 @@
+export default {
+ data: {
+ x: 0,
+ y: 0,
+ width: 100,
+ height: 100
+ },
+
+ html: `
`,
+
+ test ( assert, component, target ) {
+ const svg = target.querySelector( 'svg' );
+ const rect = target.querySelector( 'rect' );
+
+ assert.equal( svg.namespaceURI, 'http://www.w3.org/2000/svg' );
+ assert.equal( rect.namespaceURI, 'http://www.w3.org/2000/svg' );
+
+ component.set({ width: 150, height: 50 });
+ assert.equal( target.innerHTML, `
` );
+ },
+};
diff --git a/test/runtime/samples/svg-child-component-declared-namespace-backtick-string/main.html b/test/runtime/samples/svg-child-component-declared-namespace-backtick-string/main.html
new file mode 100644
index 0000000000..6ae6ad8590
--- /dev/null
+++ b/test/runtime/samples/svg-child-component-declared-namespace-backtick-string/main.html
@@ -0,0 +1,11 @@
+
+
+
diff --git a/test/runtime/samples/svg-child-component-declared-namespace-shorthand/Rect.html b/test/runtime/samples/svg-child-component-declared-namespace-shorthand/Rect.html
index c158d7fdf5..536f47107e 100644
--- a/test/runtime/samples/svg-child-component-declared-namespace-shorthand/Rect.html
+++ b/test/runtime/samples/svg-child-component-declared-namespace-shorthand/Rect.html
@@ -1,4 +1,4 @@
-
+
\ No newline at end of file
diff --git a/test/runtime/samples/transition-css-delay/main.html b/test/runtime/samples/transition-css-delay/main.html
index cd46050a9f..46a46aa527 100644
--- a/test/runtime/samples/transition-css-delay/main.html
+++ b/test/runtime/samples/transition-css-delay/main.html
@@ -1,6 +1,6 @@
-{{#if visible}}
+{#if visible}
delayed
-{{/if}}
+{/if}
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-aborted-outro-in-each/_config.js b/test/runtime/samples/transition-js-aborted-outro-in-each/_config.js
new file mode 100644
index 0000000000..ae23179270
--- /dev/null
+++ b/test/runtime/samples/transition-js-aborted-outro-in-each/_config.js
@@ -0,0 +1,39 @@
+export default {
+ data: {
+ things: [
+ 'one',
+ 'two',
+ 'three'
+ ]
+ },
+
+ test(assert, component, target, window, raf) {
+ const { things } = component.get();
+
+ component.set({ things: [] });
+ const spans = target.querySelectorAll('span');
+
+ raf.tick(25);
+ assert.equal(spans[0].foo, 0.75);
+ assert.equal(spans[1].foo, undefined);
+ assert.equal(spans[2].foo, undefined);
+
+ raf.tick(125);
+ assert.equal(spans[0].foo, 0);
+ assert.equal(spans[1].foo, 0.25);
+ assert.equal(spans[2].foo, 0.75);
+
+ component.set({ things });
+ raf.tick(225);
+
+ assert.htmlEqual(target.innerHTML, `
+
one
+
two
+
three
+ `);
+
+ assert.equal(spans[0].foo, 1);
+ assert.equal(spans[1].foo, 1);
+ assert.equal(spans[2].foo, 1);
+ },
+};
diff --git a/test/runtime/samples/transition-js-aborted-outro-in-each/main.html b/test/runtime/samples/transition-js-aborted-outro-in-each/main.html
new file mode 100644
index 0000000000..fabdc527a3
--- /dev/null
+++ b/test/runtime/samples/transition-js-aborted-outro-in-each/main.html
@@ -0,0 +1,19 @@
+{#each things as thing, i}
+
{thing}
+{/each}
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-aborted-outro/_config.js b/test/runtime/samples/transition-js-aborted-outro/_config.js
new file mode 100644
index 0000000000..345fed1a75
--- /dev/null
+++ b/test/runtime/samples/transition-js-aborted-outro/_config.js
@@ -0,0 +1,24 @@
+export default {
+ data: {
+ visible: true,
+ },
+
+ test(assert, component, target, window, raf) {
+ component.set({ visible: false });
+ const span = target.querySelector('span');
+
+ raf.tick(50);
+ assert.equal(span.foo, 0.5);
+
+ component.set({ visible: true });
+ assert.equal(span.foo, 1);
+
+ raf.tick(75);
+ assert.equal(span.foo, 1);
+
+ raf.tick(100);
+ assert.htmlEqual(target.innerHTML, `
+
hello
+ `);
+ },
+};
diff --git a/test/runtime/samples/transition-js-aborted-outro/main.html b/test/runtime/samples/transition-js-aborted-outro/main.html
new file mode 100644
index 0000000000..47c93a2321
--- /dev/null
+++ b/test/runtime/samples/transition-js-aborted-outro/main.html
@@ -0,0 +1,18 @@
+{#if visible}
+
hello
+{/if}
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-args/_config.js b/test/runtime/samples/transition-js-args/_config.js
new file mode 100644
index 0000000000..d7ea1240b7
--- /dev/null
+++ b/test/runtime/samples/transition-js-args/_config.js
@@ -0,0 +1,15 @@
+export default {
+ skipIntroByDefault: true,
+ nestedTransitions: true,
+ intro: true,
+
+ test(assert, component, target, window, raf) {
+ const div = target.querySelector('div');
+ assert.equal(div.foo, 0);
+ assert.equal(div.oof, 1);
+
+ raf.tick(50);
+ assert.equal(div.foo, 0.5);
+ assert.equal(div.oof, 0.5);
+ }
+};
diff --git a/test/runtime/samples/transition-js-args/main.html b/test/runtime/samples/transition-js-args/main.html
new file mode 100644
index 0000000000..890ec9a5e4
--- /dev/null
+++ b/test/runtime/samples/transition-js-args/main.html
@@ -0,0 +1,17 @@
+
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-await-block/_config.js b/test/runtime/samples/transition-js-await-block/_config.js
new file mode 100644
index 0000000000..ff9888c88b
--- /dev/null
+++ b/test/runtime/samples/transition-js-await-block/_config.js
@@ -0,0 +1,35 @@
+let fulfil;
+let reject;
+
+let promise = new Promise((f, r) => {
+ fulfil = f;
+ reject = r;
+});
+
+export default {
+ data: {
+ promise
+ },
+
+ test(assert, component, target, window, raf) {
+ component.set({ visible: true });
+ let p = target.querySelector('p');
+
+ assert.equal(p.className, 'pending');
+ assert.equal(p.foo, 0);
+
+ raf.tick(50);
+ assert.equal(p.foo, 0.5);
+
+ fulfil(42);
+
+ return promise.then(() => {
+ raf.tick(80);
+ let ps = document.querySelectorAll('p');
+ assert.equal(ps[0].className, 'pending');
+ assert.equal(ps[1].className, 'then');
+ assert.equal(ps[0].foo, 0.2);
+ assert.equal(ps[1].foo, 0.3);
+ });
+ }
+};
diff --git a/test/runtime/samples/transition-js-await-block/main.html b/test/runtime/samples/transition-js-await-block/main.html
new file mode 100644
index 0000000000..9fc038fd66
--- /dev/null
+++ b/test/runtime/samples/transition-js-await-block/main.html
@@ -0,0 +1,22 @@
+{#await promise}
+
loading...
+{:then value}
+
{value}
+{:catch error}
+
{error.message}
+{/await}
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-deferred/_config.js b/test/runtime/samples/transition-js-deferred/_config.js
new file mode 100644
index 0000000000..79d4b41a81
--- /dev/null
+++ b/test/runtime/samples/transition-js-deferred/_config.js
@@ -0,0 +1,15 @@
+export default {
+ skipIntroByDefault: true,
+
+ test(assert, component, target, window, raf) {
+ component.set({ visible: true });
+
+ return Promise.resolve().then(() => {
+ const div = target.querySelector('div');
+ assert.equal(div.foo, 0);
+
+ raf.tick(50);
+ assert.equal(div.foo, 0.5);
+ });
+ },
+};
diff --git a/test/runtime/samples/transition-js-deferred/main.html b/test/runtime/samples/transition-js-deferred/main.html
new file mode 100644
index 0000000000..01985384ad
--- /dev/null
+++ b/test/runtime/samples/transition-js-deferred/main.html
@@ -0,0 +1,20 @@
+{#if visible}
+
+{/if}
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-delay-in-out/main.html b/test/runtime/samples/transition-js-delay-in-out/main.html
index 6a0a3f88a7..43400fd67e 100644
--- a/test/runtime/samples/transition-js-delay-in-out/main.html
+++ b/test/runtime/samples/transition-js-delay-in-out/main.html
@@ -1,6 +1,6 @@
-{{#if visible}}
+{#if visible}
delayed
-{{/if}}
+{/if}
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-intro-skipped-by-default-nested/Widget.html b/test/runtime/samples/transition-js-intro-skipped-by-default-nested/Widget.html
new file mode 100644
index 0000000000..16ced20bc3
--- /dev/null
+++ b/test/runtime/samples/transition-js-intro-skipped-by-default-nested/Widget.html
@@ -0,0 +1,16 @@
+
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-intro-skipped-by-default-nested/_config.js b/test/runtime/samples/transition-js-intro-skipped-by-default-nested/_config.js
new file mode 100644
index 0000000000..9e63e6c8f7
--- /dev/null
+++ b/test/runtime/samples/transition-js-intro-skipped-by-default-nested/_config.js
@@ -0,0 +1,11 @@
+export default {
+ skipIntroByDefault: true,
+
+ test(assert, component, target, window, raf) {
+ const div = target.querySelector('div');
+ assert.equal(div.foo, undefined);
+
+ raf.tick(50);
+ assert.equal(div.foo, undefined);
+ },
+};
diff --git a/test/runtime/samples/transition-js-intro-skipped-by-default-nested/main.html b/test/runtime/samples/transition-js-intro-skipped-by-default-nested/main.html
new file mode 100644
index 0000000000..fca2ea7607
--- /dev/null
+++ b/test/runtime/samples/transition-js-intro-skipped-by-default-nested/main.html
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-intro-skipped-by-default/_config.js b/test/runtime/samples/transition-js-intro-skipped-by-default/_config.js
new file mode 100644
index 0000000000..9e63e6c8f7
--- /dev/null
+++ b/test/runtime/samples/transition-js-intro-skipped-by-default/_config.js
@@ -0,0 +1,11 @@
+export default {
+ skipIntroByDefault: true,
+
+ test(assert, component, target, window, raf) {
+ const div = target.querySelector('div');
+ assert.equal(div.foo, undefined);
+
+ raf.tick(50);
+ assert.equal(div.foo, undefined);
+ },
+};
diff --git a/test/runtime/samples/transition-js-intro-skipped-by-default/main.html b/test/runtime/samples/transition-js-intro-skipped-by-default/main.html
new file mode 100644
index 0000000000..16ced20bc3
--- /dev/null
+++ b/test/runtime/samples/transition-js-intro-skipped-by-default/main.html
@@ -0,0 +1,16 @@
+
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-nested-await/_config.js b/test/runtime/samples/transition-js-nested-await/_config.js
new file mode 100644
index 0000000000..d688c55cf1
--- /dev/null
+++ b/test/runtime/samples/transition-js-nested-await/_config.js
@@ -0,0 +1,37 @@
+let fulfil;
+
+const promise = new Promise(f => {
+ fulfil = f;
+});
+
+export default {
+ skipIntroByDefault: true,
+ nestedTransitions: true,
+
+ data: {
+ x: false,
+ promise
+ },
+
+ test(assert, component, target, window, raf) {
+ component.set({ x: true });
+ fulfil();
+
+ return promise.then(() => {
+ const div = target.querySelector('div');
+ assert.equal(div.foo, 0);
+
+ raf.tick(100);
+ assert.equal(div.foo, 1);
+
+ component.set({ x: false });
+ assert.htmlEqual(target.innerHTML, '
');
+
+ raf.tick(150);
+ assert.equal(div.foo, 0.5);
+
+ raf.tick(200);
+ assert.htmlEqual(target.innerHTML, '');
+ });
+ }
+};
diff --git a/test/runtime/samples/transition-js-nested-await/main.html b/test/runtime/samples/transition-js-nested-await/main.html
new file mode 100644
index 0000000000..039051a8bd
--- /dev/null
+++ b/test/runtime/samples/transition-js-nested-await/main.html
@@ -0,0 +1,20 @@
+{#if x}
+ {#await promise then value}
+
+ {/await}
+{/if}
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-nested-component/Widget.html b/test/runtime/samples/transition-js-nested-component/Widget.html
new file mode 100644
index 0000000000..16ced20bc3
--- /dev/null
+++ b/test/runtime/samples/transition-js-nested-component/Widget.html
@@ -0,0 +1,16 @@
+
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-nested-component/_config.js b/test/runtime/samples/transition-js-nested-component/_config.js
new file mode 100644
index 0000000000..6f2c039a40
--- /dev/null
+++ b/test/runtime/samples/transition-js-nested-component/_config.js
@@ -0,0 +1,27 @@
+export default {
+ skipIntroByDefault: true,
+ nestedTransitions: true,
+
+ data: {
+ x: false
+ },
+
+ test(assert, component, target, window, raf) {
+ component.set({ x: true });
+
+ const div = target.querySelector('div');
+ assert.equal(div.foo, 0);
+
+ raf.tick(100);
+ assert.equal(div.foo, 1);
+
+ component.set({ x: false });
+ assert.htmlEqual(target.innerHTML, '
');
+
+ raf.tick(150);
+ assert.equal(div.foo, 0.5);
+
+ raf.tick(200);
+ assert.htmlEqual(target.innerHTML, '');
+ }
+};
diff --git a/test/runtime/samples/transition-js-nested-component/main.html b/test/runtime/samples/transition-js-nested-component/main.html
new file mode 100644
index 0000000000..2930f4dc16
--- /dev/null
+++ b/test/runtime/samples/transition-js-nested-component/main.html
@@ -0,0 +1,13 @@
+{#if x}
+
+{/if}
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-nested-each-keyed/_config.js b/test/runtime/samples/transition-js-nested-each-keyed/_config.js
new file mode 100644
index 0000000000..7011ada5aa
--- /dev/null
+++ b/test/runtime/samples/transition-js-nested-each-keyed/_config.js
@@ -0,0 +1,28 @@
+export default {
+ skipIntroByDefault: true,
+ nestedTransitions: true,
+
+ data: {
+ x: false,
+ things: ['a']
+ },
+
+ test(assert, component, target, window, raf) {
+ component.set({ x: true });
+
+ const div = target.querySelector('div');
+ assert.equal(div.foo, 0);
+
+ raf.tick(100);
+ assert.equal(div.foo, 1);
+
+ component.set({ x: false });
+ assert.htmlEqual(target.innerHTML, '
');
+
+ raf.tick(150);
+ assert.equal(div.foo, 0.5);
+
+ raf.tick(200);
+ assert.htmlEqual(target.innerHTML, '');
+ },
+};
diff --git a/test/runtime/samples/transition-js-nested-each-keyed/main.html b/test/runtime/samples/transition-js-nested-each-keyed/main.html
new file mode 100644
index 0000000000..335380695d
--- /dev/null
+++ b/test/runtime/samples/transition-js-nested-each-keyed/main.html
@@ -0,0 +1,20 @@
+{#if x}
+ {#each things as thing (thing)}
+
+ {/each}
+{/if}
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-nested-each/_config.js b/test/runtime/samples/transition-js-nested-each/_config.js
new file mode 100644
index 0000000000..7011ada5aa
--- /dev/null
+++ b/test/runtime/samples/transition-js-nested-each/_config.js
@@ -0,0 +1,28 @@
+export default {
+ skipIntroByDefault: true,
+ nestedTransitions: true,
+
+ data: {
+ x: false,
+ things: ['a']
+ },
+
+ test(assert, component, target, window, raf) {
+ component.set({ x: true });
+
+ const div = target.querySelector('div');
+ assert.equal(div.foo, 0);
+
+ raf.tick(100);
+ assert.equal(div.foo, 1);
+
+ component.set({ x: false });
+ assert.htmlEqual(target.innerHTML, '
');
+
+ raf.tick(150);
+ assert.equal(div.foo, 0.5);
+
+ raf.tick(200);
+ assert.htmlEqual(target.innerHTML, '');
+ },
+};
diff --git a/test/runtime/samples/transition-js-nested-each/main.html b/test/runtime/samples/transition-js-nested-each/main.html
new file mode 100644
index 0000000000..c47940c1cf
--- /dev/null
+++ b/test/runtime/samples/transition-js-nested-each/main.html
@@ -0,0 +1,20 @@
+{#if x}
+ {#each things as thing}
+
+ {/each}
+{/if}
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-nested-if/_config.js b/test/runtime/samples/transition-js-nested-if/_config.js
new file mode 100644
index 0000000000..c8f624b2c7
--- /dev/null
+++ b/test/runtime/samples/transition-js-nested-if/_config.js
@@ -0,0 +1,28 @@
+export default {
+ skipIntroByDefault: true,
+ nestedTransitions: true,
+
+ data: {
+ x: false,
+ y: true
+ },
+
+ test(assert, component, target, window, raf) {
+ component.set({ x: true });
+
+ const div = target.querySelector('div');
+ assert.equal(div.foo, 0);
+
+ raf.tick(100);
+ assert.equal(div.foo, 1);
+
+ component.set({ x: false });
+ assert.htmlEqual(target.innerHTML, '
');
+
+ raf.tick(150);
+ assert.equal(div.foo, 0.5);
+
+ raf.tick(200);
+ assert.htmlEqual(target.innerHTML, '');
+ },
+};
diff --git a/test/runtime/samples/transition-js-nested-if/main.html b/test/runtime/samples/transition-js-nested-if/main.html
new file mode 100644
index 0000000000..cd10c9118f
--- /dev/null
+++ b/test/runtime/samples/transition-js-nested-if/main.html
@@ -0,0 +1,20 @@
+{#if x}
+ {#if y}
+
+ {/if}
+{/if}
+
+
\ No newline at end of file
diff --git a/test/runtime/samples/transition-js-nested-intro/main.html b/test/runtime/samples/transition-js-nested-intro/main.html
index c8bf70b0ae..c06e004c8c 100644
--- a/test/runtime/samples/transition-js-nested-intro/main.html
+++ b/test/runtime/samples/transition-js-nested-intro/main.html
@@ -1,6 +1,6 @@
-{{#if visible}}
+{#if visible}
delayed
-{{/if}}
+{/if}
\ No newline at end of file
diff --git a/test/runtime/samples/window-event/main.html b/test/runtime/samples/window-event/main.html
index b6679a0e44..76f5c02084 100644
--- a/test/runtime/samples/window-event/main.html
+++ b/test/runtime/samples/window-event/main.html
@@ -1,3 +1,3 @@
-<:Window on:resize='set({ width: this.innerWidth, height: this.innerHeight })'/>
+
-
{{width}}x{{height}}
\ No newline at end of file
+
{width}x{height}
\ No newline at end of file
diff --git a/test/server-side-rendering/index.js b/test/server-side-rendering/index.js
index 524b9486ff..1d3aaa6825 100644
--- a/test/server-side-rendering/index.js
+++ b/test/server-side-rendering/index.js
@@ -1,7 +1,7 @@
import assert from "assert";
import * as fs from "fs";
import * as path from "path";
-import glob from 'glob';
+import glob from 'tiny-glob/sync.js';
import {
showOutput,
@@ -105,14 +105,12 @@ describe("ssr", () => {
(config.skip ? it.skip : config.solo ? it.only : it)(dir, () => {
const cwd = path.resolve("test/runtime/samples", dir);
- glob.sync('**/*.html', { cwd: `test/runtime/samples/${dir}` }).forEach(file => {
+ glob('**/*.html', { cwd: `test/runtime/samples/${dir}` }).forEach(file => {
const resolved = require.resolve(`../runtime/samples/${dir}/${file}`);
delete require.cache[resolved];
});
- const compileOptions = Object.assign(config.compileOptions || {}, {
- store: !!config.store
- });
+ const compileOptions = config.compileOptions || {};
require("../../ssr/register")(compileOptions);
diff --git a/test/server-side-rendering/samples/attribute-dynamic/main.html b/test/server-side-rendering/samples/attribute-dynamic/main.html
index 18732ab91a..1528a49478 100644
--- a/test/server-side-rendering/samples/attribute-dynamic/main.html
+++ b/test/server-side-rendering/samples/attribute-dynamic/main.html
@@ -1 +1 @@
-
{{color}} {{font}}
+
{color} {font}
diff --git a/test/server-side-rendering/samples/component-binding-renamed/main.html b/test/server-side-rendering/samples/component-binding-renamed/main.html
index 7445660354..7f5e588534 100644
--- a/test/server-side-rendering/samples/component-binding-renamed/main.html
+++ b/test/server-side-rendering/samples/component-binding-renamed/main.html
@@ -1,4 +1,4 @@
-{{y}}
{{y}}
+{y}
{y}
diff --git a/test/server-side-rendering/samples/default-data-override/main.html b/test/server-side-rendering/samples/default-data-override/main.html
index 3605487855..1014c2df07 100644
--- a/test/server-side-rendering/samples/default-data-override/main.html
+++ b/test/server-side-rendering/samples/default-data-override/main.html
@@ -1,4 +1,4 @@
-
{{foo}}
+
{foo}
\ No newline at end of file
diff --git a/test/stats/samples/imports/_config.js b/test/stats/samples/imports/_config.js
new file mode 100644
index 0000000000..f7c15183dd
--- /dev/null
+++ b/test/stats/samples/imports/_config.js
@@ -0,0 +1,18 @@
+export default {
+ test(assert, stats) {
+ assert.deepEqual(stats.imports, [
+ {
+ source: 'x',
+ specifiers: [{ name: 'default', as: 'x' }]
+ },
+ {
+ source: 'y',
+ specifiers: [{ name: 'y', as: 'y' }]
+ },
+ {
+ source: 'z',
+ specifiers: [{ name: '*', as: 'z' }]
+ }
+ ]);
+ }
+};
\ No newline at end of file
diff --git a/test/stats/samples/imports/input.html b/test/stats/samples/imports/input.html
new file mode 100644
index 0000000000..a7b59691ac
--- /dev/null
+++ b/test/stats/samples/imports/input.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/test/store/index.js b/test/store/index.js
index fd84322d35..8d5dd5749c 100644
--- a/test/store/index.js
+++ b/test/store/index.js
@@ -5,32 +5,7 @@ import { parse } from 'acorn';
import { Store } from '../../store.js';
describe('store', () => {
- it('is written in ES5', () => {
- const source = fs.readFileSync('store.js', 'utf-8');
-
- const ast = parse(source, {
- sourceType: 'module'
- });
-
- const magicString = new MagicString(source);
- ast.body.forEach(node => {
- if (/^(Im|Ex)port/.test(node.type)) magicString.remove(node.start, node.end);
- });
-
- parse(magicString.toString(), {
- ecmaVersion: 5
- });
- });
-
describe('get', () => {
- it('gets a specific key', () => {
- const store = new Store({
- foo: 'bar'
- });
-
- assert.equal(store.get('foo'), 'bar');
- });
-
it('gets the entire state object', () => {
const store = new Store({
foo: 'bar'
@@ -48,12 +23,12 @@ describe('store', () => {
foo: 'bar'
});
- assert.equal(store.get('foo'), 'bar');
+ assert.equal(store.get().foo, 'bar');
});
});
- describe('observe', () => {
- it('observes state', () => {
+ describe('on', () => {
+ it('listens to an event', () => {
let newFoo;
let oldFoo;
@@ -61,65 +36,39 @@ describe('store', () => {
foo: 'bar'
});
- store.observe('foo', (n, o) => {
- newFoo = n;
- oldFoo = o;
+ store.on('state', ({ changed, current, previous }) => {
+ newFoo = current.foo;
+ oldFoo = previous.foo;
});
- assert.equal(newFoo, 'bar');
- assert.equal(oldFoo, undefined);
-
- store.set({
- foo: 'baz'
- });
+ store.set({ foo: 'baz' });
assert.equal(newFoo, 'baz');
assert.equal(oldFoo, 'bar');
});
});
- describe('onchange', () => {
- it('fires a callback when state changes', () => {
- const store = new Store();
-
- let count = 0;
- let args;
-
- store.onchange((state, changed) => {
- count += 1;
- args = { state, changed };
- });
-
- store.set({ foo: 'bar' });
+ describe('fire', () => {
+ let answer;
- assert.equal(count, 1);
- assert.deepEqual(args, {
- state: { foo: 'bar' },
- changed: { foo: true }
- });
+ const store = new Store();
- // this should be a noop
- store.set({ foo: 'bar' });
- assert.equal(count, 1);
+ store.on('custom', event => {
+ answer = event.answer;
+ });
- // this shouldn't
- store.set({ foo: 'baz' });
+ store.fire('custom', { answer: 42 });
- assert.equal(count, 2);
- assert.deepEqual(args, {
- state: { foo: 'baz' },
- changed: { foo: true }
- });
- });
+ assert.equal(answer, 42);
});
it('allows user to cancel state change callback', () => {
const store = new Store();
- const handler = store.onchange(() => {});
+ const handler = store.on('state', () => {});
assert.doesNotThrow(() => {
handler.cancel();
- }, TypeError, 'this._changeHandlers is undefined');
+ }, TypeError, 'this._handlers is undefined');
});
describe('computed', () => {
@@ -129,16 +78,16 @@ describe('store', () => {
});
store.compute('bar', ['foo'], foo => foo * 2);
- assert.equal(store.get('bar'), 2);
+ assert.equal(store.get().bar, 2);
const values = [];
- store.observe('bar', bar => {
- values.push(bar);
+ store.on('state', ({ current }) => {
+ values.push(current.bar);
});
store.set({ foo: 2 });
- assert.deepEqual(values, [2, 4]);
+ assert.deepEqual(values, [4]);
});
it('computes a property based on another computed property', () => {
@@ -148,16 +97,16 @@ describe('store', () => {
store.compute('bar', ['foo'], foo => foo * 2);
store.compute('baz', ['bar'], bar => bar * 2);
- assert.equal(store.get('baz'), 4);
+ assert.equal(store.get().baz, 4);
const values = [];
- store.observe('baz', baz => {
- values.push(baz);
+ store.on('state', ({ current }) => {
+ values.push(current.baz);
});
store.set({ foo: 2 });
- assert.deepEqual(values, [4, 8]);
+ assert.deepEqual(values, [8]);
});
it('prevents computed properties from being set', () => {
@@ -192,8 +141,27 @@ describe('store', () => {
assert.throws(() => {
store.compute('a', ['b'], b => b + 1);
- store.compute('b', ['a'], a => a + 1);
- }, /Cyclical dependency detected/);
+ store.compute('b', ['c'], c => c + 1);
+ store.compute('c', ['a'], a => a + 1);
+ }, /Cyclical dependency detected between a <-> c/);
+ });
+
+ it('does not falsely report cycles', () => {
+ const store = new Store();
+
+ store.compute('dep4', ['dep1', 'dep2', 'dep3'], (...args) => ['dep4'].concat(...args));
+ store.compute('dep1', ['source'], (...args) => ['dep1'].concat(...args));
+ store.compute('dep2', ['dep1'], (...args) => ['dep2'].concat(...args));
+ store.compute('dep3', ['dep1', 'dep2'], (...args) => ['dep3'].concat(...args));
+ store.set({source: 'source'});
+
+ assert.deepEqual(store.get().dep4, [
+ 'dep4',
+ 'dep1', 'source',
+ 'dep2', 'dep1', 'source',
+ 'dep3', 'dep1', 'source',
+ 'dep2', 'dep1', 'source'
+ ]);
});
});
@@ -209,29 +177,19 @@ describe('store', () => {
foo: value1
}, { immutable: true });
- store.observe('foo', (n, o) => {
+ store.on('state', ({ current, previous }) => {
callCount++;
- newFoo = n;
- oldFoo = o;
+ newFoo = current.foo;
+ oldFoo = previous.foo;
});
- assert.equal(callCount, 1);
- assert.equal(newFoo, value1);
- assert.equal(oldFoo, undefined);
-
- store.set({
- foo: value1
- });
+ store.set({ foo: value1 });
- assert.equal(callCount, 1);
- assert.equal(newFoo, value1);
- assert.equal(oldFoo, undefined);
+ assert.equal(callCount, 0);
- store.set({
- foo: value2
- });
+ store.set({ foo: value2 });
- assert.equal(callCount, 2);
+ assert.equal(callCount, 1);
assert.equal(newFoo, value2);
assert.equal(oldFoo, value1);
});
diff --git a/test/test.js b/test/test.js
index b501fd81a0..9bf09879b2 100644
--- a/test/test.js
+++ b/test/test.js
@@ -1,11 +1,11 @@
-const glob = require("glob");
+const glob = require("tiny-glob/sync.js");
require("./setup");
-glob.sync("**/__test__.js", { cwd: "src" }).forEach(function(file) {
+glob("**/__test__.js", { cwd: "src" }).forEach(function(file) {
require("../src/" + file);
});
-glob.sync("*/index.js", { cwd: "test" }).forEach(function(file) {
+glob("*/index.js", { cwd: "test" }).forEach(function(file) {
require("./" + file);
});
diff --git a/test/validator/index.js b/test/validator/index.js
index 6fa792dbde..852ac4191b 100644
--- a/test/validator/index.js
+++ b/test/validator/index.js
@@ -16,25 +16,35 @@ describe("validate", () => {
(solo ? it.only : skip ? it.skip : it)(dir, () => {
const config = loadConfig(`./validator/samples/${dir}/_config.js`);
- const filename = `test/validator/samples/${dir}/input.html`;
- const input = fs.readFileSync(filename, "utf-8").replace(/\s+$/, "");
+ const input = fs.readFileSync(`test/validator/samples/${dir}/input.html`, "utf-8").replace(/\s+$/, "");
const expectedWarnings = tryToLoadJson(`test/validator/samples/${dir}/warnings.json`) || [];
const expectedErrors = tryToLoadJson(`test/validator/samples/${dir}/errors.json`);
+
let error;
try {
const warnings = [];
- svelte.compile(input, {
+ const { stats } = svelte.compile(input, {
onwarn(warning) {
- warnings.push({
- message: warning.message,
- pos: warning.pos,
- loc: warning.loc
- });
+ const { code, message, pos, start, end } = warning;
+ warnings.push({ code, message, pos, start, end });
},
- dev: config.dev
+ dev: config.dev,
+ generate: false
+ });
+
+ assert.equal(stats.warnings.length, warnings.length);
+ stats.warnings.forEach((full, i) => {
+ const lite = warnings[i];
+ assert.deepEqual({
+ code: full.code,
+ message: full.message,
+ pos: full.pos,
+ start: full.start,
+ end: full.end
+ }, lite);
});
assert.deepEqual(warnings, expectedWarnings);
@@ -53,8 +63,10 @@ describe("validate", () => {
throw new Error(`Expected an error: ${expected.message}`);
}
+ assert.equal(error.code, expected.code);
assert.equal(error.message, expected.message);
- assert.deepEqual(error.loc, expected.loc);
+ assert.deepEqual(error.start, expected.start);
+ assert.deepEqual(error.end, expected.end);
assert.equal(error.pos, expected.pos);
}
});
@@ -63,7 +75,8 @@ describe("validate", () => {
it("errors if options.name is illegal", () => {
assert.throws(() => {
svelte.compile("
", {
- name: "not.valid"
+ name: "not.valid",
+ generate: false
});
}, /options\.name must be a valid identifier/);
});
@@ -74,17 +87,20 @@ describe("validate", () => {
name: "lowercase",
onwarn(warning) {
warnings.push({
+ code: warning.code,
message: warning.message,
pos: warning.pos,
- loc: warning.loc
+ start: warning.start
});
- }
+ },
+ generate: false
});
assert.deepEqual(warnings, [
{
+ code: `options-lowercase-name`,
message: "options.name should be capitalised",
pos: undefined,
- loc: undefined
+ start: undefined
}
]);
});
@@ -95,11 +111,13 @@ describe("validate", () => {
name: "_",
onwarn(warning) {
warnings.push({
+ code: warning.code,
message: warning.message,
pos: warning.pos,
- loc: warning.loc
+ start: warning.start
});
- }
+ },
+ generate: false
});
assert.deepEqual(warnings, []);
});
diff --git a/test/validator/samples/a11y-alt-text/warnings.json b/test/validator/samples/a11y-alt-text/warnings.json
index 7bddf9730b..7ce5fb2d8f 100644
--- a/test/validator/samples/a11y-alt-text/warnings.json
+++ b/test/validator/samples/a11y-alt-text/warnings.json
@@ -1,36 +1,64 @@
[
{
+ "code": "a11y-missing-attribute",
"message": "A11y:
![]()
element should have an alt attribute",
- "loc": {
+ "start": {
"line": 1,
- "column": 0
+ "column": 0,
+ "character": 0
+ },
+ "end": {
+ "line": 1,
+ "column": 19,
+ "character": 19
},
"pos": 0
},
{
+ "code": "a11y-missing-attribute",
"message": "A11y:
element should have an alt, aria-label or aria-labelledby attribute",
- "loc": {
+ "start": {
+ "line": 4,
+ "column": 1,
+ "character": 28
+ },
+ "end": {
"line": 4,
- "column": 1
+ "column": 7,
+ "character": 34
},
"pos": 28
},
{
+ "code": "a11y-missing-attribute",
"message": "A11y: