test: scaffold component testing with Vitest

This commit is contained in:
Eric Liu 2024-11-23 10:53:14 -08:00
commit 8b477b12f9
9 changed files with 2324 additions and 39 deletions

2228
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -30,6 +30,8 @@
"css/*.css" "css/*.css"
], ],
"scripts": { "scripts": {
"test": "vitest",
"test:ui": "vite",
"test:src-types": "tsc types/**/*.ts", "test:src-types": "tsc types/**/*.ts",
"test:types": "svelte-check --workspace tests", "test:types": "svelte-check --workspace tests",
"lint": "prettier --write \"**/*.{svelte,md,js,json,ts}\"", "lint": "prettier --write \"**/*.{svelte,md,js,json,ts}\"",
@ -43,9 +45,15 @@
"flatpickr": "4.6.9" "flatpickr": "4.6.9"
}, },
"devDependencies": { "devDependencies": {
"@sveltejs/vite-plugin-svelte": "^3.1.2",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/svelte": "^5.2.6",
"@testing-library/user-event": "^14.5.2",
"autoprefixer": "^10.4.8", "autoprefixer": "^10.4.8",
"carbon-components": "10.58.12", "carbon-components": "10.58.12",
"carbon-icons-svelte": "^12.1.0", "carbon-icons-svelte": "^12.1.0",
"carbon-preprocess-svelte": "^0.11.7",
"jsdom": "^25.0.1",
"postcss": "^8.4.16", "postcss": "^8.4.16",
"prettier": "^3.3.3", "prettier": "^3.3.3",
"prettier-plugin-svelte": "^3.2.8", "prettier-plugin-svelte": "^3.2.8",
@ -55,7 +63,8 @@
"svelte": "^4.2.10", "svelte": "^4.2.10",
"svelte-check": "^4.0.6", "svelte-check": "^4.0.6",
"tinyglobby": "^0.2.10", "tinyglobby": "^0.2.10",
"typescript": "^5.6.3" "typescript": "^5.6.3",
"vitest": "^2.1.5"
}, },
"standard-version": { "standard-version": {
"skip": { "skip": {

5
tests/App.test.svelte Normal file
View file

@ -0,0 +1,5 @@
<script>
import TreeView from "./TreeView/TreeView.test.svelte";
</script>
<TreeView />

View file

@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import type { ComponentProps } from "svelte"; import type { ComponentProps } from "svelte";
import { TreeView } from "carbon-components-svelte"; import { Button, TreeView } from "carbon-components-svelte";
import type { TreeNodeId } from "carbon-components-svelte/TreeView/TreeView.svelte"; import type { TreeNodeId } from "carbon-components-svelte/TreeView/TreeView.svelte";
import Analytics from "carbon-icons-svelte/lib/Analytics.svelte"; import Analytics from "carbon-icons-svelte/lib/Analytics.svelte";
@ -12,7 +12,7 @@
{ id: 0, text: "AI / Machine learning", icon: Analytics }, { id: 0, text: "AI / Machine learning", icon: Analytics },
{ {
id: 1, id: 1,
text: 0, text: "Analytics",
nodes: [ nodes: [
{ {
id: 2, id: 2,
@ -49,17 +49,19 @@
}, },
]; ];
$: if (treeview) { $: console.log("selectedIds", selectedIds);
treeview.expandAll();
treeview.expandNodes((node) => { /* $: if (treeview) {
return +node.id > 0; treeview.expandAll();
}); treeview.expandNodes((node) => {
treeview.collapseAll(); return +node.id > 0;
treeview.collapseNodes((node) => { });
return node.disabled === true; treeview.collapseAll();
}); treeview.collapseNodes((node) => {
treeview.showNode(1); return node.disabled === true;
} });
treeview.showNode(1);
} */
</script> </script>
<TreeView <TreeView
@ -75,10 +77,7 @@
on:focus={({ detail }) => console.log("focus", detail)} on:focus={({ detail }) => console.log("focus", detail)}
let:node let:node
> >
{node.id}
{node.disabled}
{node.expanded}
{node.leaf}
{node.selected}
{node.text} {node.text}
</TreeView> </TreeView>
<Button on:click={treeview.expandAll}>Expand all</Button>

View file

@ -0,0 +1,40 @@
import { render, screen } from "@testing-library/svelte";
import { user } from "../setup-tests";
import TreeView from "./TreeView.test.svelte";
describe("TreeView", () => {
const getItemByName = (name: RegExp) => {
return screen.getByRole("treeitem", {
name,
selected: false,
});
};
const getSelectedItemByName = (name: RegExp) => {
return screen.getByRole("treeitem", {
name,
selected: true,
});
};
it("can select a node", async () => {
const consoleLog = vi.spyOn(console, "log");
render(TreeView);
const firstItem = getItemByName(/AI \/ Machine learning/);
expect(firstItem).toBeInTheDocument();
await user.click(firstItem);
expect(getSelectedItemByName(/AI \/ Machine learning/)).toBeInTheDocument();
expect(consoleLog).toBeCalledWith("selectedIds", [0]);
expect(consoleLog).toBeCalledWith("select", {
disabled: false,
expanded: false,
id: 0,
leaf: true,
selected: false,
text: "AI / Machine learning",
});
});
});

15
tests/index.html Normal file
View file

@ -0,0 +1,15 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<script type="module">
import "../css/all.css";
import App from "./App.test.svelte";
const app = new App({ target: document.body });
</script>
</body>
</html>

6
tests/setup-tests.ts Normal file
View file

@ -0,0 +1,6 @@
/// <reference types="vitest/globals" />
import "@testing-library/jest-dom/vitest";
import { userEvent } from "@testing-library/user-event";
import "../css/all.css";
export const user = userEvent.setup();

View file

@ -12,6 +12,7 @@
"noUnusedLocals": true, "noUnusedLocals": true,
"noUnusedParameters": true, "noUnusedParameters": true,
"strict": true, "strict": true,
"skipLibCheck": true,
"paths": { "paths": {
"carbon-components-svelte": ["./types"], "carbon-components-svelte": ["./types"],
"carbon-components-svelte/*": ["./types/*"] "carbon-components-svelte/*": ["./types/*"]

22
vite.config.ts Normal file
View file

@ -0,0 +1,22 @@
/// <reference types="vitest" />
import { svelte, vitePreprocess } from "@sveltejs/vite-plugin-svelte";
import { optimizeImports } from "carbon-preprocess-svelte";
import { defineConfig } from "vite";
export default defineConfig({
root: "./tests",
plugins: [
svelte({
preprocess: [vitePreprocess(), optimizeImports()],
}),
],
optimizeDeps: {
exclude: ["carbon-components-svelte", "carbon-icons-svelte"],
},
resolve: process.env.VITEST ? { conditions: ["browser"] } : undefined,
test: {
globals: true,
environment: "jsdom",
setupFiles: ["./tests/setup-tests.ts"],
},
});