mirror of
https://github.com/outline/outline.git
synced 2026-06-13 11:25:03 +03:00
fix: Edits that only include a mention below edit distance do not trigger mention (#11434)
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import type { DeepPartial } from "utility-types";
|
||||
import type { ProsemirrorData } from "@shared/types";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { MentionType, NotificationEventType } from "@shared/types";
|
||||
import { createContext } from "@server/context";
|
||||
@@ -522,6 +524,71 @@ describe("revisions.create", () => {
|
||||
expect(spy).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("should send a mention notification even when change is below threshold", async () => {
|
||||
const spy = jest.spyOn(Notification, "create");
|
||||
const actor = await buildUser();
|
||||
const mentioned = await buildUser({ teamId: actor.teamId, name: "Kim" });
|
||||
|
||||
// Build a document with some initial content
|
||||
let document = await buildDocument({
|
||||
teamId: actor.teamId,
|
||||
userId: actor.id,
|
||||
});
|
||||
await Revision.createFromDocument(createContext({ user: actor }), document);
|
||||
|
||||
// Now add a mention – the only change is the mention node itself, which
|
||||
// renders as "@<label>" in plain text and may be below the 5-char
|
||||
// threshold that gates generic update notifications.
|
||||
const mentionContent: DeepPartial<ProsemirrorData> = {
|
||||
type: "doc",
|
||||
content: [
|
||||
...(document.content?.content ?? []),
|
||||
{
|
||||
type: "paragraph",
|
||||
content: [
|
||||
{
|
||||
type: "mention",
|
||||
attrs: {
|
||||
type: MentionType.User,
|
||||
label: mentioned.name,
|
||||
modelId: mentioned.id,
|
||||
actorId: actor.id,
|
||||
id: "test-mention-id",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
document.content = mentionContent as ProsemirrorData;
|
||||
document.updatedAt = new Date();
|
||||
await document.save();
|
||||
|
||||
const revision = await Revision.createFromDocument(
|
||||
createContext({ user: actor }),
|
||||
document
|
||||
);
|
||||
|
||||
const task = new RevisionCreatedNotificationsTask();
|
||||
await task.perform({
|
||||
name: "revisions.create",
|
||||
documentId: document.id,
|
||||
teamId: document.teamId,
|
||||
actorId: actor.id,
|
||||
modelId: revision.id,
|
||||
ip,
|
||||
});
|
||||
|
||||
expect(spy).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
event: NotificationEventType.MentionedInDocument,
|
||||
userId: mentioned.id,
|
||||
actorId: actor.id,
|
||||
documentId: document.id,
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
test("should not send a notification for group mentions when disableMentions is true", async () => {
|
||||
const spy = jest.spyOn(Notification, "create");
|
||||
const actor = await buildUser();
|
||||
|
||||
@@ -35,16 +35,8 @@ export default class RevisionCreatedNotificationsTask extends BaseTask<RevisionE
|
||||
|
||||
const before = await revision.before();
|
||||
|
||||
// If the content looks the same, don't send notifications
|
||||
if (!DocumentHelper.isChangeOverThreshold(before, revision, 5)) {
|
||||
Logger.info(
|
||||
"processor",
|
||||
`suppressing notifications as update has insignificant changes`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Send notifications to mentioned users first
|
||||
// Send notifications to mentioned users first – these must be processed
|
||||
// regardless of the change threshold as even a small edit can add a mention.
|
||||
const oldMentions = before
|
||||
? [...DocumentHelper.parseMentions(before, { type: MentionType.User })]
|
||||
: [];
|
||||
@@ -84,7 +76,7 @@ export default class RevisionCreatedNotificationsTask extends BaseTask<RevisionE
|
||||
}
|
||||
}
|
||||
|
||||
// send notifications to users in mentioned groups
|
||||
// Send notifications to users in mentioned groups
|
||||
const oldGroupMentions = before
|
||||
? DocumentHelper.parseMentions(before, { type: MentionType.Group })
|
||||
: [];
|
||||
@@ -148,6 +140,16 @@ export default class RevisionCreatedNotificationsTask extends BaseTask<RevisionE
|
||||
mentionedGroup.push(group.modelId);
|
||||
}
|
||||
|
||||
// If the content change is insignificant, don't send generic update
|
||||
// notifications (mention notifications above are still sent).
|
||||
if (!DocumentHelper.isChangeOverThreshold(before, revision, 5)) {
|
||||
Logger.info(
|
||||
"processor",
|
||||
`suppressing update notifications as change has insignificant edits`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const recipients = (
|
||||
await NotificationHelper.getDocumentNotificationRecipients({
|
||||
document,
|
||||
|
||||
Reference in New Issue
Block a user