diff --git a/packages/svelte/tests/custom-renderers/renderer.ts b/packages/svelte/tests/custom-renderers/renderer.ts index 2ba9f8346d..977f2b97dd 100644 --- a/packages/svelte/tests/custom-renderers/renderer.ts +++ b/packages/svelte/tests/custom-renderers/renderer.ts @@ -8,7 +8,7 @@ import { createRenderer } from '../../src/renderer/index.js'; -type ObjElement = { +export type ObjElement = { type: 'element'; name: string; attributes: Record; @@ -29,7 +29,7 @@ export type ObjFragment = { parent: ObjNode | null; elements_children: Array; }; -type ObjNode = ObjElement | ObjText | ObjComment | ObjFragment; +export type ObjNode = ObjElement | ObjText | ObjComment | ObjFragment; function insert_node( parent: ObjNode & { children?: ObjNode[] }, diff --git a/packages/svelte/tests/custom-renderers/samples/attribute-casing/_config.js b/packages/svelte/tests/custom-renderers/samples/attribute-casing/_config.js index a44fc4ae1f..2afc2d8024 100644 --- a/packages/svelte/tests/custom-renderers/samples/attribute-casing/_config.js +++ b/packages/svelte/tests/custom-renderers/samples/attribute-casing/_config.js @@ -1,8 +1,8 @@ import { test } from '../../test'; export default test({ - test({ assert, target }) { - const elements = target.children.filter((/** @type {any} */ n) => n.type === 'element'); + test({ assert, target, utils }) { + const elements = target.children.filter(utils.filter_elements()); assert.equal(elements.length, 4); diff --git a/packages/svelte/tests/custom-renderers/samples/attributes/_config.js b/packages/svelte/tests/custom-renderers/samples/attributes/_config.js index 448b8adc26..814de0ab4b 100644 --- a/packages/svelte/tests/custom-renderers/samples/attributes/_config.js +++ b/packages/svelte/tests/custom-renderers/samples/attributes/_config.js @@ -1,7 +1,7 @@ import { test } from '../../test'; export default test({ - test({ assert, target, serialize }) { + test({ assert, target, serialize, utils }) { const html = serialize(target); assert.equal( html, @@ -9,17 +9,13 @@ export default test({ ); // Verify individual attribute access on the object node - const div = target.children.find( - (/** @type {any} */ n) => n.type === 'element' && n.name === 'div' - ); + const div = target.children.find(utils.filter_elements((n) => n.name === 'div')); assert.ok(div); - assert.equal(div.attributes['class'], 'container'); - assert.equal(div.attributes['data-color'], 'red'); + assert.equal(div?.attributes['class'], 'container'); + assert.equal(div?.attributes['data-color'], 'red'); - const span = div.children.find( - (/** @type {any} */ n) => n.type === 'element' && n.name === 'span' - ); + const span = div?.children.find(utils.filter_elements((n) => n.name === 'span')); assert.ok(span); - assert.equal(span.attributes['id'], 'label'); + assert.equal(span?.attributes['id'], 'label'); } }); diff --git a/packages/svelte/tests/custom-renderers/samples/default-value-spread/_config.js b/packages/svelte/tests/custom-renderers/samples/default-value-spread/_config.js index e5fd87d389..1b52794a7b 100644 --- a/packages/svelte/tests/custom-renderers/samples/default-value-spread/_config.js +++ b/packages/svelte/tests/custom-renderers/samples/default-value-spread/_config.js @@ -2,13 +2,9 @@ import { flushSync } from 'svelte'; import { test } from '../../test'; export default test({ - test({ assert, target, dispatch_event }) { - const inputs = target.children.filter( - (/** @type {any} */ n) => n.type === 'element' && n.name === 'input' - ); - const button = target.children.find( - (/** @type {any} */ n) => n.type === 'element' && n.name === 'button' - ); + test({ assert, target, dispatch_event, utils }) { + const inputs = target.children.filter(utils.filter_elements((n) => n.name === 'input')); + const button = target.children.find(utils.filter_elements((n) => n.name === 'button')); assert.equal(inputs.length, 4); assert.ok(button); diff --git a/packages/svelte/tests/custom-renderers/samples/event-handler-no-propagation/_config.js b/packages/svelte/tests/custom-renderers/samples/event-handler-no-propagation/_config.js index 085ca682d8..b8c96b5d3d 100644 --- a/packages/svelte/tests/custom-renderers/samples/event-handler-no-propagation/_config.js +++ b/packages/svelte/tests/custom-renderers/samples/event-handler-no-propagation/_config.js @@ -2,19 +2,17 @@ import { flushSync } from 'svelte'; import { test } from '../../test'; export default test({ - test({ assert, target, serialize, logs }) { - const button = target.children.find( - (/** @type {any} */ n) => n.type === 'element' && n.name === 'button' - ); + test({ assert, target, utils, logs }) { + const button = target.children.find(utils.filter_elements((n) => n.name === 'button')); assert.ok(button); - const listeners = button.listeners?.click; + const listeners = button?.listeners?.click; assert.ok(listeners, 'button should have click listeners'); // Call the handler with multiple arguments. // Custom renderers may pass multiple arguments to event handlers, // so we need to make sure all arguments are forwarded. - for (const { handler } of listeners) { + for (const { handler } of listeners ?? []) { handler.call(button, { type: 'click' }, 'extra', 42); } flushSync(); diff --git a/packages/svelte/tests/custom-renderers/samples/event-handler-spread/_config.js b/packages/svelte/tests/custom-renderers/samples/event-handler-spread/_config.js index ebcd14cc16..39522033b0 100644 --- a/packages/svelte/tests/custom-renderers/samples/event-handler-spread/_config.js +++ b/packages/svelte/tests/custom-renderers/samples/event-handler-spread/_config.js @@ -3,19 +3,17 @@ import { test } from '../../test'; export default test({ html: '

0

', - test({ assert, target, serialize, logs }) { - const button = target.children.find( - (/** @type {any} */ n) => n.type === 'element' && n.name === 'button' - ); + test({ assert, target, serialize, logs, utils }) { + const button = target.children.find(utils.filter_elements((n) => n.name === 'button')); assert.ok(button); - const listeners = button.listeners?.click; + const listeners = button?.listeners?.click; assert.ok(listeners, 'button should have click listeners'); // Call the handler with multiple arguments. // Custom renderers may pass multiple arguments to event handlers, // so we need to make sure all arguments are forwarded through spreads too. - for (const { handler } of listeners) { + for (const { handler } of listeners ?? []) { handler.call(button, { type: 'click' }, 'extra', 42); } flushSync(); diff --git a/packages/svelte/tests/custom-renderers/samples/select-option/_config.js b/packages/svelte/tests/custom-renderers/samples/select-option/_config.js index 7e6e62edd7..f2f878a3eb 100644 --- a/packages/svelte/tests/custom-renderers/samples/select-option/_config.js +++ b/packages/svelte/tests/custom-renderers/samples/select-option/_config.js @@ -2,23 +2,19 @@ import { test } from '../../test'; export default test({ html: '

b

', - test({ assert, target, serialize }) { - const select = target.children.find( - (/** @type {any} */ n) => n.type === 'element' && n.name === 'select' - ); + test({ assert, target, serialize, utils }) { + const select = target.children.find(utils.filter_elements((n) => n.name === 'select')); assert.ok(select); // The select element should have a value attribute set via the normal attribute path - assert.equal(select.attributes['value'], 'b'); + assert.equal(select?.attributes['value'], 'b'); // Each option should have its value as a regular attribute - const options = select.children.filter( - (/** @type {any} */ n) => n.type === 'element' && n.name === 'option' - ); - assert.equal(options.length, 3); - assert.equal(options[0].attributes['value'], 'a'); - assert.equal(options[1].attributes['value'], 'b'); - assert.equal(options[2].attributes['value'], 'c'); + const options = select?.children.filter(utils.filter_elements((n) => n.name === 'option')); + assert.equal(options?.length, 3); + assert.equal(options?.[0]?.attributes['value'], 'a'); + assert.equal(options?.[1]?.attributes['value'], 'b'); + assert.equal(options?.[2]?.attributes['value'], 'c'); const html = serialize(target); assert.equal( diff --git a/packages/svelte/tests/custom-renderers/samples/special-attributes/_config.js b/packages/svelte/tests/custom-renderers/samples/special-attributes/_config.js index 4b839e5ad2..c5848dddd8 100644 --- a/packages/svelte/tests/custom-renderers/samples/special-attributes/_config.js +++ b/packages/svelte/tests/custom-renderers/samples/special-attributes/_config.js @@ -2,14 +2,10 @@ import { flushSync } from 'svelte'; import { test } from '../../test'; export default test({ - test({ assert, target, dispatch_event }) { + test({ assert, utils, target, dispatch_event }) { // Find all inputs and the button - const inputs = target.children.filter( - (/** @type {any} */ n) => n.type === 'element' && n.name === 'input' - ); - const button = target.children.find( - (/** @type {any} */ n) => n.type === 'element' && n.name === 'button' - ); + const inputs = target.children.filter(utils.filter_elements((n) => n.name === 'input')); + const button = target.children.find(utils.filter_elements((n) => n.name === 'button')); assert.equal(inputs.length, 5); assert.ok(button); diff --git a/packages/svelte/tests/custom-renderers/samples/svelte-element-autofocus/_config.js b/packages/svelte/tests/custom-renderers/samples/svelte-element-autofocus/_config.js index 8d4602f7fb..2d01190da9 100644 --- a/packages/svelte/tests/custom-renderers/samples/svelte-element-autofocus/_config.js +++ b/packages/svelte/tests/custom-renderers/samples/svelte-element-autofocus/_config.js @@ -1,18 +1,16 @@ import { test } from '../../test'; export default test({ - test({ assert, target }) { + test({ assert, target, utils }) { // If we got here, the component mounted without crashing on document.body access. // Verify autofocus is set as a regular attribute. - const input = target.children.find( - (/** @type {any} */ n) => n.type === 'element' && n.name === 'input' - ); + const input = target.children.find(utils.filter_elements((n) => n.name === 'input')); assert.ok(input, 'input element should exist'); assert.equal( - input.attributes['autofocus'], + input?.attributes['autofocus'], 'true', 'autofocus should be set as a regular attribute' ); - assert.equal(input.attributes['value'], 'test', 'value should be set as a regular attribute'); + assert.equal(input?.attributes['value'], 'test', 'value should be set as a regular attribute'); } }); diff --git a/packages/svelte/tests/custom-renderers/shared.ts b/packages/svelte/tests/custom-renderers/shared.ts index 26373b3fc5..2571d751b1 100644 --- a/packages/svelte/tests/custom-renderers/shared.ts +++ b/packages/svelte/tests/custom-renderers/shared.ts @@ -5,7 +5,14 @@ import { assert } from 'vitest'; import { compile_directory } from '../helpers.js'; import { suite_with_variants, type BaseTest } from '../suite.js'; import type { CompileOptions } from '#compiler'; -import renderer, { create_root, serialize, dispatch_event, type ObjFragment } from './renderer.js'; +import renderer, { + create_root, + serialize, + dispatch_event, + type ObjFragment, + type ObjElement, + type ObjNode +} from './renderer.js'; import { writeFile } from 'node:fs/promises'; import { globSync } from 'tinyglobby'; import { hydrate, unmount } from 'svelte'; @@ -52,6 +59,15 @@ interface CustomRendererHydrateTest extends BaseTest { }) => void | Promise; } +function filter_elements(extra_filter?: (node: ObjElement) => boolean) { + return (node: ObjNode): node is ObjElement => + node.type === 'element' && (extra_filter?.(node) ?? true); +} + +const utils = { + filter_elements +}; + interface CustomRendererNonHydrateTest extends BaseTest { html?: string; compileOptions?: Partial; @@ -65,6 +81,9 @@ interface CustomRendererNonHydrateTest extends BaseTest { runtime_error?: string; warnings?: string[]; test?: (args: { + utils: { + filter_elements: typeof filter_elements; + }; assert: Assert; target: ObjFragment; component: Record; @@ -249,6 +268,7 @@ async function run_test(cwd: string, config: CustomRendererTest, compile_options try { if (config.test) { await config.test({ + utils, assert, target: target as never, component: component ?? {}, @@ -317,6 +337,7 @@ async function run_hydration_test( try { if (config.test) { await config.test({ + utils, assert, target: target as never, component,