Skip to content
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

Uncaught exception while using Skeleton Popup #406

Open
is-sematell opened this issue Oct 25, 2024 · 5 comments
Open

Uncaught exception while using Skeleton Popup #406

is-sematell opened this issue Oct 25, 2024 · 5 comments
Labels
wontfix This will not be worked on

Comments

@is-sematell
Copy link

Summary

I've created a Tooltip component that utilizes Skeleton Popup. It works just fine in the browser.

However, when I try to test it via Testing Library, I get the below error. Seems like it is caused by userEvent.hover.

I've checked with the Skeleton community, and they believe that this is a Testing Library bug.

Error

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Unhandled Errors ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

Vitest caught 1 unhandled error during the test run.
This might cause false positive tests. Resolve unhandled errors to make sure your tests are not affected.

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ Uncaught Exception ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
SyntaxError: 'a[href], button, input, textarea, select, details, [tabindex]):not([tabindex="-1"]' is not a valid selector
 ❯ emit node_modules/.deno/[email protected]/node_modules/nwsapi/src/nwsapi.js:575:17
 ❯ Object._matches [as match] node_modules/.deno/[email protected]/node_modules/nwsapi/src/nwsapi.js:1438:9
 ❯ Array.Resolver node_modules/.deno/[email protected]/node_modules/nwsapi/src/nwsapi.js:777:17
 ❯ collect node_modules/.deno/[email protected]/node_modules/nwsapi/src/nwsapi.js:1594:21
 ❯ Object._querySelectorAll [as select] node_modules/.deno/[email protected]/node_modules/nwsapi/src/nwsapi.js:1549:36
 ❯ HTMLDivElementImpl.querySelectorAll node_modules/.deno/[email protected]/node_modules/jsdom/lib/jsdom/living/nodes/ParentNode-impl.js:78:26
 ❯ HTMLDivElement.querySelectorAll node_modules/.deno/[email protected]/node_modules/jsdom/lib/jsdom/living/generated/Element.js:1119:58
 ❯ HTMLButtonElement.open node_modules/.deno/@[email protected]/node_modules/@skeletonlabs/skeleton/dist/utilities/Popup/popup.js:119:56
    118|     }
    119|     function close(callback) {
    120|         if (!elemPopup)
       |     ^
    121|             return;
    122|         // Set transition duration
 ❯ HTMLButtonElement.callTheUserObjectsOperation node_modules/.deno/[email protected]/node_modules/jsdom/lib/jsdom/living/generated/EventListener.js:26:30
 ❯ innerInvokeEventListeners node_modules/.deno/[email protected]/node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:350:25

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯
Serialized Error: { code: 12, INDEX_SIZE_ERR: 1, DOMSTRING_SIZE_ERR: 2, HIERARCHY_REQUEST_ERR: 3, WRONG_DOCUMENT_ERR: 4, INVALID_CHARACTER_ERR: 5, NO_DATA_ALLOWED_ERR: 6, NO_MODIFICATION_ALLOWED_ERR: 7, NOT_FOUND_ERR: 8, NOT_SUPPORTED_ERR: 9, INUSE_ATTRIBUTE_ERR: 10, INVALID_STATE_ERR: 11, SYNTAX_ERR: 12, INVALID_MODIFICATION_ERR: 13, NAMESPACE_ERR: 14, INVALID_ACCESS_ERR: 15, VALIDATION_ERR: 16, TYPE_MISMATCH_ERR: 17, SECURITY_ERR: 18, NETWORK_ERR: 19, ABORT_ERR: 20, URL_MISMATCH_ERR: 21, QUOTA_EXCEEDED_ERR: 22, TIMEOUT_ERR: 23, INVALID_NODE_TYPE_ERR: 24, DATA_CLONE_ERR: 25, __proto__: { constructor: 'Function<DOMException>', name: '<unserializable>', message: '<unserializable>', code: '<unserializable>', INDEX_SIZE_ERR: 1, DOMSTRING_SIZE_ERR: 2, HIERARCHY_REQUEST_ERR: 3, WRONG_DOCUMENT_ERR: 4, INVALID_CHARACTER_ERR: 5, NO_DATA_ALLOWED_ERR: 6, NO_MODIFICATION_ALLOWED_ERR: 7, NOT_FOUND_ERR: 8, NOT_SUPPORTED_ERR: 9, INUSE_ATTRIBUTE_ERR: 10, INVALID_STATE_ERR: 11, SYNTAX_ERR: 12, INVALID_MODIFICATION_ERR: 13, NAMESPACE_ERR: 14, INVALID_ACCESS_ERR: 15, VALIDATION_ERR: 16, TYPE_MISMATCH_ERR: 17, SECURITY_ERR: 18, NETWORK_ERR: 19, ABORT_ERR: 20, URL_MISMATCH_ERR: 21, QUOTA_EXCEEDED_ERR: 22, TIMEOUT_ERR: 23, INVALID_NODE_TYPE_ERR: 24, DATA_CLONE_ERR: 25, toString: 'Function<toString>', __defineGetter__: 'Function<__defineGetter__>', __defineSetter__: 'Function<__defineSetter__>', hasOwnProperty: 'Function<hasOwnProperty>', __lookupGetter__: 'Function<__lookupGetter__>', __lookupSetter__: 'Function<__lookupSetter__>', isPrototypeOf: 'Function<isPrototypeOf>', propertyIsEnumerable: 'Function<propertyIsEnumerable>', valueOf: 'Function<valueOf>', __proto__: { constructor: 'Function<Error>', name: 'Error', message: '', toString: 'Function<toString>', __defineGetter__: 'Function<__defineGetter__>', __defineSetter__: 'Function<__defineSetter__>', hasOwnProperty: 'Function<hasOwnProperty>', __lookupGetter__: 'Function<__lookupGetter__>', __lookupSetter__: 'Function<__lookupSetter__>', isPrototypeOf: 'Function<isPrototypeOf>', propertyIsEnumerable: 'Function<propertyIsEnumerable>', valueOf: 'Function<valueOf>', __proto__: { constructor: 'Function<Object>', __defineGetter__: 'Function<__defineGetter__>', __defineSetter__: 'Function<__defineSetter__>', hasOwnProperty: 'Function<hasOwnProperty>', __lookupGetter__: 'Function<__lookupGetter__>', __lookupSetter__: 'Function<__lookupSetter__>', isPrototypeOf: 'Function<isPrototypeOf>', propertyIsEnumerable: 'Function<propertyIsEnumerable>', toString: 'Function<toString>', valueOf: 'Function<valueOf>', __proto__: null, toLocaleString: 'Function<toLocaleString>' }, toLocaleString: 'Function<toLocaleString>' }, toLocaleString: 'Function<toLocaleString>' } }
This error originated in "src/lib/components/skeleton-test/Tooltip.test.ts" test file. It doesn't mean the error was thrown inside the file itself, but while it was running.
The latest test that might've caused the error is "should render the tooltip content on hover". It might mean one of the following:
- The error was thrown, while Vitest was running this test.
- If the error occurred after the test had been completed, this was the last documented test before it was thrown.
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

Reproduction steps

  1. Setup SvelteKit: https://svelte.dev/docs/kit/creating-a-project
  2. Setup Tailwind: https://tailwindcss.com/docs/guides/sveltekit
  3. Setup Vitest + Svelte Testing Library: https://testing-library.com/docs/svelte-testing-library/setup
    • Note: Don't install @sveltejs/vite-plugin-svelte since it isn't needed for SvelteKit and causes errors
  4. Add a workaround for window.matchMedia, otherwise it may produce errors: TypeError: window.matchMedia is not a function in Vitest vitest-dev/vitest#821
  5. Install userEvent for simulating user interaction: https://testing-library.com/docs/user-event/install
  6. Add teh code below to your repo
  7. Execute vitest

Code

Tooltip.svelte

<script lang="ts">
	import { popup, type PopupSettings } from '@skeletonlabs/skeleton';

	export let label: string;
	export let target: string;
	export let content: string;

	const popupHover: PopupSettings = {
		event: 'hover',
		target,
		placement: 'top'
	};
</script>

<button class="btn variant-filled [&>*]:pointer-events-none" use:popup={popupHover}>
	<span>{label}</span>
</button>

<div class="card p-4 variant-filled-secondary" data-popup={target}>
	<p>{content}</p>
	<div class="arrow variant-filled-secondary" />
</div>

TooltipTest.svelte

<script lang="ts">
	import { initializeStores, storePopup } from '@skeletonlabs/skeleton';
	import { computePosition, autoUpdate, offset, shift, flip, arrow } from '@floating-ui/dom';
	import Tooltip from './Tooltip.svelte';

	initializeStores();
	storePopup.set({ computePosition, autoUpdate, offset, shift, flip, arrow });
</script>

<Tooltip
	target="info"
	label="More Info"
	content="We're going to check if this component can be tested in Testing Library"
/>

Tooltip.test.ts

import { render } from '@testing-library/svelte';
import userEvent from '@testing-library/user-event';
import TooltipTest from './TooltipTest.svelte';

describe('TooltipTest.svelte', () => {
	it('should render the tooltip content on hover', async () => {
		const { getByText, queryByText } = render(TooltipTest);

		const triggerElement = getByText('More Info');
		await userEvent.hover(triggerElement);

		expect(
			getByText("We're going to check if this component can be tested in Testing Library")
		).toBeVisible();

		await userEvent.unhover(triggerElement);

		expect(
			queryByText("We're going to check if this component can be tested in Testing Library")
		).not.toBeVisible();
	});
});
@mcous
Copy link
Collaborator

mcous commented Oct 25, 2024

Hi @is-sematell, for better dubugability, would you mind packaging up your reproduction as a repository (or stackblitz or whatever)? Without your Vite config and other setup, I cannot reprodce. Also please see if you can make the reproduction more minimal; e.g. I doubt SvelteKit is in play here, so try to repro without it.

Looking at your stacktrace, the error originated from the jsdom library. In my experience, these issues are typically caused by bugs in either jsdom or Svelte itself. As a workaround, you could also try:

  • Switch to happy-dom as your fake DOM
  • Use Vitest’s browser mode to run your tests inside a real browser, instead

@is-sematell
Copy link
Author

is-sematell commented Oct 28, 2024

@mcous Hey, thanks for the prompt response. I've reproduced this issue on Stackblitz with a minimal stack:

  1. Open https://stackblitz.com/edit/vitejs-vite-kesal9
  2. After the packages install, kill the dev server in the terminal
  3. Execute npm run test

Switch to happy-dom as your fake DOM

Solves the issue 😄 Stackblitz: https://stackblitz.com/edit/vitejs-vite-gnytdg

Use Vitest’s browser mode to run your tests inside a real browser, instead

Also works! Stackblitz fork: https://stackblitz.com/edit/vitejs-vite-ygytdq

@mcous
Copy link
Collaborator

mcous commented Oct 28, 2024

Nice, thank you! Glad to hear that there are workarounds. Folks seem to like happy-dom, though I’ve found it to be a bit buggier in general than jsdom. That being said, the maintainer is super responsive and bugs I’ve filed have been resolved very quickly, so I think it’s a good choice if it works well for your suite.

I’ll dig in and see if I can isolate this to something specific in jsdom and follow up here accordingly

@mcous mcous added the wontfix This will not be worked on label Oct 28, 2024
@mcous
Copy link
Collaborator

mcous commented Oct 28, 2024

Ok, so unfortunately this looks like a bug in the nwsapi library that jsdom relies on for CSS selector parsing. They've got a few open issues that look like they could be the same issue:

If you are heavily invested in using JSDOM, some users in those threads are recommending forcing a resolution of nwsapi to an older version (2.2.2) to resolve the issue. Regardless, doesn't look like this is related to anything we're doing in this library nor in Skeleton.

Gonna poke around a little more, but will likely close this issue as a can't fix, since issues have already been filed with no movement in the relevant repo

@is-sematell
Copy link
Author

@mcous I see. Thank you so much for looking into it and helping out with some workarounds!

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

2 participants