@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 { describe, expect,
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import {
|
|
4
4
|
BridgeAction,
|
|
@@ -116,7 +116,7 @@ const registryFor = (driver: BridgeDriver, variables: Record<string, string> = {
|
|
|
116
116
|
};
|
|
117
117
|
|
|
118
118
|
describe("actions modules", () => {
|
|
119
|
-
|
|
119
|
+
it("lists its action ids in the manifest", () => {
|
|
120
120
|
const registry = registryFor({
|
|
121
121
|
...baseDriver(),
|
|
122
122
|
modules: {
|
|
@@ -151,7 +151,7 @@ describe("actions modules", () => {
|
|
|
151
151
|
]);
|
|
152
152
|
});
|
|
153
153
|
|
|
154
|
-
|
|
154
|
+
it("hands the whole argument bag to the handler", async () => {
|
|
155
155
|
const received: BridgeValues[] = [];
|
|
156
156
|
|
|
157
157
|
const registry = registryFor({
|
|
@@ -179,7 +179,7 @@ describe("actions modules", () => {
|
|
|
179
179
|
]);
|
|
180
180
|
});
|
|
181
181
|
|
|
182
|
-
|
|
182
|
+
it("refuses to run while the game is stopped", async () => {
|
|
183
183
|
const registry = registryFor({
|
|
184
184
|
...baseDriver(),
|
|
185
185
|
modules: {
|
|
@@ -202,7 +202,7 @@ describe("actions modules", () => {
|
|
|
202
202
|
).rejects.toThrow('module "broadcast" needs the game to be running');
|
|
203
203
|
});
|
|
204
204
|
|
|
205
|
-
|
|
205
|
+
it("rejects a driver that reuses a read action id", () => {
|
|
206
206
|
expect(() =>
|
|
207
207
|
registryFor({
|
|
208
208
|
...baseDriver(),
|
|
@@ -222,7 +222,7 @@ describe("actions modules", () => {
|
|
|
222
222
|
});
|
|
223
223
|
|
|
224
224
|
describe("manifest events", () => {
|
|
225
|
-
|
|
225
|
+
it("lists the log patterns and the names the driver raises itself", () => {
|
|
226
226
|
const registry = registryFor({
|
|
227
227
|
...baseDriver(),
|
|
228
228
|
events: {
|
|
@@ -252,7 +252,7 @@ describe("manifest events", () => {
|
|
|
252
252
|
]);
|
|
253
253
|
});
|
|
254
254
|
|
|
255
|
-
|
|
255
|
+
it("stays on the log patterns when the driver raises nothing itself", () => {
|
|
256
256
|
const registry = registryFor({
|
|
257
257
|
...baseDriver(),
|
|
258
258
|
events: {
|
|
@@ -273,7 +273,7 @@ describe("manifest events", () => {
|
|
|
273
273
|
});
|
|
274
274
|
|
|
275
275
|
describe("collection row actions", () => {
|
|
276
|
-
|
|
276
|
+
it("passes the row and the arguments without the row id", async () => {
|
|
277
277
|
const seen: {
|
|
278
278
|
row: BridgeRow;
|
|
279
279
|
args: BridgeValues;
|
|
@@ -318,7 +318,7 @@ describe("collection row actions", () => {
|
|
|
318
318
|
]);
|
|
319
319
|
});
|
|
320
320
|
|
|
321
|
-
|
|
321
|
+
it("keeps listing the built-in actions beside the row actions", () => {
|
|
322
322
|
const registry = registryFor({
|
|
323
323
|
...baseDriver(),
|
|
324
324
|
modules: {
|
|
@@ -398,7 +398,7 @@ describe("offline row actions", () => {
|
|
|
398
398
|
},
|
|
399
399
|
});
|
|
400
400
|
|
|
401
|
-
|
|
401
|
+
it("hands an offline action the id alone when the row is not listed", async () => {
|
|
402
402
|
const seen: BridgeRow[] = [];
|
|
403
403
|
const registry = registryFor(
|
|
404
404
|
rosterDriver(
|
|
@@ -419,7 +419,7 @@ describe("offline row actions", () => {
|
|
|
419
419
|
]);
|
|
420
420
|
});
|
|
421
421
|
|
|
422
|
-
|
|
422
|
+
it("still refuses an unlisted row for an action that is not offline", async () => {
|
|
423
423
|
const registry = registryFor(
|
|
424
424
|
rosterDriver(
|
|
425
425
|
false,
|
|
@@ -437,7 +437,7 @@ describe("offline row actions", () => {
|
|
|
437
437
|
});
|
|
438
438
|
|
|
439
439
|
describe("preview modules", () => {
|
|
440
|
-
|
|
440
|
+
it("lists the preview action in the manifest", () => {
|
|
441
441
|
const registry = registryFor({
|
|
442
442
|
...baseDriver(),
|
|
443
443
|
modules: {
|
|
@@ -466,7 +466,7 @@ describe("preview modules", () => {
|
|
|
466
466
|
]);
|
|
467
467
|
});
|
|
468
468
|
|
|
469
|
-
|
|
469
|
+
it("shows the module the pending values as variables and leaves the rest as they are stored", async () => {
|
|
470
470
|
const seen: {
|
|
471
471
|
version: string | null;
|
|
472
472
|
count: string | null;
|
|
@@ -520,7 +520,7 @@ describe("preview modules", () => {
|
|
|
520
520
|
]);
|
|
521
521
|
});
|
|
522
522
|
|
|
523
|
-
|
|
523
|
+
it("returns what the module answers", async () => {
|
|
524
524
|
const registry = registryFor({
|
|
525
525
|
...baseDriver(),
|
|
526
526
|
modules: {
|
|
@@ -550,7 +550,39 @@ describe("preview modules", () => {
|
|
|
550
550
|
});
|
|
551
551
|
});
|
|
552
552
|
|
|
553
|
-
|
|
553
|
+
it("passes a blocked preview through untouched", async () => {
|
|
554
|
+
const registry = registryFor({
|
|
555
|
+
...baseDriver(),
|
|
556
|
+
modules: {
|
|
557
|
+
transition: {
|
|
558
|
+
kind: BridgeKind.Preview,
|
|
559
|
+
preview: async () => ({
|
|
560
|
+
confirm: BridgeConfirm.Strong,
|
|
561
|
+
blocked: true,
|
|
562
|
+
lines: [
|
|
563
|
+
{
|
|
564
|
+
ar: "لا يوجد بيلد مستقر لهذا الإصدار بعد",
|
|
565
|
+
en: "There is no stable build for this version yet",
|
|
566
|
+
},
|
|
567
|
+
],
|
|
568
|
+
}),
|
|
569
|
+
},
|
|
570
|
+
},
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
expect((await registry.invoke("transition", BridgeAction.Preview)).result).toEqual({
|
|
574
|
+
confirm: BridgeConfirm.Strong,
|
|
575
|
+
blocked: true,
|
|
576
|
+
lines: [
|
|
577
|
+
{
|
|
578
|
+
ar: "لا يوجد بيلد مستقر لهذا الإصدار بعد",
|
|
579
|
+
en: "There is no stable build for this version yet",
|
|
580
|
+
},
|
|
581
|
+
],
|
|
582
|
+
});
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
it("refuses an action a preview module does not answer", async () => {
|
|
554
586
|
const registry = registryFor({
|
|
555
587
|
...baseDriver(),
|
|
556
588
|
modules: {
|
|
@@ -571,7 +603,7 @@ describe("preview modules", () => {
|
|
|
571
603
|
});
|
|
572
604
|
|
|
573
605
|
describe("detail modules", () => {
|
|
574
|
-
|
|
606
|
+
it("lists read and its own action ids in the manifest", () => {
|
|
575
607
|
const registry = registryFor({
|
|
576
608
|
...baseDriver(),
|
|
577
609
|
modules: {
|
|
@@ -602,7 +634,7 @@ describe("detail modules", () => {
|
|
|
602
634
|
]);
|
|
603
635
|
});
|
|
604
636
|
|
|
605
|
-
|
|
637
|
+
it("returns what read answers", async () => {
|
|
606
638
|
const registry = registryFor({
|
|
607
639
|
...baseDriver(),
|
|
608
640
|
modules: {
|
|
@@ -630,7 +662,7 @@ describe("detail modules", () => {
|
|
|
630
662
|
});
|
|
631
663
|
});
|
|
632
664
|
|
|
633
|
-
|
|
665
|
+
it("hands the argument bag to an action and returns its outcome", async () => {
|
|
634
666
|
const received: BridgeValues[] = [];
|
|
635
667
|
|
|
636
668
|
const registry = registryFor({
|
|
@@ -673,7 +705,7 @@ describe("detail modules", () => {
|
|
|
673
705
|
]);
|
|
674
706
|
});
|
|
675
707
|
|
|
676
|
-
|
|
708
|
+
it("refuses an action named after a read", () => {
|
|
677
709
|
expect(() =>
|
|
678
710
|
registryFor({
|
|
679
711
|
...baseDriver(),
|
|
@@ -690,7 +722,7 @@ describe("detail modules", () => {
|
|
|
690
722
|
).toThrow('module "modpackStatus" declares action "read", which is reserved for reads');
|
|
691
723
|
});
|
|
692
724
|
|
|
693
|
-
|
|
725
|
+
it("refuses an action the module does not answer", async () => {
|
|
694
726
|
const registry = registryFor({
|
|
695
727
|
...baseDriver(),
|
|
696
728
|
modules: {
|
|
@@ -708,7 +740,7 @@ describe("detail modules", () => {
|
|
|
708
740
|
});
|
|
709
741
|
|
|
710
742
|
describe("the setup singleton", () => {
|
|
711
|
-
|
|
743
|
+
it("rides the manifest as its own block and never joins the panel modules", () => {
|
|
712
744
|
const steps = [
|
|
713
745
|
{
|
|
714
746
|
kind: BridgeSetupStepKind.Driver as const,
|
|
@@ -736,13 +768,13 @@ describe("the setup singleton", () => {
|
|
|
736
768
|
expect(manifest.modules.some((module) => module.kind === BridgeKind.Setup)).toBe(false);
|
|
737
769
|
});
|
|
738
770
|
|
|
739
|
-
|
|
771
|
+
it("leaves the manifest block empty for a driver that declares no setup", () => {
|
|
740
772
|
expect(registryFor(baseDriver()).manifest().setup).toBeNull();
|
|
741
773
|
});
|
|
742
774
|
});
|
|
743
775
|
|
|
744
776
|
describe("protected action dispatch", () => {
|
|
745
|
-
|
|
777
|
+
it("advertises protection and refuses old callers before touching files", async () => {
|
|
746
778
|
let calls = 0;
|
|
747
779
|
const registry = registryFor({
|
|
748
780
|
...baseDriver(),
|
|
@@ -768,7 +800,7 @@ describe("protected action dispatch", () => {
|
|
|
768
800
|
await registry.invoke("world", "replace", {}, "01993720-0000-7000-8000-000000000001");
|
|
769
801
|
expect(calls).toBe(1);
|
|
770
802
|
});
|
|
771
|
-
|
|
803
|
+
it("rejects protection metadata for unknown actions or running-only modules", () => {
|
|
772
804
|
for (const module of [
|
|
773
805
|
{
|
|
774
806
|
kind: BridgeKind.Actions as const,
|
|
@@ -830,7 +862,7 @@ describe("activity", () => {
|
|
|
830
862
|
},
|
|
831
863
|
});
|
|
832
864
|
|
|
833
|
-
|
|
865
|
+
it("answers an invoke with its result and the entries the handler reported", async () => {
|
|
834
866
|
const { registry, ring } = harnessFor(whitelistDriver());
|
|
835
867
|
|
|
836
868
|
expect(await registry.invoke("whitelist", "add")).toEqual({
|
|
@@ -842,7 +874,7 @@ describe("activity", () => {
|
|
|
842
874
|
expect(ring.drain(0).events).toEqual([]);
|
|
843
875
|
});
|
|
844
876
|
|
|
845
|
-
|
|
877
|
+
it("answers an empty list when the handler reported nothing", async () => {
|
|
846
878
|
const { registry } = harnessFor({
|
|
847
879
|
...baseDriver(),
|
|
848
880
|
modules: {
|
|
@@ -863,7 +895,7 @@ describe("activity", () => {
|
|
|
863
895
|
});
|
|
864
896
|
});
|
|
865
897
|
|
|
866
|
-
|
|
898
|
+
it("sends what a failing handler reported to the events ring", async () => {
|
|
867
899
|
const { registry, ring } = harnessFor(whitelistDriver(true));
|
|
868
900
|
|
|
869
901
|
await expect(registry.invoke("whitelist", "add")).rejects.toThrow("read-only");
|
|
@@ -946,7 +978,7 @@ describe("activity", () => {
|
|
|
946
978
|
},
|
|
947
979
|
});
|
|
948
980
|
|
|
949
|
-
|
|
981
|
+
it("reports the keys whose value changed when the handler reported nothing", async () => {
|
|
950
982
|
const { registry } = harnessFor(
|
|
951
983
|
settingsDriver({
|
|
952
984
|
stored: {
|
|
@@ -980,7 +1012,7 @@ describe("activity", () => {
|
|
|
980
1012
|
]);
|
|
981
1013
|
});
|
|
982
1014
|
|
|
983
|
-
|
|
1015
|
+
it("finishes the write even when a stored value cannot be compared", async () => {
|
|
984
1016
|
const { registry } = harnessFor(
|
|
985
1017
|
settingsDriver({
|
|
986
1018
|
stored: {},
|
|
@@ -1005,7 +1037,7 @@ describe("activity", () => {
|
|
|
1005
1037
|
});
|
|
1006
1038
|
});
|
|
1007
1039
|
|
|
1008
|
-
|
|
1040
|
+
it("reports nothing when no value changed", async () => {
|
|
1009
1041
|
const { registry } = harnessFor(
|
|
1010
1042
|
settingsDriver({
|
|
1011
1043
|
stored: {
|
|
@@ -1023,7 +1055,7 @@ describe("activity", () => {
|
|
|
1023
1055
|
).toEqual([]);
|
|
1024
1056
|
});
|
|
1025
1057
|
|
|
1026
|
-
|
|
1058
|
+
it("keeps the handler's own entry instead of the default", async () => {
|
|
1027
1059
|
const { registry } = harnessFor(
|
|
1028
1060
|
settingsDriver({
|
|
1029
1061
|
stored: {
|
|
@@ -1042,7 +1074,7 @@ describe("activity", () => {
|
|
|
1042
1074
|
]);
|
|
1043
1075
|
});
|
|
1044
1076
|
|
|
1045
|
-
|
|
1077
|
+
it("reports every written key when the settings could not be read first", async () => {
|
|
1046
1078
|
const { registry } = harnessFor(
|
|
1047
1079
|
settingsDriver({
|
|
1048
1080
|
stored: {},
|
|
@@ -1063,7 +1095,7 @@ describe("activity", () => {
|
|
|
1063
1095
|
});
|
|
1064
1096
|
});
|
|
1065
1097
|
|
|
1066
|
-
|
|
1098
|
+
it("never carries the value of a secret field", async () => {
|
|
1067
1099
|
const secret = "hunter22hunter22";
|
|
1068
1100
|
|
|
1069
1101
|
const { registry } = harnessFor(
|
|
@@ -1085,7 +1117,7 @@ describe("activity", () => {
|
|
|
1085
1117
|
expect(JSON.stringify(activity)).not.toContain(secret);
|
|
1086
1118
|
});
|
|
1087
1119
|
|
|
1088
|
-
|
|
1120
|
+
it("drops a detail a handler keyed by a secret field", async () => {
|
|
1089
1121
|
const { registry } = harnessFor({
|
|
1090
1122
|
...settingsDriver({
|
|
1091
1123
|
stored: {},
|
|
@@ -1126,7 +1158,7 @@ describe("activity", () => {
|
|
|
1126
1158
|
});
|
|
1127
1159
|
});
|
|
1128
1160
|
|
|
1129
|
-
|
|
1161
|
+
it("reports no default for a catalog install", async () => {
|
|
1130
1162
|
const { registry } = harnessFor({
|
|
1131
1163
|
...baseDriver(),
|
|
1132
1164
|
modules: {
|
|
@@ -1234,7 +1266,7 @@ describe("availability", () => {
|
|
|
1234
1266
|
throw new Error("the invoke did not refuse");
|
|
1235
1267
|
};
|
|
1236
1268
|
|
|
1237
|
-
|
|
1269
|
+
it("advertises availability only for a collection that declares the hook", () => {
|
|
1238
1270
|
const registry = registryFor({
|
|
1239
1271
|
...baseDriver(),
|
|
1240
1272
|
modules: {
|
|
@@ -1273,7 +1305,7 @@ describe("availability", () => {
|
|
|
1273
1305
|
]);
|
|
1274
1306
|
});
|
|
1275
1307
|
|
|
1276
|
-
|
|
1308
|
+
it("answers the reasons per row and leaves available rows out", async () => {
|
|
1277
1309
|
const registry = registryFor(
|
|
1278
1310
|
worldsDriver({
|
|
1279
1311
|
listed: 0,
|
|
@@ -1292,7 +1324,7 @@ describe("availability", () => {
|
|
|
1292
1324
|
});
|
|
1293
1325
|
});
|
|
1294
1326
|
|
|
1295
|
-
|
|
1327
|
+
it("narrows the answer to one row when asked for its id", async () => {
|
|
1296
1328
|
const registry = registryFor(
|
|
1297
1329
|
worldsDriver({
|
|
1298
1330
|
listed: 0,
|
|
@@ -1312,7 +1344,7 @@ describe("availability", () => {
|
|
|
1312
1344
|
});
|
|
1313
1345
|
});
|
|
1314
1346
|
|
|
1315
|
-
|
|
1347
|
+
it("refuses an unavailable row action before the driver is entered", async () => {
|
|
1316
1348
|
const spies = {
|
|
1317
1349
|
listed: 0,
|
|
1318
1350
|
deleted: [] as string[],
|
|
@@ -1338,7 +1370,7 @@ describe("availability", () => {
|
|
|
1338
1370
|
]);
|
|
1339
1371
|
});
|
|
1340
1372
|
|
|
1341
|
-
|
|
1373
|
+
it("lets the action run when the hook itself fails", async () => {
|
|
1342
1374
|
const spies = {
|
|
1343
1375
|
listed: 0,
|
|
1344
1376
|
deleted: [] as string[],
|
|
@@ -1355,7 +1387,7 @@ describe("availability", () => {
|
|
|
1355
1387
|
]);
|
|
1356
1388
|
});
|
|
1357
1389
|
|
|
1358
|
-
|
|
1390
|
+
it("lets an availability read join a list already in flight and never reuses a settled one", async () => {
|
|
1359
1391
|
const spies = {
|
|
1360
1392
|
listed: 0,
|
|
1361
1393
|
deleted: [] as string[],
|
|
@@ -1375,7 +1407,7 @@ describe("availability", () => {
|
|
|
1375
1407
|
expect(spies.listed).toBe(3);
|
|
1376
1408
|
});
|
|
1377
1409
|
|
|
1378
|
-
|
|
1410
|
+
it("lists fresh for every list read and every action", async () => {
|
|
1379
1411
|
const spies = {
|
|
1380
1412
|
listed: 0,
|
|
1381
1413
|
deleted: [] as string[],
|
|
@@ -1393,7 +1425,7 @@ describe("availability", () => {
|
|
|
1393
1425
|
expect(spies.listed).toBe(3);
|
|
1394
1426
|
});
|
|
1395
1427
|
|
|
1396
|
-
|
|
1428
|
+
it("forgets a list in flight when any module mutates", async () => {
|
|
1397
1429
|
let listed = 0;
|
|
1398
1430
|
let release = () => {};
|
|
1399
1431
|
const gate = new Promise<void>((resolve) => {
|
|
@@ -1444,7 +1476,7 @@ describe("availability", () => {
|
|
|
1444
1476
|
await first;
|
|
1445
1477
|
});
|
|
1446
1478
|
|
|
1447
|
-
|
|
1479
|
+
it("drops reasons for actions the module cannot refuse and clamps long ones", async () => {
|
|
1448
1480
|
const registry = registryFor({
|
|
1449
1481
|
...baseDriver(),
|
|
1450
1482
|
modules: {
|
|
@@ -1485,7 +1517,7 @@ describe("availability", () => {
|
|
|
1485
1517
|
});
|
|
1486
1518
|
});
|
|
1487
1519
|
|
|
1488
|
-
|
|
1520
|
+
it("drops entries the wire would refuse so the answer always validates", async () => {
|
|
1489
1521
|
const registry = registryFor({
|
|
1490
1522
|
...baseDriver(),
|
|
1491
1523
|
modules: {
|
|
@@ -1528,7 +1560,7 @@ describe("availability", () => {
|
|
|
1528
1560
|
expect(bridgeAvailabilitySchema.safeParse(result).success).toBe(true);
|
|
1529
1561
|
});
|
|
1530
1562
|
|
|
1531
|
-
|
|
1563
|
+
it("enforces the allow-list of a detail and answers its reasons", async () => {
|
|
1532
1564
|
const updates: BridgeValues[] = [];
|
|
1533
1565
|
let pressable: string[] = [];
|
|
1534
1566
|
const stale: LocalizedText = {
|
|
@@ -1572,8 +1604,8 @@ describe("availability", () => {
|
|
|
1572
1604
|
module: {
|
|
1573
1605
|
update: stale,
|
|
1574
1606
|
repair: {
|
|
1575
|
-
ar: "هذا الإجراء
|
|
1576
|
-
en: "This action
|
|
1607
|
+
ar: "هذا الإجراء غير متاح حاليًا",
|
|
1608
|
+
en: "This action isn't available right now",
|
|
1577
1609
|
},
|
|
1578
1610
|
},
|
|
1579
1611
|
subjects: {},
|
|
@@ -1594,7 +1626,7 @@ describe("availability", () => {
|
|
|
1594
1626
|
expect(updates).toHaveLength(1);
|
|
1595
1627
|
});
|
|
1596
1628
|
|
|
1597
|
-
|
|
1629
|
+
it("refuses an actions module, a settings write and a catalog removal through their hooks", async () => {
|
|
1598
1630
|
const closed: LocalizedText = {
|
|
1599
1631
|
ar: "مقفل الحين",
|
|
1600
1632
|
en: "Closed right now",
|
|
@@ -1713,7 +1745,7 @@ describe("availability", () => {
|
|
|
1713
1745
|
});
|
|
1714
1746
|
});
|
|
1715
1747
|
|
|
1716
|
-
|
|
1748
|
+
it("does not answer availability for a module that declares no hook", async () => {
|
|
1717
1749
|
const registry = registryFor({
|
|
1718
1750
|
...baseDriver(),
|
|
1719
1751
|
modules: {
|
|
@@ -1729,7 +1761,7 @@ describe("availability", () => {
|
|
|
1729
1761
|
);
|
|
1730
1762
|
});
|
|
1731
1763
|
|
|
1732
|
-
|
|
1764
|
+
it("refuses a driver that names a row action availability", () => {
|
|
1733
1765
|
expect(() =>
|
|
1734
1766
|
registryFor({
|
|
1735
1767
|
...baseDriver(),
|
|
@@ -1748,7 +1780,7 @@ describe("availability", () => {
|
|
|
1748
1780
|
).toThrow('module "worlds" declares action "availability", which is reserved for reads');
|
|
1749
1781
|
});
|
|
1750
1782
|
|
|
1751
|
-
|
|
1783
|
+
it("turns the gates that never enter the driver into refusals without text", async () => {
|
|
1752
1784
|
const registry = registryFor({
|
|
1753
1785
|
...baseDriver(),
|
|
1754
1786
|
modules: {
|
|
@@ -53,8 +53,8 @@ interface CacheEntry {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
const UNAVAILABLE_TEXT: LocalizedText = {
|
|
56
|
-
ar: "هذا الإجراء
|
|
57
|
-
en: "This action
|
|
56
|
+
ar: "هذا الإجراء غير متاح حاليًا",
|
|
57
|
+
en: "This action isn't available right now",
|
|
58
58
|
};
|
|
59
59
|
|
|
60
60
|
const requiresRunning = (module: BridgePanelModule) => {
|