Skip to content

Bug: props passed into Svelte component should not be converted to $state, causes problems #455

@KieranP

Description

@KieranP

Copied from vitest-community/vitest-browser-svelte#19 because the issue exists here too

Currently, this plugin is converting props passed into the render function into a $state:

const props = $state(options.props ?? {})

However, this is not desirable behavior and leads to things working in the browser but failing with this plugin.

Consider the following:

Parent.svelte:

<script>
	import Child from './Child.svelte'
	
	let defaultProps = {
		title: '',
		body: ''
	}
</script>

<Child {defaultProps} />

Child.svelte

<script>
	const { defaultProps } = $props()

	console.log(defaultProps)
	
	function clone() {
		console.log(structuredClone(defaultProps))
	}
</script>

<button onclick={clone}>
	Clone
</button>

In the browser, this works fine. defaultProps is passed unchanged into Child, and clicking Clone button works as expected.

However, consider this in plugin:

import { render } from '@testing-library/svelte'
import Child from './Child.svelte'

describe('compatibility test', () => {
  let defaultProps = {
    title: '',
    body: ''
  }

  it('successfully clones object', () => {
    const { screen } = render(Child, {
      ...defaultProps
    })

    const btn = screen.findByRole('button')
    await btn.click()
  })
})

This fails, because defaultProps passed into render is converted to $state. That $state is then passed into structuredClone, and that fails with:

DataCloneError: Failed to execute 'structuredClone' on 'Window': [object] could not be cloned

In short, this plugins conversion of props into $state is causing many failures that do not happen when actually run in a browser.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions