diff --git a/.gitignore b/.gitignore index ee1daa2c03..22389f683c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ node_modules /compiler.*js /index.*js /ssr.*js +/action /internal /store /easing diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dd186cfcb..1fa6ec5796 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Svelte changelog +## Unreleased + +* Return the context object in `setContext` [#7427](https://github.com/sveltejs/svelte/issues/7427) + +## 3.47.0 + +* Add support for dynamic elements through `` ([#2324](https://github.com/sveltejs/svelte/issues/2324)) +* Miscellaneous variable context fixes in `{@const}` ([#7222](https://github.com/sveltejs/svelte/pull/7222)) +* Fix `{#key}` block not being reactive when the key variable is not otherwise used ([#7408](https://github.com/sveltejs/svelte/issues/7408)) +* Add `Symbol` as a known global ([#7418](https://github.com/sveltejs/svelte/issues/7418)) + +## 3.46.6 + +* Actually include action TypeScript interface in published package ([#7407](https://github.com/sveltejs/svelte/pull/7407)) + +## 3.46.5 + +* Add TypeScript interfaces for typing actions ([#6538](https://github.com/sveltejs/svelte/issues/6538)) +* Do not generate `unused-export-let` warning inside ` + +Foo +``` ### `` @@ -1683,7 +1705,7 @@ All except `scrollX` and `scrollY` are readonly. Similarly to ``, this element allows you to add listeners to events on `document.body`, such as `mouseenter` and `mouseleave`, which don't fire on `window`. It also lets you use [actions](/docs#template-syntax-element-directives-use-action) on the `` element. -`` also has to appear at the top level of your component. +As with ``, this element may only appear the top level of your component and must never be inside a block or element. ```sv `, this element allows you to add listeners to even This element makes it possible to insert elements into `document.head`. During server-side rendering, `head` content is exposed separately to the main `html` content. -As with `` and ``, this element has to appear at the top level of your component and cannot be inside a block or other element. +As with `` and ``, this element may only appear at the top level of your component and must never be inside a block or element. ```sv diff --git a/site/content/docs/03-run-time.md b/site/content/docs/03-run-time.md index 636a98834d..a0d3f4148c 100644 --- a/site/content/docs/03-run-time.md +++ b/site/content/docs/03-run-time.md @@ -148,7 +148,7 @@ setContext(key: any, context: any) --- -Associates an arbitrary `context` object with the current component and the specified `key`. The context is then available to children of the component (including slotted content) with `getContext`. +Associates an arbitrary `context` object with the current component and the specified `key` and returns that object. The context is then available to children of the component (including slotted content) with `getContext`. Like lifecycle functions, this must be called during component initialisation. diff --git a/site/content/docs/04-compile-time.md b/site/content/docs/04-compile-time.md index 1ee41eeb93..35a57ced85 100644 --- a/site/content/docs/04-compile-time.md +++ b/site/content/docs/04-compile-time.md @@ -2,11 +2,7 @@ title: Compile time --- -Typically, you won't interact with the Svelte compiler directly, but will instead integrate it into your build system using a bundler plugin: - -* [rollup-plugin-svelte](https://github.com/sveltejs/rollup-plugin-svelte) for users of [Rollup](https://rollupjs.org) -* [svelte-loader](https://github.com/sveltejs/svelte-loader) for users of [webpack](https://webpack.js.org) -* or one of the [community-maintained plugins](https://sveltesociety.dev/tools) +Typically, you won't interact with the Svelte compiler directly, but will instead integrate it into your build system using a bundler plugin. The bundler plugin that the Svelte team most recommends and invests in is [vite-plugin-svelte](https://github.com/sveltejs/vite-plugin-svelte). The [SvelteKit](https://kit.svelte.dev/) framework provides a setup leveraging `vite-plugin-svelte` to build applications as well as a [tool for packaging Svelte component libraries](https://kit.svelte.dev/docs/packaging). Svelte Society maintains a list of [other bundler plugins](https://sveltesociety.dev/tools/#bundling) for additional tools like Rollup and Webpack. Nonetheless, it's useful to understand how to use the compiler, since bundler plugins generally expose compiler options to you. @@ -77,7 +73,7 @@ The following options can be passed to the compiler. None are required: | `accessors` | `false` | If `true`, getters and setters will be created for the component's props. If `false`, they will only be created for readonly exported values (i.e. those declared with `const`, `class` and `function`). If compiling with `customElement: true` this option defaults to `true`. | `customElement` | `false` | If `true`, tells the compiler to generate a custom element constructor instead of a regular Svelte component. | `tag` | `null` | A `string` that tells Svelte what tag name to register the custom element with. It must be a lowercase alphanumeric string with at least one hyphen, e.g. `"my-element"`. -| `css` | `true` | If `true`, styles will be included in the JavaScript class and injected at runtime. It's recommended that you set this to `false` and use the CSS that is statically generated, as it will result in smaller JavaScript bundles and better performance. +| `css` | `true` | If `true`, styles will be included in the JavaScript class and injected at runtime for the components actually rendered. If `false`, the CSS will be returned in the `css` field of the compilation result. Most Svelte bundler plugins will set this to `false` and use the CSS that is statically generated for better performance, as it will result in smaller JavaScript bundles and the output can be served as cacheable `.css` files. | `cssHash` | See right | A function that takes a `{ hash, css, name, filename }` argument and returns the string that is used as a classname for scoped CSS. It defaults to returning `svelte-${hash(css)}` | `loopGuardTimeout` | 0 | A `number` that tells Svelte to break the loop if it blocks the thread for more than `loopGuardTimeout` ms. This is useful to prevent infinite loops. **Only available when `dev: true`** | `preserveComments` | `false` | If `true`, your HTML comments will be preserved during server-side rendering. By default, they are stripped out. diff --git a/site/content/examples/13-actions/00-actions/App.svelte b/site/content/examples/13-actions/00-actions/App.svelte index bd990a5360..79214ec81f 100644 --- a/site/content/examples/13-actions/00-actions/App.svelte +++ b/site/content/examples/13-actions/00-actions/App.svelte @@ -20,6 +20,9 @@ height: var(--height); left: calc(50% - var(--width) / 2); top: calc(50% - var(--height) / 2); + display: flex; + align-items: center; + padding: 8px; border-radius: 4px; background-color: #ff3e00; color: #fff; diff --git a/site/content/examples/17-special-elements/02-svelte-element/App.svelte b/site/content/examples/17-special-elements/02-svelte-element/App.svelte new file mode 100644 index 0000000000..068f7b3c4f --- /dev/null +++ b/site/content/examples/17-special-elements/02-svelte-element/App.svelte @@ -0,0 +1,12 @@ + + + + +I'm a {selected} tag diff --git a/site/content/examples/17-special-elements/02-svelte-element/meta.json b/site/content/examples/17-special-elements/02-svelte-element/meta.json new file mode 100644 index 0000000000..4ff15b716f --- /dev/null +++ b/site/content/examples/17-special-elements/02-svelte-element/meta.json @@ -0,0 +1,3 @@ +{ + "title": "" +} \ No newline at end of file diff --git a/site/content/examples/17-special-elements/02-svelte-window/App.svelte b/site/content/examples/17-special-elements/03-svelte-window/App.svelte similarity index 100% rename from site/content/examples/17-special-elements/02-svelte-window/App.svelte rename to site/content/examples/17-special-elements/03-svelte-window/App.svelte diff --git a/site/content/examples/17-special-elements/02-svelte-window/meta.json b/site/content/examples/17-special-elements/03-svelte-window/meta.json similarity index 100% rename from site/content/examples/17-special-elements/02-svelte-window/meta.json rename to site/content/examples/17-special-elements/03-svelte-window/meta.json diff --git a/site/content/examples/17-special-elements/03-svelte-window-bindings/App.svelte b/site/content/examples/17-special-elements/04-svelte-window-bindings/App.svelte similarity index 100% rename from site/content/examples/17-special-elements/03-svelte-window-bindings/App.svelte rename to site/content/examples/17-special-elements/04-svelte-window-bindings/App.svelte diff --git a/site/content/examples/17-special-elements/03-svelte-window-bindings/meta.json b/site/content/examples/17-special-elements/04-svelte-window-bindings/meta.json similarity index 100% rename from site/content/examples/17-special-elements/03-svelte-window-bindings/meta.json rename to site/content/examples/17-special-elements/04-svelte-window-bindings/meta.json diff --git a/site/content/examples/17-special-elements/04-svelte-body/App.svelte b/site/content/examples/17-special-elements/05-svelte-body/App.svelte similarity index 100% rename from site/content/examples/17-special-elements/04-svelte-body/App.svelte rename to site/content/examples/17-special-elements/05-svelte-body/App.svelte diff --git a/site/content/examples/17-special-elements/04-svelte-body/meta.json b/site/content/examples/17-special-elements/05-svelte-body/meta.json similarity index 100% rename from site/content/examples/17-special-elements/04-svelte-body/meta.json rename to site/content/examples/17-special-elements/05-svelte-body/meta.json diff --git a/site/content/examples/17-special-elements/05-svelte-head/App.svelte b/site/content/examples/17-special-elements/06-svelte-head/App.svelte similarity index 100% rename from site/content/examples/17-special-elements/05-svelte-head/App.svelte rename to site/content/examples/17-special-elements/06-svelte-head/App.svelte diff --git a/site/content/examples/17-special-elements/05-svelte-head/meta.json b/site/content/examples/17-special-elements/06-svelte-head/meta.json similarity index 100% rename from site/content/examples/17-special-elements/05-svelte-head/meta.json rename to site/content/examples/17-special-elements/06-svelte-head/meta.json diff --git a/site/content/faq/800-how-do-i-test-svelte-apps.md b/site/content/faq/800-how-do-i-test-svelte-apps.md index 5e59d5812d..1481b6ba59 100644 --- a/site/content/faq/800-how-do-i-test-svelte-apps.md +++ b/site/content/faq/800-how-do-i-test-svelte-apps.md @@ -8,4 +8,5 @@ There are a few approaches that people take when testing, but it generally invol Some resources for getting started with unit testing: - [Svelte Testing Library](https://testing-library.com/docs/svelte-testing-library/example/) +- [Example using vitest](https://github.com/vitest-dev/vitest/tree/main/examples/svelte) - [Example using uvu test runner with JSDOM](https://github.com/lukeed/uvu/tree/master/examples/svelte) diff --git a/site/content/tutorial/06-bindings/06-select-bindings/text.md b/site/content/tutorial/06-bindings/06-select-bindings/text.md index b9cf2de6ec..d0104f7f1a 100644 --- a/site/content/tutorial/06-bindings/06-select-bindings/text.md +++ b/site/content/tutorial/06-bindings/06-select-bindings/text.md @@ -10,4 +10,4 @@ We can also use `bind:value` with ` +
+ - + +
{/each} ``` diff --git a/site/content/tutorial/12-actions/01-actions/app-a/App.svelte b/site/content/tutorial/12-actions/01-actions/app-a/App.svelte index 40b4ea2673..0e78f482c5 100644 --- a/site/content/tutorial/12-actions/01-actions/app-a/App.svelte +++ b/site/content/tutorial/12-actions/01-actions/app-a/App.svelte @@ -20,6 +20,9 @@ height: var(--height); left: calc(50% - var(--width) / 2); top: calc(50% - var(--height) / 2); + display: flex; + align-items: center; + padding: 8px; border-radius: 4px; background-color: #ff3e00; color: #fff; diff --git a/site/content/tutorial/12-actions/01-actions/app-b/App.svelte b/site/content/tutorial/12-actions/01-actions/app-b/App.svelte index bd990a5360..79214ec81f 100644 --- a/site/content/tutorial/12-actions/01-actions/app-b/App.svelte +++ b/site/content/tutorial/12-actions/01-actions/app-b/App.svelte @@ -20,6 +20,9 @@ height: var(--height); left: calc(50% - var(--width) / 2); top: calc(50% - var(--height) / 2); + display: flex; + align-items: center; + padding: 8px; border-radius: 4px; background-color: #ff3e00; color: #fff; diff --git a/site/content/tutorial/16-special-elements/03-svelte-element/app-a/App.svelte b/site/content/tutorial/16-special-elements/03-svelte-element/app-a/App.svelte new file mode 100644 index 0000000000..0718efd949 --- /dev/null +++ b/site/content/tutorial/16-special-elements/03-svelte-element/app-a/App.svelte @@ -0,0 +1,18 @@ + + + + +{#if selected === 'h1'} +

I'm a h1 tag

+{:else if selected === 'h3'} +

I'm a h3 tag

+{:else if selected === 'p'} +

I'm a p tag

+{/if} diff --git a/site/content/tutorial/16-special-elements/03-svelte-element/app-b/App.svelte b/site/content/tutorial/16-special-elements/03-svelte-element/app-b/App.svelte new file mode 100644 index 0000000000..068f7b3c4f --- /dev/null +++ b/site/content/tutorial/16-special-elements/03-svelte-element/app-b/App.svelte @@ -0,0 +1,12 @@ + + + + +I'm a {selected} tag diff --git a/site/content/tutorial/16-special-elements/03-svelte-element/text.md b/site/content/tutorial/16-special-elements/03-svelte-element/text.md new file mode 100644 index 0000000000..ace344db42 --- /dev/null +++ b/site/content/tutorial/16-special-elements/03-svelte-element/text.md @@ -0,0 +1,23 @@ +--- +title: +--- + +Sometimes we don't know in advance what kind of DOM element to render. `` comes in handy here. Instead of a sequence of `if` blocks... + +```html +{#if selected === 'h1'} +

I'm a h1 tag

+{:else if selected === 'h3'} +

I'm a h3 tag

+{:else if selected === 'p'} +

I'm a p tag

+{/if} +``` + +...we can have a single dynamic component: + +```html +I'm a {selected} tag +``` + +The `this` value can be any string, or a falsy value — if it's falsy, no element is rendered. \ No newline at end of file diff --git a/site/content/tutorial/16-special-elements/03-svelte-window/app-a/App.svelte b/site/content/tutorial/16-special-elements/04-svelte-window/app-a/App.svelte similarity index 100% rename from site/content/tutorial/16-special-elements/03-svelte-window/app-a/App.svelte rename to site/content/tutorial/16-special-elements/04-svelte-window/app-a/App.svelte diff --git a/site/content/tutorial/16-special-elements/03-svelte-window/app-b/App.svelte b/site/content/tutorial/16-special-elements/04-svelte-window/app-b/App.svelte similarity index 100% rename from site/content/tutorial/16-special-elements/03-svelte-window/app-b/App.svelte rename to site/content/tutorial/16-special-elements/04-svelte-window/app-b/App.svelte diff --git a/site/content/tutorial/16-special-elements/03-svelte-window/text.md b/site/content/tutorial/16-special-elements/04-svelte-window/text.md similarity index 100% rename from site/content/tutorial/16-special-elements/03-svelte-window/text.md rename to site/content/tutorial/16-special-elements/04-svelte-window/text.md diff --git a/site/content/tutorial/16-special-elements/04-svelte-window-bindings/app-a/App.svelte b/site/content/tutorial/16-special-elements/05-svelte-window-bindings/app-a/App.svelte similarity index 100% rename from site/content/tutorial/16-special-elements/04-svelte-window-bindings/app-a/App.svelte rename to site/content/tutorial/16-special-elements/05-svelte-window-bindings/app-a/App.svelte diff --git a/site/content/tutorial/16-special-elements/04-svelte-window-bindings/app-b/App.svelte b/site/content/tutorial/16-special-elements/05-svelte-window-bindings/app-b/App.svelte similarity index 100% rename from site/content/tutorial/16-special-elements/04-svelte-window-bindings/app-b/App.svelte rename to site/content/tutorial/16-special-elements/05-svelte-window-bindings/app-b/App.svelte diff --git a/site/content/tutorial/16-special-elements/04-svelte-window-bindings/text.md b/site/content/tutorial/16-special-elements/05-svelte-window-bindings/text.md similarity index 100% rename from site/content/tutorial/16-special-elements/04-svelte-window-bindings/text.md rename to site/content/tutorial/16-special-elements/05-svelte-window-bindings/text.md diff --git a/site/content/tutorial/16-special-elements/05-svelte-body/app-a/App.svelte b/site/content/tutorial/16-special-elements/06-svelte-body/app-a/App.svelte similarity index 100% rename from site/content/tutorial/16-special-elements/05-svelte-body/app-a/App.svelte rename to site/content/tutorial/16-special-elements/06-svelte-body/app-a/App.svelte diff --git a/site/content/tutorial/16-special-elements/05-svelte-body/app-b/App.svelte b/site/content/tutorial/16-special-elements/06-svelte-body/app-b/App.svelte similarity index 100% rename from site/content/tutorial/16-special-elements/05-svelte-body/app-b/App.svelte rename to site/content/tutorial/16-special-elements/06-svelte-body/app-b/App.svelte diff --git a/site/content/tutorial/16-special-elements/05-svelte-body/text.md b/site/content/tutorial/16-special-elements/06-svelte-body/text.md similarity index 100% rename from site/content/tutorial/16-special-elements/05-svelte-body/text.md rename to site/content/tutorial/16-special-elements/06-svelte-body/text.md diff --git a/site/content/tutorial/16-special-elements/06-svelte-head/app-a/App.svelte b/site/content/tutorial/16-special-elements/07-svelte-head/app-a/App.svelte similarity index 100% rename from site/content/tutorial/16-special-elements/06-svelte-head/app-a/App.svelte rename to site/content/tutorial/16-special-elements/07-svelte-head/app-a/App.svelte diff --git a/site/content/tutorial/16-special-elements/06-svelte-head/app-b/App.svelte b/site/content/tutorial/16-special-elements/07-svelte-head/app-b/App.svelte similarity index 100% rename from site/content/tutorial/16-special-elements/06-svelte-head/app-b/App.svelte rename to site/content/tutorial/16-special-elements/07-svelte-head/app-b/App.svelte diff --git a/site/content/tutorial/16-special-elements/06-svelte-head/text.md b/site/content/tutorial/16-special-elements/07-svelte-head/text.md similarity index 100% rename from site/content/tutorial/16-special-elements/06-svelte-head/text.md rename to site/content/tutorial/16-special-elements/07-svelte-head/text.md diff --git a/site/content/tutorial/16-special-elements/07-svelte-options/app-a/App.svelte b/site/content/tutorial/16-special-elements/08-svelte-options/app-a/App.svelte similarity index 100% rename from site/content/tutorial/16-special-elements/07-svelte-options/app-a/App.svelte rename to site/content/tutorial/16-special-elements/08-svelte-options/app-a/App.svelte diff --git a/site/content/tutorial/16-special-elements/07-svelte-options/app-a/Todo.svelte b/site/content/tutorial/16-special-elements/08-svelte-options/app-a/Todo.svelte similarity index 100% rename from site/content/tutorial/16-special-elements/07-svelte-options/app-a/Todo.svelte rename to site/content/tutorial/16-special-elements/08-svelte-options/app-a/Todo.svelte diff --git a/site/content/tutorial/16-special-elements/07-svelte-options/app-a/flash.js b/site/content/tutorial/16-special-elements/08-svelte-options/app-a/flash.js similarity index 100% rename from site/content/tutorial/16-special-elements/07-svelte-options/app-a/flash.js rename to site/content/tutorial/16-special-elements/08-svelte-options/app-a/flash.js diff --git a/site/content/tutorial/16-special-elements/07-svelte-options/app-b/App.svelte b/site/content/tutorial/16-special-elements/08-svelte-options/app-b/App.svelte similarity index 100% rename from site/content/tutorial/16-special-elements/07-svelte-options/app-b/App.svelte rename to site/content/tutorial/16-special-elements/08-svelte-options/app-b/App.svelte diff --git a/site/content/tutorial/16-special-elements/07-svelte-options/app-b/Todo.svelte b/site/content/tutorial/16-special-elements/08-svelte-options/app-b/Todo.svelte similarity index 100% rename from site/content/tutorial/16-special-elements/07-svelte-options/app-b/Todo.svelte rename to site/content/tutorial/16-special-elements/08-svelte-options/app-b/Todo.svelte diff --git a/site/content/tutorial/16-special-elements/07-svelte-options/app-b/flash.js b/site/content/tutorial/16-special-elements/08-svelte-options/app-b/flash.js similarity index 100% rename from site/content/tutorial/16-special-elements/07-svelte-options/app-b/flash.js rename to site/content/tutorial/16-special-elements/08-svelte-options/app-b/flash.js diff --git a/site/content/tutorial/16-special-elements/07-svelte-options/text.md b/site/content/tutorial/16-special-elements/08-svelte-options/text.md similarity index 100% rename from site/content/tutorial/16-special-elements/07-svelte-options/text.md rename to site/content/tutorial/16-special-elements/08-svelte-options/text.md diff --git a/site/content/tutorial/16-special-elements/08-svelte-fragment/app-a/App.svelte b/site/content/tutorial/16-special-elements/09-svelte-fragment/app-a/App.svelte similarity index 100% rename from site/content/tutorial/16-special-elements/08-svelte-fragment/app-a/App.svelte rename to site/content/tutorial/16-special-elements/09-svelte-fragment/app-a/App.svelte diff --git a/site/content/tutorial/16-special-elements/08-svelte-fragment/app-a/Box.svelte b/site/content/tutorial/16-special-elements/09-svelte-fragment/app-a/Box.svelte similarity index 100% rename from site/content/tutorial/16-special-elements/08-svelte-fragment/app-a/Box.svelte rename to site/content/tutorial/16-special-elements/09-svelte-fragment/app-a/Box.svelte diff --git a/site/content/tutorial/16-special-elements/08-svelte-fragment/app-b/App.svelte b/site/content/tutorial/16-special-elements/09-svelte-fragment/app-b/App.svelte similarity index 100% rename from site/content/tutorial/16-special-elements/08-svelte-fragment/app-b/App.svelte rename to site/content/tutorial/16-special-elements/09-svelte-fragment/app-b/App.svelte diff --git a/site/content/tutorial/16-special-elements/08-svelte-fragment/app-b/Box.svelte b/site/content/tutorial/16-special-elements/09-svelte-fragment/app-b/Box.svelte similarity index 100% rename from site/content/tutorial/16-special-elements/08-svelte-fragment/app-b/Box.svelte rename to site/content/tutorial/16-special-elements/09-svelte-fragment/app-b/Box.svelte diff --git a/site/content/tutorial/16-special-elements/08-svelte-fragment/text.md b/site/content/tutorial/16-special-elements/09-svelte-fragment/text.md similarity index 100% rename from site/content/tutorial/16-special-elements/08-svelte-fragment/text.md rename to site/content/tutorial/16-special-elements/09-svelte-fragment/text.md diff --git a/site/content/tutorial/17-module-context/02-module-exports/text.md b/site/content/tutorial/17-module-context/02-module-exports/text.md index d5b4b96621..ec8364da22 100644 --- a/site/content/tutorial/17-module-context/02-module-exports/text.md +++ b/site/content/tutorial/17-module-context/02-module-exports/text.md @@ -16,7 +16,7 @@ Anything exported from a `context="module"` script block becomes an export from ``` -...we can then import it from `App.svelte`... +...we can then import it in `App.svelte`... ```html + +

{foo}

+{#each nums as num, index} + {@const bar = nums.map((num) => { + const func = (foos, num) => { + return [...foos.map((foo) => foo), num]; + } + return func(foos[index].nums, num); + })} +

bar: {bar}, num: {num}

+{/each} diff --git a/test/runtime/samples/const-tag-each-duplicated-variable1/_config.js b/test/runtime/samples/const-tag-each-duplicated-variable1/_config.js new file mode 100644 index 0000000000..1f3e5856f2 --- /dev/null +++ b/test/runtime/samples/const-tag-each-duplicated-variable1/_config.js @@ -0,0 +1,29 @@ +export default { + html: ` +

bar: 1,2,3,0,2,4,-100,0,100, num: 1

+

bar: 1,2,3,0,2,4,-100,0,100, num: 2

+

bar: 1,2,3,0,2,4,-100,0,100, num: 3

+ `, + async test({ component, target, assert }) { + assert.htmlEqual( + target.innerHTML, + ` +

bar: 1,2,3,0,2,4,-100,0,100, num: 1

+

bar: 1,2,3,0,2,4,-100,0,100, num: 2

+

bar: 1,2,3,0,2,4,-100,0,100, num: 3

+ ` + ); + + component.nums = [1, 2, 3, 4]; + + assert.htmlEqual( + target.innerHTML, + ` +

bar: 1,2,3,0,2,4,-100,0,100, num: 1

+

bar: 1,2,3,0,2,4,-100,0,100, num: 2

+

bar: 1,2,3,0,2,4,-100,0,100, num: 3

+

bar: 1,2,3,0,2,4,-100,0,100, num: 4

+ ` + ); + } +}; diff --git a/test/runtime/samples/const-tag-each-duplicated-variable1/main.svelte b/test/runtime/samples/const-tag-each-duplicated-variable1/main.svelte new file mode 100644 index 0000000000..00c53dd4ff --- /dev/null +++ b/test/runtime/samples/const-tag-each-duplicated-variable1/main.svelte @@ -0,0 +1,19 @@ + + +{#each nums as num} + {@const bar = foos.map((foos) => foos.nums)} +

bar: {bar}, num: {num}

+{/each} diff --git a/test/runtime/samples/const-tag-each-duplicated-variable2/_config.js b/test/runtime/samples/const-tag-each-duplicated-variable2/_config.js new file mode 100644 index 0000000000..16f48218f1 --- /dev/null +++ b/test/runtime/samples/const-tag-each-duplicated-variable2/_config.js @@ -0,0 +1,32 @@ +export default { + html: ` +

foo: dummy-foo, num: dummy-num

+

bar: 1,2,3,2,, num: 1

+

bar: 1,2,3,2,, num: 2

+

bar: 1,2,3,2,, num: 3

+ `, + async test({ component, target, assert }) { + assert.htmlEqual( + target.innerHTML, + ` +

foo: dummy-foo, num: dummy-num

+

bar: 1,2,3,2,, num: 1

+

bar: 1,2,3,2,, num: 2

+

bar: 1,2,3,2,, num: 3

+ ` + ); + + component.nums = [1, 2, 3, 4]; + + assert.htmlEqual( + target.innerHTML, + ` +

foo: dummy-foo, num: dummy-num

+

bar: 1,2,3,2,4,, num: 1

+

bar: 1,2,3,2,4,, num: 2

+

bar: 1,2,3,2,4,, num: 3

+

bar: 1,2,3,2,4,, num: 4

+ ` + ); + } +}; diff --git a/test/runtime/samples/const-tag-each-duplicated-variable2/main.svelte b/test/runtime/samples/const-tag-each-duplicated-variable2/main.svelte new file mode 100644 index 0000000000..1f7afd92fd --- /dev/null +++ b/test/runtime/samples/const-tag-each-duplicated-variable2/main.svelte @@ -0,0 +1,33 @@ + + +

foo: {foo}, num: {num}

+{#each nums as num} + {@const bar = foos.map((foo) => + foo.nums.filter((num) => { + if (Object.keys($$slots).length) { + return false; + } else if (Object.keys(foo).length) { + return nums.includes(num) || default_nums.includes(num); + } else { + return false; + } + }) || num + )} +

bar: {bar}, num: {num}

+{/each} diff --git a/test/runtime/samples/const-tag-each-duplicated-variable3/_config.js b/test/runtime/samples/const-tag-each-duplicated-variable3/_config.js new file mode 100644 index 0000000000..cde4226a25 --- /dev/null +++ b/test/runtime/samples/const-tag-each-duplicated-variable3/_config.js @@ -0,0 +1,29 @@ +export default { + html: ` +

0

+

bar: 1,2,3,1,1,2,3,2, num: 1

+

bar: 0,2,4,1,0,2,4,2, num: 2

+ `, + async test({ component, target, assert }) { + assert.htmlEqual( + target.innerHTML, + ` +

0

+

bar: 1,2,3,1,1,2,3,2, num: 1

+

bar: 0,2,4,1,0,2,4,2, num: 2

+ ` + ); + + component.nums = [1, 2, 3]; + + assert.htmlEqual( + target.innerHTML, + ` +

0

+

bar: 1,2,3,1,1,2,3,2,1,2,3,3, num: 1

+

bar: 0,2,4,1,0,2,4,2,0,2,4,3, num: 2

+

bar: -100,0,100,1,-100,0,100,2,-100,0,100,3, num: 3

+ ` + ); + } +}; diff --git a/test/runtime/samples/const-tag-each-duplicated-variable3/main.svelte b/test/runtime/samples/const-tag-each-duplicated-variable3/main.svelte new file mode 100644 index 0000000000..f559627d23 --- /dev/null +++ b/test/runtime/samples/const-tag-each-duplicated-variable3/main.svelte @@ -0,0 +1,25 @@ + + +

{foo}

+{#each nums as num, index} + {@const bar = nums.map((num) => { + return (function (foos, num) { + return [...foos.map((foo) => foo), num]; + })(foos[index].nums, num); + })} +

bar: {bar}, num: {num}

+{/each} diff --git a/test/runtime/samples/const-tag-each-function/_config.js b/test/runtime/samples/const-tag-each-function/_config.js new file mode 100644 index 0000000000..cde4226a25 --- /dev/null +++ b/test/runtime/samples/const-tag-each-function/_config.js @@ -0,0 +1,29 @@ +export default { + html: ` +

0

+

bar: 1,2,3,1,1,2,3,2, num: 1

+

bar: 0,2,4,1,0,2,4,2, num: 2

+ `, + async test({ component, target, assert }) { + assert.htmlEqual( + target.innerHTML, + ` +

0

+

bar: 1,2,3,1,1,2,3,2, num: 1

+

bar: 0,2,4,1,0,2,4,2, num: 2

+ ` + ); + + component.nums = [1, 2, 3]; + + assert.htmlEqual( + target.innerHTML, + ` +

0

+

bar: 1,2,3,1,1,2,3,2,1,2,3,3, num: 1

+

bar: 0,2,4,1,0,2,4,2,0,2,4,3, num: 2

+

bar: -100,0,100,1,-100,0,100,2,-100,0,100,3, num: 3

+ ` + ); + } +}; diff --git a/test/runtime/samples/const-tag-each-function/main.svelte b/test/runtime/samples/const-tag-each-function/main.svelte new file mode 100644 index 0000000000..2e027c6620 --- /dev/null +++ b/test/runtime/samples/const-tag-each-function/main.svelte @@ -0,0 +1,26 @@ + + +

{foo}

+{#each nums as num, index} + {@const bar = nums.map((num) => { + function func(foos, num) { + return [...foos.map((foo) => foo), num]; + } + return func(foos[index].nums, num); + })} +

bar: {bar}, num: {num}

+{/each} diff --git a/test/runtime/samples/const-tag-shadow-2/_config.js b/test/runtime/samples/const-tag-shadow-2/_config.js new file mode 100644 index 0000000000..9ad4aed48c --- /dev/null +++ b/test/runtime/samples/const-tag-shadow-2/_config.js @@ -0,0 +1,37 @@ +export default { + html: ` +

1

+

3,6,9

+

2

+

3,6,9

+

3

+

3,6,9

+ `, + test({ component, target, assert }) { + component.baz = 5; + assert.htmlEqual( + target.innerHTML, + ` +

1

+

5,10,15

+

2

+

5,10,15

+

3

+

5,10,15

+ ` + ); + + component.array = [3, 4, 5]; + assert.htmlEqual( + target.innerHTML, + ` +

3

+

15,20,25

+

4

+

15,20,25

+

5

+

15,20,25

+ ` + ); + } +}; diff --git a/test/runtime/samples/const-tag-shadow-2/main.svelte b/test/runtime/samples/const-tag-shadow-2/main.svelte new file mode 100644 index 0000000000..c3bcb2f605 --- /dev/null +++ b/test/runtime/samples/const-tag-shadow-2/main.svelte @@ -0,0 +1,15 @@ + + +{#each array as item} +

{foo(item)}

+ {@const bar = array.map((item) => { + const bar = baz; + const foo = (item) => item * bar; + return foo(item); + })} +

{bar}

+{/each} diff --git a/test/runtime/samples/context-setcontext-return/_config.js b/test/runtime/samples/context-setcontext-return/_config.js new file mode 100644 index 0000000000..28a78f1359 --- /dev/null +++ b/test/runtime/samples/context-setcontext-return/_config.js @@ -0,0 +1,5 @@ +export default { + html: ` +
true
+ ` +}; diff --git a/test/runtime/samples/context-setcontext-return/main.svelte b/test/runtime/samples/context-setcontext-return/main.svelte new file mode 100644 index 0000000000..87153ee846 --- /dev/null +++ b/test/runtime/samples/context-setcontext-return/main.svelte @@ -0,0 +1,7 @@ + + +
{a === b}
diff --git a/test/runtime/samples/dynamic-element-action-update/_config.js b/test/runtime/samples/dynamic-element-action-update/_config.js new file mode 100644 index 0000000000..ebbe6f05a9 --- /dev/null +++ b/test/runtime/samples/dynamic-element-action-update/_config.js @@ -0,0 +1,45 @@ +let logs = []; + +export default { + html: ` +

tag is h1.

+ `, + props: { + logs + }, + after_test() { + logs = []; + }, + + async test({ assert, component, target }) { + assert.equal(component.tag, 'h1'); + + assert.deepEqual(logs, ['create: h1,opt1']); + component.opt = 'opt2'; + + assert.equal(component.tag, 'h1'); + assert.deepEqual(logs, ['create: h1,opt1', 'update: h1,opt2']); + + component.tag = 'h2'; + + assert.equal(component.tag, 'h2'); + assert.deepEqual(logs, [ + 'create: h1,opt1', + 'update: h1,opt2', + 'destroy', + 'create: h2,opt2' + ]); + assert.htmlEqual(target.innerHTML, '

tag is h2.

'); + + component.tag = false; + assert.deepEqual(logs, [ + 'create: h1,opt1', + 'update: h1,opt2', + 'destroy', + 'create: h2,opt2', + 'destroy' + ]); + + assert.htmlEqual(target.innerHTML, ''); + } +}; diff --git a/test/runtime/samples/dynamic-element-action-update/main.svelte b/test/runtime/samples/dynamic-element-action-update/main.svelte new file mode 100644 index 0000000000..da269e115e --- /dev/null +++ b/test/runtime/samples/dynamic-element-action-update/main.svelte @@ -0,0 +1,14 @@ + + +tag is {tag}. diff --git a/test/runtime/samples/dynamic-element-animation-2/_config.js b/test/runtime/samples/dynamic-element-animation-2/_config.js new file mode 100644 index 0000000000..27b28bb349 --- /dev/null +++ b/test/runtime/samples/dynamic-element-animation-2/_config.js @@ -0,0 +1,105 @@ +let originalDivGetBoundingClientRect; +let originalSpanGetBoundingClientRect; +let originalParagraphGetBoundingClientRect; + +export default { + skip_if_ssr: true, + props: { + things: [ + { id: 1, name: 'a' }, + { id: 2, name: 'b' }, + { id: 3, name: 'c' }, + { id: 4, name: 'd' }, + { id: 5, name: 'e' } + ], + tag: 'div' + }, + + html: ` +
a
+
b
+
c
+
d
+
e
+ `, + + before_test() { + originalDivGetBoundingClientRect = + window.HTMLDivElement.prototype.getBoundingClientRect; + originalSpanGetBoundingClientRect = + window.HTMLSpanElement.prototype.getBoundingClientRect; + originalParagraphGetBoundingClientRect = + window.HTMLParagraphElement.prototype.getBoundingClientRect; + + window.HTMLDivElement.prototype.getBoundingClientRect = + fakeGetBoundingClientRect; + window.HTMLSpanElement.prototype.getBoundingClientRect = + fakeGetBoundingClientRect; + window.HTMLParagraphElement.prototype.getBoundingClientRect = + fakeGetBoundingClientRect; + + function fakeGetBoundingClientRect() { + const index = [...this.parentNode.children].indexOf(this); + const top = index * 30; + + return { + left: 0, + right: 100, + top, + bottom: top + 20 + }; + } + }, + after_test() { + window.HTMLDivElement.prototype.getBoundingClientRect = + originalDivGetBoundingClientRect; + window.HTMLSpanElement.prototype.getBoundingClientRect = + originalSpanGetBoundingClientRect; + window.HTMLParagraphElement.prototype.getBoundingClientRect = + originalParagraphGetBoundingClientRect; + }, + + async test({ assert, component, target, raf }) { + // switch tag and things at the same time + await component.update('p', [ + { id: 5, name: 'e' }, + { id: 2, name: 'b' }, + { id: 3, name: 'c' }, + { id: 4, name: 'd' }, + { id: 1, name: 'a' } + ]); + + const ps = document.querySelectorAll('p'); + assert.equal(ps[0].dy, 120); + assert.equal(ps[4].dy, -120); + + raf.tick(50); + assert.equal(ps[0].dy, 60); + assert.equal(ps[4].dy, -60); + + raf.tick(100); + assert.equal(ps[0].dy, 0); + assert.equal(ps[4].dy, 0); + + await component.update('span', [ + { id: 1, name: 'a' }, + { id: 2, name: 'b' }, + { id: 3, name: 'c' }, + { id: 4, name: 'd' }, + { id: 5, name: 'e' } + ]); + + const spans = document.querySelectorAll('span'); + + assert.equal(spans[0].dy, 120); + assert.equal(spans[4].dy, -120); + + raf.tick(150); + assert.equal(spans[0].dy, 60); + assert.equal(spans[4].dy, -60); + + raf.tick(200); + assert.equal(spans[0].dy, 0); + assert.equal(spans[4].dy, 0); + } +}; diff --git a/test/runtime/samples/dynamic-element-animation-2/main.svelte b/test/runtime/samples/dynamic-element-animation-2/main.svelte new file mode 100644 index 0000000000..f655a40af9 --- /dev/null +++ b/test/runtime/samples/dynamic-element-animation-2/main.svelte @@ -0,0 +1,26 @@ + + +{#each things as thing (thing.id)} + {thing.name} +{/each} \ No newline at end of file diff --git a/test/runtime/samples/dynamic-element-animation/_config.js b/test/runtime/samples/dynamic-element-animation/_config.js new file mode 100644 index 0000000000..e3c57a868e --- /dev/null +++ b/test/runtime/samples/dynamic-element-animation/_config.js @@ -0,0 +1,62 @@ +export default { + props: { + things: [ + { id: 1, name: 'a' }, + { id: 2, name: 'b' }, + { id: 3, name: 'c' }, + { id: 4, name: 'd' }, + { id: 5, name: 'e' } + ], + tag: 'div' + }, + + html: ` +
a
+
b
+
c
+
d
+
e
+ `, + + test({ assert, component, target, raf }) { + component.tag = 'p'; + assert.equal(target.querySelectorAll('p').length, 5); + + component.tag = 'div'; + let divs = target.querySelectorAll('div'); + divs.forEach(div => { + div.getBoundingClientRect = function() { + const index = [...this.parentNode.children].indexOf(this); + const top = index * 30; + + return { + left: 0, + right: 100, + top, + bottom: top + 20 + }; + }; + }); + + component.things = [ + { id: 5, name: 'e' }, + { id: 2, name: 'b' }, + { id: 3, name: 'c' }, + { id: 4, name: 'd' }, + { id: 1, name: 'a' } + ]; + + divs = target.querySelectorAll('div'); + assert.ok(~divs[0].style.animation.indexOf('__svelte')); + assert.equal(divs[1].style.animation, ''); + assert.equal(divs[2].style.animation, ''); + assert.equal(divs[3].style.animation, ''); + assert.ok(~divs[4].style.animation.indexOf('__svelte')); + + raf.tick(100); + assert.deepEqual([ + divs[0].style.animation, + divs[4].style.animation + ], ['', '']); + } +}; diff --git a/test/runtime/samples/dynamic-element-animation/main.svelte b/test/runtime/samples/dynamic-element-animation/main.svelte new file mode 100644 index 0000000000..596d12c77a --- /dev/null +++ b/test/runtime/samples/dynamic-element-animation/main.svelte @@ -0,0 +1,18 @@ + + +{#each things as thing (thing.id)} + {thing.name} +{/each} \ No newline at end of file diff --git a/test/runtime/samples/dynamic-element-attribute/_config.js b/test/runtime/samples/dynamic-element-attribute/_config.js new file mode 100644 index 0000000000..6e7c340437 --- /dev/null +++ b/test/runtime/samples/dynamic-element-attribute/_config.js @@ -0,0 +1,17 @@ +export default { + props: { + tag: 'div' + }, + html: '
Foo
', + + test({ assert, component, target }) { + component.tag = 'h1'; + + assert.htmlEqual( + target.innerHTML, + ` +

Foo

+ ` + ); + } +}; diff --git a/test/runtime/samples/dynamic-element-attribute/main.svelte b/test/runtime/samples/dynamic-element-attribute/main.svelte new file mode 100644 index 0000000000..2498e06de9 --- /dev/null +++ b/test/runtime/samples/dynamic-element-attribute/main.svelte @@ -0,0 +1,5 @@ + + +Foo diff --git a/test/runtime/samples/dynamic-element-binding-invalid/_config.js b/test/runtime/samples/dynamic-element-binding-invalid/_config.js new file mode 100644 index 0000000000..14c6d775dc --- /dev/null +++ b/test/runtime/samples/dynamic-element-binding-invalid/_config.js @@ -0,0 +1,3 @@ +export default { + error: "'value' is not a valid binding on elements" +}; diff --git a/test/runtime/samples/dynamic-element-binding-invalid/main.svelte b/test/runtime/samples/dynamic-element-binding-invalid/main.svelte new file mode 100644 index 0000000000..45f8f96061 --- /dev/null +++ b/test/runtime/samples/dynamic-element-binding-invalid/main.svelte @@ -0,0 +1,6 @@ + + + diff --git a/test/runtime/samples/dynamic-element-binding-this/_config.js b/test/runtime/samples/dynamic-element-binding-this/_config.js new file mode 100644 index 0000000000..e0722c9375 --- /dev/null +++ b/test/runtime/samples/dynamic-element-binding-this/_config.js @@ -0,0 +1,8 @@ +export default { + html: '
', + + test({ assert, component, target }) { + const div = target.querySelector('div'); + assert.equal(div, component.foo); + } +}; diff --git a/test/runtime/samples/dynamic-element-binding-this/main.svelte b/test/runtime/samples/dynamic-element-binding-this/main.svelte new file mode 100644 index 0000000000..75e8b02ce1 --- /dev/null +++ b/test/runtime/samples/dynamic-element-binding-this/main.svelte @@ -0,0 +1,6 @@ + + + diff --git a/test/runtime/samples/dynamic-element-change-tag/_config.js b/test/runtime/samples/dynamic-element-change-tag/_config.js new file mode 100644 index 0000000000..9e4bf6fd32 --- /dev/null +++ b/test/runtime/samples/dynamic-element-change-tag/_config.js @@ -0,0 +1,17 @@ +export default { + props: { + tag: 'div' + }, + html: '
Foo
', + + test({ assert, component, target }) { + component.tag = 'h1'; + + assert.htmlEqual( + target.innerHTML, + ` +

Foo

+ ` + ); + } +}; diff --git a/test/runtime/samples/dynamic-element-change-tag/main.svelte b/test/runtime/samples/dynamic-element-change-tag/main.svelte new file mode 100644 index 0000000000..a9c4d5c00c --- /dev/null +++ b/test/runtime/samples/dynamic-element-change-tag/main.svelte @@ -0,0 +1,5 @@ + + +Foo \ No newline at end of file diff --git a/test/runtime/samples/dynamic-element-empty-tag/_config.js b/test/runtime/samples/dynamic-element-empty-tag/_config.js new file mode 100644 index 0000000000..22dc25b41e --- /dev/null +++ b/test/runtime/samples/dynamic-element-empty-tag/_config.js @@ -0,0 +1,3 @@ +export default { + html: '' +}; diff --git a/test/runtime/samples/dynamic-element-empty-tag/main.svelte b/test/runtime/samples/dynamic-element-empty-tag/main.svelte new file mode 100644 index 0000000000..e3889ce0f5 --- /dev/null +++ b/test/runtime/samples/dynamic-element-empty-tag/main.svelte @@ -0,0 +1,5 @@ + + +Foo diff --git a/test/runtime/samples/dynamic-element-event-handler1/_config.js b/test/runtime/samples/dynamic-element-event-handler1/_config.js new file mode 100644 index 0000000000..03b8f7879d --- /dev/null +++ b/test/runtime/samples/dynamic-element-event-handler1/_config.js @@ -0,0 +1,21 @@ +let clicked = false; +function handler() { + clicked = true; +} + +export default { + props: { + handler + }, + html: '', + + test({ assert, target }) { + assert.equal(clicked, false); + + const button = target.querySelector('button'); + const click = new window.MouseEvent('click'); + button.dispatchEvent(click); + + assert.equal(clicked, true); + } +}; diff --git a/test/runtime/samples/dynamic-element-event-handler1/main.svelte b/test/runtime/samples/dynamic-element-event-handler1/main.svelte new file mode 100644 index 0000000000..7a7fef9c22 --- /dev/null +++ b/test/runtime/samples/dynamic-element-event-handler1/main.svelte @@ -0,0 +1,6 @@ + + +Foo \ No newline at end of file diff --git a/test/runtime/samples/dynamic-element-event-handler2/_config.js b/test/runtime/samples/dynamic-element-event-handler2/_config.js new file mode 100644 index 0000000000..22cbe735a7 --- /dev/null +++ b/test/runtime/samples/dynamic-element-event-handler2/_config.js @@ -0,0 +1,23 @@ +let clicked = false; +function handler() { + clicked = true; +} + +export default { + props: { + tag: 'div', + handler + }, + html: '
Foo
', + + test({ assert, component, target }) { + assert.equal(clicked, false); + + component.tag = 'button'; + const button = target.querySelector('button'); + const click = new window.MouseEvent('click'); + button.dispatchEvent(click); + + assert.equal(clicked, true); + } +}; diff --git a/test/runtime/samples/dynamic-element-event-handler2/main.svelte b/test/runtime/samples/dynamic-element-event-handler2/main.svelte new file mode 100644 index 0000000000..f2534c1f62 --- /dev/null +++ b/test/runtime/samples/dynamic-element-event-handler2/main.svelte @@ -0,0 +1,6 @@ + + +Foo diff --git a/test/runtime/samples/dynamic-element-expression/_config.js b/test/runtime/samples/dynamic-element-expression/_config.js new file mode 100644 index 0000000000..acad91c901 --- /dev/null +++ b/test/runtime/samples/dynamic-element-expression/_config.js @@ -0,0 +1,3 @@ +export default { + html: '
Foo
' +}; diff --git a/test/runtime/samples/dynamic-element-expression/main.svelte b/test/runtime/samples/dynamic-element-expression/main.svelte new file mode 100644 index 0000000000..7ec11e4ef6 --- /dev/null +++ b/test/runtime/samples/dynamic-element-expression/main.svelte @@ -0,0 +1 @@ +Foo \ No newline at end of file diff --git a/test/runtime/samples/dynamic-element-invalid-this/_config.js b/test/runtime/samples/dynamic-element-invalid-this/_config.js new file mode 100644 index 0000000000..3aaa554991 --- /dev/null +++ b/test/runtime/samples/dynamic-element-invalid-this/_config.js @@ -0,0 +1,9 @@ +export default { + compileOptions: { + dev: true + }, + props: { + tag: 123 + }, + error: ' expects "this" attribute to be a string.' +}; diff --git a/test/runtime/samples/dynamic-element-invalid-this/main.svelte b/test/runtime/samples/dynamic-element-invalid-this/main.svelte new file mode 100644 index 0000000000..bcc2c293bb --- /dev/null +++ b/test/runtime/samples/dynamic-element-invalid-this/main.svelte @@ -0,0 +1,5 @@ + + + diff --git a/test/runtime/samples/dynamic-element-null-tag/_config.js b/test/runtime/samples/dynamic-element-null-tag/_config.js new file mode 100644 index 0000000000..22dc25b41e --- /dev/null +++ b/test/runtime/samples/dynamic-element-null-tag/_config.js @@ -0,0 +1,3 @@ +export default { + html: '' +}; diff --git a/test/runtime/samples/dynamic-element-null-tag/main.svelte b/test/runtime/samples/dynamic-element-null-tag/main.svelte new file mode 100644 index 0000000000..58dc96ff2a --- /dev/null +++ b/test/runtime/samples/dynamic-element-null-tag/main.svelte @@ -0,0 +1,5 @@ + + +Foo diff --git a/test/runtime/samples/dynamic-element-pass-props/_config.js b/test/runtime/samples/dynamic-element-pass-props/_config.js new file mode 100644 index 0000000000..35f8b7abdf --- /dev/null +++ b/test/runtime/samples/dynamic-element-pass-props/_config.js @@ -0,0 +1,16 @@ +let clicked = false; + +export default { + props: { + tag: 'div', + onClick: () => clicked = true + }, + html: '
Foo
', + + async test({ assert, target, window }) { + const div = target.querySelector('div'); + await div.dispatchEvent(new window.MouseEvent('click')); + + assert.equal(clicked, true); + } +}; diff --git a/test/runtime/samples/dynamic-element-pass-props/main.svelte b/test/runtime/samples/dynamic-element-pass-props/main.svelte new file mode 100644 index 0000000000..6a54a93f27 --- /dev/null +++ b/test/runtime/samples/dynamic-element-pass-props/main.svelte @@ -0,0 +1,6 @@ + + +Foo \ No newline at end of file diff --git a/test/runtime/samples/dynamic-element-slot/Foo.svelte b/test/runtime/samples/dynamic-element-slot/Foo.svelte new file mode 100644 index 0000000000..51dda4b7e3 --- /dev/null +++ b/test/runtime/samples/dynamic-element-slot/Foo.svelte @@ -0,0 +1,7 @@ +

Foo

+
+ +
+
+ +
diff --git a/test/runtime/samples/dynamic-element-slot/_config.js b/test/runtime/samples/dynamic-element-slot/_config.js new file mode 100644 index 0000000000..aa9da522a3 --- /dev/null +++ b/test/runtime/samples/dynamic-element-slot/_config.js @@ -0,0 +1,29 @@ +export default { + props: { + x: true + }, + + html: ` +

Foo

+
+

This is default slot

+
+
+

This is other slot

+
+ `, + + test({ assert, component, target }) { + component.tag = 'h2'; + + assert.htmlEqual(target.innerHTML, ` +

Foo

+
+

This is default slot

+
+
+

This is other slot

+
+ `); + } +}; diff --git a/test/runtime/samples/dynamic-element-slot/main.svelte b/test/runtime/samples/dynamic-element-slot/main.svelte new file mode 100644 index 0000000000..4b1cd81969 --- /dev/null +++ b/test/runtime/samples/dynamic-element-slot/main.svelte @@ -0,0 +1,10 @@ + + + + This is default slot + This is other slot + + diff --git a/test/runtime/samples/dynamic-element-store/_config.js b/test/runtime/samples/dynamic-element-store/_config.js new file mode 100644 index 0000000000..ded19eef79 --- /dev/null +++ b/test/runtime/samples/dynamic-element-store/_config.js @@ -0,0 +1,3 @@ +export default { + html: '
' +}; diff --git a/test/runtime/samples/dynamic-element-store/main.svelte b/test/runtime/samples/dynamic-element-store/main.svelte new file mode 100644 index 0000000000..84a577ecee --- /dev/null +++ b/test/runtime/samples/dynamic-element-store/main.svelte @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/test/runtime/samples/dynamic-element-string/_config.js b/test/runtime/samples/dynamic-element-string/_config.js new file mode 100644 index 0000000000..acad91c901 --- /dev/null +++ b/test/runtime/samples/dynamic-element-string/_config.js @@ -0,0 +1,3 @@ +export default { + html: '
Foo
' +}; diff --git a/test/runtime/samples/dynamic-element-string/main.svelte b/test/runtime/samples/dynamic-element-string/main.svelte new file mode 100644 index 0000000000..62d65d5f20 --- /dev/null +++ b/test/runtime/samples/dynamic-element-string/main.svelte @@ -0,0 +1 @@ +Foo \ No newline at end of file diff --git a/test/runtime/samples/dynamic-element-template-literals/_config.js b/test/runtime/samples/dynamic-element-template-literals/_config.js new file mode 100644 index 0000000000..d37164b4d8 --- /dev/null +++ b/test/runtime/samples/dynamic-element-template-literals/_config.js @@ -0,0 +1,21 @@ +export default { + props: { + size: 1 + }, + html: '

This is h1 tag

', + + test({ assert, component, target }) { + const h1 = target.firstChild; + component.size = 2; + + assert.htmlEqual( + target.innerHTML, + ` +

This is h2 tag

+ ` + ); + + const h2 = target.firstChild; + assert.notEqual(h1, h2); + } +}; diff --git a/test/runtime/samples/dynamic-element-template-literals/main.svelte b/test/runtime/samples/dynamic-element-template-literals/main.svelte new file mode 100644 index 0000000000..84b63dcca7 --- /dev/null +++ b/test/runtime/samples/dynamic-element-template-literals/main.svelte @@ -0,0 +1,5 @@ + + +This is h{size} tag diff --git a/test/runtime/samples/dynamic-element-transition/_config.js b/test/runtime/samples/dynamic-element-transition/_config.js new file mode 100644 index 0000000000..cb8474afc1 --- /dev/null +++ b/test/runtime/samples/dynamic-element-transition/_config.js @@ -0,0 +1,17 @@ +export default { + test({ assert, component, target, raf }) { + component.visible = true; + const h1 = target.querySelector('h1'); + assert.equal(h1.style.animation, '__svelte_3809512021_0 100ms linear 0ms 1 both'); + + raf.tick(150); + component.tag = 'h2'; + const h2 = target.querySelector('h2'); + assert.equal(h1.style.animation, ''); + assert.equal(h2.style.animation, ''); + + raf.tick(50); + component.visible = false; + assert.equal(h2.style.animation, '__svelte_3750847757_0 100ms linear 0ms 1 both'); + } +}; diff --git a/test/runtime/samples/dynamic-element-transition/main.svelte b/test/runtime/samples/dynamic-element-transition/main.svelte new file mode 100644 index 0000000000..b8c0eff0bd --- /dev/null +++ b/test/runtime/samples/dynamic-element-transition/main.svelte @@ -0,0 +1,17 @@ + + +{#if visible} + +{/if} diff --git a/test/runtime/samples/dynamic-element-undefined-tag/_config.js b/test/runtime/samples/dynamic-element-undefined-tag/_config.js new file mode 100644 index 0000000000..d0bd665d3d --- /dev/null +++ b/test/runtime/samples/dynamic-element-undefined-tag/_config.js @@ -0,0 +1,19 @@ +export default { + html: '', + test({ component, target, assert }) { + component.tag = 'h1'; + assert.htmlEqual(target.innerHTML, '

Foo

'); + + component.tag = null; + assert.htmlEqual(target.innerHTML, ''); + + component.tag = 'div'; + assert.htmlEqual(target.innerHTML, '
Foo
'); + + component.tag = false; + assert.htmlEqual(target.innerHTML, ''); + + component.tag = 'span'; + assert.htmlEqual(target.innerHTML, 'Foo'); + } +}; diff --git a/test/runtime/samples/dynamic-element-undefined-tag/main.svelte b/test/runtime/samples/dynamic-element-undefined-tag/main.svelte new file mode 100644 index 0000000000..6aca93ca13 --- /dev/null +++ b/test/runtime/samples/dynamic-element-undefined-tag/main.svelte @@ -0,0 +1,5 @@ + + +Foo diff --git a/test/runtime/samples/dynamic-element-variable/_config.js b/test/runtime/samples/dynamic-element-variable/_config.js new file mode 100644 index 0000000000..20e0fa9418 --- /dev/null +++ b/test/runtime/samples/dynamic-element-variable/_config.js @@ -0,0 +1,20 @@ +export default { + props: { + tag: 'div', + text: 'Foo' + }, + html: '
Foo
', + + test({ assert, component, target }) { + const div = target.firstChild; + component.tag = 'nav'; + component.text = 'Bar'; + + assert.htmlEqual(target.innerHTML, ` + + `); + + const h1 = target.firstChild; + assert.notEqual(div, h1); + } +}; diff --git a/test/runtime/samples/dynamic-element-variable/main.svelte b/test/runtime/samples/dynamic-element-variable/main.svelte new file mode 100644 index 0000000000..d60953bba5 --- /dev/null +++ b/test/runtime/samples/dynamic-element-variable/main.svelte @@ -0,0 +1,6 @@ + + +{text} \ No newline at end of file diff --git a/test/runtime/samples/inline-style-directive/_config.js b/test/runtime/samples/inline-style-directive/_config.js index ec32e157e5..f5732ae0af 100644 --- a/test/runtime/samples/inline-style-directive/_config.js +++ b/test/runtime/samples/inline-style-directive/_config.js @@ -1,6 +1,8 @@ export default { html: ` -

+
+

+
`, test({ assert, target, window }) { diff --git a/test/runtime/samples/inline-style-directive/main.svelte b/test/runtime/samples/inline-style-directive/main.svelte index 1d60aefa6f..ff8acfce68 100644 --- a/test/runtime/samples/inline-style-directive/main.svelte +++ b/test/runtime/samples/inline-style-directive/main.svelte @@ -2,4 +2,6 @@ export let myColor = "red"; -

+

+

+

diff --git a/test/runtime/samples/inline-style/_config.js b/test/runtime/samples/inline-style/_config.js index 3e984d4c69..192659346c 100644 --- a/test/runtime/samples/inline-style/_config.js +++ b/test/runtime/samples/inline-style/_config.js @@ -4,9 +4,9 @@ export default { `, test({ assert, component, target, window }) { - const p = target.querySelector('div'); + const div = target.querySelector('div'); - const styles = window.getComputedStyle(p); + const styles = window.getComputedStyle(div); assert.equal(styles.color, 'red'); } }; diff --git a/test/runtime/samples/key-block-component-slot/Component1.svelte b/test/runtime/samples/key-block-component-slot/Component1.svelte new file mode 100644 index 0000000000..d0ea817d54 --- /dev/null +++ b/test/runtime/samples/key-block-component-slot/Component1.svelte @@ -0,0 +1 @@ + diff --git a/test/runtime/samples/key-block-component-slot/Component2.svelte b/test/runtime/samples/key-block-component-slot/Component2.svelte new file mode 100644 index 0000000000..ca04744936 --- /dev/null +++ b/test/runtime/samples/key-block-component-slot/Component2.svelte @@ -0,0 +1,12 @@ + diff --git a/test/runtime/samples/key-block-component-slot/_config.js b/test/runtime/samples/key-block-component-slot/_config.js new file mode 100644 index 0000000000..8fbbeaec64 --- /dev/null +++ b/test/runtime/samples/key-block-component-slot/_config.js @@ -0,0 +1,18 @@ +const logs = []; + +export default { + html: '', + props: { + logs + }, + async test({ assert, component, target, raf }) { + assert.deepEqual(logs, ['mount']); + + const button = target.querySelector('button'); + + const click = new window.MouseEvent('click'); + await button.dispatchEvent(click); + + assert.deepEqual(logs, ['mount', 'unmount', 'mount']); + } +}; diff --git a/test/runtime/samples/key-block-component-slot/main.svelte b/test/runtime/samples/key-block-component-slot/main.svelte new file mode 100644 index 0000000000..77fde32d9c --- /dev/null +++ b/test/runtime/samples/key-block-component-slot/main.svelte @@ -0,0 +1,17 @@ + + + + {#key reset} + + {/key} + + + \ No newline at end of file diff --git a/test/server-side-rendering/samples/attribute-escaped-quotes/_expected.html b/test/server-side-rendering/samples/attribute-escaped-quotes/_expected.html index c3c9405d7b..e99c5b0f6e 100644 --- a/test/server-side-rendering/samples/attribute-escaped-quotes/_expected.html +++ b/test/server-side-rendering/samples/attribute-escaped-quotes/_expected.html @@ -1,3 +1,4 @@
\ No newline at end of file + foo="">\" + bar="">\" +> diff --git a/test/server-side-rendering/samples/attribute-escaped-quotes/main.svelte b/test/server-side-rendering/samples/attribute-escaped-quotes/main.svelte index ed34f4d129..aeed0f20d1 100644 --- a/test/server-side-rendering/samples/attribute-escaped-quotes/main.svelte +++ b/test/server-side-rendering/samples/attribute-escaped-quotes/main.svelte @@ -1,5 +1,6 @@ -
\ No newline at end of file +
diff --git a/test/server-side-rendering/samples/dynamic-element-string/_expected.html b/test/server-side-rendering/samples/dynamic-element-string/_expected.html new file mode 100644 index 0000000000..cb98432e14 --- /dev/null +++ b/test/server-side-rendering/samples/dynamic-element-string/_expected.html @@ -0,0 +1 @@ +
Foo
diff --git a/test/server-side-rendering/samples/dynamic-element-string/main.svelte b/test/server-side-rendering/samples/dynamic-element-string/main.svelte new file mode 100644 index 0000000000..62d65d5f20 --- /dev/null +++ b/test/server-side-rendering/samples/dynamic-element-string/main.svelte @@ -0,0 +1 @@ +Foo \ No newline at end of file diff --git a/test/server-side-rendering/samples/dynamic-element-variable/_expected.html b/test/server-side-rendering/samples/dynamic-element-variable/_expected.html new file mode 100644 index 0000000000..3ae445f54c --- /dev/null +++ b/test/server-side-rendering/samples/dynamic-element-variable/_expected.html @@ -0,0 +1,2 @@ +

Foo

+
Bar
\ No newline at end of file diff --git a/test/server-side-rendering/samples/dynamic-element-variable/main.svelte b/test/server-side-rendering/samples/dynamic-element-variable/main.svelte new file mode 100644 index 0000000000..9aaba18bf1 --- /dev/null +++ b/test/server-side-rendering/samples/dynamic-element-variable/main.svelte @@ -0,0 +1,7 @@ + + +Foo +Bar \ No newline at end of file diff --git a/test/validator/samples/dynamic-element-invalid-tag/errors.json b/test/validator/samples/dynamic-element-invalid-tag/errors.json new file mode 100644 index 0000000000..c8d3c52490 --- /dev/null +++ b/test/validator/samples/dynamic-element-invalid-tag/errors.json @@ -0,0 +1,17 @@ +[ + { + "message": "Invalid element definition", + "code": "invalid-element-definition", + "start": { + "line": 2, + "column": 17, + "character": 23 + }, + "end": { + "line": 2, + "column": 17, + "character": 23 + }, + "pos": 23 + } +] diff --git a/test/validator/samples/dynamic-element-invalid-tag/input.svelte b/test/validator/samples/dynamic-element-invalid-tag/input.svelte new file mode 100644 index 0000000000..bc6b8be822 --- /dev/null +++ b/test/validator/samples/dynamic-element-invalid-tag/input.svelte @@ -0,0 +1,3 @@ +
+ foo +
diff --git a/test/validator/samples/dynamic-element-missing-tag/errors.json b/test/validator/samples/dynamic-element-missing-tag/errors.json new file mode 100644 index 0000000000..8243deeb80 --- /dev/null +++ b/test/validator/samples/dynamic-element-missing-tag/errors.json @@ -0,0 +1,15 @@ +[{ + "code": "missing-element-definition", + "message": " must have a 'this' attribute", + "start": { + "line": 2, + "column": 1, + "character": 7 + }, + "end": { + "line": 2, + "column": 1, + "character": 7 + }, + "pos": 7 +}] diff --git a/test/validator/samples/dynamic-element-missing-tag/input.svelte b/test/validator/samples/dynamic-element-missing-tag/input.svelte new file mode 100644 index 0000000000..4b645d25a1 --- /dev/null +++ b/test/validator/samples/dynamic-element-missing-tag/input.svelte @@ -0,0 +1,3 @@ +
+ foo +
diff --git a/test/validator/samples/dynamic-element-this/errors.json b/test/validator/samples/dynamic-element-this/errors.json new file mode 100644 index 0000000000..7d61c20ee2 --- /dev/null +++ b/test/validator/samples/dynamic-element-this/errors.json @@ -0,0 +1,15 @@ +[{ + "code": "unexpected-reserved-word", + "message": "'this' is a reserved word in JavaScript and cannot be used here", + "start": { + "line": 2, + "column": 18, + "character": 24 + }, + "end": { + "line": 2, + "column": 18, + "character": 24 + }, + "pos": 24 + }] diff --git a/test/validator/samples/dynamic-element-this/input.svelte b/test/validator/samples/dynamic-element-this/input.svelte new file mode 100644 index 0000000000..1a5079b924 --- /dev/null +++ b/test/validator/samples/dynamic-element-this/input.svelte @@ -0,0 +1,3 @@ +
+ foo +
diff --git a/test/validator/samples/unreferenced-variables/input.svelte b/test/validator/samples/unreferenced-variables/input.svelte index 8c9e0b15f3..cebd861985 100644 --- a/test/validator/samples/unreferenced-variables/input.svelte +++ b/test/validator/samples/unreferenced-variables/input.svelte @@ -1,25 +1,48 @@ + + -{$q} +{$q2} diff --git a/test/validator/samples/unreferenced-variables/warnings.json b/test/validator/samples/unreferenced-variables/warnings.json index dfac58ebdb..4097ba023b 100644 --- a/test/validator/samples/unreferenced-variables/warnings.json +++ b/test/validator/samples/unreferenced-variables/warnings.json @@ -2,76 +2,76 @@ { "code": "unused-export-let", "end": { - "character": 103, - "column": 12, - "line": 8 + "character": 519, + "column": 13, + "line": 31 }, - "message": "Component has unused export property 'd'. If it is for external reference only, please consider using `export const d`", - "pos": 102, + "message": "Component has unused export property 'd2'. If it is for external reference only, please consider using `export const d2`", + "pos": 517, "start": { - "character": 102, + "character": 517, "column": 11, - "line": 8 + "line": 31 } }, { "code": "unused-export-let", "end": { - "character": 106, - "column": 15, - "line": 8 + "character": 523, + "column": 17, + "line": 31 }, - "message": "Component has unused export property 'e'. If it is for external reference only, please consider using `export const e`", - "pos": 105, + "message": "Component has unused export property 'e2'. If it is for external reference only, please consider using `export const e2`", + "pos": 521, "start": { - "character": 105, - "column": 14, - "line": 8 + "character": 521, + "column": 15, + "line": 31 } }, { "code": "unused-export-let", "end": { - "character": 130, - "column": 18, - "line": 9 + "character": 549, + "column": 19, + "line": 32 }, - "message": "Component has unused export property 'g'. If it is for external reference only, please consider using `export const g`", - "pos": 125, + "message": "Component has unused export property 'g2'. If it is for external reference only, please consider using `export const g2`", + "pos": 543, "start": { - "character": 125, + "character": 543, "column": 13, - "line": 9 + "line": 32 } }, { "code": "unused-export-let", "end": { - "character": 150, - "column": 18, - "line": 10 + "character": 570, + "column": 19, + "line": 33 }, - "message": "Component has unused export property 'h'. If it is for external reference only, please consider using `export const h`", - "pos": 145, + "message": "Component has unused export property 'h2'. If it is for external reference only, please consider using `export const h2`", + "pos": 564, "start": { - "character": 145, + "character": 564, "column": 13, - "line": 10 + "line": 33 } }, { "code": "unused-export-let", "end": { - "character": 199, - "column": 25, - "line": 12 + "character": 621, + "column": 26, + "line": 35 }, - "message": "Component has unused export property 'j'. If it is for external reference only, please consider using `export const j`", - "pos": 187, + "message": "Component has unused export property 'j2'. If it is for external reference only, please consider using `export const j2`", + "pos": 608, "start": { - "character": 187, + "character": 608, "column": 13, - "line": 12 + "line": 35 } } ]