@serverkgg/bridge 0.1.2 → 0.1.4
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 +3 -2
- package/rules/package.md +65 -0
- package/src/blog/articleFrontmatter.test.ts +10 -10
- package/src/blog/compile.test.ts +9 -9
- package/src/bot/botDeploy.test.ts +16 -16
- package/src/bot/botEnvironment.test.ts +8 -8
- package/src/bot/botIdentity.test.ts +12 -12
- package/src/bot/botPanel.test.ts +13 -13
- package/src/bot/botPanel.ts +4 -4
- package/src/bot/botState.test.ts +3 -3
- package/src/bot/botTerminal.test.ts +5 -5
- package/src/bot/botVariables.test.ts +8 -8
- package/src/bot/detect/botToken.test.ts +6 -6
- package/src/bot/detect/detect.test.ts +21 -21
- package/src/bot/detect/detectTable.test.ts +5 -5
- package/src/bot/detect/envExample.test.ts +2 -2
- package/src/bot/detect/envScan.test.ts +4 -4
- package/src/bot/detect/inferBotPlatform.test.ts +4 -4
- package/src/bot/detect/keys.test.ts +3 -3
- package/src/bot/detect/sensitiveKey.test.ts +5 -5
- package/src/bot/detect/serverkJson.test.ts +5 -5
- package/src/catalogs/curseforge.test.ts +35 -35
- package/src/catalogs/thunderstore.test.ts +9 -9
- package/src/cli/detectTable.test.ts +3 -3
- package/src/cli/link.test.ts +11 -11
- package/src/cli/main.ts +8 -0
- package/src/cli/rules.test.ts +198 -0
- package/src/cli/rules.ts +188 -0
- package/src/cli/validate.test.ts +179 -31
- package/src/cli/validate.ts +44 -0
- package/src/codecs/ini.test.ts +13 -13
- package/src/codecs/javaProperties.test.ts +11 -11
- package/src/codecs/sourceCfg.test.ts +14 -14
- package/src/codecs/xmlProperties.test.ts +10 -10
- package/src/core/bridgePort.test.ts +6 -6
- package/src/core/bridgeUserError.test.ts +4 -4
- package/src/core/bridgeValue.test.ts +5 -5
- package/src/core/describeDownloadFailure.test.ts +12 -12
- package/src/core/describeDownloadFailure.ts +10 -10
- package/src/guides/markdown.test.ts +31 -31
- package/src/install/installStamp.test.ts +9 -9
- package/src/manifest/extension.ts +36 -0
- package/src/manifest/index.ts +1 -0
- package/src/manifest/manifest.test.ts +208 -90
- package/src/manifest/manifest.ts +34 -0
- package/src/net/loopback.test.ts +10 -10
- package/src/presence/rosterSync.test.ts +7 -7
- package/src/probes/a2s.test.ts +5 -5
- package/src/probes/minecraftPing.test.ts +17 -17
- package/src/probes/raknetPing.test.ts +13 -13
- package/src/protocol/bridgePreview.ts +1 -0
- package/src/rcon/rconAccess.test.ts +20 -20
- package/src/rcon/rconAccess.ts +14 -14
- package/src/rcon/rconClient.test.ts +49 -49
- package/src/rcon/rconFrame.test.ts +14 -14
- package/src/rcon/rconIds.test.ts +4 -4
- package/src/rcon/rconWriter.test.ts +6 -6
- package/src/runtime/bridgeActivity.test.ts +15 -15
- package/src/runtime/bridgeBackupLease.test.ts +9 -9
- package/src/runtime/bridgeConfigReader.test.ts +5 -5
- package/src/runtime/bridgeConsoleHandler.test.ts +8 -8
- package/src/runtime/bridgeContext.test.ts +5 -5
- package/src/runtime/bridgeDriver.test.ts +94 -94
- package/src/runtime/bridgeEvents.test.ts +15 -15
- package/src/runtime/bridgeFiles.test.ts +54 -54
- package/src/runtime/bridgeInstall.test.ts +10 -10
- package/src/runtime/bridgeLiveConfig.test.ts +6 -6
- package/src/runtime/bridgePending.test.ts +6 -6
- package/src/runtime/bridgeRedaction.test.ts +16 -16
- package/src/runtime/bridgeRegistry.test.ts +84 -52
- package/src/runtime/bridgeRegistry.ts +2 -2
- package/src/runtime/bridgeServer.test.ts +31 -31
- package/src/runtime/bridgeSetup.test.ts +27 -27
- package/src/runtime/bridgeSetup.ts +1 -1
- package/src/runtime/bridgeSetupHandlers.test.ts +13 -13
- package/src/runtime/bridgeSignal.test.ts +7 -7
- package/src/runtime/bridgeSupervisor.test.ts +42 -42
- package/src/runtime/serve.ts +4 -4
- package/src/steam/avatars.test.ts +13 -13
- package/src/steam/steamApp.test.ts +8 -8
- package/src/steam/steamcmd.test.ts +17 -17
- package/src/steam/steamcmd.ts +4 -4
- package/src/steam/steamcmdNarrator.test.ts +4 -4
- package/src/steam/workshop.test.ts +5 -5
- package/src/utils/changedSettingKeys.test.ts +5 -5
- package/src/utils/describeExecFailure.test.ts +4 -4
- package/src/utils/describeExecFailure.ts +1 -1
- package/src/utils/sameSettingValue.test.ts +7 -7
- package/src/utils/token.test.ts +7 -7
- package/src/wine/protonCommand.test.ts +5 -5
- package/src/wine/wineCommand.test.ts +6 -6
- package/src/wine/winePrefix.test.ts +6 -6
- package/src/wire/activity.test.ts +8 -8
- package/src/wire/panel.test.ts +28 -28
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect,
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from "bun:test";
|
|
2
2
|
import { mkdtemp, rm } from "node:fs/promises";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
@@ -162,7 +162,7 @@ describe("pending dispatch", () => {
|
|
|
162
162
|
rejected: null,
|
|
163
163
|
};
|
|
164
164
|
|
|
165
|
-
|
|
165
|
+
it("answers pendingList with what the driver lists", async () => {
|
|
166
166
|
const server = createServer({
|
|
167
167
|
...baseOptions(socket),
|
|
168
168
|
onPendingList: async () => listed,
|
|
@@ -183,7 +183,7 @@ describe("pending dispatch", () => {
|
|
|
183
183
|
});
|
|
184
184
|
});
|
|
185
185
|
|
|
186
|
-
|
|
186
|
+
it("answers pendingList with the unsupported sentinel when the driver declares no pending module", async () => {
|
|
187
187
|
const server = createServer({
|
|
188
188
|
...baseOptions(socket),
|
|
189
189
|
onPendingList: async () => ({
|
|
@@ -216,7 +216,7 @@ describe("pending dispatch", () => {
|
|
|
216
216
|
});
|
|
217
217
|
});
|
|
218
218
|
|
|
219
|
-
|
|
219
|
+
it("passes the uploaded path to pendingAdd and answers with the refreshed list", async () => {
|
|
220
220
|
const received: string[] = [];
|
|
221
221
|
|
|
222
222
|
const server = createServer({
|
|
@@ -247,7 +247,7 @@ describe("pending dispatch", () => {
|
|
|
247
247
|
});
|
|
248
248
|
});
|
|
249
249
|
|
|
250
|
-
|
|
250
|
+
it("refuses a pendingAdd carrying no path", async () => {
|
|
251
251
|
const server = createServer({
|
|
252
252
|
...baseOptions(socket),
|
|
253
253
|
onPendingAdd: unreachable("pendingAdd"),
|
|
@@ -268,7 +268,7 @@ describe("pending dispatch", () => {
|
|
|
268
268
|
});
|
|
269
269
|
});
|
|
270
270
|
|
|
271
|
-
|
|
271
|
+
it("answers pendingAdd with the rejection the driver reported beside the refreshed list", async () => {
|
|
272
272
|
const rejected: BridgePendingResult = {
|
|
273
273
|
...listed,
|
|
274
274
|
rejected: {
|
|
@@ -299,7 +299,7 @@ describe("pending dispatch", () => {
|
|
|
299
299
|
});
|
|
300
300
|
});
|
|
301
301
|
|
|
302
|
-
|
|
302
|
+
it("names an unknown method so an older agent can degrade", async () => {
|
|
303
303
|
const server = createServer(baseOptions(socket));
|
|
304
304
|
|
|
305
305
|
const response = await call(socket, {
|
|
@@ -367,7 +367,7 @@ describe("setup dispatch", () => {
|
|
|
367
367
|
runtime,
|
|
368
368
|
};
|
|
369
369
|
|
|
370
|
-
|
|
370
|
+
it("answers setupStatus with what the driver reported", async () => {
|
|
371
371
|
const server = createServer({
|
|
372
372
|
...baseOptions(socket),
|
|
373
373
|
onSetupStatus: () => reported,
|
|
@@ -388,7 +388,7 @@ describe("setup dispatch", () => {
|
|
|
388
388
|
});
|
|
389
389
|
});
|
|
390
390
|
|
|
391
|
-
|
|
391
|
+
it("answers setupStatus with the unsupported sentinel when the driver declares no setup", async () => {
|
|
392
392
|
const server = createServer({
|
|
393
393
|
...baseOptions(socket),
|
|
394
394
|
onSetupStatus: () => unsupportedSetup(),
|
|
@@ -412,7 +412,7 @@ describe("setup dispatch", () => {
|
|
|
412
412
|
});
|
|
413
413
|
});
|
|
414
414
|
|
|
415
|
-
|
|
415
|
+
it("passes the step, action and args of a setupSubmit to the driver", async () => {
|
|
416
416
|
const received: {
|
|
417
417
|
step: string;
|
|
418
418
|
action: string;
|
|
@@ -465,7 +465,7 @@ describe("setup dispatch", () => {
|
|
|
465
465
|
});
|
|
466
466
|
});
|
|
467
467
|
|
|
468
|
-
|
|
468
|
+
it("refuses a setupSubmit carrying no step id", async () => {
|
|
469
469
|
const server = createServer({
|
|
470
470
|
...baseOptions(socket),
|
|
471
471
|
onSetupSubmit: unreachable("setupSubmit"),
|
|
@@ -487,7 +487,7 @@ describe("setup dispatch", () => {
|
|
|
487
487
|
});
|
|
488
488
|
});
|
|
489
489
|
|
|
490
|
-
|
|
490
|
+
it("answers a rejected setupSubmit with a failed prompt instead of a failed call", async () => {
|
|
491
491
|
const server = createServer({
|
|
492
492
|
...baseOptions(socket),
|
|
493
493
|
onSetupSubmit: async () => ({
|
|
@@ -538,7 +538,7 @@ describe("setup dispatch", () => {
|
|
|
538
538
|
});
|
|
539
539
|
});
|
|
540
540
|
|
|
541
|
-
|
|
541
|
+
it("answers setupSubmit with the unsupported sentinel when the driver implements no submit", async () => {
|
|
542
542
|
const server = createServer({
|
|
543
543
|
...baseOptions(socket),
|
|
544
544
|
onSetupSubmit: async () => ({
|
|
@@ -605,7 +605,7 @@ describe("error serialisation", () => {
|
|
|
605
605
|
return response;
|
|
606
606
|
};
|
|
607
607
|
|
|
608
|
-
|
|
608
|
+
it("carries the localized text of a user error beside the message", async () => {
|
|
609
609
|
expect(
|
|
610
610
|
await thrown(
|
|
611
611
|
new BridgeUserError({
|
|
@@ -624,7 +624,7 @@ describe("error serialisation", () => {
|
|
|
624
624
|
});
|
|
625
625
|
});
|
|
626
626
|
|
|
627
|
-
|
|
627
|
+
it("carries the failure code of a failure error and no text", async () => {
|
|
628
628
|
expect(await thrown(new BridgeFailureError(BridgeFailureCode.CatalogRestricted, "the author blocked it"))).toEqual({
|
|
629
629
|
id: 1,
|
|
630
630
|
ok: false,
|
|
@@ -633,7 +633,7 @@ describe("error serialisation", () => {
|
|
|
633
633
|
});
|
|
634
634
|
});
|
|
635
635
|
|
|
636
|
-
|
|
636
|
+
it("marks a runtime refusal unchanged and carries its text", async () => {
|
|
637
637
|
expect(
|
|
638
638
|
await thrown(
|
|
639
639
|
new BridgeRefusalError('module "worlds" cannot run "delete" right now', {
|
|
@@ -653,7 +653,7 @@ describe("error serialisation", () => {
|
|
|
653
653
|
});
|
|
654
654
|
});
|
|
655
655
|
|
|
656
|
-
|
|
656
|
+
it("marks a runtime refusal without text unchanged and sends no text", async () => {
|
|
657
657
|
expect(await thrown(new BridgeRefusalError('no module named "worlds"'))).toEqual({
|
|
658
658
|
id: 1,
|
|
659
659
|
ok: false,
|
|
@@ -662,7 +662,7 @@ describe("error serialisation", () => {
|
|
|
662
662
|
});
|
|
663
663
|
});
|
|
664
664
|
|
|
665
|
-
|
|
665
|
+
it("carries the message alone for an ordinary error", async () => {
|
|
666
666
|
expect(await thrown(new Error("the file could not be read"))).toEqual({
|
|
667
667
|
id: 1,
|
|
668
668
|
ok: false,
|
|
@@ -682,7 +682,7 @@ describe("backup ownership dispatch", () => {
|
|
|
682
682
|
recursive: true,
|
|
683
683
|
});
|
|
684
684
|
});
|
|
685
|
-
|
|
685
|
+
it("carries the lease token through renew and release frames", async () => {
|
|
686
686
|
const socket = join(dir, "bridge.sock");
|
|
687
687
|
const renewals: (string | undefined)[] = [];
|
|
688
688
|
const releases: (string | undefined)[] = [];
|
|
@@ -746,7 +746,7 @@ describe("error replies", () => {
|
|
|
746
746
|
});
|
|
747
747
|
});
|
|
748
748
|
|
|
749
|
-
|
|
749
|
+
it("hide a secret value from the error and the customer text", async () => {
|
|
750
750
|
const server = createServer({
|
|
751
751
|
...baseOptions(socket),
|
|
752
752
|
redact: (value) => value.split(SECRET).join("••••"),
|
|
@@ -830,7 +830,7 @@ describe("failure logging", () => {
|
|
|
830
830
|
return lines;
|
|
831
831
|
};
|
|
832
832
|
|
|
833
|
-
|
|
833
|
+
it("logs a refused action as a refusal with its message and no stack", async () => {
|
|
834
834
|
expect(
|
|
835
835
|
await logged(
|
|
836
836
|
new BridgeUserError({
|
|
@@ -849,7 +849,7 @@ describe("failure logging", () => {
|
|
|
849
849
|
]);
|
|
850
850
|
});
|
|
851
851
|
|
|
852
|
-
|
|
852
|
+
it("logs an ordinary error as a failure with its stack", async () => {
|
|
853
853
|
const [line] = await logged(new Error("the marker could not be written"));
|
|
854
854
|
|
|
855
855
|
expect(line?.message).toBe("bridge call failed");
|
|
@@ -857,7 +857,7 @@ describe("failure logging", () => {
|
|
|
857
857
|
expect(String(line?.fields.stack)).toContain("the marker could not be written");
|
|
858
858
|
});
|
|
859
859
|
|
|
860
|
-
|
|
860
|
+
it("logs a refusal with the cause the driver attached", async () => {
|
|
861
861
|
expect(
|
|
862
862
|
await logged(
|
|
863
863
|
new BridgeUserError(
|
|
@@ -907,7 +907,7 @@ describe("activity on the answer frame", () => {
|
|
|
907
907
|
subject: "Steve",
|
|
908
908
|
};
|
|
909
909
|
|
|
910
|
-
|
|
910
|
+
it("carries the entries an invoke reported beside its result", async () => {
|
|
911
911
|
const server = createServer({
|
|
912
912
|
...baseOptions(socket),
|
|
913
913
|
onInvoke: async () => ({
|
|
@@ -941,7 +941,7 @@ describe("activity on the answer frame", () => {
|
|
|
941
941
|
});
|
|
942
942
|
});
|
|
943
943
|
|
|
944
|
-
|
|
944
|
+
it("carries the entries a setup submit reported beside its result", async () => {
|
|
945
945
|
const server = createServer({
|
|
946
946
|
...baseOptions(socket),
|
|
947
947
|
onSetupSubmit: async () => ({
|
|
@@ -970,7 +970,7 @@ describe("activity on the answer frame", () => {
|
|
|
970
970
|
});
|
|
971
971
|
});
|
|
972
972
|
|
|
973
|
-
|
|
973
|
+
it("carries an empty list when nothing was reported, so the platform knows the runtime reports", async () => {
|
|
974
974
|
const server = createServer({
|
|
975
975
|
...baseOptions(socket),
|
|
976
976
|
onInvoke: async () => ({
|
|
@@ -997,7 +997,7 @@ describe("activity on the answer frame", () => {
|
|
|
997
997
|
});
|
|
998
998
|
});
|
|
999
999
|
|
|
1000
|
-
|
|
1000
|
+
it("leaves the field off the answers of methods that report no activity", async () => {
|
|
1001
1001
|
const server = createServer(baseOptions(socket));
|
|
1002
1002
|
|
|
1003
1003
|
const response = await call(socket, {
|
|
@@ -1020,7 +1020,7 @@ describe("activity on the answer frame", () => {
|
|
|
1020
1020
|
action: "add",
|
|
1021
1021
|
};
|
|
1022
1022
|
|
|
1023
|
-
|
|
1023
|
+
it("sends the entries to the events ring once when the caller left before the answer", async () => {
|
|
1024
1024
|
const ring: BridgeActivity[][] = [];
|
|
1025
1025
|
|
|
1026
1026
|
let finish: () => void = () => undefined;
|
|
@@ -1068,7 +1068,7 @@ describe("activity on the answer frame", () => {
|
|
|
1068
1068
|
]);
|
|
1069
1069
|
});
|
|
1070
1070
|
|
|
1071
|
-
|
|
1071
|
+
it("sends nothing to the ring when the answer reached the caller", async () => {
|
|
1072
1072
|
const ring: BridgeActivity[][] = [];
|
|
1073
1073
|
|
|
1074
1074
|
const server = createServer({
|
|
@@ -1099,7 +1099,7 @@ describe("activity on the answer frame", () => {
|
|
|
1099
1099
|
expect(ring).toEqual([]);
|
|
1100
1100
|
});
|
|
1101
1101
|
|
|
1102
|
-
|
|
1102
|
+
it("sends the entries to the ring when the answer cannot be written", async () => {
|
|
1103
1103
|
const ring: BridgeActivity[][] = [];
|
|
1104
1104
|
|
|
1105
1105
|
const server = createServer({
|
|
@@ -1144,7 +1144,7 @@ describe("failure frames", () => {
|
|
|
1144
1144
|
});
|
|
1145
1145
|
});
|
|
1146
1146
|
|
|
1147
|
-
|
|
1147
|
+
it("carry the cause in the staff error and keep the customer text friendly", async () => {
|
|
1148
1148
|
const SECRET = "tok-1234567890-secret";
|
|
1149
1149
|
|
|
1150
1150
|
const server = createServer({
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, expect,
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
2
|
import { BridgeSetupPromptKind, BridgeSetupStepState } from "../core";
|
|
3
3
|
import type { BridgeSetupRuntime } from "../protocol";
|
|
4
4
|
import { failedSetup, normalizeSetupRuntime, setupSummaryOf, unsupportedSetup } from "./bridgeSetup";
|
|
@@ -23,11 +23,11 @@ const runtimeWith = (prompt: BridgeSetupRuntime["prompt"]): BridgeSetupRuntime =
|
|
|
23
23
|
});
|
|
24
24
|
|
|
25
25
|
describe("the setup summary", () => {
|
|
26
|
-
|
|
26
|
+
it("has nothing to summarise while the driver reported no runtime", () => {
|
|
27
27
|
expect(setupSummaryOf(null)).toBeNull();
|
|
28
28
|
});
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
it("names the active driver step", () => {
|
|
31
31
|
expect(
|
|
32
32
|
setupSummaryOf(
|
|
33
33
|
runtimeWith({
|
|
@@ -41,7 +41,7 @@ describe("the setup summary", () => {
|
|
|
41
41
|
});
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
it("names no step once every driver step is done", () => {
|
|
45
45
|
expect(
|
|
46
46
|
setupSummaryOf({
|
|
47
47
|
steps: [
|
|
@@ -58,7 +58,7 @@ describe("the setup summary", () => {
|
|
|
58
58
|
});
|
|
59
59
|
});
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
it("asks for attention while a link prompt waits on the customer", () => {
|
|
62
62
|
expect(
|
|
63
63
|
setupSummaryOf(
|
|
64
64
|
runtimeWith({
|
|
@@ -73,7 +73,7 @@ describe("the setup summary", () => {
|
|
|
73
73
|
).toBe(true);
|
|
74
74
|
});
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
it("asks for attention on an action prompt and on a failed one", () => {
|
|
77
77
|
expect(
|
|
78
78
|
setupSummaryOf(
|
|
79
79
|
runtimeWith({
|
|
@@ -95,7 +95,7 @@ describe("the setup summary", () => {
|
|
|
95
95
|
).toBe(true);
|
|
96
96
|
});
|
|
97
97
|
|
|
98
|
-
|
|
98
|
+
it("waits quietly while a progress prompt runs", () => {
|
|
99
99
|
expect(
|
|
100
100
|
setupSummaryOf(
|
|
101
101
|
runtimeWith({
|
|
@@ -110,7 +110,7 @@ describe("the setup summary", () => {
|
|
|
110
110
|
});
|
|
111
111
|
|
|
112
112
|
describe("the unsupported sentinel", () => {
|
|
113
|
-
|
|
113
|
+
it("answers a driver that declares no setup", () => {
|
|
114
114
|
expect(unsupportedSetup()).toEqual({
|
|
115
115
|
supported: false,
|
|
116
116
|
runtime: null,
|
|
@@ -119,7 +119,7 @@ describe("the unsupported sentinel", () => {
|
|
|
119
119
|
});
|
|
120
120
|
|
|
121
121
|
describe("a rejected submit", () => {
|
|
122
|
-
|
|
122
|
+
it("turns the user error into a failed prompt keeping the previous actions", () => {
|
|
123
123
|
const result = failedSetup(
|
|
124
124
|
runtimeWith({
|
|
125
125
|
kind: BridgeSetupPromptKind.Link,
|
|
@@ -164,7 +164,7 @@ describe("a rejected submit", () => {
|
|
|
164
164
|
});
|
|
165
165
|
});
|
|
166
166
|
|
|
167
|
-
|
|
167
|
+
it("carries no actions over from a prompt that had none", () => {
|
|
168
168
|
const result = failedSetup(
|
|
169
169
|
runtimeWith({
|
|
170
170
|
kind: BridgeSetupPromptKind.Wait,
|
|
@@ -180,7 +180,7 @@ describe("a rejected submit", () => {
|
|
|
180
180
|
});
|
|
181
181
|
});
|
|
182
182
|
|
|
183
|
-
|
|
183
|
+
it("stays empty when the driver never reported a runtime", () => {
|
|
184
184
|
expect(failedSetup(null, text("nothing to fail"))).toEqual({
|
|
185
185
|
supported: true,
|
|
186
186
|
runtime: null,
|
|
@@ -236,7 +236,7 @@ const link = (
|
|
|
236
236
|
};
|
|
237
237
|
|
|
238
238
|
describe("normalizing a reported runtime", () => {
|
|
239
|
-
|
|
239
|
+
it("has nothing to normalize while the driver reported no runtime", () => {
|
|
240
240
|
expect(
|
|
241
241
|
normalizeSetupRuntime(null, {
|
|
242
242
|
declared,
|
|
@@ -247,7 +247,7 @@ describe("normalizing a reported runtime", () => {
|
|
|
247
247
|
).toBeNull();
|
|
248
248
|
});
|
|
249
249
|
|
|
250
|
-
|
|
250
|
+
it("drops a step the driver never declared", () => {
|
|
251
251
|
const { normalized, reasons } = normalizing(
|
|
252
252
|
withSteps([
|
|
253
253
|
{
|
|
@@ -272,7 +272,7 @@ describe("normalizing a reported runtime", () => {
|
|
|
272
272
|
]);
|
|
273
273
|
});
|
|
274
274
|
|
|
275
|
-
|
|
275
|
+
it("drops the second report of the same step", () => {
|
|
276
276
|
const { normalized, reasons } = normalizing(
|
|
277
277
|
withSteps([
|
|
278
278
|
{
|
|
@@ -297,7 +297,7 @@ describe("normalizing a reported runtime", () => {
|
|
|
297
297
|
]);
|
|
298
298
|
});
|
|
299
299
|
|
|
300
|
-
|
|
300
|
+
it("keeps the first active step and pends the rest", () => {
|
|
301
301
|
const { normalized, reasons } = normalizing(
|
|
302
302
|
withSteps([
|
|
303
303
|
{
|
|
@@ -326,7 +326,7 @@ describe("normalizing a reported runtime", () => {
|
|
|
326
326
|
]);
|
|
327
327
|
});
|
|
328
328
|
|
|
329
|
-
|
|
329
|
+
it("clamps a percent that left the scale", () => {
|
|
330
330
|
expect(
|
|
331
331
|
normalizing(
|
|
332
332
|
runtimeWith({
|
|
@@ -361,7 +361,7 @@ describe("normalizing a reported runtime", () => {
|
|
|
361
361
|
});
|
|
362
362
|
});
|
|
363
363
|
|
|
364
|
-
|
|
364
|
+
it("drops a percent that is not a number", () => {
|
|
365
365
|
const { normalized, reasons } = normalizing(
|
|
366
366
|
runtimeWith({
|
|
367
367
|
kind: BridgeSetupPromptKind.Progress,
|
|
@@ -382,7 +382,7 @@ describe("normalizing a reported runtime", () => {
|
|
|
382
382
|
]);
|
|
383
383
|
});
|
|
384
384
|
|
|
385
|
-
|
|
385
|
+
it("cuts a detail line to the length the platform takes", () => {
|
|
386
386
|
const { normalized, reasons } = normalizing(
|
|
387
387
|
runtimeWith({
|
|
388
388
|
kind: BridgeSetupPromptKind.Progress,
|
|
@@ -403,7 +403,7 @@ describe("normalizing a reported runtime", () => {
|
|
|
403
403
|
]);
|
|
404
404
|
});
|
|
405
405
|
|
|
406
|
-
|
|
406
|
+
it("drops an empty detail line", () => {
|
|
407
407
|
const { normalized, reasons } = normalizing(
|
|
408
408
|
runtimeWith({
|
|
409
409
|
kind: BridgeSetupPromptKind.Progress,
|
|
@@ -421,7 +421,7 @@ describe("normalizing a reported runtime", () => {
|
|
|
421
421
|
]);
|
|
422
422
|
});
|
|
423
423
|
|
|
424
|
-
|
|
424
|
+
it("drops an action whose id is not kebab-case and the duplicate beside it", () => {
|
|
425
425
|
const { normalized, reasons } = normalizing(
|
|
426
426
|
runtimeWith({
|
|
427
427
|
kind: BridgeSetupPromptKind.Action,
|
|
@@ -459,7 +459,7 @@ describe("normalizing a reported runtime", () => {
|
|
|
459
459
|
]);
|
|
460
460
|
});
|
|
461
461
|
|
|
462
|
-
|
|
462
|
+
it("keeps only as many actions as the platform renders", () => {
|
|
463
463
|
const { normalized, reasons } = normalizing(
|
|
464
464
|
runtimeWith({
|
|
465
465
|
kind: BridgeSetupPromptKind.Failed,
|
|
@@ -480,7 +480,7 @@ describe("normalizing a reported runtime", () => {
|
|
|
480
480
|
]);
|
|
481
481
|
});
|
|
482
482
|
|
|
483
|
-
|
|
483
|
+
it("cuts a long code and drops an empty one", () => {
|
|
484
484
|
expect(
|
|
485
485
|
normalizing(
|
|
486
486
|
link({
|
|
@@ -502,7 +502,7 @@ describe("normalizing a reported runtime", () => {
|
|
|
502
502
|
]);
|
|
503
503
|
});
|
|
504
504
|
|
|
505
|
-
|
|
505
|
+
it("re-emits an expiry as an iso stamp and drops one it cannot read", () => {
|
|
506
506
|
expect(
|
|
507
507
|
normalizing(
|
|
508
508
|
link({
|
|
@@ -524,7 +524,7 @@ describe("normalizing a reported runtime", () => {
|
|
|
524
524
|
]);
|
|
525
525
|
});
|
|
526
526
|
|
|
527
|
-
|
|
527
|
+
it("turns a link the browser cannot open into a failed prompt keeping its actions", () => {
|
|
528
528
|
const { normalized, reasons } = normalizing(
|
|
529
529
|
link({
|
|
530
530
|
url: "javascript:alert(1)",
|
|
@@ -540,7 +540,7 @@ describe("normalizing a reported runtime", () => {
|
|
|
540
540
|
expect(normalized?.prompt).toEqual({
|
|
541
541
|
kind: BridgeSetupPromptKind.Failed,
|
|
542
542
|
message: {
|
|
543
|
-
ar: "اللعبة
|
|
543
|
+
ar: "أعادت اللعبة رابط تسجيل دخول غير صالح، جرب مرة ثانية.",
|
|
544
544
|
en: "The game reported a broken sign-in link. Try again.",
|
|
545
545
|
},
|
|
546
546
|
actions: [
|
|
@@ -555,7 +555,7 @@ describe("normalizing a reported runtime", () => {
|
|
|
555
555
|
]);
|
|
556
556
|
});
|
|
557
557
|
|
|
558
|
-
|
|
558
|
+
it("turns a url it cannot parse into a failed prompt", () => {
|
|
559
559
|
expect(
|
|
560
560
|
normalizing(
|
|
561
561
|
link({
|
|
@@ -565,7 +565,7 @@ describe("normalizing a reported runtime", () => {
|
|
|
565
565
|
).toBe(BridgeSetupPromptKind.Failed);
|
|
566
566
|
});
|
|
567
567
|
|
|
568
|
-
|
|
568
|
+
it("leaves a healthy runtime exactly as the driver reported it", () => {
|
|
569
569
|
const source = link({});
|
|
570
570
|
const { normalized, reasons } = normalizing(source);
|
|
571
571
|
|
|
@@ -68,7 +68,7 @@ export const failedSetup = (runtime: BridgeSetupRuntime | null, text: LocalizedT
|
|
|
68
68
|
};
|
|
69
69
|
|
|
70
70
|
const BROKEN_LINK_TEXT: LocalizedText = {
|
|
71
|
-
ar: "اللعبة
|
|
71
|
+
ar: "أعادت اللعبة رابط تسجيل دخول غير صالح، جرب مرة ثانية.",
|
|
72
72
|
en: "The game reported a broken sign-in link. Try again.",
|
|
73
73
|
};
|
|
74
74
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, expect,
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import type { BridgeContext } from "../context";
|
|
4
4
|
import { BridgeKind, BridgeSetupPromptKind, BridgeSetupStepKind, BridgeSetupStepState, BridgeUserError } from "../core";
|
|
@@ -140,7 +140,7 @@ const setupWith = (submit?: BridgeSetupModule["submit"]): BridgeSetupModule => (
|
|
|
140
140
|
});
|
|
141
141
|
|
|
142
142
|
describe("the setup handlers", () => {
|
|
143
|
-
|
|
143
|
+
it("answer unsupported for a driver that declares no setup", async () => {
|
|
144
144
|
const { logger } = recorder();
|
|
145
145
|
const handlers = createSetupHandlers(driverWith(), logger);
|
|
146
146
|
|
|
@@ -155,7 +155,7 @@ describe("the setup handlers", () => {
|
|
|
155
155
|
});
|
|
156
156
|
});
|
|
157
157
|
|
|
158
|
-
|
|
158
|
+
it("keep nothing for a driver that declares no setup, whatever it reports", () => {
|
|
159
159
|
const { logger, warnings } = recorder();
|
|
160
160
|
const handlers = createSetupHandlers(driverWith(), logger);
|
|
161
161
|
|
|
@@ -165,7 +165,7 @@ describe("the setup handlers", () => {
|
|
|
165
165
|
expect(warnings).toEqual([]);
|
|
166
166
|
});
|
|
167
167
|
|
|
168
|
-
|
|
168
|
+
it("answer the normalized runtime the driver reported", () => {
|
|
169
169
|
const { logger, warnings } = recorder();
|
|
170
170
|
const handlers = createSetupHandlers(driverWith(setupWith()), logger);
|
|
171
171
|
|
|
@@ -206,7 +206,7 @@ describe("the setup handlers", () => {
|
|
|
206
206
|
]);
|
|
207
207
|
});
|
|
208
208
|
|
|
209
|
-
|
|
209
|
+
it("answer unsupported for a setup that exports no submit", async () => {
|
|
210
210
|
const { logger } = recorder();
|
|
211
211
|
const handlers = createSetupHandlers(driverWith(setupWith()), logger);
|
|
212
212
|
|
|
@@ -216,7 +216,7 @@ describe("the setup handlers", () => {
|
|
|
216
216
|
});
|
|
217
217
|
});
|
|
218
218
|
|
|
219
|
-
|
|
219
|
+
it("turn a user error into a failed prompt that keeps the previous actions", async () => {
|
|
220
220
|
const { logger, warnings } = recorder();
|
|
221
221
|
|
|
222
222
|
const handlers = createSetupHandlers(
|
|
@@ -254,7 +254,7 @@ describe("the setup handlers", () => {
|
|
|
254
254
|
expect(warnings.at(-1)?.message).toBe("setup submit rejected");
|
|
255
255
|
});
|
|
256
256
|
|
|
257
|
-
|
|
257
|
+
it("add one rejected entry built from the user error", async () => {
|
|
258
258
|
const { logger } = recorder();
|
|
259
259
|
|
|
260
260
|
const handlers = createSetupHandlers(
|
|
@@ -288,7 +288,7 @@ describe("the setup handlers", () => {
|
|
|
288
288
|
]);
|
|
289
289
|
});
|
|
290
290
|
|
|
291
|
-
|
|
291
|
+
it("answer what the driver reported while submitting", async () => {
|
|
292
292
|
const { logger } = recorder();
|
|
293
293
|
|
|
294
294
|
const handlers = createSetupHandlers(
|
|
@@ -313,7 +313,7 @@ describe("the setup handlers", () => {
|
|
|
313
313
|
]);
|
|
314
314
|
});
|
|
315
315
|
|
|
316
|
-
|
|
316
|
+
it("answer the runtime the driver reported while submitting", async () => {
|
|
317
317
|
const { logger } = recorder();
|
|
318
318
|
|
|
319
319
|
const handlers = createSetupHandlers(
|
|
@@ -349,7 +349,7 @@ describe("the setup handlers", () => {
|
|
|
349
349
|
});
|
|
350
350
|
});
|
|
351
351
|
|
|
352
|
-
|
|
352
|
+
it("let an error the driver cannot explain out", async () => {
|
|
353
353
|
const { logger } = recorder();
|
|
354
354
|
|
|
355
355
|
const handlers = createSetupHandlers(
|
|
@@ -372,7 +372,7 @@ describe("the setup handlers redaction", () => {
|
|
|
372
372
|
|
|
373
373
|
const redact = (value: string) => value.split(SECRET).join("••••");
|
|
374
374
|
|
|
375
|
-
|
|
375
|
+
it("blanks a secret value in the prompt a driver reports", () => {
|
|
376
376
|
const { logger } = recorder();
|
|
377
377
|
const handlers = createSetupHandlers(driverWith(setupWith()), logger, redact);
|
|
378
378
|
|
|
@@ -399,7 +399,7 @@ describe("the setup handlers redaction", () => {
|
|
|
399
399
|
});
|
|
400
400
|
});
|
|
401
401
|
|
|
402
|
-
|
|
402
|
+
it("blanks a secret value in every text of a link prompt", () => {
|
|
403
403
|
const { logger } = recorder();
|
|
404
404
|
const handlers = createSetupHandlers(driverWith(setupWith()), logger, redact);
|
|
405
405
|
const reported = signIn();
|
|
@@ -429,7 +429,7 @@ describe("the setup handlers redaction", () => {
|
|
|
429
429
|
});
|
|
430
430
|
});
|
|
431
431
|
|
|
432
|
-
|
|
432
|
+
it("blanks a secret value in the text of a rejected submit", async () => {
|
|
433
433
|
const { logger } = recorder();
|
|
434
434
|
const handlers = createSetupHandlers(
|
|
435
435
|
driverWith(
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import { describe, expect,
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
2
|
import { leadsGroup, readProcessGroup, signalGroup } from "./bridgeSignal";
|
|
3
3
|
|
|
4
4
|
const MISSING_PID = 2 ** 22 - 1;
|
|
5
5
|
|
|
6
6
|
describe("readProcessGroup", () => {
|
|
7
|
-
|
|
7
|
+
it("reads the process group of this process", async () => {
|
|
8
8
|
const group = await readProcessGroup(process.pid);
|
|
9
9
|
|
|
10
10
|
expect(group).not.toBeNull();
|
|
11
11
|
expect(group).toBeGreaterThan(0);
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
it("puts a detached child in a group of its own and an attached one in ours", async () => {
|
|
15
15
|
const detached = Bun.spawn(
|
|
16
16
|
[
|
|
17
17
|
"sleep",
|
|
@@ -49,13 +49,13 @@ describe("readProcessGroup", () => {
|
|
|
49
49
|
}
|
|
50
50
|
});
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
it("answers null for a pid that does not exist", async () => {
|
|
53
53
|
expect(await readProcessGroup(MISSING_PID)).toBeNull();
|
|
54
54
|
});
|
|
55
55
|
});
|
|
56
56
|
|
|
57
57
|
describe("leadsGroup", () => {
|
|
58
|
-
|
|
58
|
+
it("only a pid equal to its own group leads it", () => {
|
|
59
59
|
expect(leadsGroup(1234, 1234)).toBe(true);
|
|
60
60
|
expect(leadsGroup(1234, 1200)).toBe(false);
|
|
61
61
|
expect(leadsGroup(1234, null)).toBe(false);
|
|
@@ -63,7 +63,7 @@ describe("leadsGroup", () => {
|
|
|
63
63
|
});
|
|
64
64
|
|
|
65
65
|
describe("signalGroup", () => {
|
|
66
|
-
|
|
66
|
+
it("signals every process sharing the leader's group", async () => {
|
|
67
67
|
const leader = Bun.spawn(
|
|
68
68
|
[
|
|
69
69
|
"bash",
|
|
@@ -90,7 +90,7 @@ describe("signalGroup", () => {
|
|
|
90
90
|
expect(() => process.kill(child, 0)).toThrow();
|
|
91
91
|
}, 20_000);
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
it("refuses to signal a group the pid does not lead", async () => {
|
|
94
94
|
const attached = Bun.spawn(
|
|
95
95
|
[
|
|
96
96
|
"sleep",
|