diff --git a/spec/unit/pushprocessor.spec.ts b/spec/unit/pushprocessor.spec.ts index 122084d92..8664b0198 100644 --- a/spec/unit/pushprocessor.spec.ts +++ b/spec/unit/pushprocessor.spec.ts @@ -13,6 +13,23 @@ import { } from "../../src"; import { mockClientMethodsUser } from "../test-utils/client"; +const msc3914RoomCallRule: IPushRule = { + rule_id: ".org.matrix.msc3914.rule.room.call", + default: true, + enabled: true, + conditions: [ + { + kind: ConditionKind.EventMatch, + key: "type", + pattern: "org.matrix.msc3401.call", + }, + { + kind: ConditionKind.CallStarted, + }, + ], + actions: [PushRuleActionName.Notify, { set_tweak: TweakName.Sound, value: "default" }], +}; + describe("NotificationService", function () { const testUserId = "@ali:matrix.org"; const testDisplayName = "Alice M"; @@ -22,23 +39,6 @@ describe("NotificationService", function () { let pushProcessor: PushProcessor; - const msc3914RoomCallRule: IPushRule = { - rule_id: ".org.matrix.msc3914.rule.room.call", - default: true, - enabled: true, - conditions: [ - { - kind: ConditionKind.EventMatch, - key: "type", - pattern: "org.matrix.msc3401.call", - }, - { - kind: ConditionKind.CallStarted, - }, - ], - actions: [PushRuleActionName.Notify, { set_tweak: TweakName.Sound, value: "default" }], - }; - let matrixClient: MatrixClient; beforeEach(function () { @@ -197,142 +197,6 @@ describe("NotificationService", function () { pushProcessor = new PushProcessor(matrixClient); }); - it("should add default rules in the correct order", () => { - const pushRules = PushProcessor.rewriteDefaultRules({ - device: {}, - global: { - content: [], - override: [ - // Include user-defined push rules inbetween .m.rule.master and other default rules to assert they are maintained in-order. - { - rule_id: ".m.rule.master", - default: true, - enabled: false, - conditions: [], - actions: [], - }, - { - actions: [ - PushRuleActionName.Notify, - { - set_tweak: TweakName.Sound, - value: "default", - }, - { - set_tweak: TweakName.Highlight, - }, - ], - enabled: true, - pattern: "coffee", - rule_id: "coffee", - default: false, - }, - { - actions: [ - PushRuleActionName.Notify, - { - set_tweak: TweakName.Sound, - value: "default", - }, - { - set_tweak: TweakName.Highlight, - }, - ], - conditions: [ - { - kind: ConditionKind.ContainsDisplayName, - }, - ], - enabled: true, - default: true, - rule_id: ".m.rule.contains_display_name", - }, - { - actions: [ - PushRuleActionName.Notify, - { - set_tweak: TweakName.Sound, - value: "default", - }, - ], - conditions: [ - { - is: "2", - kind: ConditionKind.RoomMemberCount, - }, - ], - enabled: true, - rule_id: ".m.rule.room_one_to_one", - default: true, - }, - ], - room: [], - sender: [], - underride: [ - { - actions: [ - PushRuleActionName.Notify, - { - set_tweak: TweakName.Highlight, - value: false, - }, - ], - conditions: [], - enabled: true, - rule_id: "user-defined", - default: false, - }, - msc3914RoomCallRule, - { - actions: [ - PushRuleActionName.Notify, - { - set_tweak: TweakName.Highlight, - value: false, - }, - ], - conditions: [], - enabled: true, - rule_id: ".m.rule.fallback", - default: true, - }, - ], - }, - }); - - // By the time we get here, we expect the PushProcessor to have merged the new .m.rule.is_room_mention rule into the existing list of rules. - // Check that has happened, and that it is in the right place. - const containsDisplayNameRuleIdx = pushRules.global.override?.findIndex( - (rule) => rule.rule_id === RuleId.ContainsDisplayName, - ); - expect(containsDisplayNameRuleIdx).toBeGreaterThan(-1); - const isRoomMentionRuleIdx = pushRules.global.override?.findIndex( - (rule) => rule.rule_id === RuleId.IsRoomMention, - ); - expect(isRoomMentionRuleIdx).toBeGreaterThan(-1); - const mReactionRuleIdx = pushRules.global.override?.findIndex((rule) => rule.rule_id === ".m.rule.reaction"); - expect(mReactionRuleIdx).toBeGreaterThan(-1); - - expect(containsDisplayNameRuleIdx).toBeLessThan(isRoomMentionRuleIdx!); - expect(isRoomMentionRuleIdx).toBeLessThan(mReactionRuleIdx!); - - expect(pushRules.global.override?.map((r) => r.rule_id)).toEqual([ - ".m.rule.master", - "coffee", - ".m.rule.contains_display_name", - ".m.rule.room_one_to_one", - ".m.rule.is_room_mention", - ".m.rule.reaction", - ".org.matrix.msc3786.rule.room.server_acl", - ]); - expect(pushRules.global.underride?.map((r) => r.rule_id)).toEqual([ - "user-defined", - ".org.matrix.msc3914.rule.room.call", - // Assert that unknown default rules are maintained - ".m.rule.fallback", - ]); - }); - // User IDs it("should bing on a user ID.", function () { @@ -848,3 +712,141 @@ describe("Test PushProcessor.partsForDottedKey", function () { expect(PushProcessor.partsForDottedKey(path)).toStrictEqual(expected); }); }); + +describe("rewriteDefaultRules", () => { + it("should add default rules in the correct order", () => { + const pushRules = PushProcessor.rewriteDefaultRules({ + device: {}, + global: { + content: [], + override: [ + // Include user-defined push rules inbetween .m.rule.master and other default rules to assert they are maintained in-order. + { + rule_id: ".m.rule.master", + default: true, + enabled: false, + conditions: [], + actions: [], + }, + { + actions: [ + PushRuleActionName.Notify, + { + set_tweak: TweakName.Sound, + value: "default", + }, + { + set_tweak: TweakName.Highlight, + }, + ], + enabled: true, + pattern: "coffee", + rule_id: "coffee", + default: false, + }, + { + actions: [ + PushRuleActionName.Notify, + { + set_tweak: TweakName.Sound, + value: "default", + }, + { + set_tweak: TweakName.Highlight, + }, + ], + conditions: [ + { + kind: ConditionKind.ContainsDisplayName, + }, + ], + enabled: true, + default: true, + rule_id: ".m.rule.contains_display_name", + }, + { + actions: [ + PushRuleActionName.Notify, + { + set_tweak: TweakName.Sound, + value: "default", + }, + ], + conditions: [ + { + is: "2", + kind: ConditionKind.RoomMemberCount, + }, + ], + enabled: true, + rule_id: ".m.rule.room_one_to_one", + default: true, + }, + ], + room: [], + sender: [], + underride: [ + { + actions: [ + PushRuleActionName.Notify, + { + set_tweak: TweakName.Highlight, + value: false, + }, + ], + conditions: [], + enabled: true, + rule_id: "user-defined", + default: false, + }, + msc3914RoomCallRule, + { + actions: [ + PushRuleActionName.Notify, + { + set_tweak: TweakName.Highlight, + value: false, + }, + ], + conditions: [], + enabled: true, + rule_id: ".m.rule.fallback", + default: true, + }, + ], + }, + }); + + // By the time we get here, we expect the PushProcessor to have merged the new .m.rule.is_room_mention rule into the existing list of rules. + // Check that has happened, and that it is in the right place. + const containsDisplayNameRuleIdx = pushRules.global.override?.findIndex( + (rule) => rule.rule_id === RuleId.ContainsDisplayName, + ); + expect(containsDisplayNameRuleIdx).toBeGreaterThan(-1); + const isRoomMentionRuleIdx = pushRules.global.override?.findIndex( + (rule) => rule.rule_id === RuleId.IsRoomMention, + ); + expect(isRoomMentionRuleIdx).toBeGreaterThan(-1); + const mReactionRuleIdx = pushRules.global.override?.findIndex((rule) => rule.rule_id === ".m.rule.reaction"); + expect(mReactionRuleIdx).toBeGreaterThan(-1); + + expect(containsDisplayNameRuleIdx).toBeLessThan(isRoomMentionRuleIdx!); + expect(isRoomMentionRuleIdx).toBeLessThan(mReactionRuleIdx!); + + expect(pushRules.global.override?.map((r) => r.rule_id)).toEqual([ + ".m.rule.master", + "coffee", + ".m.rule.contains_display_name", + ".m.rule.room_one_to_one", + ".m.rule.is_room_mention", + ".m.rule.reaction", + ".org.matrix.msc3786.rule.room.server_acl", + ]); + expect(pushRules.global.underride?.map((r) => r.rule_id)).toEqual([ + "user-defined", + ".org.matrix.msc3914.rule.room.call", + // Assert that unknown default rules are maintained + ".m.rule.fallback", + ]); + }); +}); diff --git a/src/pushprocessor.ts b/src/pushprocessor.ts index c88ca40af..05ecc6d28 100644 --- a/src/pushprocessor.ts +++ b/src/pushprocessor.ts @@ -172,7 +172,7 @@ const EXPECTED_DEFAULT_UNDERRIDE_RULE_IDS: OrderedRules = [ * @param kind - the kind of push rule set being merged. * @param incomingRules - the existing set of known push rules for the user. * @param defaultRules - a lookup table for the default definitions of push rules. - * @param defaultRuleIds - the IDs of the expected push rules, in order. + * @param orderedRuleIds - the IDs of the expected push rules, in order. * * @returns A copy of `incomingRules`, with any missing default rules inserted in the right place. */ @@ -180,7 +180,7 @@ function mergeRulesWithDefaults( kind: PushRuleKind, incomingRules: IPushRule[], defaultRules: Record, - defaultRuleIds: OrderedRules, + orderedRuleIds: OrderedRules, ): IPushRule[] { // Find the indices of the edges of the user-defined rules in the incoming rules const mappedIncomingRules = incomingRules.map((rule) => rule.default); @@ -194,10 +194,10 @@ function mergeRulesWithDefaults( // Re-insert any user-defined rules that were in `incomingRules` newRules.push(...incomingRules.slice(...userDefinedRulesRange)); } else if (ruleId in defaultRules) { - logger.warn(`Adding default global push rule ${ruleId}`); + logger.warn(`Adding default global ${kind} push rule ${ruleId}`); newRules.push(defaultRules[ruleId]); } else { - logger.warn(`Missing default global push rule ${ruleId}`); + logger.warn(`Missing default global ${kind} push rule ${ruleId}`); } } @@ -208,7 +208,7 @@ function mergeRulesWithDefaults( ...incomingRules.slice(0, userDefinedRulesRange[0]), ...incomingRules.slice(userDefinedRulesRange[1]), ]) { - const ruleIndex = defaultRuleIds.indexOf(rule.rule_id); + const ruleIndex = orderedRuleIds.indexOf(rule.rule_id); if (ruleIndex === -1) { // an unrecognised rule; copy it over newRules.push(rule); @@ -216,7 +216,7 @@ function mergeRulesWithDefaults( } while (ruleIndex > nextExpectedRuleIdIndex) { // insert new rules - const defaultRuleId = defaultRuleIds[nextExpectedRuleIdIndex]; + const defaultRuleId = orderedRuleIds[nextExpectedRuleIdIndex]; insertDefaultPushRule(defaultRuleId); nextExpectedRuleIdIndex += 1; } @@ -226,7 +226,7 @@ function mergeRulesWithDefaults( } // Now copy over any remaining default rules - for (const ruleId of defaultRuleIds.slice(nextExpectedRuleIdIndex)) { + for (const ruleId of orderedRuleIds.slice(nextExpectedRuleIdIndex)) { insertDefaultPushRule(ruleId); }