@slates/test 1.0.0-rc.26 → 1.0.0-rc.28

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/dist/index.cjs CHANGED
@@ -20,10 +20,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var index_exports = {};
22
22
  __export(index_exports, {
23
+ authenticateSlateTriggerGroupWebhookDelivery: () => authenticateSlateTriggerGroupWebhookDelivery,
23
24
  connectSlateTriggerGroupGateway: () => connectSlateTriggerGroupGateway,
24
25
  createLocalSlateTestClient: () => createLocalSlateTestClient,
25
26
  createSlatesTestClient: () => createSlatesTestClient,
26
27
  describeMcpCompatibleToolSchemas: () => describeMcpCompatibleToolSchemas,
28
+ expandSlateTriggerGroupWebhook: () => expandSlateTriggerGroupWebhook,
27
29
  expectMcpCompatibleToolSchema: () => expectMcpCompatibleToolSchema,
28
30
  expectSlateContract: () => expectSlateContract,
29
31
  expectSlateError: () => expectSlateError,
@@ -38,6 +40,7 @@ __export(index_exports, {
38
40
  processSlateTriggerGroupWebhook: () => processSlateTriggerGroupWebhook,
39
41
  receiveSlateTriggerGroupGatewayFrames: () => receiveSlateTriggerGroupGatewayFrames,
40
42
  registerSlateTriggerGroupWebhook: () => registerSlateTriggerGroupWebhook,
43
+ renewSlateTriggerGroupWebhook: () => renewSlateTriggerGroupWebhook,
41
44
  unregisterSlateTriggerGroupWebhook: () => unregisterSlateTriggerGroupWebhook,
42
45
  withSlateProfile: () => withSlateProfile
43
46
  });
@@ -255,17 +258,24 @@ var expectSlateContract = async (d) => {
255
258
  }
256
259
  return contract;
257
260
  };
258
- var registerSlateTriggerGroupWebhook = async (d) => d.client.registerTriggerGroupWebhook({
259
- triggerGroupId: d.triggerGroupId,
260
- webhookTargetIdentifier: d.webhookTargetIdentifier,
261
- webhookTargetPayload: d.webhookTargetPayload,
262
- webhookUrl: d.webhookUrl
263
- });
261
+ var registerSlateTriggerGroupWebhook = async (d) => {
262
+ let { client, ...input } = d;
263
+ return client.registerTriggerGroupWebhook(input);
264
+ };
265
+ var renewSlateTriggerGroupWebhook = async (d) => {
266
+ let { client, ...input } = d;
267
+ return client.renewTriggerGroupWebhook(input);
268
+ };
269
+ var expandSlateTriggerGroupWebhook = async (d) => {
270
+ let { client, ...input } = d;
271
+ return client.expandTriggerGroupWebhook(input);
272
+ };
264
273
  var pollSlateTriggerGroupEvents = async (d) => {
265
274
  d.client.ensureSession();
266
275
  return d.client.pollTriggerGroup({
267
276
  triggerGroupId: d.triggerGroupId,
268
- state: d.state ?? null
277
+ state: d.state ?? null,
278
+ selection: d.selection
269
279
  });
270
280
  };
271
281
  var connectSlateTriggerGroupGateway = async (d) => {
@@ -292,6 +302,14 @@ var processSlateTriggerGroupWebhook = async (d) => d.client.processTriggerGroupW
292
302
  body: d.body,
293
303
  webhookRegistrationPayload: d.webhookRegistrationPayload ?? null
294
304
  });
