Skip to content

Commit 1bd2fa2

Browse files
test(executeQuery): add core action test suite
1 parent 319e4f7 commit 1bd2fa2

1 file changed

Lines changed: 164 additions & 0 deletions

File tree

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
const assert = require("node:assert/strict");
2+
const {test, describe} = require("node:test");
3+
const group = typeof describe === "function" ? describe : (_n, fn) => fn();
4+
5+
// Add tests/shims to module resolution so 'logger' and 'node_helper' resolve to our shims
6+
const path = require("node:path");
7+
const ModuleLib = require("module");
8+
const shimDir = path.resolve(__dirname, "../shims");
9+
process.env.NODE_PATH = shimDir + (process.env.NODE_PATH ? path.delimiter + process.env.NODE_PATH : "");
10+
if (typeof ModuleLib._initPaths === "function") ModuleLib._initPaths();
11+
12+
// Import node_helper.js (returns the helper instance from our shimmed NodeHelper.create)
13+
const helperFactory = require("../../node_helper.js");
14+
15+
function freshHelper () {
16+
const h = Object.assign({}, helperFactory);
17+
h.__sent = [];
18+
h.__responses = [];
19+
h.sendSocketNotification = (what, payload) => { h.__sent.push({what, payload}); };
20+
h.sendResponse = (_res, err, data) => { h.__responses.push({err, data}); };
21+
return h;
22+
}
23+
24+
group("executeQuery core actions", () => {
25+
test("HIDE forwards query unchanged to socket", () => {
26+
const h = freshHelper();
27+
const q = {action: "HIDE", module: "clock"};
28+
const res = {};
29+
const result = h.executeQuery(q, res);
30+
assert.equal(result, true);
31+
assert.deepEqual(h.__sent[0], {what: "HIDE", payload: q});
32+
assert.equal(h.__responses.length, 1);
33+
});
34+
35+
test("SHOW and TOGGLE also forward query", () => {
36+
const h = freshHelper();
37+
const res = {};
38+
h.executeQuery({action: "SHOW", module: "all"}, res);
39+
h.executeQuery({action: "TOGGLE", module: "module_1_clock"}, res);
40+
assert.deepEqual(h.__sent[0], {what: "SHOW", payload: {action: "SHOW", module: "all"}});
41+
assert.deepEqual(h.__sent[1], {what: "TOGGLE", payload: {action: "TOGGLE", module: "module_1_clock"}});
42+
assert.equal(h.__responses.length, 2);
43+
});
44+
45+
test("BRIGHTNESS forwards numeric value", () => {
46+
const h = freshHelper();
47+
const res = {};
48+
const q = {action: "BRIGHTNESS", value: 90};
49+
const ok = h.executeQuery(q, res);
50+
assert.equal(ok, true);
51+
assert.deepEqual(h.__sent[0], {what: "BRIGHTNESS", payload: 90});
52+
assert.equal(h.__responses.length, 1);
53+
});
54+
55+
test("TEMP forwards value and responds", () => {
56+
const h = freshHelper();
57+
const res = {};
58+
const q = {action: "TEMP", value: 22};
59+
const ok = h.executeQuery(q, res);
60+
assert.equal(ok, true);
61+
assert.deepEqual(h.__sent[0], {what: "TEMP", payload: 22});
62+
assert.equal(h.__responses.length, 1);
63+
});
64+
65+
test("SHOW_ALERT builds default payload when fields missing", () => {
66+
const h = freshHelper();
67+
const res = {};
68+
const ok = h.executeQuery({action: "SHOW_ALERT"}, res);
69+
assert.equal(ok, true);
70+
assert.equal(h.__sent[0].what, "SHOW_ALERT");
71+
assert.deepEqual(h.__sent[0].payload, {type: "alert", title: "Note", message: "Attention!", timer: 4000});
72+
assert.equal(h.__responses.length, 1);
73+
});
74+
75+
test("SHOW_ALERT respects provided fields and multiplies timer by 1000", () => {
76+
const h = freshHelper();
77+
const res = {};
78+
h.executeQuery({action: "SHOW_ALERT", type: "warning", title: "T", message: "M", timer: 2}, res);
79+
assert.deepEqual(h.__sent[0], {what: "SHOW_ALERT", payload: {type: "warning", title: "T", message: "M", timer: 2000}});
80+
});
81+
82+
test("HIDE_ALERT and REFRESH emit simple notifications", () => {
83+
const h = freshHelper();
84+
const res = {};
85+
h.executeQuery({action: "HIDE_ALERT"}, res);
86+
h.executeQuery({action: "REFRESH"}, res);
87+
assert.deepEqual(h.__sent[0], {what: "HIDE_ALERT", payload: undefined});
88+
assert.deepEqual(h.__sent[1], {what: "REFRESH", payload: undefined});
89+
assert.equal(h.__responses.length, 2);
90+
});
91+
92+
test("NOTIFICATION without payload sends undefined payload", () => {
93+
const h = freshHelper();
94+
const res = {};
95+
const ok = h.executeQuery({action: "NOTIFICATION", notification: "HELLO"}, res);
96+
assert.equal(ok, true);
97+
assert.deepEqual(h.__sent[0], {what: "NOTIFICATION", payload: {notification: "HELLO", payload: undefined}});
98+
assert.equal(h.__responses.length, 1);
99+
});
100+
101+
test("NOTIFICATION parses JSON string payload", () => {
102+
const h = freshHelper();
103+
const res = {};
104+
const ok = h.executeQuery({action: "NOTIFICATION", notification: "HELLO", payload: "{\"a\":1}"}, res);
105+
assert.equal(ok, true);
106+
assert.deepEqual(h.__sent[0], {what: "NOTIFICATION", payload: {notification: "HELLO", payload: {a: 1}}});
107+
});
108+
109+
test("NOTIFICATION passes raw string when payload is not JSON", () => {
110+
const h = freshHelper();
111+
const res = {};
112+
h.executeQuery({action: "NOTIFICATION", notification: "HELLO", payload: "plain"}, res);
113+
assert.deepEqual(h.__sent[0], {what: "NOTIFICATION", payload: {notification: "HELLO", payload: "plain"}});
114+
});
115+
116+
test("NOTIFICATION invalid JSON returns error via sendResponse", () => {
117+
const h = freshHelper();
118+
const res = {};
119+
const ok = h.executeQuery({action: "NOTIFICATION", notification: "HELLO", payload: "{"}, res);
120+
assert.equal(ok, true);
121+
assert.equal(h.__sent.length, 0, "should not send socket notification on parse error");
122+
assert.equal(h.__responses.length, 1);
123+
assert.ok(h.__responses[0].err instanceof Error);
124+
});
125+
126+
test("USER_PRESENCE forwards boolean and updates state", () => {
127+
const h = freshHelper();
128+
const res = {};
129+
const ok = h.executeQuery({action: "USER_PRESENCE", value: true}, res);
130+
assert.equal(ok, true);
131+
assert.deepEqual(h.__sent[0], {what: "USER_PRESENCE", payload: true});
132+
assert.equal(h.userPresence, true);
133+
assert.equal(h.__responses.length, 1);
134+
});
135+
136+
test("MANAGE_CLASSES: string key maps to lower-case actions and sends modules", () => {
137+
const h = freshHelper();
138+
h.thisConfig = {classes: {Group1: {hide: "calendar", show: ["newsfeed"], toggle: ["clock", "weather"]}}};
139+
const res = {};
140+
h.executeQuery({action: "MANAGE_CLASSES", payload: {classes: "Group1"}}, res);
141+
// Order depends on object key iteration; check membership instead of order.
142+
const sent = h.__sent.reduce((acc, s) => acc.add(`${s.what}:${JSON.stringify(s.payload)}`), new Set());
143+
assert.ok(sent.has("HIDE:{\"module\":\"calendar\"}"));
144+
assert.ok(sent.has("SHOW:{\"module\":\"newsfeed\"}"));
145+
assert.ok(sent.has("TOGGLE:{\"module\":\"clock\"}"));
146+
assert.ok(sent.has("TOGGLE:{\"module\":\"weather\"}"));
147+
assert.equal(h.__responses.length, 1);
148+
});
149+
150+
test("MANAGE_CLASSES: array of class names processes each", () => {
151+
const h = freshHelper();
152+
h.thisConfig = {classes: {
153+
A: {show: ["one"]},
154+
B: {hide: ["two"], toggle: "three"}
155+
}};
156+
const res = {};
157+
h.executeQuery({action: "MANAGE_CLASSES", payload: {classes: ["A", "B"]}}, res);
158+
const sent = h.__sent.reduce((acc, s) => acc.add(`${s.what}:${JSON.stringify(s.payload)}`), new Set());
159+
assert.ok(sent.has("SHOW:{\"module\":\"one\"}"));
160+
assert.ok(sent.has("HIDE:{\"module\":\"two\"}"));
161+
assert.ok(sent.has("TOGGLE:{\"module\":\"three\"}"));
162+
assert.equal(h.__responses.length, 1);
163+
});
164+
});

0 commit comments

Comments
 (0)