Skip to content

Commit 081c203

Browse files
kamilooxtypeofweb
andauthored
fix: karma regex (#82)
* fix: karma regex * tests: add tests for addKarma command and for KARMA_REGEX * Add tests Co-authored-by: Michal Miszczyszyn <[email protected]>
1 parent afa5955 commit 081c203

File tree

8 files changed

+173
-9
lines changed

8 files changed

+173
-9
lines changed
File renamed without changes.

count-messages.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@ import { getWeekNumber } from './src/utils';
77

88
/* eslint-disable @typescript-eslint/no-unsafe-call */
99
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
10-
if (process.env.NODE_ENV === 'production') {
11-
require('dotenv').config({ path: '.env' });
12-
} else {
13-
require('dotenv').config({ path: '.env.dev' });
10+
if (process.env.NODE_ENV !== 'test') {
11+
require('dotenv').config();
1412
}
1513

1614
const API_URL = `https://discord.com/api/v9`;

package.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010
"eslint": "eslint --fix",
1111
"tsc": "tsc --noEmit -p tsconfig.json",
1212
"lint": "yarn tsc && yarn eslint",
13-
"test": "yarn lint && yarn test:unit",
14-
"test:ci": "yarn lint && yarn coverage",
15-
"test:unit": "yarn mocha --file test/before-each.spec.ts 'src/**/*.spec.ts'",
13+
"test": "cross-env NODE_ENV=test yarn lint && yarn test:unit",
14+
"test:ci": "cross-env NODE_ENV=test yarn lint && yarn coverage",
15+
"test:unit": "cross-env NODE_ENV=test yarn mocha --file test/before-each.spec.ts 'src/**/*.spec.ts'",
1616
"coverage": "nyc yarn test:unit",
1717
"mocha": "mocha",
1818
"clean": "rm -rf dist",
@@ -56,6 +56,7 @@
5656
"@typescript-eslint/parser": "4.26.0",
5757
"chai": "4.3.4",
5858
"chai-as-promised": "7.1.1",
59+
"cross-env": "7.0.3",
5960
"eslint": "7.27.0",
6061
"eslint-config-prettier": "8.3.0",
6162
"eslint-plugin-functional": "3.2.1",

src/commands/karma.spec.ts

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import { expect } from 'chai';
2+
import type * as Discord from 'discord.js';
3+
import Sinon from 'sinon';
4+
import * as Db from '../db';
5+
6+
import { getMessageMock, getMemberMock } from '../../test/mocks';
7+
8+
import { addKarma, KARMA_REGEX } from './karma';
9+
10+
type MemberMock = ReturnType<typeof getMemberMock>;
11+
12+
const getAddKarmaMsgMock = (from: MemberMock, membersToReward: ReadonlyArray<MemberMock>) => {
13+
const msg = getMessageMock('msg', {
14+
mentions: {
15+
members: {
16+
size: membersToReward.length,
17+
values: () => [
18+
...[from, ...membersToReward].map(({ id, mention }) => ({
19+
fetch: () => ({ id, toString: () => mention }),
20+
})),
21+
],
22+
},
23+
},
24+
author: { id: from.id, toString: () => from.mention },
25+
});
26+
27+
return msg;
28+
};
29+
30+
type DB = ReturnType<typeof Db.initDb>;
31+
32+
describe('add karma', () => {
33+
const AggregateMock = {
34+
sort() {
35+
return this;
36+
},
37+
limit() {
38+
return this;
39+
},
40+
toArray() {
41+
return [];
42+
},
43+
};
44+
45+
const CollectionMock = {
46+
insertMany: Sinon.stub(),
47+
aggregate: Sinon.stub().returns(AggregateMock),
48+
};
49+
50+
const DbMock = {
51+
collection: Sinon.stub().returns(CollectionMock),
52+
} as unknown as DB;
53+
54+
beforeEach(() => {
55+
Sinon.stub(Db, 'initDb').returns(Promise.resolve(DbMock));
56+
});
57+
afterEach(() => {
58+
Sinon.reset();
59+
Sinon.restore();
60+
});
61+
62+
describe('checks regex', () => {
63+
it('checks if one user should be given a karma', () => {
64+
const memberToReward = getMemberMock();
65+
66+
const msg = getMessageMock('msg', { content: `${memberToReward.mention} ++` });
67+
expect(KARMA_REGEX.test(msg.content)).to.have.be.true;
68+
});
69+
70+
it('checks if two users should be given a karma', () => {
71+
const firstMemberToReward = getMemberMock();
72+
const secondMemberToReward = getMemberMock();
73+
74+
const firstMsg = getMessageMock('msg', {
75+
content: `${firstMemberToReward.mention} ${secondMemberToReward.mention} ++`,
76+
});
77+
expect(KARMA_REGEX.test(firstMsg.content)).to.have.be.true;
78+
79+
const secondMsg = getMessageMock('msg', {
80+
content: `${firstMemberToReward.mention} ++ ${secondMemberToReward.mention}`,
81+
});
82+
expect(KARMA_REGEX.test(secondMsg.content)).to.have.be.true;
83+
84+
const thirdMsg = getMessageMock('msg', {
85+
content: `${firstMemberToReward.mention} ++ ${secondMemberToReward.mention} ++`,
86+
});
87+
expect(KARMA_REGEX.test(thirdMsg.content)).to.have.be.true;
88+
});
89+
90+
it('checks if one user should not be given a karma', () => {
91+
const memberToReward = getMemberMock();
92+
93+
const msg = getMessageMock('msg', { content: `random message ${memberToReward.mention} ++` });
94+
expect(KARMA_REGEX.test(msg.content)).to.have.be.false;
95+
});
96+
});
97+
98+
it('should add karma for one user', async () => {
99+
const from = getMemberMock();
100+
const memberToReward = getMemberMock();
101+
102+
const msg = getAddKarmaMsgMock(from, [memberToReward]);
103+
104+
await addKarma.execute(msg as unknown as Discord.Message, []);
105+
106+
const arg = CollectionMock.insertMany.lastCall.firstArg[0];
107+
expect(arg.from).to.eql(from.id);
108+
expect(arg.to).to.eql(memberToReward.id);
109+
expect(arg.value).to.eql(1);
110+
});
111+
112+
it('should add karma for two users', async () => {
113+
const from = getMemberMock();
114+
115+
const firstMemberToReward = getMemberMock();
116+
const secondMemberToReward = getMemberMock();
117+
118+
const msg = getAddKarmaMsgMock(from, [firstMemberToReward, secondMemberToReward]);
119+
120+
await addKarma.execute(msg as unknown as Discord.Message, []);
121+
122+
{
123+
const arg = CollectionMock.insertMany.lastCall.firstArg[0];
124+
expect(arg.from).to.eql(from.id);
125+
expect(arg.to).to.eql(firstMemberToReward.id);
126+
expect(arg.value).to.eql(1);
127+
}
128+
{
129+
const arg = CollectionMock.insertMany.lastCall.firstArg[1];
130+
expect(arg.from).to.eql(from.id);
131+
expect(arg.to).to.eql(secondMemberToReward.id);
132+
expect(arg.value).to.eql(1);
133+
}
134+
});
135+
});

src/commands/karma.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { getKarmaCollection, initDb } from '../db';
1313
import type { Command } from '../types';
1414

1515
export const KARMA_REGEX = new RegExp(
16-
`^(${Discord.MessageMentions.USERS_PATTERN.source}\\s*)+\\+\\+\\s*$`,
16+
`^(${Discord.MessageMentions.USERS_PATTERN.source}).*\\+\\+\\s*`,
1717
);
1818

1919
const addKarma: Command = {

test/mocks.spec.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { expect } from 'chai';
2+
import Discord from 'discord.js';
3+
4+
import { getMemberMock } from './mocks';
5+
6+
describe('mocks', () => {
7+
it('should return correct user mention and id', () => {
8+
const { id, mention } = getMemberMock();
9+
10+
const isMemberMentionCorrect = Discord.MessageMentions.USERS_PATTERN.test(mention);
11+
12+
expect(isMemberMentionCorrect).to.be.true;
13+
expect(mention).to.have.include(id);
14+
});
15+
});

test/mocks.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,11 @@ export const getMessageMock = <T extends Message>(
6161
};
6262
return proxyExistenceMutating(mockMessage, name);
6363
};
64+
65+
export const getMemberMock = () => {
66+
const id = (Math.random() * 1e18).toFixed();
67+
68+
const mention = `<@${id}>`;
69+
70+
return { id, mention };
71+
};

yarn.lock

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1519,7 +1519,14 @@ cron-parser@^2.13.0:
15191519
is-nan "^1.3.0"
15201520
moment-timezone "^0.5.31"
15211521

1522-
cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
1522+
1523+
version "7.0.3"
1524+
resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf"
1525+
integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==
1526+
dependencies:
1527+
cross-spawn "^7.0.1"
1528+
1529+
cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
15231530
version "7.0.3"
15241531
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
15251532
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==

0 commit comments

Comments
 (0)