305
+ var authenticateSlateTriggerGroupWebhookDelivery = async (d) => d.client.authenticateTriggerGroupWebhookDelivery({
306
+ triggerGroupId: d.triggerGroupId,
307
+ url: d.url,
308
+ method: d.method ?? "POST",
309
+ headers: d.headers,
310
+ body: d.body,
311
+ deliveryConfig: d.deliveryConfig
312
+ });
295
313
  var unregisterSlateTriggerGroupWebhook = async (d) => d.client.unregisterTriggerGroupWebhook({
296
314
  triggerGroupId: d.triggerGroupId,
297
315
  webhookRegistrationIdentifier: d.webhookRegistrationIdentifier,
@@ -14885,10 +14903,12 @@ var describeMcpCompatibleToolSchemas = (name, source) => {
14885
14903
  };
14886
14904
  // Annotate the CommonJS export names for ESM import in node:
14887
14905
  0 && (module.exports = {
14906
+ authenticateSlateTriggerGroupWebhookDelivery,
14888
14907
  connectSlateTriggerGroupGateway,
14889
14908
  createLocalSlateTestClient,
14890
14909
  createSlatesTestClient,
14891
14910
  describeMcpCompatibleToolSchemas,
14911
+ expandSlateTriggerGroupWebhook,
14892
14912
  expectMcpCompatibleToolSchema,
14893
14913
  expectSlateContract,
14894
14914
  expectSlateError,
@@ -14903,6 +14923,7 @@ var describeMcpCompatibleToolSchemas = (name, source) => {
14903
14923
  processSlateTriggerGroupWebhook,
14904
14924
  receiveSlateTriggerGroupGatewayFrames,
14905
14925
  registerSlateTriggerGroupWebhook,
14926
+ renewSlateTriggerGroupWebhook,
14906
14927
  unregisterSlateTriggerGroupWebhook,
14907
14928
  withSlateProfile
14908
14929
  });
package/dist/index.d.cts CHANGED
@@ -145,6 +145,7 @@ declare let getSlateContract: (client: SlatesTestClient) => Promise<{
145
145
  } | undefined;
146
146
  authMethods?: string[] | undefined;
147
147
  adapter?: string | null | undefined;
148
+ toolCategoryIds?: string[] | undefined;
148
149
  } | {
149
150
  id: string;
150
151
  name: string;
@@ -202,6 +203,7 @@ declare let getSlateContract: (client: SlatesTestClient) => Promise<{
202
203
  } | undefined;
203
204
  authMethods?: string[] | undefined;
204
205
  adapter?: string | null | undefined;
206
+ toolCategoryIds?: string[] | undefined;
205
207
  }[];
206
208
  triggers: {
207
209
  id: string;
@@ -244,14 +246,22 @@ declare let getSlateContract: (client: SlatesTestClient) => Promise<{
244
246
  type: "webhook";
245
247
  registration: {
246
248
  mode: "auto";
249
+ deliveryConfig?: {
250
+ userConfigSchema: Record<string, any>;
251
+ fullConfigSchema: Record<string, any>;
252
+ } | undefined;
247
253
  } | {
248
254
  mode: "manual";
249
255
  userConfigSchema: Record<string, any>;
250
256
  fullConfigSchema: Record<string, any>;
251
257
  };
258
+ supportsExpansion?: boolean | undefined;
259
+ supportsRenewal?: boolean | undefined;
260
+ reconcileIntervalSeconds?: number | undefined;
252
261
  };
253
262
  description?: string | undefined;
254
263
  metadata?: Record<string, any> | undefined;
264
+ selectionSchema?: Record<string, any> | undefined;
255
265
  }[];
256
266
  authMethods: {
257
267
  id: string;
@@ -272,6 +282,10 @@ declare let getSlateContract: (client: SlatesTestClient) => Promise<{
272
282
  getProfile?: {
273
283
  enabled: boolean;
274
284
  } | undefined;
285
+ adminSetup?: {
286
+ enabled: boolean;
287
+ required?: boolean | undefined;
288
+ } | undefined;
275
289
  };
276
290
  docs: {
277
291
  name: string;
@@ -338,6 +352,7 @@ declare let expectSlateContract: (d: {
338
352
  } | undefined;
339
353
  authMethods?: string[] | undefined;
340
354
  adapter?: string | null | undefined;
355
+ toolCategoryIds?: string[] | undefined;
341
356
  } | {
342
357
  id: string;
343
358
  name: string;
@@ -395,6 +410,7 @@ declare let expectSlateContract: (d: {
395
410
  } | undefined;
396
411
  authMethods?: string[] | undefined;
397
412
  adapter?: string | null | undefined;
413
+ toolCategoryIds?: string[] | undefined;
398
414
  }[];
399
415
  triggers: {
400
416
  id: string;
@@ -437,14 +453,22 @@ declare let expectSlateContract: (d: {
437
453
  type: "webhook";
438
454
  registration: {
439
455
  mode: "auto";
456
+ deliveryConfig?: {
457
+ userConfigSchema: Record<string, any>;
458
+ fullConfigSchema: Record<string, any>;
459
+ } | undefined;
440
460
  } | {
441
461
  mode: "manual";
442
462
  userConfigSchema: Record<string, any>;
443
463
  fullConfigSchema: Record<string, any>;
444
464
  };
465
+ supportsExpansion?: boolean | undefined;
466
+ supportsRenewal?: boolean | undefined;
467
+ reconcileIntervalSeconds?: number | undefined;
445
468
  };
446
469
  description?: string | undefined;
447
470
  metadata?: Record<string, any> | undefined;
471
+ selectionSchema?: Record<string, any> | undefined;
448
472
  }[];
449
473
  authMethods: {
450
474
  id: string;
@@ -465,6 +489,10 @@ declare let expectSlateContract: (d: {
465
489
  getProfile?: {
466
490
  enabled: boolean;
467
491
  } | undefined;
492
+ adminSetup?: {
493
+ enabled: boolean;
494
+ required?: boolean | undefined;
495
+ } | undefined;
468
496
  };
469
497
  docs: {
470
498
  name: string;
@@ -483,13 +511,87 @@ declare let expectSlateContract: (d: {
483
511
  }>;
484
512
  declare let registerSlateTriggerGroupWebhook: (d: {
485
513
  client: SlatesTestClient;
486
- triggerGroupId: string;
487
- webhookTargetIdentifier: string;
488
- webhookTargetPayload: any;
489
- webhookUrl: string;
490
- }) => Promise<{
514
+ } & Parameters<SlatesTestClient["registerTriggerGroupWebhook"]>[0]) => Promise<{
515
+ webhookRegistrationIdentifier: string;
516
+ webhookRegistrationPayload: any;
517
+ expiresAt?: string | null | undefined;
518
+ renewAfter?: string | null | undefined;
519
+ routingKeys?: string[] | undefined;
520
+ requestTraces?: {
521
+ startedAt: string;
522
+ durationMs: number;
523
+ request: {
524
+ method: string;
525
+ url: string;
526
+ headers?: Record<string, string> | undefined;
527
+ body?: {
528
+ text: string;
529
+ contentType?: string | undefined;
530
+ truncated?: boolean | undefined;
531
+ } | undefined;
532
+ };
533
+ response?: {
534
+ status: number;
535
+ statusText?: string | undefined;
536
+ headers?: Record<string, string> | undefined;
537
+ body?: {
538
+ text: string;
539
+ contentType?: string | undefined;
540
+ truncated?: boolean | undefined;
541
+ } | undefined;
542
+ } | undefined;
543
+ error?: {
544
+ message: string;
545
+ code?: string | undefined;
546
+ } | undefined;
547
+ }[] | undefined;
548
+ }>;
549
+ declare let renewSlateTriggerGroupWebhook: (d: {
550
+ client: SlatesTestClient;
551
+ } & Parameters<SlatesTestClient["renewTriggerGroupWebhook"]>[0]) => Promise<{
491
552
  webhookRegistrationIdentifier: string;
492
553
  webhookRegistrationPayload: any;
554
+ expiresAt?: string | null | undefined;
555
+ renewAfter?: string | null | undefined;
556
+ routingKeys?: string[] | undefined;
557
+ requestTraces?: {
558
+ startedAt: string;
559
+ durationMs: number;
560
+ request: {
561
+ method: string;
562
+ url: string;
563
+ headers?: Record<string, string> | undefined;
564
+ body?: {
565
+ text: string;
566
+ contentType?: string | undefined;
567
+ truncated?: boolean | undefined;
568
+ } | undefined;
569
+ };
570
+ response?: {
571
+ status: number;
572
+ statusText?: string | undefined;
573
+ headers?: Record<string, string> | undefined;
574
+ body?: {
575
+ text: string;
576
+ contentType?: string | undefined;
577
+ truncated?: boolean | undefined;
578
+ } | undefined;
579
+ } | undefined;
580
+ error?: {
581
+ message: string;
582
+ code?: string | undefined;
583
+ } | undefined;
584
+ }[] | undefined;
585
+ }>;
586
+ declare let expandSlateTriggerGroupWebhook: (d: {
587
+ client: SlatesTestClient;
588
+ } & Parameters<SlatesTestClient["expandTriggerGroupWebhook"]>[0]) => Promise<{
589
+ events: {
590
+ payload: Record<string, any>;
591
+ triggerIds: string[];
592
+ idempotencyKey?: string | undefined;
593
+ }[];
594
+ updatedState?: any;
493
595
  requestTraces?: {
494
596
  startedAt: string;
495
597
  durationMs: number;
@@ -523,6 +625,7 @@ declare let pollSlateTriggerGroupEvents: (d: {
523
625
  client: SlatesTestClient;
524
626
  triggerGroupId: string;
525
627
  state?: any;
628
+ selection?: Record<string, any>;
526
629
  }) => Promise<{
527
630
  events: {
528
631
  payload: Record<string, any>;
@@ -666,6 +769,7 @@ declare let processSlateTriggerGroupWebhook: (d: {
666
769
  triggerIds: string[];
667
770
  idempotencyKey?: string | undefined;
668
771
  }[];
772
+ requiresExpansion?: boolean | undefined;
669
773
  response?: {
670
774
  status: number;
671
775
  headers: Record<string, string>;
@@ -706,6 +810,48 @@ declare let processSlateTriggerGroupWebhook: (d: {
706
810
  } | undefined;
707
811
  }[] | undefined;
708
812
  }>;
813
+ declare let authenticateSlateTriggerGroupWebhookDelivery: (d: {
814
+ client: SlatesTestClient;
815
+ triggerGroupId: string;
816
+ url: string;
817
+ method?: string;
818
+ headers?: Record<string, string>;
819
+ body?: string | Uint8Array | null;
820
+ deliveryConfig: unknown;
821
+ }) => Promise<{
822
+ routingKeys: string[];
823
+ rejected?: {
824
+ status: number;
825
+ } | null | undefined;
826
+ requestTraces?: {
827
+ startedAt: string;
828
+ durationMs: number;
829
+ request: {
830
+ method: string;
831
+ url: string;
832
+ headers?: Record<string, string> | undefined;
833
+ body?: {
834
+ text: string;
835
+ contentType?: string | undefined;
836
+ truncated?: boolean | undefined;
837
+ } | undefined;
838
+ };
839
+ response?: {
840
+ status: number;
841
+ statusText?: string | undefined;
842
+ headers?: Record<string, string> | undefined;
843
+ body?: {
844
+ text: string;
845
+ contentType?: string | undefined;
846
+ truncated?: boolean | undefined;
847
+ } | undefined;
848
+ } | undefined;
849
+ error?: {
850
+ message: string;
851
+ code?: string | undefined;
852
+ } | undefined;
853
+ }[] | undefined;
854
+ }>;
709
855
  declare let unregisterSlateTriggerGroupWebhook: (d: {
710
856
  client: SlatesTestClient;
711
857
  triggerGroupId: string;
@@ -793,4 +939,4 @@ declare let getMcpCompatibleToolSchemaCases: (source: ToolSchemaSource) => Reado
793
939
  declare let expectMcpCompatibleToolSchema: (tool: ToolSchemaTarget) => void;
794
940
  declare let describeMcpCompatibleToolSchemas: (name: string, source: ToolSchemaSource) => void;
795
941
 
796
- export { type ExpectedSlateAction, type ExpectedSlateTriggerGroup, type SlatesRuntimeContext, type SlatesTestClient, connectSlateTriggerGroupGateway, createLocalSlateTestClient, createSlatesTestClient, describeMcpCompatibleToolSchemas, expectMcpCompatibleToolSchema, expectSlateContract, expectSlateError, expectToolCall, getMcpCompatibleToolSchemaCases, getSlateContract, getVitestExpect, loadSlatesProfile, loadSlatesRuntimeContext, mapSlateTriggerEvent, pollSlateTriggerGroupEvents, processSlateTriggerGroupWebhook, receiveSlateTriggerGroupGatewayFrames, registerSlateTriggerGroupWebhook, unregisterSlateTriggerGroupWebhook, withSlateProfile };
942
+ export { type ExpectedSlateAction, type ExpectedSlateTriggerGroup, type SlatesRuntimeContext, type SlatesTestClient, authenticateSlateTriggerGroupWebhookDelivery, connectSlateTriggerGroupGateway, createLocalSlateTestClient, createSlatesTestClient, describeMcpCompatibleToolSchemas, expandSlateTriggerGroupWebhook, expectMcpCompatibleToolSchema, expectSlateContract, expectSlateError, expectToolCall, getMcpCompatibleToolSchemaCases, getSlateContract, getVitestExpect, loadSlatesProfile, loadSlatesRuntimeContext, mapSlateTriggerEvent, pollSlateTriggerGroupEvents, processSlateTriggerGroupWebhook, receiveSlateTriggerGroupGatewayFrames, registerSlateTriggerGroupWebhook, renewSlateTriggerGroupWebhook, unregisterSlateTriggerGroupWebhook, withSlateProfile };
package/dist/index.d.ts CHANGED
@@ -145,6 +145,7 @@ declare let getSlateContract: (client: SlatesTestClient) => Promise<{
145
145
  } | undefined;
146
146
  authMethods?: string[] | undefined;
147
147
  adapter?: string | null | undefined;
148
+ toolCategoryIds?: string[] | undefined;
148
149
  } | {
149
150
  id: string;
150
151
  name: string;
@@ -202,6 +203,7 @@ declare let getSlateContract: (client: SlatesTestClient) => Promise<{
202
203
  } | undefined;
203
204
  authMethods?: string[] | undefined;
204
205
  adapter?: string | null | undefined;
206
+ toolCategoryIds?: string[] | undefined;
205
207
  }[];
206
208
  triggers: {
207
209
  id: string;
@@ -244,14 +246,22 @@ declare let getSlateContract: (client: SlatesTestClient) => Promise<{
244
246
  type: "webhook";
245
247
  registration: {
246
248
  mode: "auto";
249
+ deliveryConfig?: {
250
+ userConfigSchema: Record<string, any>;
251
+ fullConfigSchema: Record<string, any>;
252
+ } | undefined;
247
253
  } | {
248
254
  mode: "manual";
249
255
  userConfigSchema: Record<string, any>;
250
256
  fullConfigSchema: Record<string, any>;
251
257
  };
258
+ supportsExpansion?: boolean | undefined;
259
+ supportsRenewal?: boolean | undefined;
260
+ reconcileIntervalSeconds?: number | undefined;
252
261
  };
253
262
  description?: string | undefined;
254
263
  metadata?: Record<string, any> | undefined;
264
+ selectionSchema?: Record<string, any> | undefined;
255
265
  }[];
256
266
  authMethods: {
257
267
  id: string;
@@ -272,6 +282,10 @@ declare let getSlateContract: (client: SlatesTestClient) => Promise<{
272
282
  getProfile?: {
273
283
  enabled: boolean;
274
284
  } | undefined;
285
+ adminSetup?: {
286
+ enabled: boolean;
287
+ required?: boolean | undefined;
288
+ } | undefined;
275
289
  };
276
290
  docs: {
277
291
  name: string;
@@ -338,6 +352,7 @@ declare let expectSlateContract: (d: {
338
352
  } | undefined;
339
353
  authMethods?: string[] | undefined;
340
354
  adapter?: string | null | undefined;
355
+ toolCategoryIds?: string[] | undefined;
341
356
  } | {
342
357
  id: string;
343
358
  name: string;
@@ -395,6 +410,7 @@ declare let expectSlateContract: (d: {
395
410
  } | undefined;
396
411
  authMethods?: string[] | undefined;
397
412
  adapter?: string | null | undefined;
413
+ toolCategoryIds?: string[] | undefined;
398
414
  }[];
399
415
  triggers: {
400
416
  id: string;
@@ -437,14 +453,22 @@ declare let expectSlateContract: (d: {
437
453
  type: "webhook";
438
454
  registration: {
439
455
  mode: "auto";
456
+ deliveryConfig?: {
457
+ userConfigSchema: Record<string, any>;
458
+ fullConfigSchema: Record<string, any>;
459
+ } | undefined;
440
460
  } | {
441
461
  mode: "manual";
442
462
  userConfigSchema: Record<string, any>;
443
463
  fullConfigSchema: Record<string, any>;
444
464
  };
465
+ supportsExpansion?: boolean | undefined;
466
+ supportsRenewal?: boolean | undefined;
467
+ reconcileIntervalSeconds?: number | undefined;
445
468
  };
446
469
  description?: string | undefined;
447
470
  metadata?: Record<string, any> | undefined;
471
+ selectionSchema?: Record<string, any> | undefined;
448
472
  }[];
449
473
  authMethods: {
450
474
  id: string;
@@ -465,6 +489,10 @@ declare let expectSlateContract: (d: {
465
489
  getProfile?: {
466
490
  enabled: boolean;
467
491
  } | undefined;
492
+ adminSetup?: {
493
+ enabled: boolean;
494
+ required?: boolean | undefined;
495
+ } | undefined;
468
496
  };
469
497
  docs: {
470
498
  name: string;
@@ -483,13 +511,87 @@ declare let expectSlateContract: (d: {
483
511
  }>;
484
512
  declare let registerSlateTriggerGroupWebhook: (d: {
485
513
  client: SlatesTestClient;
486
- triggerGroupId: string;
487
- webhookTargetIdentifier: string;
488
- webhookTargetPayload: any;
489
- webhookUrl: string;
490
- }) => Promise<{
514
+ } & Parameters<SlatesTestClient["registerTriggerGroupWebhook"]>[0]) => Promise<{
515
+ webhookRegistrationIdentifier: string;
516
+ webhookRegistrationPayload: any;
517
+ expiresAt?: string | null | undefined;
518
+ renewAfter?: string | null | undefined;
519
+ routingKeys?: string[] | undefined;
520
+ requestTraces?: {
521
+ startedAt: string;
522
+ durationMs: number;
523
+ request: {
524
+ method: string;
525
+ url: string;
526
+ headers?: Record<string, string> | undefined;
527
+ body?: {
528
+ text: string;
529
+ contentType?: string | undefined;
530
+ truncated?: boolean | undefined;
531
+ } | undefined;
532
+ };
533
+ response?: {
534
+ status: number;
535
+ statusText?: string | undefined;
536
+ headers?: Record<string, string> | undefined;
537
+ body?: {
538
+ text: string;
539
+ contentType?: string | undefined;
540
+ truncated?: boolean | undefined;
541
+ } | undefined;
542
+ } | undefined;
543
+ error?: {
544
+ message: string;
545
+ code?: string | undefined;
546
+ } | undefined;
547
+ }[] | undefined;
548
+ }>;
549
+ declare let renewSlateTriggerGroupWebhook: (d: {
550
+ client: SlatesTestClient;
551
+ } & Parameters<SlatesTestClient["renewTriggerGroupWebhook"]>[0]) => Promise<{
491
552
  webhookRegistrationIdentifier: string;
492
553
  webhookRegistrationPayload: any;
554
+ expiresAt?: string | null | undefined;
555
+ renewAfter?: string | null | undefined;
556
+ routingKeys?: string[] | undefined;
557
+ requestTraces?: {
558
+ startedAt: string;
559
+ durationMs: number;
560
+ request: {
561
+ method: string;
562
+ url: string;
563
+ headers?: Record<string, string> | undefined;
564
+ body?: {
565
+ text: string;
566
+ contentType?: string | undefined;
567
+ truncated?: boolean | undefined;
568
+ } | undefined;
569
+ };
570
+ response?: {
571
+ status: number;
572
+ statusText?: string | undefined;
573
+ headers?: Record<string, string> | undefined;
574
+ body?: {
575
+ text: string;
576
+ contentType?: string | undefined;
577
+ truncated?: boolean | undefined;
578
+ } | undefined;
579
+ } | undefined;
580
+ error?: {
581
+ message: string;
582
+ code?: string | undefined;
583
+ } | undefined;
584
+ }[] | undefined;
585
+ }>;
586
+ declare let expandSlateTriggerGroupWebhook: (d: {
587
+ client: SlatesTestClient;
588
+ } & Parameters<SlatesTestClient["expandTriggerGroupWebhook"]>[0]) => Promise<{
589
+ events: {
590
+ payload: Record<string, any>;
591
+ triggerIds: string[];
592
+ idempotencyKey?: string | undefined;
593
+ }[];
594
+ updatedState?: any;
493
595
  requestTraces?: {
494
596
  startedAt: string;
495
597
  durationMs: number;
@@ -523,6 +625,7 @@ declare let pollSlateTriggerGroupEvents: (d: {
523
625
  client: SlatesTestClient;
524
626
  triggerGroupId: string;
525
627
  state?: any;
628
+ selection?: Record<string, any>;
526
629
  }) => Promise<{
527
630
  events: {
528
631
  payload: Record<string, any>;
@@ -666,6 +769,7 @@ declare let processSlateTriggerGroupWebhook: (d: {
666
769
  triggerIds: string[];
667
770
  idempotencyKey?: string | undefined;
668
771
  }[];
772
+ requiresExpansion?: boolean | undefined;
669
773
  response?: {
670
774
  status: number;
671
775
  headers: Record<string, string>;
@@ -706,6 +810,48 @@ declare let processSlateTriggerGroupWebhook: (d: {
706
810
  } | undefined;
707
811
  }[] | undefined;
708
812
  }>;
813
+ declare let authenticateSlateTriggerGroupWebhookDelivery: (d: {
814
+ client: SlatesTestClient;
815
+ triggerGroupId: string;
816
+ url: string;
817
+ method?: string;
818
+ headers?: Record<string, string>;
819
+ body?: string | Uint8Array | null;
820
+ deliveryConfig: unknown;
821
+ }) => Promise<{
822
+ routingKeys: string[];
823
+ rejected?: {
824
+ status: number;
825
+ } | null | undefined;
826
+ requestTraces?: {
827
+ startedAt: string;
828
+ durationMs: number;
829
+ request: {
830
+ method: string;
831
+ url: string;
832
+ headers?: Record<string, string> | undefined;
833
+ body?: {
834
+ text: string;
835
+ contentType?: string | undefined;
836
+ truncated?: boolean | undefined;
837
+ } | undefined;
838
+ };
839
+ response?: {
840
+ status: number;
841
+ statusText?: string | undefined;
842
+ headers?: Record<string, string> | undefined;
843
+ body?: {
844
+ text: string;
845
+ contentType?: string | undefined;
846
+ truncated?: boolean | undefined;
847
+ } | undefined;
848
+ } | undefined;
849
+ error?: {
850
+ message: string;
851
+ code?: string | undefined;
852
+ } | undefined;
853
+ }[] | undefined;
854
+ }>;
709
855
  declare let unregisterSlateTriggerGroupWebhook: (d: {
710
856
  client: SlatesTestClient;
711
857
  triggerGroupId: string;
@@ -793,4 +939,4 @@ declare let getMcpCompatibleToolSchemaCases: (source: ToolSchemaSource) => Reado
793
939
  declare let expectMcpCompatibleToolSchema: (tool: ToolSchemaTarget) => void;
794
940
  declare let describeMcpCompatibleToolSchemas: (name: string, source: ToolSchemaSource) => void;
795
941
 
796
- export { type ExpectedSlateAction, type ExpectedSlateTriggerGroup, type SlatesRuntimeContext, type SlatesTestClient, connectSlateTriggerGroupGateway, createLocalSlateTestClient, createSlatesTestClient, describeMcpCompatibleToolSchemas, expectMcpCompatibleToolSchema, expectSlateContract, expectSlateError, expectToolCall, getMcpCompatibleToolSchemaCases, getSlateContract, getVitestExpect, loadSlatesProfile, loadSlatesRuntimeContext, mapSlateTriggerEvent, pollSlateTriggerGroupEvents, processSlateTriggerGroupWebhook, receiveSlateTriggerGroupGatewayFrames, registerSlateTriggerGroupWebhook, unregisterSlateTriggerGroupWebhook, withSlateProfile };
942
+ export { type ExpectedSlateAction, type ExpectedSlateTriggerGroup, type SlatesRuntimeContext, type SlatesTestClient, authenticateSlateTriggerGroupWebhookDelivery, connectSlateTriggerGroupGateway, createLocalSlateTestClient, createSlatesTestClient, describeMcpCompatibleToolSchemas, expandSlateTriggerGroupWebhook, expectMcpCompatibleToolSchema, expectSlateContract, expectSlateError, expectToolCall, getMcpCompatibleToolSchemaCases, getSlateContract, getVitestExpect, loadSlatesProfile, loadSlatesRuntimeContext, mapSlateTriggerEvent, pollSlateTriggerGroupEvents, processSlateTriggerGroupWebhook, receiveSlateTriggerGroupGatewayFrames, registerSlateTriggerGroupWebhook, renewSlateTriggerGroupWebhook, unregisterSlateTriggerGroupWebhook, withSlateProfile };
@@ -223,17 +223,24 @@ var expectSlateContract = async (d) => {
223
223
  }
224
224
  return contract;
225
225
  };
226
- var registerSlateTriggerGroupWebhook = async (d) => d.client.registerTriggerGroupWebhook({
227
- triggerGroupId: d.triggerGroupId,
228
- webhookTargetIdentifier: d.webhookTargetIdentifier,
229
- webhookTargetPayload: d.webhookTargetPayload,
230
- webhookUrl: d.webhookUrl
231
- });
226
+ var registerSlateTriggerGroupWebhook = async (d) => {
227
+ let { client, ...input } = d;
228
+ return client.registerTriggerGroupWebhook(input);
229
+ };
230
+ var renewSlateTriggerGroupWebhook = async (d) => {
231
+ let { client, ...input } = d;
232
+ return client.renewTriggerGroupWebhook(input);
233
+ };
234
+ var expandSlateTriggerGroupWebhook = async (d) => {
235
+ let { client, ...input } = d;
236
+ return client.expandTriggerGroupWebhook(input);
237
+ };
232
238
  var pollSlateTriggerGroupEvents = async (d) => {
233
239
  d.client.ensureSession();
234
240
  return d.client.pollTriggerGroup({
235
241
  triggerGroupId: d.triggerGroupId,
236
- state: d.state ?? null
242
+ state: d.state ?? null,
243
+ selection: d.selection
237
244
  });
238
245
  };
239
246
  var connectSlateTriggerGroupGateway = async (d) => {
@@ -260,6 +267,14 @@ var processSlateTriggerGroupWebhook = async (d) => d.client.processTriggerGroupW
260
267
  body: d.body,
261
268
  webhookRegistrationPayload: d.webhookRegistrationPayload ?? null
262
269
  });
270
+ var authenticateSlateTriggerGroupWebhookDelivery = async (d) => d.client.authenticateTriggerGroupWebhookDelivery({
271
+ triggerGroupId: d.triggerGroupId,
272
+ url: d.url,
273
+ method: d.method ?? "POST",
274
+ headers: d.headers,
275
+ body: d.body,
276
+ deliveryConfig: d.deliveryConfig
277
+ });
263
278
  var unregisterSlateTriggerGroupWebhook = async (d) => d.client.unregisterTriggerGroupWebhook({
264
279
  triggerGroupId: d.triggerGroupId,
265
280
  webhookRegistrationIdentifier: d.webhookRegistrationIdentifier,
@@ -14852,10 +14867,12 @@ var describeMcpCompatibleToolSchemas = (name, source) => {
14852
14867
  });
14853
14868
  };
14854
14869
  export {
14870
+ authenticateSlateTriggerGroupWebhookDelivery,
14855
14871
  connectSlateTriggerGroupGateway,
14856
14872
  createLocalSlateTestClient,
14857
14873
  createSlatesTestClient,
14858
14874
  describeMcpCompatibleToolSchemas,
14875
+ expandSlateTriggerGroupWebhook,
14859
14876
  expectMcpCompatibleToolSchema,
14860
14877
  expectSlateContract,
14861
14878
  expectSlateError,
@@ -14870,6 +14887,7 @@ export {
14870
14887
  processSlateTriggerGroupWebhook,
14871
14888
  receiveSlateTriggerGroupGatewayFrames,
14872
14889
  registerSlateTriggerGroupWebhook,
14890
+ renewSlateTriggerGroupWebhook,
14873
14891
  unregisterSlateTriggerGroupWebhook,
14874
14892
  withSlateProfile
14875
14893
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slates/test",
3
- "version": "1.0.0-rc.26",
3
+ "version": "1.0.0-rc.28",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -40,11 +40,11 @@
40
40
  },
41
41
  "dependencies": {
42
42
  "@lowerdeck/testing-tools": "latest",
43
- "@slates/client": "1.0.0-rc.29",
44
- "@slates/profiles": "1.0.0-rc.27"
43
+ "@slates/client": "1.0.0-rc.33",
44
+ "@slates/profiles": "1.0.0-rc.29"
45
45
  },
46
46
  "devDependencies": {
47
- "@slates/provider": "1.0.0-rc.29",
47
+ "@slates/provider": "1.0.0-rc.34",
48
48
  "@slates/tsconfig": "1.0.0-rc.1",
49
49
  "typescript": "5.8.2",
50
50
  "vitest": "^3.1.2",
package/src/runtime.ts CHANGED
@@ -352,29 +352,42 @@ export let expectSlateContract = async (d: {
352
352
  return contract;
353
353
  };
354
354
 
355
- export let registerSlateTriggerGroupWebhook = async (d: {
356
- client: SlatesTestClient;
357
- triggerGroupId: string;
358
- webhookTargetIdentifier: string;
359
- webhookTargetPayload: any;
360
- webhookUrl: string;
361
- }) =>
362
- d.client.registerTriggerGroupWebhook({
363
- triggerGroupId: d.triggerGroupId,
364
- webhookTargetIdentifier: d.webhookTargetIdentifier,
365
- webhookTargetPayload: d.webhookTargetPayload,
366
- webhookUrl: d.webhookUrl
367
- });
355
+ export let registerSlateTriggerGroupWebhook = async (
356
+ d: { client: SlatesTestClient } & Parameters<
357
+ SlatesTestClient['registerTriggerGroupWebhook']
358
+ >[0]
359
+ ) => {
360
+ let { client, ...input } = d;
361
+ return client.registerTriggerGroupWebhook(input);
362
+ };
363
+
364
+ export let renewSlateTriggerGroupWebhook = async (
365
+ d: { client: SlatesTestClient } & Parameters<SlatesTestClient['renewTriggerGroupWebhook']>[0]
366
+ ) => {
367
+ let { client, ...input } = d;
368
+ return client.renewTriggerGroupWebhook(input);
369
+ };
370
+
371
+ export let expandSlateTriggerGroupWebhook = async (
372
+ d: { client: SlatesTestClient } & Parameters<
373
+ SlatesTestClient['expandTriggerGroupWebhook']
374
+ >[0]
375
+ ) => {
376
+ let { client, ...input } = d;
377
+ return client.expandTriggerGroupWebhook(input);
378
+ };
368
379
 
369
380
  export let pollSlateTriggerGroupEvents = async (d: {
370
381
  client: SlatesTestClient;
371
382
  triggerGroupId: string;
372
383
  state?: any;
384
+ selection?: Record<string, any>;
373
385
  }) => {
374
386
  d.client.ensureSession();
375
387
  return d.client.pollTriggerGroup({
376
388
  triggerGroupId: d.triggerGroupId,
377
- state: d.state ?? null
389
+ state: d.state ?? null,
390
+ selection: d.selection
378
391
  });
379
392
  };
380
393
 
@@ -424,6 +437,24 @@ export let processSlateTriggerGroupWebhook = async (d: {
424
437
  webhookRegistrationPayload: d.webhookRegistrationPayload ?? null
425
438
  });
426
439
 
440
+ export let authenticateSlateTriggerGroupWebhookDelivery = async (d: {
441
+ client: SlatesTestClient;
442
+ triggerGroupId: string;
443
+ url: string;
444
+ method?: string;
445
+ headers?: Record<string, string>;
446
+ body?: string | Uint8Array | null;
447
+ deliveryConfig: unknown;
448
+ }) =>
449
+ d.client.authenticateTriggerGroupWebhookDelivery({
450
+ triggerGroupId: d.triggerGroupId,
451
+ url: d.url,
452
+ method: d.method ?? 'POST',
453
+ headers: d.headers,
454
+ body: d.body,
455
+ deliveryConfig: d.deliveryConfig
456
+ });
457
+
427
458
  export let unregisterSlateTriggerGroupWebhook = async (d: {
428
459
  client: SlatesTestClient;
429
460
  triggerGroupId: string;
@@ -0,0 +1,561 @@
1
+ import {
2
+ Slate,
3
+ SlateAuth,
4
+ SlateConfig,
5
+ SlateSpecification,
6
+ SlateTrigger,
7
+ triggerGroup
8
+ } from '@slates/provider';
9
+ import { describe, expect, it } from 'vitest';
10
+ import { z } from 'zod';
11
+ import {
12
+ authenticateSlateTriggerGroupWebhookDelivery,
13
+ createLocalSlateTestClient,
14
+ expandSlateTriggerGroupWebhook,
15
+ pollSlateTriggerGroupEvents,
16
+ processSlateTriggerGroupWebhook,
17
+ registerSlateTriggerGroupWebhook,
18
+ renewSlateTriggerGroupWebhook
19
+ } from './index';
20
+
21
+ let fixture = (
22
+ options: {
23
+ selection?: 'required' | 'default';
24
+ legacy?: boolean;
25
+ expiresAt?: string | null;
26
+ renewAfter?: string | null;
27
+ invalidExpansion?: boolean;
28
+ reconcileIntervalSeconds?: number;
29
+ deliveryConfig?: boolean;
30
+ } = {}
31
+ ) => {
32
+ let contexts: { operation: string; auth: unknown; config: unknown; input: any }[] = [];
33
+ let auth = SlateAuth.create<{ token: string }>()
34
+ .output(z.object({ token: z.string() }))
35
+ .addTokenAuth({
36
+ type: 'auth.token',
37
+ key: 'token',
38
+ name: 'Token',
39
+ inputSchema: z.object({ token: z.string() }),
40
+ getOutput: async ctx => ({ output: ctx.input })
41
+ });
42
+ let spec = SlateSpecification.create({
43
+ key: 'lifecycle',
44
+ name: 'Lifecycle',
45
+ description: 'Trigger lifecycle contract',
46
+ auth,
47
+ config: SlateConfig.create(z.object({ tenant: z.string() }))
48
+ });
49
+ let selectionSchema =
50
+ options.selection === 'required'
51
+ ? z.object({ resource: z.string() })
52
+ : options.selection === 'default'
53
+ ? z.object({ resource: z.string().default('default-resource') })
54
+ : undefined;
55
+ let record = (operation: string, ctx: { auth: unknown; config: unknown; input: any }) => {
56
+ contexts.push({ operation, auth: ctx.auth, config: ctx.config, input: ctx.input });
57
+ };
58
+ let registration = {
59
+ webhookRegistrationIdentifier: 'registration',
60
+ webhookRegistrationPayload: { secret: 'verification' },
61
+ ...(options.expiresAt !== undefined ? { expiresAt: options.expiresAt } : {}),
62
+ ...(options.renewAfter !== undefined ? { renewAfter: options.renewAfter } : {})
63
+ };
64
+ let group = triggerGroup(spec, { key: 'webhook', name: 'Webhook', selectionSchema })
65
+ .webhook({
66
+ reconcileIntervalSeconds: options.reconcileIntervalSeconds,
67
+ deliveryConfig: options.deliveryConfig
68
+ ? {
69
+ userConfigSchema: z.object({ topicName: z.string() }),
70
+ fullConfigSchema: z.object({ topicName: z.string(), audience: z.string() }),
71
+ setup: async ctx => {
72
+ record('setup', ctx);
73
+ return {
74
+ webhookSetupDocument: `Deliver to ${ctx.input.webhookUrl}`,
75
+ partialWebhookRegistrationPayload: {}
76
+ };
77
+ },
78
+ finish: async ctx => {
79
+ record('finish', ctx);
80
+ return {
81
+ webhookRegistrationPayload: {
82
+ ...ctx.input.userWebhookRegistrationPayload,
83
+ audience: ctx.input.webhookUrl
84
+ }
85
+ };
86
+ },
87
+ authenticate: async ctx => {
88
+ record('authenticate', ctx);
89
+ let status = Number(ctx.input.request.headers.get('x-reject'));
90
+ if (status) return { rejected: { status } };
91
+ let body = JSON.parse(await ctx.input.request.text()) as { keys: string[] };
92
+ return { routingKeys: body.keys };
93
+ }
94
+ }
95
+ : undefined,
96
+ autoRegistration: {
97
+ webhookTargetList: async ctx => {
98
+ record('targets', ctx);
99
+ return { targets: [], nextPageToken: null };
100
+ },
101
+ webhookRegister: async ctx => {
102
+ record('register', ctx);
103
+ return registration;
104
+ },
105
+ webhookRenew: options.legacy
106
+ ? undefined
107
+ : async ctx => {
108
+ record('renew', ctx);
109
+ return {
110
+ ...registration,
111
+ webhookRegistrationIdentifier: 'renewed-registration'
112
+ };
113
+ },
114
+ webhookUnregister: async () => {}
115
+ },
116
+ process: async ctx => {
117
+ record('process', ctx);
118
+ return {
119
+ events: [
120
+ {
121
+ payload: { raw: true },
122
+ matchers: [{ tenant: 'tenant' }],
123
+ idempotencyKey: 'raw-key'
124
+ }
125
+ ]
126
+ };
127
+ },
128
+ expandWebhook: options.legacy
129
+ ? undefined
130
+ : async ctx => {
131
+ record('expand', ctx);
132
+ // Malformed output deliberately exercises the runtime contract boundary.
133
+ if (options.invalidExpansion) return { events: [{ payload: [] }] };
134
+ let payload = z
135
+ .object({ empty: z.boolean().optional(), preserve: z.boolean().optional() })
136
+ .nullable()
137
+ .parse(ctx.input.payload);
138
+ if (payload?.empty) return { events: [], updatedState: null };
139
+ if (payload?.preserve) return { events: [] };
140
+ return {
141
+ events: [
142
+ { payload: { kind: 'selected', id: 'one' }, idempotencyKey: 'one' },
143
+ { payload: { kind: 'other', id: 'two' }, idempotencyKey: 'two' },
144
+ { payload: { kind: 'selected', id: 'three' }, idempotencyKey: 'three' }
145
+ ],
146
+ updatedState: { cursor: 'next' }
147
+ };
148
+ }
149
+ })
150
+ .routingMatchers(async () => [{ tenant: 'tenant' }])
151
+ .build();
152
+ let poll = triggerGroup(spec, { key: 'poll', name: 'Poll', selectionSchema })
153
+ .polling({
154
+ pollEvents: async ctx => {
155
+ record('poll', ctx);
156
+ return { events: [], updatedState: ctx.input.state };
157
+ }
158
+ })
159
+ .routingMatchers(async () => [])
160
+ .build();
161
+ let matches = 0;
162
+ let selectedInput = z.object({
163
+ kind: z.string().optional(),
164
+ id: z.string().optional(),
165
+ raw: z.boolean().optional()
166
+ });
167
+ let selected = SlateTrigger.create(spec, { key: 'selected', name: 'Selected' })
168
+ .triggerGroup(group)
169
+ .input(selectedInput)
170
+ .output(z.object({ id: z.string() }))
171
+ .matches(payload => {
172
+ matches++;
173
+ let event = selectedInput.safeParse(payload);
174
+ return event.success && (event.data.kind === 'selected' || event.data.raw === true);
175
+ })
176
+ .map(async ctx => {
177
+ let id = ctx.input.id ?? 'raw';
178
+ return { type: 'selected', id, output: { id } };
179
+ })
180
+ .build();
181
+ let slate = Slate.create({
182
+ spec,
183
+ tools: [],
184
+ triggers: [selected],
185
+ triggerGroups: [group, poll]
186
+ });
187
+ let client = createLocalSlateTestClient({
188
+ slate,
189
+ state: {
190
+ config: { tenant: 'tenant' },
191
+ auth: { authenticationMethodId: 'token', output: { token: 'credential' } }
192
+ }
193
+ });
194
+ return { client, contexts, matches: () => matches };
195
+ };
196
+
197
+ let registrationInput = {
198
+ triggerGroupId: 'webhook',
199
+ webhookTargetIdentifier: 'target',
200
+ webhookTargetPayload: { resource: 'target' },
201
+ webhookUrl: 'https://example.com/webhook'
202
+ };
203
+ let renewalInput = {
204
+ ...registrationInput,
205
+ webhookRegistrationIdentifier: 'registration',
206
+ webhookRegistrationPayload: { secret: 'verification' },
207
+ operationId: 'stable-operation'
208
+ };
209
+ let expansionInput = {
210
+ triggerGroupId: 'webhook',
211
+ payload: { raw: true },
212
+ state: { cursor: 'before' },
213
+ deliveryId: 'delivery',
214
+ webhookRegistrationPayload: { secret: 'verification' }
215
+ };
216
+
217
+ describe('trigger lifecycle protocol helpers', () => {
218
+ it('passes the saved delivery config unchanged and independently from user selection', async () => {
219
+ let { client, contexts } = fixture({ deliveryConfig: true });
220
+ let deliveryConfig = {
221
+ topicName: 'projects/p/topics/t',
222
+ audience: 'https://example.com/delivery',
223
+ nested: { kept: ['as', 'saved'] }
224
+ };
225
+ await registerSlateTriggerGroupWebhook({
226
+ client,
227
+ ...registrationInput,
228
+ operationId: 'initial-registration-operation',
229
+ deliveryConfig
230
+ });
231
+ await renewSlateTriggerGroupWebhook({ client, ...renewalInput, deliveryConfig });
232
+ expect(contexts.map(ctx => [ctx.operation, ctx.input.deliveryConfig])).toEqual([
233
+ ['register', deliveryConfig],
234
+ ['renew', deliveryConfig]
235
+ ]);
236
+ expect(contexts[0]?.input.operationId).toBe('initial-registration-operation');
237
+ await registerSlateTriggerGroupWebhook({
238
+ client,
239
+ ...registrationInput,
240
+ selection: { deliveryConfig }
241
+ });
242
+ expect(contexts.at(-1)?.input.deliveryConfig).toBeUndefined();
243
+ expect(contexts.at(-1)?.input.operationId).toBeUndefined();
244
+ });
245
+
246
+ it('exposes the delivery config of an automatic group and completes it without credentials', async () => {
247
+ let { client, contexts } = fixture({ deliveryConfig: true });
248
+ expect((await client.getTriggerGroup('webhook')).triggerGroup.invocation).toMatchObject({
249
+ registration: {
250
+ mode: 'auto',
251
+ deliveryConfig: {
252
+ userConfigSchema: { type: 'object', required: ['topicName'] },
253
+ fullConfigSchema: { type: 'object', required: ['topicName', 'audience'] }
254
+ }
255
+ }
256
+ });
257
+ client.clearAuth();
258
+ let webhookUrl = 'https://example.com/delivery';
259
+ let setup = await client.setupTriggerGroupWebhookManually({
260
+ triggerGroupId: 'webhook',
261
+ webhookUrl
262
+ });
263
+ expect(setup).toEqual({
264
+ webhookSetupDocument: `Deliver to ${webhookUrl}`,
265
+ partialWebhookRegistrationPayload: {}
266
+ });
267
+ let finished = await client.finishTriggerGroupWebhookManualSetup({
268
+ triggerGroupId: 'webhook',
269
+ webhookUrl,
270
+ partialWebhookRegistrationPayload: setup.partialWebhookRegistrationPayload,
271
+ userWebhookRegistrationPayload: { topicName: 'projects/p/topics/t' }
272
+ });
273
+ expect(finished.webhookRegistrationPayload).toEqual({
274
+ topicName: 'projects/p/topics/t',
275
+ audience: webhookUrl
276
+ });
277
+ expect(contexts.map(ctx => [ctx.operation, ctx.auth, ctx.config])).toEqual([
278
+ ['setup', {}, {}],
279
+ ['finish', {}, {}]
280
+ ]);
281
+ await expect(
282
+ fixture().client.setupTriggerGroupWebhookManually({
283
+ triggerGroupId: 'webhook',
284
+ webhookUrl
285
+ })
286
+ ).rejects.toThrow('does not support manual webhook registration');
287
+ });
288
+
289
+ it('authenticates a delivery through the delivery config without credentials', async () => {
290
+ let { client, contexts } = fixture({ deliveryConfig: true });
291
+ client.clearAuth();
292
+ let deliveryConfig = {
293
+ topicName: 'projects/p/topics/t',
294
+ audience: 'https://example.com/d'
295
+ };
296
+ let delivery = {
297
+ client,
298
+ triggerGroupId: 'webhook',
299
+ url: 'https://example.com/d',
300
+ deliveryConfig
301
+ };
302
+ expect(
303
+ await authenticateSlateTriggerGroupWebhookDelivery({
304
+ ...delivery,
305
+ body: JSON.stringify({ keys: ['resource:one', 'resource:two'] })
306
+ })
307
+ ).toEqual({ routingKeys: ['resource:one', 'resource:two'], rejected: null });
308
+ expect(
309
+ await authenticateSlateTriggerGroupWebhookDelivery({
310
+ ...delivery,
311
+ body: JSON.stringify({ keys: [] })
312
+ })
313
+ ).toEqual({ routingKeys: [], rejected: null });
314
+ expect(
315
+ await authenticateSlateTriggerGroupWebhookDelivery({
316
+ ...delivery,
317
+ headers: { 'x-reject': '503' }
318
+ })
319
+ ).toEqual({ routingKeys: [], rejected: { status: 503 } });
320
+ expect(contexts.map(ctx => [ctx.operation, ctx.auth, ctx.config])).toEqual(
321
+ Array(3).fill(['authenticate', {}, {}])
322
+ );
323
+ expect(contexts.map(ctx => ctx.input.deliveryConfig)).toEqual(
324
+ Array(3).fill(deliveryConfig)
325
+ );
326
+ await expect(
327
+ authenticateSlateTriggerGroupWebhookDelivery({
328
+ ...delivery,
329
+ client: fixture().client,
330
+ body: JSON.stringify({ keys: [] })
331
+ })
332
+ ).rejects.toThrow('does not support webhook delivery authentication');
333
+ });
334
+
335
+ it('advertises schemas and capabilities while preserving old group specifications', async () => {
336
+ let { client } = fixture({ selection: 'default' });
337
+ expect((await client.getTriggerGroup('webhook')).triggerGroup).toMatchObject({
338
+ selectionSchema: {
339
+ type: 'object',
340
+ properties: { resource: { type: 'string', default: 'default-resource' } }
341
+ },
342
+ invocation: { type: 'webhook', supportsExpansion: true, supportsRenewal: true }
343
+ });
344
+ let legacy = fixture({ legacy: true });
345
+ let oldGroup = (await legacy.client.getTriggerGroup('webhook')).triggerGroup;
346
+ expect(oldGroup).not.toHaveProperty('selectionSchema');
347
+ expect(oldGroup.invocation).toEqual({ type: 'webhook', registration: { mode: 'auto' } });
348
+ expect(
349
+ (await client.getTriggerGroup('webhook')).triggerGroup.selectionSchema
350
+ ).not.toHaveProperty('required');
351
+ });
352
+
353
+ it('declares bounded reconciliation and passes scheduled null payloads unchanged', async () => {
354
+ for (let reconcileIntervalSeconds of [
355
+ 0,
356
+ 899,
357
+ 900.5,
358
+ Number.NaN,
359
+ Number.POSITIVE_INFINITY
360
+ ]) {
361
+ expect(() => fixture({ reconcileIntervalSeconds })).toThrow(
362
+ 'integer of at least 900 seconds'
363
+ );
364
+ }
365
+ expect(() => fixture({ legacy: true, reconcileIntervalSeconds: 900 })).toThrow(
366
+ 'requires an expandWebhook handler'
367
+ );
368
+ let { client, contexts } = fixture({ reconcileIntervalSeconds: 900 });
369
+ expect((await client.getTriggerGroup('webhook')).triggerGroup.invocation).toMatchObject({
370
+ reconcileIntervalSeconds: 900,
371
+ supportsExpansion: true
372
+ });
373
+ let result = await expandSlateTriggerGroupWebhook({
374
+ client,
375
+ ...expansionInput,
376
+ payload: null,
377
+ deliveryId: 'scheduled-run'
378
+ });
379
+ expect(result.events).toHaveLength(3);
380
+ expect(contexts[0]?.input).toMatchObject({
381
+ payload: null,
382
+ deliveryId: 'scheduled-run',
383
+ state: expansionInput.state,
384
+ webhookRegistrationPayload: expansionInput.webhookRegistrationPayload
385
+ });
386
+ });
387
+
388
+ it('verifies without credentials and expands zero or many events with connection context', async () => {
389
+ let { client, contexts, matches } = fixture({ selection: 'required' });
390
+ let processed = await processSlateTriggerGroupWebhook({
391
+ client,
392
+ triggerGroupId: 'webhook',
393
+ url: registrationInput.webhookUrl,
394
+ webhookRegistrationPayload: expansionInput.webhookRegistrationPayload
395
+ });
396
+ expect(processed).toMatchObject({
397
+ requiresExpansion: true,
398
+ events: [{ triggerIds: [], idempotencyKey: 'raw-key' }]
399
+ });
400
+ expect(matches()).toBe(0);
401
+ expect(contexts[0]).toMatchObject({ operation: 'process', auth: {}, config: {} });
402
+ let expanded = await expandSlateTriggerGroupWebhook({
403
+ client,
404
+ ...expansionInput,
405
+ selection: { resource: 'chosen' }
406
+ });
407
+ expect(expanded).toMatchObject({
408
+ updatedState: { cursor: 'next' },
409
+ events: [
410
+ { idempotencyKey: 'one', triggerIds: ['selected'] },
411
+ { idempotencyKey: 'two', triggerIds: [] },
412
+ { idempotencyKey: 'three', triggerIds: ['selected'] }
413
+ ]
414
+ });
415
+ expect(contexts[1]).toMatchObject({
416
+ operation: 'expand',
417
+ auth: { token: 'credential' },
418
+ config: { tenant: 'tenant' },
419
+ input: {
420
+ payload: expansionInput.payload,
421
+ state: expansionInput.state,
422
+ deliveryId: expansionInput.deliveryId,
423
+ webhookRegistrationPayload: expansionInput.webhookRegistrationPayload,
424
+ selection: { resource: 'chosen' }
425
+ }
426
+ });
427
+ expect(matches()).toBe(3);
428
+ expect(
429
+ await client.mapTriggerEvent('selected', expanded.events[0]!.payload)
430
+ ).toMatchObject({ output: { id: 'one' } });
431
+ let cleared = await expandSlateTriggerGroupWebhook({
432
+ client,
433
+ ...expansionInput,
434
+ payload: { empty: true },
435
+ selection: { resource: 'chosen' }
436
+ });
437
+ expect(cleared).toMatchObject({ events: [], updatedState: null });
438
+ let preserved = await expandSlateTriggerGroupWebhook({
439
+ client,
440
+ ...expansionInput,
441
+ payload: { preserve: true },
442
+ selection: { resource: 'chosen' }
443
+ });
444
+ expect(preserved.events).toEqual([]);
445
+ expect(preserved).not.toHaveProperty('updatedState');
446
+ });
447
+
448
+ it('validates selection before every affected handler and applies accepted defaults', async () => {
449
+ let { client, contexts } = fixture({ selection: 'required' });
450
+ let calls = [
451
+ () => client.listTriggerGroupWebhookTargets({ triggerGroupId: 'webhook' }),
452
+ () => registerSlateTriggerGroupWebhook({ client, ...registrationInput }),
453
+ () => renewSlateTriggerGroupWebhook({ client, ...renewalInput }),
454
+ () => expandSlateTriggerGroupWebhook({ client, ...expansionInput }),
455
+ () => pollSlateTriggerGroupEvents({ client, triggerGroupId: 'poll' })
456
+ ];
457
+ for (let call of calls) await expect(call()).rejects.toThrow('Invalid selection');
458
+ expect(contexts).toEqual([]);
459
+ let defaults = fixture({ selection: 'default' });
460
+ await defaults.client.listTriggerGroupWebhookTargets({ triggerGroupId: 'webhook' });
461
+ await registerSlateTriggerGroupWebhook({ client: defaults.client, ...registrationInput });
462
+ await renewSlateTriggerGroupWebhook({ client: defaults.client, ...renewalInput });
463
+ await expandSlateTriggerGroupWebhook({ client: defaults.client, ...expansionInput });
464
+ await pollSlateTriggerGroupEvents({ client: defaults.client, triggerGroupId: 'poll' });
465
+ expect(defaults.contexts.map(ctx => ctx.input.selection)).toEqual(
466
+ Array(5).fill({ resource: 'default-resource' })
467
+ );
468
+ await pollSlateTriggerGroupEvents({
469
+ client: defaults.client,
470
+ triggerGroupId: 'poll',
471
+ selection: { resource: 'explicit' }
472
+ });
473
+ expect(defaults.contexts.at(-1)?.input.selection).toEqual({ resource: 'explicit' });
474
+ });
475
+
476
+ it('keeps groups without selection, expansion, or renewal backward compatible', async () => {
477
+ let { client, contexts } = fixture({ legacy: true });
478
+ await registerSlateTriggerGroupWebhook({ client, ...registrationInput });
479
+ await pollSlateTriggerGroupEvents({ client, triggerGroupId: 'poll' });
480
+ expect(contexts.map(ctx => ctx.input.selection)).toEqual([{}, {}]);
481
+ let processed = await processSlateTriggerGroupWebhook({
482
+ client,
483
+ triggerGroupId: 'webhook',
484
+ url: registrationInput.webhookUrl
485
+ });
486
+ expect(processed.events[0]?.triggerIds).toEqual(['selected']);
487
+ expect(processed).not.toHaveProperty('requiresExpansion');
488
+ await expect(renewSlateTriggerGroupWebhook({ client, ...renewalInput })).rejects.toThrow(
489
+ 'does not support webhook renewal'
490
+ );
491
+ await expect(
492
+ expandSlateTriggerGroupWebhook({ client, ...expansionInput })
493
+ ).rejects.toThrow('does not support webhook expansion');
494
+ });
495
+
496
+ it('requires authenticated context for expansion and renewal', async () => {
497
+ let { client, contexts } = fixture();
498
+ client.clearAuth();
499
+ await expect(
500
+ expandSlateTriggerGroupWebhook({ client, ...expansionInput })
501
+ ).rejects.toMatchObject({
502
+ data: { code: 'request.precondition_failed' }
503
+ });
504
+ await expect(
505
+ renewSlateTriggerGroupWebhook({ client, ...renewalInput })
506
+ ).rejects.toMatchObject({
507
+ data: { code: 'request.precondition_failed' }
508
+ });
509
+ expect(contexts).toEqual([]);
510
+ await processSlateTriggerGroupWebhook({
511
+ client,
512
+ triggerGroupId: 'webhook',
513
+ url: registrationInput.webhookUrl
514
+ });
515
+ expect(contexts[0]).toMatchObject({ operation: 'process', auth: {}, config: {} });
516
+ });
517
+
518
+ it('passes stable renewal identity and validates nullable ISO scheduling metadata', async () => {
519
+ let { client, contexts } = fixture({
520
+ expiresAt: '2026-12-01T12:00:00+01:00',
521
+ renewAfter: null
522
+ });
523
+ let registered = await registerSlateTriggerGroupWebhook({ client, ...registrationInput });
524
+ expect(registered).toMatchObject({
525
+ expiresAt: '2026-12-01T12:00:00+01:00',
526
+ renewAfter: null
527
+ });
528
+ let renewed = await renewSlateTriggerGroupWebhook({
529
+ client,
530
+ ...renewalInput,
531
+ selection: { resource: 'chosen' }
532
+ });
533
+ expect(renewed).toMatchObject({
534
+ webhookRegistrationIdentifier: 'renewed-registration',
535
+ expiresAt: registered.expiresAt,
536
+ renewAfter: null
537
+ });
538
+ expect(contexts.at(-1)).toMatchObject({
539
+ operation: 'renew',
540
+ auth: { token: 'credential' },
541
+ config: { tenant: 'tenant' },
542
+ input: {
543
+ operationId: 'stable-operation',
544
+ webhookRegistrationIdentifier: 'registration',
545
+ webhookTargetIdentifier: 'target',
546
+ selection: { resource: 'chosen' }
547
+ }
548
+ });
549
+ let invalid = fixture({ expiresAt: 'tomorrow' });
550
+ await expect(
551
+ registerSlateTriggerGroupWebhook({ client: invalid.client, ...registrationInput })
552
+ ).rejects.toThrow('invalid result');
553
+ await expect(
554
+ renewSlateTriggerGroupWebhook({ client: invalid.client, ...renewalInput })
555
+ ).rejects.toThrow('invalid result');
556
+ let invalidExpansion = fixture({ invalidExpansion: true });
557
+ await expect(
558
+ expandSlateTriggerGroupWebhook({ client: invalidExpansion.client, ...expansionInput })
559
+ ).rejects.toThrow('invalid result');
560
+ });
561
+ });