Skip to content

Svelte 5: rendering a component with a global transition causes an error #416

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ivenuss opened this issue Dec 4, 2024 · 3 comments
Closed
Labels
wontfix This will not be worked on

Comments

@ivenuss
Copy link

ivenuss commented Dec 4, 2024

Problem

During migration from Svelte 4 to Svelte 5 I am getting error when I try to render component with global transition.

If I remove the global transition from <p in:slide|global> to <p in:slide>, it no longer throws any error.

Reproduction

Test

// MyComponent.test.ts
import { cleanup, render } from '@testing-library/svelte';
import { afterEach, describe, expect, it } from 'vitest';
import TestMyComponent from './MyComponent.test.svelte';

afterEach(() => {
  cleanup();
});

describe('FormErrorMessage', async () => {
  it('renders', async () => {
    const result = render(TestMyComponent);
    expect(() => result.getByText('message text')).not.toThrow();
  });
});

Components

<!-- TestMyComponent.svelte -->
<script lang="ts">
  import MyComponent from './MyComponent.svelte';
</script>

<MyComponent>message text</MyComponent>
<!-- MyComponent.svelte -->
<p in:slide|global>
  <slot />
</p>

Error log

TypeError: element.animate is not a function
   in MyComponent.svelte
   in MyComponent.test.svelte

 ❯ animate ../../node_modules/.pnpm/[email protected]/node_modules/svelte/src/internal/client/dom/elements/transitions.js:377:26
    375|   // for bidirectional transitions, we start from the current position,
    376|   // rather than doing a full intro/outro
    377|   var t1 = counterpart?.t() ?? 1 - t2;
       |                          ^
    378|   counterpart?.abort();

Package versions

"svelte": "^5.5.3",
"vitest": "^2.1.8",
"@testing-library/svelte": "^5.2.6",
@mcous mcous added the wontfix This will not be worked on label Dec 4, 2024
@mcous
Copy link
Collaborator

mcous commented Dec 4, 2024

Svelte transitions now require the web animations API, which is not available in jsdom nor happy-dom, due to their lack of GUI. Since this is internal to Svelte, there's nothing (reasonable) for us to do in svelte-testing-library to resolve this.

If you would like to run component-level tests of transitions, you either need to:

  • Use a real browser via something like Playwright or Vitest's browser mode
  • Try to fake out Element.prototype.animate with mock functions (not recommended)

Alternatively, my preferred approach is to move my interesting logic to components and modules that don't involve transitions, test those components, and then pull those into components that only care about the transitions. From there, I don't bother writing additional component tests, because I can trust that Svelte tests its own transition logic

For more context, see various posts in #284:

@mcous mcous closed this as not planned Won't fix, can't repro, duplicate, stale Dec 4, 2024
@glumn
Copy link

glumn commented Jan 6, 2025

An additional workaround could be to simply mock svelte/transition inside a vitest-setup file for instance.

vi.mock("svelte/transition")

@mcous
Copy link
Collaborator

mcous commented Jan 6, 2025

Component tests tend to be fairly highly integrated - your test runs your own code, the Svelte runtime, the browser/fake DOM runtime, etc. all together. For that reason, I strongly recommend against mocking out "third-party" things like the svelte/transition module. Mocks floating around a highly integrated test, imitating logic you don't control, connected to other "third-party" code in ways you can't easily understand, cause long term pain, in my experience.

Mocks are best reserved for situations where you completely isolate your code under test with those mocks, which is not possible with component tests

peterpeterparker added a commit to dfinity/gix-components that referenced this issue Feb 4, 2025
# Motivation

Svelte requires require the [web animations
API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API),
and neither [jsdom](https://github.com/jsdom/jsdom) nor
[happy-dom](https://github.com/capricorn86/happy-dom) implements it.

While in Gix-cmp or OISY we are able to apply some mocks in the
configuration, this is insuffisent for the existing large test suite of
NNS dapp for which many tests fail, when migrating to Svelte v5, with
the error:

> TypeError: Cannot set properties of undefined (setting 'onfinish')

As suggested in one of the related issues (see linked below), we can
overcome the problem by disabling animations in test mode.

# References

-
testing-library/svelte-testing-library#284 (comment)
- testing-library/svelte-testing-library#416

# CI issues

-
https://github.com/dfinity/nns-dapp/actions/runs/13129931873/job/36632946426

# Changes

- Implement utils for fade, fly and scale that returns an empty
transition configuration for test mode
- Expose utils to make to re-usable by consumers as well

# Tests

Errors do not happen anymore in NNS dapp - Svelte v5 wip branch running
in the CI.

-
https://github.com/dfinity/nns-dapp/actions/runs/13131104521/job/36636304026?pr=6020

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
wontfix This will not be worked on
Projects
None yet
Development

No branches or pull requests

3 participants