You've already forked matrix-js-sdk
mirror of
https://github.com/matrix-org/matrix-js-sdk.git
synced 2025-08-09 10:22:46 +03:00
Add alt event type matching in Relations model (#3018)
* allow alt event types in relations model * remove unneccesary checks on remove relation * comment * assert on event emitted
This commit is contained in:
@@ -14,13 +14,21 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { M_POLL_START } from "matrix-events-sdk";
|
||||||
|
|
||||||
import { EventTimelineSet } from "../../src/models/event-timeline-set";
|
import { EventTimelineSet } from "../../src/models/event-timeline-set";
|
||||||
import { MatrixEvent, MatrixEventEvent } from "../../src/models/event";
|
import { MatrixEvent, MatrixEventEvent } from "../../src/models/event";
|
||||||
import { Room } from "../../src/models/room";
|
import { Room } from "../../src/models/room";
|
||||||
import { Relations } from "../../src/models/relations";
|
import { Relations, RelationsEvent } from "../../src/models/relations";
|
||||||
import { TestClient } from "../TestClient";
|
import { TestClient } from "../TestClient";
|
||||||
|
import { RelationType } from "../../src";
|
||||||
|
import { logger } from "../../src/logger";
|
||||||
|
|
||||||
describe("Relations", function () {
|
describe("Relations", function () {
|
||||||
|
afterEach(() => {
|
||||||
|
jest.spyOn(logger, "error").mockRestore();
|
||||||
|
});
|
||||||
|
|
||||||
it("should deduplicate annotations", function () {
|
it("should deduplicate annotations", function () {
|
||||||
const room = new Room("room123", null!, null!);
|
const room = new Room("room123", null!, null!);
|
||||||
const relations = new Relations("m.annotation", "m.reaction", room);
|
const relations = new Relations("m.annotation", "m.reaction", room);
|
||||||
@@ -75,6 +83,92 @@ describe("Relations", function () {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("addEvent()", () => {
|
||||||
|
const relationType = RelationType.Reference;
|
||||||
|
const eventType = M_POLL_START.stable!;
|
||||||
|
const altEventTypes = [M_POLL_START.unstable!];
|
||||||
|
const room = new Room("room123", null!, null!);
|
||||||
|
|
||||||
|
it("should not add events without a relation", async () => {
|
||||||
|
// dont pollute console
|
||||||
|
const logSpy = jest.spyOn(logger, "error").mockImplementation(() => {});
|
||||||
|
const relations = new Relations(relationType, eventType, room);
|
||||||
|
const emitSpy = jest.spyOn(relations, "emit");
|
||||||
|
const event = new MatrixEvent({ type: eventType });
|
||||||
|
|
||||||
|
await relations.addEvent(event);
|
||||||
|
expect(logSpy).toHaveBeenCalledWith("Event must have relation info");
|
||||||
|
// event not added
|
||||||
|
expect(relations.getRelations().length).toBe(0);
|
||||||
|
expect(emitSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not add events of incorrect event type", async () => {
|
||||||
|
// dont pollute console
|
||||||
|
const logSpy = jest.spyOn(logger, "error").mockImplementation(() => {});
|
||||||
|
const relations = new Relations(relationType, eventType, room);
|
||||||
|
const emitSpy = jest.spyOn(relations, "emit");
|
||||||
|
const event = new MatrixEvent({
|
||||||
|
type: "different-event-type",
|
||||||
|
content: {
|
||||||
|
"m.relates_to": {
|
||||||
|
event_id: "$2s4yYpEkVQrPglSCSqB_m6E8vDhWsg0yFNyOJdVIb_o",
|
||||||
|
rel_type: relationType,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await relations.addEvent(event);
|
||||||
|
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(`Event relation info doesn't match this container`);
|
||||||
|
// event not added
|
||||||
|
expect(relations.getRelations().length).toBe(0);
|
||||||
|
expect(emitSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("adds events that match alt event types", async () => {
|
||||||
|
const relations = new Relations(relationType, eventType, room, altEventTypes);
|
||||||
|
const emitSpy = jest.spyOn(relations, "emit");
|
||||||
|
const event = new MatrixEvent({
|
||||||
|
type: M_POLL_START.unstable!,
|
||||||
|
content: {
|
||||||
|
"m.relates_to": {
|
||||||
|
event_id: "$2s4yYpEkVQrPglSCSqB_m6E8vDhWsg0yFNyOJdVIb_o",
|
||||||
|
rel_type: relationType,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await relations.addEvent(event);
|
||||||
|
|
||||||
|
// event added
|
||||||
|
expect(relations.getRelations()).toEqual([event]);
|
||||||
|
expect(emitSpy).toHaveBeenCalledWith(RelationsEvent.Add, event);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not add events of incorrect relation type", async () => {
|
||||||
|
const logSpy = jest.spyOn(logger, "error").mockImplementation(() => {});
|
||||||
|
const relations = new Relations(relationType, eventType, room);
|
||||||
|
const event = new MatrixEvent({
|
||||||
|
type: eventType,
|
||||||
|
content: {
|
||||||
|
"m.relates_to": {
|
||||||
|
event_id: "$2s4yYpEkVQrPglSCSqB_m6E8vDhWsg0yFNyOJdVIb_o",
|
||||||
|
rel_type: "m.annotation",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await relations.addEvent(event);
|
||||||
|
const emitSpy = jest.spyOn(relations, "emit");
|
||||||
|
|
||||||
|
expect(logSpy).toHaveBeenCalledWith(`Event relation info doesn't match this container`);
|
||||||
|
// event not added
|
||||||
|
expect(relations.getRelations().length).toBe(0);
|
||||||
|
expect(emitSpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("should emit created regardless of ordering", async function () {
|
it("should emit created regardless of ordering", async function () {
|
||||||
const targetEvent = new MatrixEvent({
|
const targetEvent = new MatrixEvent({
|
||||||
sender: "@bob:example.com",
|
sender: "@bob:example.com",
|
||||||
|
@@ -33,6 +33,9 @@ export type EventHandlerMap = {
|
|||||||
[RelationsEvent.Redaction]: (event: MatrixEvent) => void;
|
[RelationsEvent.Redaction]: (event: MatrixEvent) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const matchesEventType = (eventType: string, targetEventType: string, altTargetEventTypes: string[] = []): boolean =>
|
||||||
|
[targetEventType, ...altTargetEventTypes].includes(eventType);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A container for relation events that supports easy access to common ways of
|
* A container for relation events that supports easy access to common ways of
|
||||||
* aggregating such events. Each instance holds events that of a single relation
|
* aggregating such events. Each instance holds events that of a single relation
|
||||||
@@ -55,11 +58,13 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
|||||||
* @param relationType - The type of relation involved, such as "m.annotation", "m.reference", "m.replace", etc.
|
* @param relationType - The type of relation involved, such as "m.annotation", "m.reference", "m.replace", etc.
|
||||||
* @param eventType - The relation event's type, such as "m.reaction", etc.
|
* @param eventType - The relation event's type, such as "m.reaction", etc.
|
||||||
* @param client - The client which created this instance. For backwards compatibility also accepts a Room.
|
* @param client - The client which created this instance. For backwards compatibility also accepts a Room.
|
||||||
|
* @param altEventTypes - alt event types for relation events, for example to support unstable prefixed event types
|
||||||
*/
|
*/
|
||||||
public constructor(
|
public constructor(
|
||||||
public readonly relationType: RelationType | string,
|
public readonly relationType: RelationType | string,
|
||||||
public readonly eventType: string,
|
public readonly eventType: string,
|
||||||
client: MatrixClient | Room,
|
client: MatrixClient | Room,
|
||||||
|
public readonly altEventTypes?: string[],
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.client = client instanceof Room ? client.client : client;
|
this.client = client instanceof Room ? client.client : client;
|
||||||
@@ -84,7 +89,7 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
|||||||
const relationType = relation.rel_type;
|
const relationType = relation.rel_type;
|
||||||
const eventType = event.getType();
|
const eventType = event.getType();
|
||||||
|
|
||||||
if (this.relationType !== relationType || this.eventType !== eventType) {
|
if (this.relationType !== relationType || !matchesEventType(eventType, this.eventType, this.altEventTypes)) {
|
||||||
logger.error("Event relation info doesn't match this container");
|
logger.error("Event relation info doesn't match this container");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -122,20 +127,6 @@ export class Relations extends TypedEventEmitter<RelationsEvent, EventHandlerMap
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const relation = event.getRelation();
|
|
||||||
if (!relation) {
|
|
||||||
logger.error("Event must have relation info");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const relationType = relation.rel_type;
|
|
||||||
const eventType = event.getType();
|
|
||||||
|
|
||||||
if (this.relationType !== relationType || this.eventType !== eventType) {
|
|
||||||
logger.error("Event relation info doesn't match this container");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.relations.delete(event);
|
this.relations.delete(event);
|
||||||
|
|
||||||
if (this.relationType === RelationType.Annotation) {
|
if (this.relationType === RelationType.Annotation) {
|
||||||
|
Reference in New Issue
Block a user