Skip to content

Commit 0e23956

Browse files
Update unit tests
1 parent a04013d commit 0e23956

File tree

2 files changed

+43
-32
lines changed

2 files changed

+43
-32
lines changed

test/unit/node/heart.test.ts

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,10 @@
11
import { logger } from "@coder/logger"
22
import { readFile, writeFile, stat, utimes } from "fs/promises"
3-
import { Heart, heartbeatTimer } from "../../../src/node/heart"
4-
import { wrapper } from "../../../src/node/wrapper"
3+
import { Heart } from "../../../src/node/heart"
54
import { clean, mockLogger, tmpdir } from "../../utils/helpers"
65

76
const mockIsActive = (resolveTo: boolean) => jest.fn().mockResolvedValue(resolveTo)
87

9-
jest.mock("../../../src/node/wrapper", () => {
10-
const original = jest.requireActual("../../../src/node/wrapper")
11-
return {
12-
...original,
13-
wrapper: {
14-
exit: jest.fn(),
15-
},
16-
}
17-
})
18-
198
describe("Heart", () => {
209
const testName = "heartTests"
2110
let testDir = ""
@@ -27,7 +16,7 @@ describe("Heart", () => {
2716
testDir = await tmpdir(testName)
2817
})
2918
beforeEach(() => {
30-
heart = new Heart(`${testDir}/shutdown.txt`, undefined, mockIsActive(true))
19+
heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive(true))
3120
})
3221
afterAll(() => {
3322
jest.restoreAllMocks()
@@ -53,7 +42,7 @@ describe("Heart", () => {
5342

5443
expect(fileContents).toBe(text)
5544

56-
heart = new Heart(pathToFile, undefined, mockIsActive(true))
45+
heart = new Heart(pathToFile, mockIsActive(true))
5746
await heart.beat()
5847
// Check that the heart wrote to the heartbeatFilePath and overwrote our text
5948
const fileContentsAfterBeat = await readFile(pathToFile, { encoding: "utf8" })
@@ -63,7 +52,7 @@ describe("Heart", () => {
6352
expect(fileStatusAfterEdit.mtimeMs).toBeGreaterThan(0)
6453
})
6554
it("should log a warning when given an invalid file path", async () => {
66-
heart = new Heart(`fakeDir/fake.txt`, undefined, mockIsActive(false))
55+
heart = new Heart(`fakeDir/fake.txt`, mockIsActive(false))
6756
await heart.beat()
6857
expect(logger.warn).toHaveBeenCalled()
6958
})
@@ -82,7 +71,7 @@ describe("Heart", () => {
8271
it("should beat twice without warnings", async () => {
8372
// Use fake timers so we can speed up setTimeout
8473
jest.useFakeTimers()
85-
heart = new Heart(`${testDir}/hello.txt`, undefined, mockIsActive(true))
74+
heart = new Heart(`${testDir}/hello.txt`, mockIsActive(true))
8675
await heart.beat()
8776
// we need to speed up clocks, timeouts
8877
// call heartbeat again (and it won't be alive I think)
@@ -93,37 +82,47 @@ describe("Heart", () => {
9382
})
9483

9584
describe("heartbeatTimer", () => {
96-
beforeAll(() => {
85+
const testName = "heartbeatTimer"
86+
let testDir = ""
87+
beforeAll(async () => {
88+
await clean(testName)
89+
testDir = await tmpdir(testName)
9790
mockLogger()
9891
})
9992
afterAll(() => {
10093
jest.restoreAllMocks()
10194
})
95+
beforeEach(() => {
96+
jest.useFakeTimers()
97+
})
10298
afterEach(() => {
10399
jest.resetAllMocks()
100+
jest.clearAllTimers()
101+
jest.useRealTimers()
104102
})
105-
it("should call beat when isActive resolves to true", async () => {
103+
it("should call isActive when timeout expires", async () => {
106104
const isActive = true
107105
const mockIsActive = jest.fn().mockResolvedValue(isActive)
108-
const mockBeatFn = jest.fn()
109-
await heartbeatTimer(mockIsActive, mockBeatFn)
106+
const heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive)
107+
await heart.beat()
108+
jest.advanceTimersByTime(60 * 1000)
110109
expect(mockIsActive).toHaveBeenCalled()
111-
expect(mockBeatFn).toHaveBeenCalled()
112110
})
113111
it("should log a warning when isActive rejects", async () => {
114112
const errorMsg = "oh no"
115113
const error = new Error(errorMsg)
116114
const mockIsActive = jest.fn().mockRejectedValue(error)
117-
const mockBeatFn = jest.fn()
118-
await heartbeatTimer(mockIsActive, mockBeatFn)
115+
const heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive)
116+
await heart.beat()
117+
jest.advanceTimersByTime(60 * 1000)
118+
119119
expect(mockIsActive).toHaveBeenCalled()
120-
expect(mockBeatFn).not.toHaveBeenCalled()
121120
expect(logger.warn).toHaveBeenCalledWith(errorMsg)
122121
})
123122
})
124123

125-
describe("idleTimeout", () => {
126-
const testName = "idleHeartTests"
124+
describe("stateChange", () => {
125+
const testName = "stateChange"
127126
let testDir = ""
128127
let heart: Heart
129128
beforeAll(async () => {
@@ -140,12 +139,23 @@ describe("idleTimeout", () => {
140139
heart.dispose()
141140
}
142141
})
143-
it("should call beat when isActive resolves to true", async () => {
142+
it("should change to alive after a beat", async () => {
143+
heart = new Heart(`${testDir}/shutdown.txt`, mockIsActive(true))
144+
const mockOnChange = jest.fn()
145+
heart.onChange(mockOnChange)
146+
await heart.beat()
147+
148+
expect(mockOnChange.mock.calls[0][0]).toBe("alive")
149+
})
150+
it.only("should change to idle when not active", async () => {
144151
jest.useFakeTimers()
145-
heart = new Heart(`${testDir}/shutdown.txt`, 60, mockIsActive(true))
152+
heart = new Heart(`${testDir}/shutdown.txt`, () => new Promise((resolve) => resolve(false)))
153+
const mockOnChange = jest.fn()
154+
heart.onChange(mockOnChange)
155+
await heart.beat()
146156

147-
jest.advanceTimersByTime(60 * 1000)
148-
expect(wrapper.exit).toHaveBeenCalled()
157+
await jest.advanceTimersByTime(60 * 1000)
158+
expect(mockOnChange.mock.calls[1][0]).toBe("idle")
149159
jest.clearAllTimers()
150160
jest.useRealTimers()
151161
})

test/unit/node/main.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ jest.mock("@coder/logger", () => ({
1616
debug: jest.fn(),
1717
warn: jest.fn(),
1818
error: jest.fn(),
19+
named: jest.fn(),
1920
level: 0,
2021
},
2122
field: jest.fn(),
@@ -94,7 +95,7 @@ describe("main", () => {
9495

9596
// Mock routes module
9697
jest.doMock("../../../src/node/routes", () => ({
97-
register: jest.fn().mockResolvedValue(jest.fn()),
98+
register: jest.fn().mockResolvedValue({ disposeRoutes: jest.fn() }),
9899
}))
99100

100101
// Mock loadCustomStrings to succeed
@@ -131,7 +132,7 @@ describe("main", () => {
131132

132133
// Mock routes module
133134
jest.doMock("../../../src/node/routes", () => ({
134-
register: jest.fn().mockResolvedValue(jest.fn()),
135+
register: jest.fn().mockResolvedValue({ disposeRoutes: jest.fn() }),
135136
}))
136137

137138
// Import runCodeServer after mocking

0 commit comments

Comments
 (0)