Skip to content

Commit 6a1656f

Browse files
committed
test: add unit tests
1 parent 1aaa32f commit 6a1656f

File tree

3 files changed

+170
-0
lines changed

3 files changed

+170
-0
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { describe, expect, it, vi } from "vitest";
2+
3+
import { ILogger } from "../../src/internal.js";
4+
import { NotifierFactory } from "../../src/notifier/notifier.factory.js";
5+
import { NotifierConfig } from "../../src/notifier/notifierConfig.interface.js";
6+
import { NullNotifier } from "../../src/notifier/null.notifier.js";
7+
import { SlackNotifier } from "../../src/notifier/slack.notifier.js";
8+
9+
describe("NotifierFactory", () => {
10+
const logger: ILogger = {
11+
debug: vi.fn(),
12+
error: vi.fn(),
13+
info: vi.fn(),
14+
warn: vi.fn(),
15+
};
16+
17+
it("creates SlackNotifier instance with valid Slack configuration", () => {
18+
const config: NotifierConfig<"slack"> = {
19+
notifierProvider: "slack",
20+
opts: {
21+
webhookUrl: "https://hooks.slack.com/test",
22+
},
23+
};
24+
25+
const notifier = NotifierFactory.create(config, logger);
26+
expect(notifier).toBeInstanceOf(SlackNotifier);
27+
});
28+
29+
it("creates NullNotifier instance for null provider", () => {
30+
const config = {
31+
notifierProvider: "null" as const,
32+
};
33+
34+
const notifier = NotifierFactory.create(config, logger);
35+
expect(notifier).toBeInstanceOf(NullNotifier);
36+
});
37+
});
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { describe, expect, it, vi } from "vitest";
2+
3+
import { NotifierContext } from "../../src/notifier/notifier.interface.js";
4+
import { NullNotifier } from "../../src/notifier/null.notifier.js";
5+
import { AnyIndexerFetchedEvent, ChainId } from "../../src/types/index.js";
6+
7+
describe("NullNotifier", () => {
8+
it("sends message without performing any action", async () => {
9+
const notifier = new NullNotifier();
10+
const context: NotifierContext = {
11+
chainId: 1 as ChainId,
12+
event: { eventName: "ProfileCreated" } as AnyIndexerFetchedEvent,
13+
stack: "test stack",
14+
};
15+
16+
const consoleSpy = vi.spyOn(console, "log");
17+
18+
const result = await notifier.send("test message", context);
19+
expect(result).toBeUndefined();
20+
expect(consoleSpy).not.toHaveBeenCalled();
21+
});
22+
});
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { IncomingWebhook } from "@slack/webhook";
2+
import { beforeEach, describe, expect, it, vi } from "vitest";
3+
4+
import { ILogger } from "../../src/internal.js";
5+
import { NotifierContext } from "../../src/notifier/notifier.interface.js";
6+
import { SlackNotifier, SlackOptions } from "../../src/notifier/slack.notifier.js";
7+
import { AnyIndexerFetchedEvent, ChainId } from "../../src/types/index.js";
8+
9+
vi.mock("@slack/webhook", () => ({
10+
IncomingWebhook: vi.fn().mockImplementation(() => ({
11+
send: vi.fn().mockResolvedValue(undefined),
12+
})),
13+
}));
14+
15+
describe("SlackNotifier", () => {
16+
let logger: ILogger;
17+
let options: SlackOptions;
18+
let notifier: SlackNotifier;
19+
let mockWebhook: IncomingWebhook;
20+
21+
beforeEach(() => {
22+
logger = {
23+
debug: vi.fn(),
24+
error: vi.fn(),
25+
info: vi.fn(),
26+
warn: vi.fn(),
27+
};
28+
29+
options = {
30+
webhookUrl: "https://hooks.slack.com/test",
31+
username: "Test Bot",
32+
iconEmoji: ":test:",
33+
};
34+
35+
notifier = new SlackNotifier(options, logger);
36+
mockWebhook = notifier["webhook"];
37+
});
38+
39+
it("initializes with default values when minimal options provided", () => {
40+
const minimalNotifier = new SlackNotifier(
41+
{ webhookUrl: "https://hooks.slack.com/test" },
42+
logger,
43+
);
44+
expect(minimalNotifier).toBeDefined();
45+
});
46+
47+
it("sends formatted message to Slack", async () => {
48+
const message = "Test error message";
49+
const context: NotifierContext = {
50+
chainId: 1 as ChainId,
51+
event: { eventName: "ProfileCreated" } as AnyIndexerFetchedEvent,
52+
stack: "test stack",
53+
};
54+
55+
await notifier.send(message, context);
56+
57+
expect(mockWebhook.send).toHaveBeenCalledWith(
58+
expect.objectContaining({
59+
username: "Test Bot",
60+
icon_emoji: ":test:",
61+
blocks: expect.arrayContaining([
62+
expect.objectContaining({
63+
text: expect.objectContaining({
64+
text: expect.stringContaining("1"),
65+
}),
66+
}),
67+
]),
68+
}),
69+
);
70+
expect(logger.debug).toHaveBeenCalled();
71+
});
72+
73+
it("handles stack trace in context", async () => {
74+
const message = "Test error message";
75+
const context: NotifierContext = {
76+
chainId: 1 as ChainId,
77+
event: { eventName: "ProfileCreated" } as AnyIndexerFetchedEvent,
78+
stack: "Error stack trace",
79+
};
80+
81+
await notifier.send(message, context);
82+
83+
expect(mockWebhook.send).toHaveBeenCalledWith(
84+
expect.objectContaining({
85+
blocks: expect.arrayContaining([
86+
expect.objectContaining({
87+
text: expect.objectContaining({
88+
text: expect.stringContaining("Error stack trace"),
89+
}),
90+
}),
91+
]),
92+
}),
93+
);
94+
});
95+
96+
it("logs error when webhook send fails", async () => {
97+
const error = new Error("Webhook error");
98+
vi.mocked(mockWebhook.send).mockRejectedValueOnce(error);
99+
100+
const message = "Test error message";
101+
const context: NotifierContext = {
102+
chainId: 1 as ChainId,
103+
event: { eventName: "ProfileCreated" } as AnyIndexerFetchedEvent,
104+
stack: "test stack",
105+
};
106+
107+
await notifier.send(message, context);
108+
109+
expect(logger.error).toHaveBeenCalled();
110+
});
111+
});

0 commit comments

Comments
 (0)