mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-16 14:17:22 +01:00
improve code and tests for banned words and slurs (#10211)
* remove removePunctuationFromString function from test code It's not needed now that the test banned words don't contain underscores. * prevent tests accidentally throwing messageGroupChatSpam This commit makes the user for most tests have contributor tiers so that the user can't trigger the messageGroupChatSpam error message (for posting messages too quickly). This is useful when some of the tests fail due to broken code because that makes more messages be posted than expected. If the user doesn't have tiers, the messageGroupChatSpam error message would be triggered, which gives misleading information about the test failure. * add tests for banned swear and slur words posted in mixed case * allow banned word error message to show bad words in the same case the user typed them * stop using randomly-chosen real banned words in tests The test modified in this commit had been using real banned words, which meant that those words were being displayed to the contributors when the test failed. NB the 'check all banned words are matched' test also uses the real banned words but the test failure messages don't show the words. * improve translatability of bannedWordUsed error message
This commit is contained in:
@@ -11,7 +11,7 @@ import {
|
||||
TAVERN_ID,
|
||||
} from '../../../../../website/server/models/group';
|
||||
import { v4 as generateUUID } from 'uuid';
|
||||
import { getMatchesByWordArray, removePunctuationFromString } from '../../../../../website/server/libs/stringUtils';
|
||||
import { getMatchesByWordArray } from '../../../../../website/server/libs/stringUtils';
|
||||
import bannedWords from '../../../../../website/server/libs/bannedWords';
|
||||
import guildsAllowingBannedWords from '../../../../../website/server/libs/guildsAllowingBannedWords';
|
||||
import * as email from '../../../../../website/server/libs/email';
|
||||
@@ -24,10 +24,10 @@ describe('POST /chat', () => {
|
||||
let user, groupWithChat, member, additionalMember;
|
||||
let testMessage = 'Test Message';
|
||||
let testBannedWordMessage = 'TESTPLACEHOLDERSWEARWORDHERE';
|
||||
let testBannedWordMessage1 = 'TESTPLACEHOLDERSWEARWORDHERE1';
|
||||
let testSlurMessage = 'message with TESTPLACEHOLDERSLURWORDHERE';
|
||||
let bannedWordErrorMessage = t('bannedWordUsed').split('.');
|
||||
bannedWordErrorMessage[0] += ` (${removePunctuationFromString(testBannedWordMessage.toLowerCase())})`;
|
||||
bannedWordErrorMessage = bannedWordErrorMessage.join('.');
|
||||
let testSlurMessage1 = 'TESTPLACEHOLDERSLURWORDHERE1';
|
||||
let bannedWordErrorMessage = t('bannedWordUsed', {swearWordsUsed: testBannedWordMessage});
|
||||
|
||||
before(async () => {
|
||||
let { group, groupLeader, members } = await createAndPopulateGroup({
|
||||
@@ -39,6 +39,7 @@ describe('POST /chat', () => {
|
||||
members: 2,
|
||||
});
|
||||
user = groupLeader;
|
||||
await user.update({'contributor.level': SPAM_MIN_EXEMPT_CONTRIB_LEVEL}); // prevent tests accidentally throwing messageGroupChatSpam
|
||||
groupWithChat = group;
|
||||
member = members[0];
|
||||
additionalMember = members[1];
|
||||
@@ -136,9 +137,19 @@ describe('POST /chat', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('checks error message has the banned words used', async () => {
|
||||
let randIndex = Math.floor(Math.random() * (bannedWords.length + 1));
|
||||
let testBannedWords = bannedWords.slice(randIndex, randIndex + 2).map((w) => w.replace(/\\/g, ''));
|
||||
it('errors when word is typed in mixed case', async () => {
|
||||
let substrLength = Math.floor(testBannedWordMessage.length / 2);
|
||||
let chatMessage = testBannedWordMessage.substring(0, substrLength).toLowerCase() + testBannedWordMessage.substring(substrLength).toUpperCase();
|
||||
await expect(user.post('/groups/habitrpg/chat', { message: chatMessage }))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: t('bannedWordUsed', {swearWordsUsed: chatMessage}),
|
||||
});
|
||||
});
|
||||
|
||||
it('checks error message has all the banned words used, regardless of case', async () => {
|
||||
let testBannedWords = [testBannedWordMessage.toUpperCase(), testBannedWordMessage1.toLowerCase()];
|
||||
let chatMessage = `Mixing ${testBannedWords[0]} and ${testBannedWords[1]} is bad for you.`;
|
||||
await expect(user.post('/groups/habitrpg/chat', { message: chatMessage}))
|
||||
.to.eventually.be.rejected
|
||||
@@ -320,6 +331,17 @@ describe('POST /chat', () => {
|
||||
members[0].flags.chatRevoked = false;
|
||||
await members[0].update({'flags.chatRevoked': false});
|
||||
});
|
||||
|
||||
it('errors when slur is typed in mixed case', async () => {
|
||||
let substrLength = Math.floor(testSlurMessage1.length / 2);
|
||||
let chatMessage = testSlurMessage1.substring(0, substrLength).toLowerCase() + testSlurMessage1.substring(substrLength).toUpperCase();
|
||||
await expect(user.post('/groups/habitrpg/chat', { message: chatMessage }))
|
||||
.to.eventually.be.rejected.and.eql({
|
||||
code: 400,
|
||||
error: 'BadRequest',
|
||||
message: t('bannedSlurUsed'),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('does not error when sending a message to a private guild with a user with revoked chat', async () => {
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"communityGuidelines": "Community Guidelines",
|
||||
"communityGuidelinesRead1": "Please read our",
|
||||
"communityGuidelinesRead2": "before chatting.",
|
||||
"bannedWordUsed": "Oops! Looks like this post contains a swearword, religious oath, or reference to an addictive substance or adult topic. Habitica has users from all backgrounds, so we keep our chat very clean. Feel free to edit your message so you can post it!",
|
||||
"bannedWordUsed": "Oops! Looks like this post contains a swearword, religious oath, or reference to an addictive substance or adult topic (<%= swearWordsUsed %>). Habitica has users from all backgrounds, so we keep our chat very clean. Feel free to edit your message so you can post it!",
|
||||
"bannedSlurUsed": "Your post contained inappropriate language, and your chat privileges have been revoked.",
|
||||
"party": "Party",
|
||||
"createAParty": "Create A Party",
|
||||
|
||||
@@ -160,10 +160,7 @@ api.postChat = {
|
||||
if (group.privacy !== 'private' && !guildsAllowingBannedWords[group._id]) {
|
||||
let matchedBadWords = getBannedWordsFromText(req.body.message);
|
||||
if (matchedBadWords.length > 0) {
|
||||
// @TODO replace this split mechanism with something that works properly in translations
|
||||
let message = res.t('bannedWordUsed').split('.');
|
||||
message[0] += ` (${matchedBadWords.join(', ')})`;
|
||||
throw new BadRequest(message.join('.'));
|
||||
throw new BadRequest(res.t('bannedWordUsed', {swearWordsUsed: matchedBadWords.join(', ')}));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,10 +5,10 @@ export function removePunctuationFromString (str) {
|
||||
|
||||
export function getMatchesByWordArray (str, wordsToMatch) {
|
||||
let matchedWords = [];
|
||||
let wordRegexs = wordsToMatch.map((word) => new RegExp(`\\b([^a-z]+)?${word.toLowerCase()}([^a-z]+)?\\b`));
|
||||
let wordRegexs = wordsToMatch.map((word) => new RegExp(`\\b([^a-z]+)?${word}([^a-z]+)?\\b`, 'i'));
|
||||
for (let i = 0; i < wordRegexs.length; i += 1) {
|
||||
let regEx = wordRegexs[i];
|
||||
let match = str.toLowerCase().match(regEx);
|
||||
let match = str.match(regEx);
|
||||
if (match !== null && match[0] !== null) {
|
||||
let trimmedMatch = removePunctuationFromString(match[0]).trim();
|
||||
matchedWords.push(trimmedMatch);
|
||||
|
||||
Reference in New Issue
Block a user