diff --git a/test/api/unit/libs/highlightMentions.js b/test/api/unit/libs/highlightMentions.js new file mode 100644 index 0000000000..6d46e14aee --- /dev/null +++ b/test/api/unit/libs/highlightMentions.js @@ -0,0 +1,60 @@ +import mongoose from 'mongoose'; +import { + highlightMentions, +} from '../../../../website/server/libs/highlightMentions'; + +describe('highlightMentions', () => { + beforeEach(() => { + const mockFind = { + select () { + return this; + }, + lean () { + return this; + }, + exec () { + return Promise.resolve([{ + auth: { local: { username: 'user' } }, _id: '111', + }, { auth: { local: { username: 'user2' } }, _id: '222' }, { auth: { local: { username: 'user3' } }, _id: '333' }, { auth: { local: { username: 'user-dash' } }, _id: '444' }, { auth: { local: { username: 'user_underscore' } }, _id: '555' }, + ]); + }, + }; + + sinon.stub(mongoose.Model, 'find').returns(mockFind); + }); + + afterEach(() => { + sinon.restore(); + }); + + it('doesn\'t change text without mentions', async () => { + const text = 'some chat text'; + const result = await highlightMentions(text); + expect(result[0]).to.equal(text); + }); + it('highlights existing users', async () => { + const text = '@user: message'; + const result = await highlightMentions(text); + expect(result[0]).to.equal('[@user](/profile/111): message'); + }); + it('highlights special characters', async () => { + const text = '@user-dash: message @user_underscore'; + const result = await highlightMentions(text); + expect(result[0]).to.equal('[@user-dash](/profile/444): message [@user_underscore](/profile/555)'); + }); + it('doesn\'t highlight nonexisting users', async () => { + const text = '@nouser message'; + const result = await highlightMentions(text); + expect(result[0]).to.equal('@nouser message'); + }); + it('highlights multiple existing users', async () => { + const text = '@user message (@user2) @user3 @user'; + const result = await highlightMentions(text); + expect(result[0]).to.equal('[@user](/profile/111) message ([@user2](/profile/222)) [@user3](/profile/333) [@user](/profile/111)'); + }); + it('doesn\'t highlight more than 5 users', async () => { + const text = '@user @user2 @user3 @user4 @user5 @user6'; + const result = await highlightMentions(text); + expect(result[0]).to.equal(text); + }); +}); diff --git a/test/api/unit/models/user.test.js b/test/api/unit/models/user.test.js index 298aa31c18..1e01c52b16 100644 --- a/test/api/unit/models/user.test.js +++ b/test/api/unit/models/user.test.js @@ -386,6 +386,7 @@ describe('User Model', () => { user = await user.save(); // verify that it's been awarded expect(user.achievements.beastMaster).to.equal(true); + expect(user.notifications.find(notification => notification.type === 'ACHIEVEMENT_BEAST_MASTER')).to.exist; // reset the user user.achievements.beastMasterCount = 0; @@ -417,6 +418,28 @@ describe('User Model', () => { expect(user.achievements.beastMaster).to.not.equal(true); }); + it('adds achievements to notification list', async () => { + let user = new User(); + user = await user.save(); // necessary for user.isSelected to work correctly + + // Create conditions for achievements to be awarded + user.achievements.beastMasterCount = 3; + user.achievements.mountMasterCount = 3; + user.achievements.triadBingoCount = 3; + // verify that it was not awarded initially + expect(user.achievements.beastMaster).to.not.equal(true); + // verify that it was not awarded initially + expect(user.achievements.mountMaster).to.not.equal(true); + // verify that it was not awarded initially + expect(user.achievements.triadBingo).to.not.equal(true); + + user = await user.save(); + // verify that it's been awarded + expect(user.notifications.find(notification => notification.type === 'ACHIEVEMENT_BEAST_MASTER')).to.exist; + expect(user.notifications.find(notification => notification.type === 'ACHIEVEMENT_MOUNT_MASTER')).to.exist; + expect(user.notifications.find(notification => notification.type === 'ACHIEVEMENT_TRIAD_BINGO')).to.exist; + }); + context('manage unallocated stats points notifications', () => { it('doesn\'t add a notification if there are no points to allocate', async () => { let user = new User(); diff --git a/test/api/v3/integration/groups/POST-groups_groupId_join.test.js b/test/api/v3/integration/groups/POST-groups_groupId_join.test.js index 319e1f1373..dbb2e00f15 100644 --- a/test/api/v3/integration/groups/POST-groups_groupId_join.test.js +++ b/test/api/v3/integration/groups/POST-groups_groupId_join.test.js @@ -318,6 +318,7 @@ describe('POST /group/:groupId/join', () => { name: 'Testing Party', type: 'party', }); + await leader.post(`/groups/${party._id}/invite`, { uuids: [member._id], }); @@ -329,7 +330,9 @@ describe('POST /group/:groupId/join', () => { await leader.sync(); expect(member).to.have.nested.property('achievements.partyUp', true); + expect(member.notifications.find(notification => notification.type === 'ACHIEVEMENT_PARTY_UP')).to.exist; expect(leader).to.have.nested.property('achievements.partyUp', true); + expect(leader.notifications.find(notification => notification.type === 'ACHIEVEMENT_PARTY_UP')).to.exist; }); it('does not award Party On achievement to party of size 2', async () => { @@ -353,7 +356,9 @@ describe('POST /group/:groupId/join', () => { await leader.sync(); expect(member).to.have.nested.property('achievements.partyOn', true); + expect(member.notifications.find(notification => notification.type === 'ACHIEVEMENT_PARTY_ON')).to.exist; expect(leader).to.have.nested.property('achievements.partyOn', true); + expect(leader.notifications.find(notification => notification.type === 'ACHIEVEMENT_PARTY_ON')).to.exist; }); }); }); diff --git a/website/client/src/components/chat/chatCard.vue b/website/client/src/components/chat/chatCard.vue index 9824f97d2e..9341d9002d 100644 --- a/website/client/src/components/chat/chatCard.vue +++ b/website/client/src/components/chat/chatCard.vue @@ -33,6 +33,7 @@ ({{ msg.client }})

@@ -139,7 +140,6 @@