misskey/packages/frontend/test/reactions-viewer.test.ts
copilot-swe-agent[bot] e559718631 test: add unit tests for reaction count logic to prevent regression
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
2025-08-19 23:57:13 +00:00

105 lines
No EOL
4 KiB
TypeScript

/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { describe, test, assert } from 'vitest';
import './init';
describe('MkReactionsViewer', () => {
test('should handle reaction count updates without duplication', () => {
// Test the logic that was causing the bug
// Simulate the corrected watch function logic
const initialReactions = [["👍", 5], ["❤️", 3], ["🎉", 2]];
const newSource = {"👍": 6, "❤️": 3, "🎉": 2, "😊": 1};
const maxNumber = 10;
// Apply the corrected logic
let newReactions: [string, number][] = [];
for (let i = 0; i < initialReactions.length; i++) {
const reaction = initialReactions[i][0];
if (reaction in newSource && newSource[reaction] !== 0) {
// Fixed: Create new array instead of modifying in place
newReactions.push([reaction, newSource[reaction]]);
}
}
const newReactionsNames = newReactions.map(([x]) => x);
newReactions = [
...newReactions,
...Object.entries(newSource)
.sort(([, a], [, b]) => b - a)
.filter(([y], i) => i < maxNumber && !newReactionsNames.includes(y)),
];
// Verify results
const thumbsUp = newReactions.find(([emoji]) => emoji === "👍");
const heart = newReactions.find(([emoji]) => emoji === "❤️");
const newEmoji = newReactions.find(([emoji]) => emoji === "😊");
assert.ok(thumbsUp, "👍 reaction should exist");
assert.strictEqual(thumbsUp[1], 6, "👍 count should be updated to 6");
assert.ok(heart, "❤️ reaction should exist");
assert.strictEqual(heart[1], 3, "❤️ count should remain 3");
assert.ok(newEmoji, "😊 reaction should be added");
assert.strictEqual(newEmoji[1], 1, "😊 count should be 1");
// Verify original array is unchanged
assert.strictEqual(initialReactions[0][1], 5, "Original reactions should not be modified");
});
test('should maintain correct counts during multiple rapid updates', () => {
// Test scenario that would cause duplication in the old code
let reactions = [["👍", 5], ["❤️", 3]];
// First update
const update1 = {"👍": 6, "❤️": 3, "🎉": 1};
let newReactions1: [string, number][] = [];
for (let i = 0; i < reactions.length; i++) {
const reaction = reactions[i][0];
if (reaction in update1 && update1[reaction] !== 0) {
newReactions1.push([reaction, update1[reaction]]);
}
}
// Add new reactions
const existingNames1 = newReactions1.map(([x]) => x);
newReactions1.push(...Object.entries(update1).filter(([name]) => !existingNames1.includes(name)));
// Second update (simulating rapid updates when real-time mode is off)
const update2 = {"👍": 7, "❤️": 4, "🎉": 1, "😊": 2};
let newReactions2: [string, number][] = [];
// Use the result from first update as input
for (let i = 0; i < newReactions1.length; i++) {
const reaction = newReactions1[i][0];
if (reaction in update2 && update2[reaction] !== 0) {
newReactions2.push([reaction, update2[reaction]]);
}
}
// Add any new reactions from second update
const existingNames2 = newReactions2.map(([x]) => x);
newReactions2.push(...Object.entries(update2).filter(([name]) => !existingNames2.includes(name)));
// Verify final state
const thumbsUp = newReactions2.find(([emoji]) => emoji === "👍");
const heart = newReactions2.find(([emoji]) => emoji === "❤️");
const party = newReactions2.find(([emoji]) => emoji === "🎉");
const smile = newReactions2.find(([emoji]) => emoji === "😊");
assert.strictEqual(thumbsUp?.[1], 7, "👍 should have correct final count");
assert.strictEqual(heart?.[1], 4, "❤️ should have correct final count");
assert.strictEqual(party?.[1], 1, "🎉 should have correct final count");
assert.strictEqual(smile?.[1], 2, "😊 should have correct final count");
// Verify no duplication occurred
const thumbsUpCount = newReactions2.filter(([emoji]) => emoji === "👍").length;
assert.strictEqual(thumbsUpCount, 1, "👍 should appear only once in final array");
});
});