@7365admin1/module-hygiene 4.30.1 → 4.30.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@7365admin1/module-hygiene",
3
3
  "license": "MIT",
4
- "version": "4.30.1",
4
+ "version": "4.30.2",
5
5
  "author": "7365admin1",
6
6
  "main": "dist/index.js",
7
7
  "module": "dist/index.mjs",
@@ -19,6 +19,7 @@ import test from "node:test";
19
19
  import assert from "node:assert/strict";
20
20
  import {
21
21
  COMPLETION_PHOTO_MESSAGE,
22
+ readCompletion,
22
23
  requiresCompletionPhoto,
23
24
  } from "./.build/completion-photo.util.mjs";
24
25
 
@@ -127,6 +128,68 @@ test("REJECTING is never blocked, even completing the set", () => {
127
128
  );
128
129
  });
129
130
 
131
+ /* ── which approve finishes the set: ONE definition with the clients ───── */
132
+
133
+ test("an approve finishes the set when every other unit is approved or rejected", () => {
134
+ const units = [
135
+ { unit: "u1", approve: true, reject: false, status: "completed" },
136
+ { unit: "u2", approve: false, reject: true, status: "completed" },
137
+ { unit: "u3", approve: false, reject: false, status: "open" },
138
+ ];
139
+ assert.equal(readCompletion(units, "u3").completesSet, true);
140
+ // Intermediate: another unit is still untouched.
141
+ assert.equal(readCompletion(units, "u1").completesSet, false);
142
+ });
143
+
144
+ test("actioned means approve/reject, NOT status — status at rest is open/closed", () => {
145
+ /*
146
+ * Staging holds units that are `closed` while approved or rejected. The units
147
+ * list (`isFullyActioned`) and both clients count those as done, so the photo
148
+ * rule must too, or the server and the screen disagree about the last tick.
149
+ */
150
+ const units = [
151
+ { unit: "u1", approve: true, reject: false, status: "closed" },
152
+ { unit: "u2", approve: false, reject: false, status: "open" },
153
+ ];
154
+ assert.equal(readCompletion(units, "u2").completesSet, true);
155
+
156
+ // And a status alone, with neither flag, is not an action.
157
+ const statusOnly = [
158
+ { unit: "u1", approve: false, reject: false, status: "completed" },
159
+ { unit: "u2", approve: false, reject: false, status: "open" },
160
+ ];
161
+ assert.equal(readCompletion(statusOnly, "u2").completesSet, false);
162
+ });
163
+
164
+ test("a one-unit set: its only tick finishes it; an empty set finishes nothing", () => {
165
+ assert.equal(readCompletion([{ unit: "u1" }], "u1").completesSet, true);
166
+ assert.deepEqual(readCompletion([], "u1"), {
167
+ completesSet: false,
168
+ hasEvidence: false,
169
+ });
170
+ });
171
+
172
+ test("ids compare as strings (ObjectId vs the route param)", () => {
173
+ const oid = { toString: () => "68f05fbe0c11062938dadad9" };
174
+ const units = [
175
+ { unit: oid, approve: false, reject: false },
176
+ { unit: "u2", approve: true, reject: false },
177
+ ];
178
+ assert.equal(
179
+ readCompletion(units, "68f05fbe0c11062938dadad9").completesSet,
180
+ true
181
+ );
182
+ });
183
+
184
+ test("evidence counts only OTHER units' photos", () => {
185
+ const units = [
186
+ { unit: "u1", approve: false, reject: true, attachment: ["f1"] },
187
+ { unit: "u2", approve: false, reject: false, attachment: [] },
188
+ ];
189
+ assert.equal(readCompletion(units, "u2").hasEvidence, true);
190
+ assert.equal(readCompletion(units, "u1").hasEvidence, false);
191
+ });
192
+
130
193
  /* ── controls ──────────────────────────────────────────────────────────── */
131
194
 
132
195
  test("CONTROL: the rule can actually say yes", () => {