In previous episode, fileInfo
function in preload.js
got quite long, so let's write some tests.
We can start by installing jest
, which looks like the most popular backend testing framework for Javascript:
$ npm install --save-dev jest
And we can also put it in package.json
for convenience:
"test": "jest"
Problem with testing preload.js
There are two conventions for organizing tests in Javascript - either moving all specs to separate folder, or putting __tests__
folders all over the place. I never really understood the appeal of scattering tests files all over, so we'll be doing the tidy thing and have them all in spec
.
The first thing I tried was just creating spec/preload.spec.js
and importing preload.js
from there. Unfortunately that runs into contextBridge.exposeInMainWorld
not being defined.
Rewrite preload.js
So let's do the easy thing - reduce preload.js
to just this:
let { contextBridge } = require("electron")
let api = require("./preload/api")
contextBridge.exposeInMainWorld("api", api)
Which doesn't need any unit tests, as it's just one line of code. It will get covered by integration tests later.
And let's move the rest of the code from preload.js
to preload/api.js
, with just this export
:
module.exports = {
directoryContents,
currentDirectory,
}
Add tests
I'm not interested in checking low level system calls, so I just created:
spec/preload/examples
-
spec/preload/examples/example_01.md
- small file with 5 bytes -
spec/preload/examples/example_02.md
- symlink toexample_01.md
-
spec/preload/examples/example_03
- directory -
spec/preload/examples/example_03/.gitkeep
- empty file so it actually stays in git, as git does not do empty directories -
spec/preload/examples/example_04
- link toexample_03
-
spec/preload/examples/missing
- broken symlink
This is good enough for our test - it won't verify special files, and files deleted while we're running our function, but let's not get too fancy.
Unfortunately we have a few more problems. We don't know what will be the exact Date
returned, and if we just put the files in the repository, and check them out, there's no guarantee they'll come out with the same last modified date.
So I thought I'd just do something along the lines of:
expect(result[0].mtime).toBeInstanceOf(Date)
But that returned mysterious:
Expected constructor: Date
Received constructor: Date
Looks like node has multiple Date
classes? It's very incidental to what we're doing so I didn't investigate it further. If anyone knows the answer, let me know in comments.
spec/preload/api.spec.js
And so here's our spec file:
let path = require('path')
let api = require("../../preload/api.js")
test("currentDirectory", () => {
expect(api.currentDirectory()).toEqual(path.join(__dirname, "../.."))
})
test("directoryContents", async () => {
let examplesDir = `${__dirname}/examples`
let result = await api.directoryContents(examplesDir)
expect(result).toMatchObject([
{
linkTarget: null,
name: "example_01.md",
mtime: expect.anything(),
size: 6,
type: "file",
},
{
linkTarget: "example_01.md",
name: "example_02.md",
mtime: expect.anything(),
size: 6,
type: "file",
},
{
linkTarget: null,
name: "example_03",
mtime: expect.anything(),
type: "directory",
},
{
linkTarget: "example_03",
name: "example_04",
mtime: expect.anything(),
type: "directory",
},
{
linkTarget: "example_05.md",
name: "missing",
type: "broken",
},
])
})
Of course we could do a lot more testing, but it's a start.
How to test backend code
To be honest we shouldn't even be putting that much code in the preload
- it should just do minimum work to setup some calls to the backend, and the logic should be in the backend.
We can do very similar testing for anything in the backend - just move all complicated logic to separate files, and test those files. They are executed in regular node environment.
Then add some integration tests for the whole thing.
Results
Here's the results:
In the next few episodes, we'll be doing some purely frontend coding for our app.
As usual, all the code for the episode is here.
Top comments (0)