Skip to content

Commit

Permalink
Sync svelte docs (#1095)
Browse files Browse the repository at this point in the history
sync svelte docs

Co-authored-by: Rich-Harris <[email protected]>
  • Loading branch information
github-actions[bot] and Rich-Harris authored Jan 7, 2025
1 parent 8b56182 commit b8e19ba
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 2 deletions.
17 changes: 17 additions & 0 deletions apps/svelte.dev/content/docs/svelte/02-runes/03-$derived.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,20 @@ In essence, `$derived(expression)` is equivalent to `$derived.by(() => expressio
Anything read synchronously inside the `$derived` expression (or `$derived.by` function body) is considered a _dependency_ of the derived state. When the state changes, the derived will be marked as _dirty_ and recalculated when it is next read.

To exempt a piece of state from being treated as a dependency, use [`untrack`](svelte#untrack).

## Update propagation

Svelte uses something called _push-pull reactivity_ — when state is updated, everything that depends on the state (whether directly or indirectly) is immediately notified of the change (the 'push'), but derived values are not re-evaluated until they are actually read (the 'pull').

If the new value of a derived is referentially identical to its previous value, downstream updates will be skipped. In other words, Svelte will only update the text inside the button when `large` changes, not when `count` changes, even though `large` depends on `count`:

```svelte
<script>
let count = $state(0);
let large = $derived(count > 10);
</script>
<button onclick={() => count++}>
{large}
</button>
```
61 changes: 59 additions & 2 deletions apps/svelte.dev/content/docs/svelte/07-misc/02-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ You can now write unit tests for code inside your `.js/.ts` files:
/// file: multiplier.svelte.test.js
import { flushSync } from 'svelte';
import { expect, test } from 'vitest';
import { multiplier } from './multiplier.js';
import { multiplier } from './multiplier.svelte.js';

test('Multiplier', () => {
let double = multiplier(0, 2);
Expand All @@ -54,9 +54,30 @@ test('Multiplier', () => {
});
```

```js
/// file: multiplier.svelte.js
/**
* @param {number} initial
* @param {number} k
*/
export function multiplier(initial, k) {
let count = $state(initial);

return {
get value() {
return count * k;
},
/** @param {number} c */
set: (c) => {
count = c;
}
};
}
```

### Using runes inside your test files

It is possible to use runes inside your test files. First ensure your bundler knows to route the file through the Svelte compiler before running the test by adding `.svelte` to the filename (e.g `multiplier.svelte.test.js`). After that, you can use runes inside your tests.
Since Vitest processes your test files the same way as your source files, you can use runes inside your tests as long as the filename includes `.svelte`:

```js
/// file: multiplier.svelte.test.js
Expand All @@ -76,6 +97,21 @@ test('Multiplier', () => {
});
```

```js
/// file: multiplier.svelte.js
/**
* @param {() => number} getCount
* @param {number} k
*/
export function multiplier(getCount, k) {
return {
get value() {
return getCount() * k;
}
};
}
```

If the code being tested uses effects, you need to wrap the test inside `$effect.root`:

```js
Expand Down Expand Up @@ -106,6 +142,27 @@ test('Effect', () => {
});
```

```js
/// file: logger.svelte.js
/**
* @param {() => any} getValue
*/
export function logger(getValue) {
/** @type {any[]} */
let log = $state([]);

$effect(() => {
log.push(getValue());
});

return {
get value() {
return log;
}
};
}
```

### Component testing

It is possible to test your components in isolation using Vitest.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,4 @@ Custom elements can be a useful way to package components for consumption in a n
- The deprecated `let:` directive has no effect, because custom elements do not have a way to pass data to the parent component that fills the slot
- Polyfills are required to support older browsers
- You can use Svelte's context feature between regular Svelte components within a custom element, but you can't use them across custom elements. In other words, you can't use `setContext` on a parent custom element and read that with `getContext` in a child custom element.
- Don't declare properties or attributes starting with `on`, as their usage will be interpreted as an event listener. In other words, Svelte treats `<custom-element oneworld={true}></custom-element>` as `customElement.addEventListener('eworld', true)` (and not as `customElement.oneworld = true`)

0 comments on commit b8e19ba

Please sign in to comment.