@whooshbang/contract-mock 1.0.0-rc.36 → 1.0.0-rc.37

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/CHANGELOG.md CHANGED
@@ -5,6 +5,17 @@ recorded here.
5
5
 
6
6
  ## Unreleased
7
7
 
8
+ ## 1.0.0-rc.37
9
+
10
+ ### Added
11
+
12
+ - Exercise `@whooshbang/contracts@1.0.0-rc.25` with `@whooshbang/sdk@1.0.0-rc.34`.
13
+ The environment recipient policy answers `connectable_channels` from the
14
+ mock's own routes and connections, by the same test its recipient sessions
15
+ apply (FXO-2638).
16
+ - An unconfigured project's recipient brand is named "My App", as the service
17
+ now answers, rather than the project's internal name (FXO-2621).
18
+
8
19
  ## 1.0.0-rc.36
9
20
 
10
21
  ### Added
package/dist/core.js CHANGED
@@ -6,7 +6,7 @@ import { canonicalIanaTimeZone, classifyWebhookDeliveryOutcome, isCustomizableRe
6
6
  import { getScenarioDefinition } from "./scenarios.js";
7
7
  import { subscriberDataExportFixture } from "./subscriber-data-export.js";
8
8
  import { parseInteractionControlInput } from "./interaction-control.js";
9
- const CONTRACT_VERSION = "1.0.0-rc.24";
9
+ const CONTRACT_VERSION = "1.0.0-rc.25";
10
10
  const TEST_SIMULATOR_CAPABILITIES = {
11
11
  schema: "whooshbang.provider-capabilities.v1",
12
12
  provider: "simulator",
@@ -209,7 +209,9 @@ function defaultProjectRecipientExperience(state, project) {
209
209
  brand: {
210
210
  accent_color: RECIPIENT_BRAND_DEFAULT_ACCENT_COLOR,
211
211
  color_scheme: "system",
212
- display_name: project.name,
212
+ // The service's default (`RECIPIENT_BRAND_DEFAULT_DISPLAY_NAME` in the
213
+ // domain package, which this published mock does not depend on).
214
+ display_name: "My App",
213
215
  },
214
216
  default_locale: project.default_locale,
215
217
  diagnostic_id: state.idGenerator("diagnostic"),
@@ -854,6 +856,28 @@ const RECIPIENT_ENROLLMENT_POLICIES = {
854
856
  * candidate is the notifier's exact default route. Other attached connections
855
857
  * remain configured but inert and cannot make the selected provider ambiguous.
856
858
  */
859
+ /**
860
+ * The channels a recipient could authorize on in one environment, by the same
861
+ * test session creation applies below. The policy read carries it
862
+ * (FXO-2638), so the mock answers it from the same state.
863
+ */
864
+ function recipientConnectableChannels(state, scope) {
865
+ const channels = ["email", "slack", "telegram"];
866
+ // The generated type spells a bounded array as tuples; three members fit.
867
+ return channels.filter((channel) => RECIPIENT_ENROLLMENT_POLICIES[channel] === undefined ||
868
+ recipientConnectableConnection(state, {
869
+ ...scope,
870
+ channel,
871
+ notifierId: "default",
872
+ }) !== undefined);
873
+ }
874
+ function experienceOrganization(state, projectId) {
875
+ const project = state.projects.get(projectId);
876
+ if (project === undefined) {
877
+ throw new Error("Internal recipient-experience project is missing.");
878
+ }
879
+ return project.organization_id;
880
+ }
857
881
  function recipientConnectableConnection(state, scope) {
858
882
  const routeKey = notifierConnectionKey(scope.projectId, scope.environment, scope.notifierId);
859
883
  const attached = state.notifierConnections.get(routeKey) ?? new Set();
@@ -2326,6 +2350,8 @@ function initialState(options, scenarioName) {
2326
2350
  for (const environment of project.environments) {
2327
2351
  const environmentExperience = {
2328
2352
  allowed_origins: ["https://app.example.test"],
2353
+ // Resolved on every read; the seed only has to be a valid shape.
2354
+ connectable_channels: [],
2329
2355
  diagnostic_id: state.idGenerator("diagnostic"),
2330
2356
  enabled_channels: ["telegram"],
2331
2357
  environment: environment.kind,
@@ -4000,7 +4026,14 @@ function addPublicRoutes(app, getState, options) {
4000
4026
  recordDiagnostic(state, identity, "getEnvironmentRecipientExperience", {
4001
4027
  resourceId: environment.id,
4002
4028
  });
4003
- return validatedResponse(experience, validateEnvironmentRecipientExperience, 200, state);
4029
+ return validatedResponse({
4030
+ ...experience,
4031
+ connectable_channels: recipientConnectableChannels(state, {
4032
+ environment: environment.kind,
4033
+ organizationId: experienceOrganization(state, projectId),
4034
+ projectId,
4035
+ }),
4036
+ }, validateEnvironmentRecipientExperience, 200, state);
4004
4037
  });
4005
4038
  app.put("/v1/projects/:projectId/environments/:environmentId/recipient-experience", async (context) => {
4006
4039
  const state = getState();
@@ -4028,6 +4061,11 @@ function addPublicRoutes(app, getState, options) {
4028
4061
  }
4029
4062
  const next = {
4030
4063
  ...parsed.value,
4064
+ connectable_channels: recipientConnectableChannels(state, {
4065
+ environment: environment.kind,
4066
+ organizationId: experienceOrganization(state, projectId),
4067
+ projectId,
4068
+ }),
4031
4069
  diagnostic_id: state.idGenerator("diagnostic"),
4032
4070
  environment: environment.kind,
4033
4071
  environment_id: environment.id,