Skip to content

Commit

Permalink
add: offset & limit
Browse files Browse the repository at this point in the history
  • Loading branch information
SIY1121 committed Mar 31, 2021
1 parent 1daf7a4 commit de8dad1
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 2 deletions.
7 changes: 5 additions & 2 deletions __tests__/grpc/courseService.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,15 +254,18 @@ describe('searchCourse', () => {
Mon: [false, true, true, true, true, true, true],
},
},
limit: 50,
offset: 10,
}
const resCourse = createDBCourse(testData[0], 2020, v4())
mocked(searchCourseUseCase).mockImplementation(
async ({ year, searchMode, keywords, timetable }) => {
async ({ year, searchMode, keywords, timetable, limit, offset }) => {
expect(year).toBe(req.year)
expect(searchMode).toBe(req.searchMode)
expect(keywords).toEqual(keywords)
expect(timetable?.SpringA?.Mon).toEqual(req.timetable.SpringA.Mon)

expect(limit).toBe(req.limit)
expect(offset).toBe(req.offset)
return [resCourse]
}
)
Expand Down
57 changes: 57 additions & 0 deletions __tests__/usecase/searchCourse.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { v4 } from 'uuid'
import { connectDatabase } from '../../src/database'
import { Course } from '../../src/database/model/course'
import { Day, Module } from '../../src/database/model/enums'
import { InvalidArgumentError } from '../../src/error'
import { createDBCourse } from '../../src/grpc/converter'
import { searchCourseUseCase, SearchMode } from '../../src/usecase/searchCourse'
import { clearDB } from '../_cleardb'
Expand Down Expand Up @@ -104,8 +105,11 @@ test('キーワード検索単体', async () => {
year: 2020,
keywords: ['情報'],
searchMode: SearchMode.Cover,
offset: 0,
limit: 30,
})
expect(res.length > 0).toBe(true)
expect(res.length <= 30).toBe(true)
res.forEach((c) => expect(c.name.includes('情報')).toBe(true))
})

Expand All @@ -114,8 +118,11 @@ test('キーワード複数', async () => {
year: 2020,
keywords: ['情報', 'スポーツ'],
searchMode: SearchMode.Cover,
offset: 0,
limit: 30,
})
expect(res.length > 0).toBe(true)
expect(res.length <= 30).toBe(true)
res.forEach((c) =>
expect(c.name.includes('情報') || c.name.includes('スポーツ')).toBe(true)
)
Expand All @@ -126,11 +133,37 @@ test('キーワードなしで全部', async () => {
year: 2020,
keywords: [],
searchMode: SearchMode.Cover,
offset: 0,
limit: initialData.length,
})
expect(res.length > 0).toBe(true)
expect(res.length).toBe(initialData.length)
})

test('不正なoffset', () => {
return expect(
searchCourseUseCase({
year: 2020,
keywords: ['情報'],
searchMode: SearchMode.Cover,
offset: -1,
limit: 30,
})
).rejects.toThrow(InvalidArgumentError)
})

test('不正なlimit', () => {
return expect(
searchCourseUseCase({
year: 2020,
keywords: ['情報'],
searchMode: SearchMode.Cover,
offset: 0,
limit: 0,
})
).rejects.toThrow(InvalidArgumentError)
})

