Skip to content

Commit 0e4c062

Browse files
author
Joe Previte
committed
feat: add tests for node/heart.ts
1 parent c35bf13 commit 0e4c062

File tree

2 files changed

+80
-4
lines changed

2 files changed

+80
-4
lines changed

src/node/heart.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,21 @@ export class Heart {
2727

2828
logger.trace("heartbeat")
2929
fs.writeFile(this.heartbeatPath, "").catch((error) => {
30-
logger.warn(error.message)
30+
logger.warn(error.message) // TODO@jsjoeio - write code for this line
3131
})
3232
this.lastHeartbeat = Date.now()
3333
if (typeof this.heartbeatTimer !== "undefined") {
34-
clearTimeout(this.heartbeatTimer)
34+
clearTimeout(this.heartbeatTimer) // TODO@jsjoeio - write code for this line
3535
}
3636
this.heartbeatTimer = setTimeout(() => {
37-
this.isActive()
37+
this.isActive() // TODO@jsjoeio - start write code for here.
3838
.then((active) => {
3939
if (active) {
4040
this.beat()
4141
}
4242
})
4343
.catch((error) => {
44-
logger.warn(error.message)
44+
logger.warn(error.message) // TODO@jsjoeio - end.
4545
})
4646
}, this.heartbeatInterval)
4747
}

test/unit/node/heart.test.ts

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { readFile, writeFile } from "fs/promises"
2+
import { logger } from "@coder/logger"
3+
import { Heart } from "../../../src/node/heart"
4+
import { clean, mockLogger, tmpdir } from "../../utils/helpers"
5+
6+
describe("Heart", () => {
7+
function isFakeActive(resolveTo: boolean): () => Promise<boolean> {
8+
return () => new Promise((resolve) => setTimeout(() => resolve(resolveTo), 500))
9+
}
10+
const testName = "heartTests"
11+
let testDir = ""
12+
13+
beforeAll(async () => {
14+
mockLogger()
15+
await clean(testName)
16+
testDir = await tmpdir(testName)
17+
})
18+
19+
afterEach(() => {
20+
jest.clearAllMocks()
21+
})
22+
23+
it("should write to a file when given a valid file path", async () => {
24+
// Set up heartbeat file with contents
25+
const text = "test"
26+
const pathToFile = `${testDir}/file.txt`
27+
await writeFile(pathToFile, text)
28+
const fileContents = await readFile(pathToFile, { encoding: "utf8" })
29+
expect(fileContents).toBe(text)
30+
// call beat
31+
const heart = new Heart(pathToFile, isFakeActive(true))
32+
try {
33+
heart.beat()
34+
// Check that the heart wrote to the heartbeatFilePath and overwrote our text
35+
const fileContentsAfterBeat = await readFile(pathToFile, { encoding: "utf8" })
36+
expect(fileContentsAfterBeat).not.toBe(text)
37+
} catch (_e) {}
38+
heart.dispose()
39+
})
40+
41+
it("should log a warning when given an invalid file path", async () => {
42+
const heart = new Heart(`fakeDir/fake.txt`, isFakeActive(false))
43+
try {
44+
heart.beat()
45+
// HACK@jsjoeio - beat has some async logic but is not an async method
46+
// Therefore, we have to create an artificial wait in order to make sure
47+
// all async code has completed before asserting
48+
await new Promise((r) => setTimeout(r, 100))
49+
expect(logger.trace).toHaveBeenCalled()
50+
expect(logger.warn).toHaveBeenCalled()
51+
} catch (_e) {}
52+
heart.dispose()
53+
// expect(logger.warn).toHaveBeenCalledWith(`hi`)
54+
})
55+
56+
it("should let you know if the beat is alive", () => {
57+
const heart = new Heart(`${testDir}/shutdown.txt`, isFakeActive(true))
58+
try {
59+
heart.beat()
60+
} catch (_e) {}
61+
62+
const isAlive = heart.alive()
63+
expect(isAlive).toBe(true)
64+
heart.dispose()
65+
})
66+
67+
it("should shutdown when dispose is called", () => {
68+
try {
69+
const heart = new Heart(`${testDir}/shutdown.txt`, isFakeActive(true))
70+
heart.dispose()
71+
72+
const isAlive = heart.alive()
73+
expect(isAlive).toBe(false)
74+
} catch (_e) {}
75+
})
76+
})

0 commit comments

Comments
 (0)