-
Notifications
You must be signed in to change notification settings - Fork 738
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add scheduled task module and weekly reset ranking function (#176)
- Loading branch information
Showing
10 changed files
with
311 additions
and
105 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { Module } from '@nestjs/common'; | ||
import { CronJobService } from './cron-job.service'; | ||
import { RankService } from '../rank/rank.service'; | ||
|
||
@Module({ | ||
providers: [CronJobService, RankService], | ||
}) | ||
export class CronJobModule {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { Injectable } from '@nestjs/common'; | ||
import { Cron } from '@nestjs/schedule'; | ||
import { RankService } from '../rank/rank.service'; | ||
|
||
@Injectable() | ||
export class CronJobService { | ||
private static readonly EVERY_MONDAY_AT_2AM = '0 2 * * 1'; | ||
|
||
constructor(private readonly rankService: RankService) {} | ||
|
||
@Cron(CronJobService.EVERY_MONDAY_AT_2AM) | ||
async resetRankList() { | ||
this.rankService.resetRankList(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { Test, TestingModule } from '@nestjs/testing'; | ||
import { RankController } from '../rank.controller'; | ||
import { RankService } from '../rank.service'; | ||
import { MockRedisModule } from '../../../test/helper/mockRedis'; | ||
import { JwtModule } from '@nestjs/jwt'; | ||
import { createUser } from '../../../test/fixture/user'; | ||
import { | ||
createEmptyRankList, | ||
createRankListWithFirstUserFinishedCourse, | ||
createRankListWithUserFinishedCourse2Times, | ||
} from '../../../test/fixture/rank'; | ||
|
||
const user = createUser(); | ||
const emptyRankList = createEmptyRankList(); | ||
const firstUserFinished = createRankListWithFirstUserFinishedCourse(); | ||
const userFinishedTwice = createRankListWithUserFinishedCourse2Times(); | ||
|
||
describe('rank controller', () => { | ||
let rankController: RankController; | ||
let rankService: RankService; | ||
|
||
beforeEach(async () => { | ||
const testHelper = await setupTesting(); | ||
|
||
rankService = testHelper.rankService; | ||
rankController = testHelper.rankController; | ||
}); | ||
|
||
it('should return empty rank list', async () => { | ||
const result = emptyRankList; | ||
jest | ||
.spyOn(rankService, 'getRankList') | ||
.mockImplementation(async () => result); | ||
|
||
const res = await rankController.getRankList(user); | ||
expect(res).toBe(result); | ||
expect(rankService.getRankList).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should return rank list with first user finished course', async () => { | ||
const result = userFinishedTwice; | ||
jest | ||
.spyOn(rankService, 'getRankList') | ||
.mockImplementation(async () => result); | ||
|
||
const res = await rankController.getRankList(user); | ||
expect(res).toBe(result); | ||
expect(rankService.getRankList).toHaveBeenCalled(); | ||
}); | ||
|
||
it('should return rank list with user finished course 2 times', async () => { | ||
const result = firstUserFinished; | ||
jest | ||
.spyOn(rankService, 'getRankList') | ||
.mockImplementation(async () => result); | ||
|
||
const res = await rankController.getRankList(user); | ||
expect(res).toBe(result); | ||
expect(rankService.getRankList).toHaveBeenCalled(); | ||
}); | ||
}); | ||
|
||
async function setupTesting() { | ||
const mockRankService = { | ||
getRankList: jest.fn(() => { | ||
return firstUserFinished; | ||
}), | ||
}; | ||
|
||
const moduleRef: TestingModule = await Test.createTestingModule({ | ||
imports: [ | ||
MockRedisModule, | ||
JwtModule.register({ | ||
secret: process.env.SECRET, | ||
signOptions: { expiresIn: '7d' }, | ||
}), | ||
], | ||
controllers: [RankController], | ||
providers: [ | ||
{ | ||
provide: RankService, | ||
useValue: mockRankService, | ||
}, | ||
], | ||
}).compile(); | ||
return { | ||
rankController: moduleRef.get<RankController>(RankController), | ||
rankService: moduleRef.get<RankService>(RankService), | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { Test, TestingModule } from '@nestjs/testing'; | ||
import { RankService } from '../rank.service'; | ||
import { MockRedisModule } from '../../../test/helper/mockRedis'; | ||
import { JwtModule } from '@nestjs/jwt'; | ||
import { createUser } from '../../../test/fixture/user'; | ||
import { | ||
createEmptyRankList, | ||
createRankListWithFirstUserFinishedCourse, | ||
createRankListWithUserFinishedCourse2Times, | ||
} from '../../../test/fixture/rank'; | ||
|
||
const user = createUser(); | ||
const emptyRankList = createEmptyRankList(); | ||
const firstUserFinished = createRankListWithFirstUserFinishedCourse(); | ||
const userFinishedTwice = createRankListWithUserFinishedCourse2Times(); | ||
|
||
describe('rank service', () => { | ||
let rankService: RankService; | ||
|
||
beforeEach(async () => { | ||
const testHelper = await setupTesting(); | ||
|
||
rankService = testHelper.rankService; | ||
await rankService.resetRankList(); | ||
}); | ||
|
||
afterAll(async () => { | ||
await rankService.resetRankList(); | ||
}); | ||
|
||
describe('RankList', () => { | ||
it('should return empty rank list', async () => { | ||
await rankService.resetRankList(); | ||
const res = await rankService.getRankList(user); | ||
|
||
expect(res).toEqual(emptyRankList); | ||
}); | ||
|
||
it('should return rank list with first user finished course', async () => { | ||
await rankService.userFinishCourse(user.userId, user.username); | ||
const res = await rankService.getRankList(user); | ||
|
||
expect(res).toEqual(firstUserFinished); | ||
|
||
await rankService.resetRankList(); | ||
}); | ||
|
||
it('should return rank list with user finished course 2 times', async () => { | ||
await rankService.userFinishCourse(user.userId, user.username); | ||
await rankService.userFinishCourse(user.userId, user.username); | ||
const res = await rankService.getRankList(user); | ||
|
||
expect(res).toEqual(userFinishedTwice); | ||
|
||
await rankService.resetRankList(); | ||
}); | ||
|
||
it('should return empty rank list after reset', async () => { | ||
await rankService.userFinishCourse(user.userId, user.username); | ||
await rankService.resetRankList(); | ||
const res = await rankService.getRankList(user); | ||
|
||
expect(res).toEqual(emptyRankList); | ||
}); | ||
}); | ||
}); | ||
|
||
async function setupTesting() { | ||
const moduleRef: TestingModule = await Test.createTestingModule({ | ||
imports: [ | ||
MockRedisModule, | ||
JwtModule.register({ | ||
secret: process.env.SECRET, | ||
signOptions: { expiresIn: '7d' }, | ||
}), | ||
], | ||
providers: [RankService], | ||
}).compile(); | ||
return { | ||
rankService: moduleRef.get<RankService>(RankService), | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
export function createEmptyRankList() { | ||
return { | ||
list: [], | ||
self: { | ||
username: 'testUser', | ||
count: 0, | ||
rank: null, | ||
}, | ||
}; | ||
} | ||
|
||
export function createRankListWithFirstUserFinishedCourse() { | ||
return { | ||
list: [ | ||
{ | ||
username: 'testUser', | ||
count: '1', | ||
}, | ||
], | ||
self: { | ||
username: 'testUser', | ||
count: '1', | ||
rank: 0, | ||
}, | ||
}; | ||
} | ||
|
||
export function createRankListWithUserFinishedCourse2Times() { | ||
return { | ||
list: [ | ||
{ | ||
username: 'testUser', | ||
count: '2', | ||
}, | ||
], | ||
self: { | ||
username: 'testUser', | ||
count: '2', | ||
rank: 0, | ||
}, | ||
}; | ||
} |
Oops, something went wrong.