I am building a Svelte component library for my project and have run into several issues, particularly when trying to test components with slots. Here’s the error I’m facing:
Object literal may only specify known properties, and 'slots' does not exist in type 'SvelteComponentOptions<SvelteComponent
stackblitz example
From what I understand, the slots
field should exist according to the typings in svelte-shims.d.ts
. However, my test setup seems to contradict this when I try to use the Svelte Testing Library example for slots testing
svelte-shims.d.ts
svelte-testing-library – example slots
Other problems but I managed to find workaround along the way.
(!) [plugin typescript] src/index.ts (2:35): @rollup/plugin-typescript TS2307: Cannot find module './Button.svelte'
-
To resolve this, I had to explicitly add
import 'svelte';
insrc/index.ts
file. -
When trying to use
[email protected]
, it threw an error complaining about a missingsrc/app.html
file. I eventually switched to Rollup for bundling.
Any thoughts?
I appreciate any insights or suggestions.
vitest.config.js
import { defineConfig } from 'vitest/config'
import { svelte } from '@sveltejs/vite-plugin-svelte'
import { sveltePreprocess } from 'svelte-preprocess'
export default defineConfig({
plugins: [
import { defineConfig } from 'vitest/config';
import { svelte } from '@sveltejs/vite-plugin-svelte';
import { sveltePreprocess } from 'svelte-preprocess';
export default defineConfig(({ mode }) => ({
plugins: [
svelte({
hot: !process.env.VITEST,
preprocess: [sveltePreprocess({ typescript: true })]
})
],
resolve: {
conditions: mode === 'test' ? ['browser'] : [],
},
test: {
globals: true,
environment: 'jsdom',
},
}));
Button.svelte
<script lang="ts">
export let onClick: () => void = () => {};
</script>
<button on:click={onClick}>
<slot></slot>
</button>
Button.test.ts
import { getByText, render, waitFor } from '@testing-library/svelte';
import Button from './Button.svelte';
import { describe, it, expect } from "vitest";
describe('Button', () => {
it("it should render", async () => {
const text = "Submit";
const { getByText } = render(Button, {
slots: { default: text },
});
expect(getByText(text)).toBeInTheDocument();
})
});
tsconfig.json
{
"extends": "@tsconfig/svelte/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler",
"types": ["vitest/globals", "@testing-library/jest-dom"]
},
"include": ["src/**/*"],
"exclude": ["node_modules/*"],
}
rollup.config.js
import svelte from 'rollup-plugin-svelte';
import resolve from '@rollup/plugin-node-resolve';
import terser from '@rollup/plugin-terser';
import { sveltePreprocess } from "svelte-preprocess";
import typescript from "@rollup/plugin-typescript";
import json from '@rollup/plugin-json';
const { default: { name: pkg_name, module, main }} = await import('./package.json', { with: { type: "json" }, });
const name = pkg_name
.replace(/^(@S+/)?(svelte-)?(S+)/, '$3')
.replace(/^w/, m => m.toUpperCase())
.replace(/-w/g, m => m[1].toUpperCase());
const production = !process.env.ROLLUP_WATCH
export default {
input: 'src/index.ts',
output: [
{
sourcemap: true,
format: 'cjs',
file: main,
},
{
sourcemap: true,
format: 'esm',
file: module,
}
],
plugins: [
svelte({
preprocess: sveltePreprocess({ sourceMap: true }),
compilerOptions: {
dev: !production
},
emitCss: false,
}),
resolve({
browser: true,
dedupe: ['svelte']
}),
terser(),
json(),
typescript({
sourceMap: true,
declaration: true,
outDir: "dist",
exclude: ['**/*.test.ts', '**/*.spec.ts', '**/__tests__/**']
}),
]
};
package.json
{
"name": "web-component",
"version": "0.1.0",
"description": "",
"type": "module",
"module": "dist/index.mjs",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "rollup --config",
"test": "vitest",
"coverage": "vitest run --coverage"
},
"license": "MIT",
"files": [
"src",
"dist"
],
"devDependencies": {
"@rollup/plugin-json": "^6.1.0",
"@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/plugin-terser": "0.4.4",
"@rollup/plugin-typescript": "^12.1.1",
"@tsconfig/svelte": " ^5.0.4",
"rollup": "^4.28.1",
"rollup-plugin-filesize": "^10.0.0",
"rollup-plugin-svelte": "^7.2.2",
"svelte-check": "^4.1.1",
"svelte-preprocess": "^6.0.3",
"tslib": "^2.8.1",
"typescript": "^5.7.2",
"vitest": "^2.1.8",
"jsdom": "^25.0.1",
"@sveltejs/vite-plugin-svelte": "^4.0.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/svelte": "^5.2.4",
"@vitest/coverage-v8": "^2.1.8"
},
"peerDependencies": {
"svelte": "^5.8.1"
}
}