as shown right here lets create a svelte project first.
$ npx degit sveltejs/template my-svelte-project
$ cd my-svelte-project
$ npm install
the created project has following package.json
{
"name": "my-svelte-project",
"version": "1.0.0",
"private": true,
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w",
"start": "sirv public --no-clear"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^17.0.0",
"@rollup/plugin-node-resolve": "^11.0.0",
"rollup": "^2.3.4",
"rollup-plugin-css-only": "^3.1.0",
"rollup-plugin-livereload": "^2.0.0",
"rollup-plugin-svelte": "^7.0.0",
"rollup-plugin-terser": "^7.0.0",
"svelte": "^3.0.0"
},
"dependencies": {
"sirv-cli": "^1.0.0"
}
}
As you can see here, we don't have any dependency about the testing of our application. Lets install test related dependencies.
npm i -D jest babel-jest @babel/preset-env svelte-jester
jest* is the test runner and it also has the assertion and mocking functionalities. babel-jest and @babel/preset-env is for using latest javascript functionalities in our test modules. Like using es6 imports. Jest cannot run test modules having es6 imports in them. So we will configure jest to transform the test modules with babel. And last one is svelte-jester. We are going to import Svelte files in our test modules. Jest does not know how to process them. So we are going to use this svelte-jester to transform those files before jest runs the tests.
We will also need additional dependencies specifically for testing svelte components. And for that we are going to use testing-library
npm i -D @testing-library/svelte @testing-library/jest-dom
@testing-library/svelte is for rendering svelte components in our test functions
@testing-library/jest-dom is for having custom DOM related element matcher functions for Jest.
Now we need to configure jest. We can do this configuration in package.json
// package.json
},
// after depedencies we can add
"jest": {
"transform": {
"^.+\\.svelte$": "svelte-jester",
"^.+\\.js$": "babel-jest"
},
"moduleFileExtensions": [
"js",
"svelte"
],
"testEnvironment": "jsdom"
}
The first configuration we are setting here is the transform. And with this configuration, we are telling if a file used in test module has extension of *.svelte, then svelte-jester will transform it. If file has *.js extension, then babel-jest will transform it.
The second configuration is moduleFileExtensions and in this one we are listing the file extensions in our test modules. Jest can watch our files and run tests as soon as it detects changes in them. And with this list, we are telling jest to watch the changes in the files having these extensions.
And the last configuration, testEnvironment will be set to jsdom . Before jest version 27, this was by default jsdom. With v27 it is by default node. Since this is going to be testing a web application, the environment must be set to jsdom.
For babel transform part, we also need to add a configuration file to our project. In the folder where the package.json is, let's create a file with name of babel.config.js
.
And paste following part into that file. reference is here
// babel.config.js
module.exports = {
presets: [['@babel/preset-env', {targets: {node: 'current'}}]],
};
we completed our configuration. Finally lets add test script.
// package.json
"scripts": {
// adding
"test": "jest --watchAll"
},
Let's run test from console by running
npm test
Now jest is watching our source code and it is going to run the tests as soon as it detects changes in js and svelte files. Since we don't have any test module yet, you will see following message in console.
No tests found, exiting with code 0
now lets create a test module. Jest is looking for files having extensions either *.spec.js or *.test.js. I choose .spec.js.
Lets create a new file. App.spec.js
// 1 - first lets import the target component.
// lets test App.svelte
import App from './App.svelte';
// 2 - and we are going to render this component
// with @testing-library . lets import
import { render, screen } from '@testing-library/svelte';
// 3 - and lets also import
import '@testing-library/jest-dom';
// 4 - and lets add our test
it('has Hello Text', () => {
// 5 - first we render the App.svelte
render(App);
// 6 - Then we are going to query the element we
// are looking for. We will use query functions
// coming with screen.
const message = screen.queryByText('Hello Text');
// 7 - And last part is the assertion
expect(message).toBeInTheDocument();
})
Now in test console we are going to see following output
FAIL src/App.spec.js
✕ has Hello Text (46 ms)
● has Hello Text
expect(received).toBeInTheDocument()
received value must be an HTMLElement or an SVGElement.
Received has value: null
6 | render(App);
7 | const message = screen.queryByText('Hello Text');
> 8 | expect(message).toBeInTheDocument();
| ^
9 | })
at __EXTERNAL_MATCHER_TRAP__ (node_modules/expect/build/index.js:342:30)
at Object.toBeInTheDocument (node_modules/expect/build/index.js:343:15)
at Object.<anonymous> (src/App.spec.js:8:21)
console.warn
<App> was created without expected prop 'name'
at new App (src/App.svelte:123:12)
at render (node_modules/@testing-library/svelte/dist/pure.js:81:21)
at Object.<anonymous> (src/App.spec.js:6:5)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 1 total
Snapshots: 0 total
Time: 2.067 s
Ran all test suites.
Watch Usage: Press w to show more.
The App does not have Hello Text in it. Lets clear everything in App.svelte and just add the expected text to it.
<!-- App.svelte -->
Hello Text
Now the test is passing and you will see following output in console.
PASS src/App.spec.js
✓ has Hello Text (16 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.953 s, estimated 2 s
We completed test setup of our project.
Github repo for this project can be found here
You can also check this video tutorial for the same setup steps of svelte projects
And if you would be interested, I have a full course TDD in svelte. Svelte with Test Driven Development
Thanks for reading