test('時間割 contain1', async () => {
const res = await searchCourseUseCase({
year: 2020,
Expand All @@ -144,8 +177,11 @@ test('時間割 contain1', async () => {
Tue: [false, true, true, false, false, false, false, false, false],
},
},
offset: 0,
limit: 30,
})
expect(res.length > 0).toBe(true)
expect(res.length <= 30).toBe(true)
res.forEach((c) =>
checkScheduleContain(c, [
{ module: Module.SpringA, day: Day.Tue, periods: [1, 2] },
Expand All @@ -167,8 +203,11 @@ test('時間割 contain2', async () => {
Tue: [false, false, true, false, false, false, false, false, false],
},
},
offset: 0,
limit: 30,
})
expect(res.length > 0).toBe(true)
expect(res.length <= 30).toBe(true)
res.forEach((c) =>
checkScheduleContain(c, [
{ module: Module.SpringA, day: Day.Tue, periods: [2] },
Expand All @@ -186,8 +225,11 @@ test('時間割 contain3', async () => {
SpringA: fillAllDayWith(new Array(7).fill(true)),
SpringB: fillAllDayWith(new Array(7).fill(true)),
},
offset: 0,
limit: 30,
})
expect(res.length > 0).toBe(true)
expect(res.length <= 30).toBe(true)
res.forEach((c) =>
checkScheduleContain(c, [
{ module: Module.SpringA },
Expand All @@ -204,8 +246,11 @@ test('時間割 contain4', async () => {
timetable: fillAllModuleWith({
Intensive: [true, false, false, false, false, false, false],
}),
offset: 0,
limit: 30,
})
expect(res.length > 0).toBe(true)
expect(res.length <= 30).toBe(true)
res.forEach((c) =>
checkScheduleContain(c, [{ day: Day.Intensive, periods: [0] }])
)
Expand All @@ -221,8 +266,11 @@ test('時間割 cover1', async () => {
Wed: [false, false, false, false, false, true, true],
},
},
offset: 0,
limit: 30,
})
expect(res.length > 0).toBe(true)
expect(res.length <= 30).toBe(true)
res.forEach((c) =>
checkScheduleCover(c, [
{ module: Module.SpringA, day: Day.Wed, periods: [5, 6] },
Expand All @@ -240,8 +288,11 @@ test('時間割 cover2', async () => {
Wed: [false, false, false, false, false, false, true],
},
},
offset: 0,
limit: 30,
})
expect(res.length > 0).toBe(true)
expect(res.length <= 30).toBe(true)
res.forEach((c) =>
checkScheduleCover(c, [
{ module: Module.SpringA, day: Day.Wed, periods: [6] },
Expand All @@ -257,8 +308,11 @@ test('時間割 cover3', async () => {
timetable: {
SpringA: fillAllDayWith(new Array(7).fill(true)),
},
offset: 0,
limit: 30,
})
expect(res.length > 0).toBe(true)
expect(res.length <= 30).toBe(true)
res.forEach((c) => checkScheduleCover(c, [{ module: Module.SpringA }]))
})

Expand All @@ -270,7 +324,10 @@ test('時間割 cover4', async () => {
timetable: fillAllModuleWith({
Intensive: new Array(8).fill(true),
}),
offset: 0,
limit: 30,
})
expect(res.length > 0).toBe(true)
expect(res.length <= 30).toBe(true)
res.forEach((c) => checkScheduleCover(c, [{ day: Day.Intensive }]))
})
2 changes: 2 additions & 0 deletions protos/CourseService.proto
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ message SearchCourseRequest {
Contain = 1;
}
SearchMode searchMode = 4;
int32 limit = 5;
int32 offset = 6;
}

message SearchCourseResponse {
Expand Down
22 changes: 22 additions & 0 deletions src/usecase/searchCourse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { getConnection, In, Raw } from 'typeorm'
import { Day, Module } from '../database/model/enums'
import { Course } from '../database/model/course'
import { InvalidArgumentError } from '../error'

export enum SearchMode {
Cover, // 指定した時限と講義の開講日時が一部でも被っていれば対象とみなす
Expand All @@ -18,16 +19,25 @@ type Input = {
keywords: string[]
year: number
searchMode: SearchMode
limit: number
offset: number
}

export async function searchCourseUseCase({
year,
timetable,
keywords,
searchMode,
offset,
limit,
}: Input): Promise<Course[]> {
const repo = getConnection().getRepository(Course)

if (offset < 0)
throw new InvalidArgumentError('offsetは0以上である必要があります')
if (limit < 1)
throw new InvalidArgumentError('limitは1以上である必要があります')

// 時間の指定がある場合
if (timetable) {
const conditions = Object.keys(timetable) // 全てのmoduleについて
Expand Down Expand Up @@ -139,6 +149,12 @@ export async function searchCourseUseCase({
// 人力パースは大変なのでデータを取得するのはTypeORMに任せる
return repo.findByIds(ids, {
relations: ['schedules', 'methods', 'recommendedGrades'],
order: {
year: 'ASC',
code: 'ASC',
},
skip: offset,
take: limit,
})
} else {
return repo.find({
Expand All @@ -157,6 +173,12 @@ export async function searchCourseUseCase({
}),
},
],
order: {
year: 'ASC',
code: 'ASC',
},
skip: offset,
take: limit,
})
}
}

0 comments on commit de8dad1

Please sign in to comment.