OMDSCloud/dictation_server/src/features/tasks/tasks.service.spec.ts
makabe.t 68aaa0e548 Merged PR 586: バックアップAPI実装
## 概要
[Task3121: バックアップAPI実装](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/3121)

- タスクのバックアップAPIとテストを実装しました。
  - 実装に当たり、タスクエンティティ定義の型を修正しています。

## レビューポイント
- テストケースに過不足はないでしょうか?
- エンティティの値を取得した際に`is_job_number_enabled`が数値となってしまうのでtypeをBooleanに変更しましたが問題ないでしょうか?

## UIの変更
- なし

## 動作確認状況
- ローカルで確認
2023-11-20 08:57:56 +00:00

3746 lines
113 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
makeDefaultAdb2cServiceMockValue,
makeDefaultNotificationhubServiceMockValue,
makeDefaultTasksRepositoryMockValue,
makeDefaultUserGroupsRepositoryMockValue,
makeDefaultUsersRepositoryMockValue,
makeTasksServiceMock,
} from './test/tasks.service.mock';
import { HttpException, HttpStatus } from '@nestjs/common';
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
import { TasksService } from './tasks.service';
import { DataSource } from 'typeorm';
import {
createCheckoutPermissions,
createTask,
createUserGroup,
getCheckoutPermissions,
getTask,
makeTaskTestingModuleWithNotificaiton,
} from './test/utility';
import { Adb2cTooManyRequestsError } from '../../gateways/adb2c/adb2c.service';
import { makeContext } from '../../common/log';
import {
makeTestAccount,
makeTestSimpleAccount,
makeTestUser,
} from '../../common/test/utility';
import { ADMIN_ROLES, TASK_STATUS, USER_ROLES } from '../../constants';
import { makeTestingModule } from '../../common/test/modules';
import { createSortCriteria } from '../users/test/utility';
import { createWorktype } from '../accounts/test/utility';
import {
createWorkflow,
createWorkflowTypist,
} from '../workflows/test/utility';
import { createTemplateFile } from '../templates/test/utility';
import { NotificationhubService } from '../../gateways/notificationhub/notificationhub.service';
import { Roles } from '../../common/types/role';
import { TasksRepositoryService } from '../../repositories/tasks/tasks.repository.service';
describe('TasksService', () => {
it('タスク一覧を取得できるadmin', async () => {
const tasksRepositoryMockValue = makeDefaultTasksRepositoryMockValue();
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
const userGroupsRepositoryMockValue =
makeDefaultUserGroupsRepositoryMockValue();
const adb2cServiceMockValue = makeDefaultAdb2cServiceMockValue();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const service = await makeTasksServiceMock(
tasksRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cServiceMockValue,
notificationhubServiceMockValue,
);
const userId = 'userId';
const offset = 0;
const limit = 20;
const status = ['Uploaded', 'Backup'];
const paramName = 'JOB_NUMBER';
const direction = 'ASC';
expect(
await service.tasksService.getTasks(
makeContext('trackingId'),
userId,
[ADMIN_ROLES.ADMIN, USER_ROLES.NONE],
offset,
limit,
status,
paramName,
direction,
),
).toEqual({
tasks: [
{
assignees: [{ typistName: 'XXXX XXX', typistUserId: 1 }],
audioCreatedDate: '2023-01-01T01:01:01.000Z',
audioDuration: '123000',
audioFileId: 1,
audioFinishedDate: '2023-01-01T01:01:01.000Z',
audioFormat: 'DS',
audioUploadedDate: '2023-01-01T01:01:01.000Z',
authorId: 'AUTHOR',
comment: 'comment',
fileName: 'test.zip',
fileSize: 123000,
isEncrypted: true,
jobNumber: '00000001',
optionItemList: [
{ optionItemLabel: 'label01', optionItemValue: 'value01' },
{ optionItemLabel: 'label02', optionItemValue: 'value02' },
{ optionItemLabel: 'label03', optionItemValue: 'value03' },
{ optionItemLabel: 'label04', optionItemValue: 'value04' },
{ optionItemLabel: 'label05', optionItemValue: 'value05' },
{ optionItemLabel: 'label06', optionItemValue: 'value06' },
{ optionItemLabel: 'label07', optionItemValue: 'value07' },
{ optionItemLabel: 'label08', optionItemValue: 'value08' },
{ optionItemLabel: 'label09', optionItemValue: 'value09' },
{ optionItemLabel: 'label10', optionItemValue: 'value10' },
],
priority: '00',
status: 'Uploaded',
transcriptionFinishedDate: undefined,
transcriptionStartedDate: undefined,
typist: undefined,
url: 'test/test.zip',
workType: 'WorkType',
},
],
total: 1,
});
});
it('アカウント情報の取得に失敗した場合、エラーを返却する', async () => {
const tasksRepositoryMockValue = makeDefaultTasksRepositoryMockValue();
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
const userGroupsRepositoryMockValue =
makeDefaultUserGroupsRepositoryMockValue();
const adb2cServiceMockValue = makeDefaultAdb2cServiceMockValue();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
usersRepositoryMockValue.findUserByExternalId = new Error('DB failed');
const service = await makeTasksServiceMock(
tasksRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cServiceMockValue,
notificationhubServiceMockValue,
);
const userId = 'userId';
const offset = 0;
const limit = 20;
const status = ['Uploaded', 'Backup'];
const paramName = 'JOB_NUMBER';
const direction = 'ASC';
await expect(
service.tasksService.getTasks(
makeContext('trackingId'),
userId,
[ADMIN_ROLES.ADMIN, USER_ROLES.NONE],
offset,
limit,
status,
paramName,
direction,
),
).rejects.toEqual(
new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
),
);
});
it('タスク一覧の取得に失敗した場合、エラーを返却するadmin', async () => {
const tasksRepositoryMockValue = makeDefaultTasksRepositoryMockValue();
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
const userGroupsRepositoryMockValue =
makeDefaultUserGroupsRepositoryMockValue();
const adb2cServiceMockValue = makeDefaultAdb2cServiceMockValue();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
tasksRepositoryMockValue.getTasksFromAccountId = new Error('DB failed');
const service = await makeTasksServiceMock(
tasksRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cServiceMockValue,
notificationhubServiceMockValue,
);
const userId = 'userId';
const offset = 0;
const limit = 20;
const status = ['Uploaded', 'Backup'];
const paramName = 'JOB_NUMBER';
const direction = 'ASC';
await expect(
service.tasksService.getTasks(
makeContext('trackingId'),
userId,
[ADMIN_ROLES.ADMIN, USER_ROLES.NONE],
offset,
limit,
status,
paramName,
direction,
),
).rejects.toEqual(
new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
),
);
});
it('取得したタスク一覧が不正な形式の場合、エラーを返却する', async () => {
const tasksRepositoryMockValue = makeDefaultTasksRepositoryMockValue();
tasksRepositoryMockValue.getTasksFromAccountId = {
tasks: [
{
id: 1,
job_number: '00000001',
account_id: 1,
is_job_number_enabled: true,
audio_file_id: 1,
status: 'Uploaded',
priority: '00',
created_at: new Date('2023-01-01T01:01:01.000'),
option_items: null, // 存在しない場合でも空配列であるはずのものがnullになっているため形式不正
finished_at: null,
started_at: null,
typist_user_id: null,
template_file_id: null,
typist_user: null,
template_file: null,
created_by: null,
updated_by: null,
updated_at: new Date('2023-01-01T01:01:01.000'),
file: {
id: 1,
account_id: 1,
owner_user_id: 1,
url: 'test/test.zip',
file_name: 'test.zip',
author_id: 'AUTHOR',
work_type_id: 'WorkType',
started_at: new Date('2023-01-01T01:01:01.000'),
duration: '123000',
finished_at: new Date('2023-01-01T01:01:01.000'),
uploaded_at: new Date('2023-01-01T01:01:01.000'),
file_size: 123000,
priority: '00',
audio_format: 'DS',
comment: 'comment',
is_encrypted: true,
deleted_at: null,
task: null,
},
},
],
permissions: [],
count: 1,
};
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
const userGroupsRepositoryMockValue =
makeDefaultUserGroupsRepositoryMockValue();
const adb2cServiceMockValue = makeDefaultAdb2cServiceMockValue();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const service = await makeTasksServiceMock(
tasksRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cServiceMockValue,
notificationhubServiceMockValue,
);
const userId = 'userId';
const offset = 0;
const limit = 20;
const status = ['Uploaded', 'Backup'];
const paramName = 'JOB_NUMBER';
const direction = 'ASC';
await expect(
service.tasksService.getTasks(
makeContext('trackingId'),
userId,
[ADMIN_ROLES.ADMIN, USER_ROLES.NONE],
offset,
limit,
status,
paramName,
direction,
),
).rejects.toEqual(
new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
),
);
});
it('タスク一覧を取得できるauthor', async () => {
const tasksRepositoryMockValue = makeDefaultTasksRepositoryMockValue();
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
const userGroupsRepositoryMockValue =
makeDefaultUserGroupsRepositoryMockValue();
const adb2cServiceMockValue = makeDefaultAdb2cServiceMockValue();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
if (usersRepositoryMockValue.findUserByExternalId instanceof Error) {
return;
}
usersRepositoryMockValue.findUserByExternalId.role = 'author';
const service = await makeTasksServiceMock(
tasksRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cServiceMockValue,
notificationhubServiceMockValue,
);
const userId = 'userId';
const offset = 0;
const limit = 20;
const status = ['Uploaded', 'Backup'];
const paramName = 'JOB_NUMBER';
const direction = 'ASC';
const result = await service.tasksService.getTasks(
makeContext('trackingId'),
userId,
[USER_ROLES.AUTHOR],
offset,
limit,
status,
paramName,
direction,
);
expect(result).toEqual({
tasks: [
{
assignees: [{ typistName: 'XXXX XXX', typistUserId: 1 }],
audioCreatedDate: '2023-01-01T01:01:01.000Z',
audioDuration: '123000',
audioFileId: 1,
audioFinishedDate: '2023-01-01T01:01:01.000Z',
audioFormat: 'DS',
audioUploadedDate: '2023-01-01T01:01:01.000Z',
authorId: 'AUTHOR',
comment: 'comment',
fileName: 'test.zip',
fileSize: 123000,
isEncrypted: true,
jobNumber: '00000001',
optionItemList: [
{ optionItemLabel: 'label01', optionItemValue: 'value01' },
{ optionItemLabel: 'label02', optionItemValue: 'value02' },
{ optionItemLabel: 'label03', optionItemValue: 'value03' },
{ optionItemLabel: 'label04', optionItemValue: 'value04' },
{ optionItemLabel: 'label05', optionItemValue: 'value05' },
{ optionItemLabel: 'label06', optionItemValue: 'value06' },
{ optionItemLabel: 'label07', optionItemValue: 'value07' },
{ optionItemLabel: 'label08', optionItemValue: 'value08' },
{ optionItemLabel: 'label09', optionItemValue: 'value09' },
{ optionItemLabel: 'label10', optionItemValue: 'value10' },
],
priority: '00',
status: 'Uploaded',
transcriptionFinishedDate: undefined,
transcriptionStartedDate: undefined,
typist: undefined,
url: 'test/test.zip',
workType: 'WorkType',
},
],
total: 1,
});
expect(
service.taskRepoService.getTasksFromAuthorIdAndAccountId,
).toHaveBeenCalledWith('abcdef', 1, 0, 20, 'JOB_NUMBER', 'ASC', [
'Uploaded',
'Backup',
]);
});
it('タスク一覧の取得に失敗した場合、エラーを返却するauthor', async () => {
const tasksRepositoryMockValue = makeDefaultTasksRepositoryMockValue();
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
const userGroupsRepositoryMockValue =
makeDefaultUserGroupsRepositoryMockValue();
const adb2cServiceMockValue = makeDefaultAdb2cServiceMockValue();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
tasksRepositoryMockValue.getTasksFromAuthorIdAndAccountId = new Error(
'DB failed',
);
const service = await makeTasksServiceMock(
tasksRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cServiceMockValue,
notificationhubServiceMockValue,
);
const userId = 'userId';
const offset = 0;
const limit = 20;
const status = ['Uploaded', 'Backup'];
const paramName = 'JOB_NUMBER';
const direction = 'ASC';
await expect(
service.tasksService.getTasks(
makeContext('trackingId'),
userId,
[USER_ROLES.AUTHOR],
offset,
limit,
status,
paramName,
direction,
),
).rejects.toEqual(
new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
),
);
});
it('タスク一覧を取得できるtypist', async () => {
const tasksRepositoryMockValue = makeDefaultTasksRepositoryMockValue();
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
const userGroupsRepositoryMockValue =
makeDefaultUserGroupsRepositoryMockValue();
const adb2cServiceMockValue = makeDefaultAdb2cServiceMockValue();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
if (usersRepositoryMockValue.findUserByExternalId instanceof Error) {
return;
}
usersRepositoryMockValue.findUserByExternalId.role = 'typist';
const service = await makeTasksServiceMock(
tasksRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cServiceMockValue,
notificationhubServiceMockValue,
);
const userId = 'userId';
const offset = 0;
const limit = 20;
const status = ['Uploaded', 'Backup'];
const paramName = 'JOB_NUMBER';
const direction = 'ASC';
const result = await service.tasksService.getTasks(
makeContext('trackingId'),
userId,
[USER_ROLES.TYPIST],
offset,
limit,
status,
paramName,
direction,
);
expect(result).toEqual({
tasks: [
{
assignees: [{ typistName: 'XXXX XXX', typistUserId: 1 }],
audioCreatedDate: '2023-01-01T01:01:01.000Z',
audioDuration: '123000',
audioFileId: 1,
audioFinishedDate: '2023-01-01T01:01:01.000Z',
audioFormat: 'DS',
audioUploadedDate: '2023-01-01T01:01:01.000Z',
authorId: 'AUTHOR',
comment: 'comment',
fileName: 'test.zip',
fileSize: 123000,
isEncrypted: true,
jobNumber: '00000001',
optionItemList: [
{ optionItemLabel: 'label01', optionItemValue: 'value01' },
{ optionItemLabel: 'label02', optionItemValue: 'value02' },
{ optionItemLabel: 'label03', optionItemValue: 'value03' },
{ optionItemLabel: 'label04', optionItemValue: 'value04' },
{ optionItemLabel: 'label05', optionItemValue: 'value05' },
{ optionItemLabel: 'label06', optionItemValue: 'value06' },
{ optionItemLabel: 'label07', optionItemValue: 'value07' },
{ optionItemLabel: 'label08', optionItemValue: 'value08' },
{ optionItemLabel: 'label09', optionItemValue: 'value09' },
{ optionItemLabel: 'label10', optionItemValue: 'value10' },
],
priority: '00',
status: 'Uploaded',
transcriptionFinishedDate: undefined,
transcriptionStartedDate: undefined,
typist: undefined,
url: 'test/test.zip',
workType: 'WorkType',
},
],
total: 1,
});
expect(
service.taskRepoService.getTasksFromTypistRelations,
).toHaveBeenCalledWith('userId', 0, 20, 'JOB_NUMBER', 'ASC', [
'Uploaded',
'Backup',
]);
});
it('タスク一覧の取得に失敗した場合、エラーを返却するtypist', async () => {
const tasksRepositoryMockValue = makeDefaultTasksRepositoryMockValue();
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
const userGroupsRepositoryMockValue =
makeDefaultUserGroupsRepositoryMockValue();
const adb2cServiceMockValue = makeDefaultAdb2cServiceMockValue();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
tasksRepositoryMockValue.getTasksFromTypistRelations = new Error(
'DB failed',
);
const service = await makeTasksServiceMock(
tasksRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cServiceMockValue,
notificationhubServiceMockValue,
);
const userId = 'userId';
const offset = 0;
const limit = 20;
const status = ['Uploaded', 'Backup'];
const paramName = 'JOB_NUMBER';
const direction = 'ASC';
await expect(
service.tasksService.getTasks(
makeContext('trackingId'),
userId,
[USER_ROLES.TYPIST],
offset,
limit,
status,
paramName,
direction,
),
).rejects.toEqual(
new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
),
);
});
it('AdB2Cのリクエスト上限超過時、専用のエラーを返却する', async () => {
const tasksRepositoryMockValue = makeDefaultTasksRepositoryMockValue();
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
const userGroupsRepositoryMockValue =
makeDefaultUserGroupsRepositoryMockValue();
const adb2cServiceMockValue = makeDefaultAdb2cServiceMockValue();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
adb2cServiceMockValue.getUsers = new Adb2cTooManyRequestsError();
const service = await makeTasksServiceMock(
tasksRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cServiceMockValue,
notificationhubServiceMockValue,
);
const userId = 'userId';
const offset = 0;
const limit = 20;
const status = ['Uploaded,Backup'];
const paramName = 'JOB_NUMBER';
const direction = 'ASC';
await expect(
service.tasksService.getTasks(
makeContext('trackingId'),
userId,
[ADMIN_ROLES.ADMIN, USER_ROLES.NONE],
offset,
limit,
status,
paramName,
direction,
),
).rejects.toEqual(
new HttpException(
makeErrorResponse('E000301'),
HttpStatus.INTERNAL_SERVER_ERROR,
),
);
});
describe('DBテスト', () => {
let source: DataSource | null = null;
beforeEach(async () => {
source = new DataSource({
type: 'sqlite',
database: ':memory:',
logging: false,
entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
synchronize: true, // trueにすると自動的にmigrationが行われるため注意
});
return source.initialize();
});
afterEach(async () => {
if (!source) return;
await source.destroy();
source = null;
});
it('[Admin] Taskが0件であっても実行できる', async () => {
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
if (!source) fail();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { external_id: externalId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'userId',
role: 'admin',
});
const service = module.get<TasksService>(TasksService);
const offset = 0;
const limit = 20;
const status = ['Uploaded,Backup'];
const paramName = 'JOB_NUMBER';
const direction = 'ASC';
const { tasks, total } = await service.getTasks(
makeContext('trackingId'),
externalId,
[ADMIN_ROLES.ADMIN, USER_ROLES.NONE],
offset,
limit,
status,
paramName,
direction,
);
expect(tasks).toEqual([]);
expect(total).toEqual(0);
});
it('[Author] Authorは自分が作成者のTask一覧を取得できる', async () => {
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
if (!source) fail();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: userId, external_id } = await makeTestUser(source, {
account_id: accountId,
external_id: 'userId',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
await createTask(
source,
accountId,
userId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Uploaded',
);
await createTask(
source,
accountId,
userId,
'MY_AUTHOR_ID',
'',
'01',
'00000002',
'Uploaded',
);
const service = module.get<TasksService>(TasksService);
const offset = 0;
const limit = 20;
const status = ['Uploaded', 'Backup'];
const paramName = 'JOB_NUMBER';
const direction = 'ASC';
const { tasks, total } = await service.getTasks(
makeContext('trackingId'),
external_id,
[USER_ROLES.AUTHOR],
offset,
limit,
status,
paramName,
direction,
);
expect(total).toEqual(2);
{
const task = tasks[0];
expect(task.jobNumber).toEqual('00000001');
}
{
const task = tasks[1];
expect(task.jobNumber).toEqual('00000002');
}
});
it('[Author] Authorは同一アカウントであっても自分以外のAuhtorのTaskは取得できない', async () => {
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
if (!source) fail();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: userId_1, external_id } = await makeTestUser(source, {
account_id: accountId,
external_id: 'userId_1',
role: 'author',
author_id: 'AUTHOR_ID_1',
});
const { id: userId_2 } = await makeTestUser(source, {
account_id: accountId,
external_id: 'userId_2',
role: 'author',
author_id: 'AUTHOR_ID_2',
});
await createTask(
source,
accountId,
userId_1,
'AUTHOR_ID_1',
'',
'01',
'00000001',
'Uploaded',
);
await createTask(
source,
accountId,
userId_2,
'AUTHOR_ID_2',
'',
'01',
'00000002',
'Uploaded',
);
const service = module.get<TasksService>(TasksService);
const offset = 0;
const limit = 20;
const status = ['Uploaded', 'Backup'];
const paramName = 'JOB_NUMBER';
const direction = 'ASC';
const { tasks, total } = await service.getTasks(
makeContext('trackingId'),
external_id,
[USER_ROLES.AUTHOR],
offset,
limit,
status,
paramName,
direction,
);
expect(total).toEqual(1);
{
const task = tasks[0];
expect(task.jobNumber).toEqual('00000001');
}
});
});
});
describe('changeCheckoutPermission', () => {
let source: DataSource | null = null;
beforeEach(async () => {
source = new DataSource({
type: 'sqlite',
database: ':memory:',
logging: false,
entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
synchronize: true, // trueにすると自動的にmigrationが行われるため注意
});
return source.initialize();
});
afterEach(async () => {
if (!source) return;
await source.destroy();
source = null;
});
it('タスクのチェックアウト権限を変更できる。(個人指定)', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId_1 } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: typistUserId_2 } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-2-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Uploaded',
);
const { userGroupId } = await createUserGroup(
source,
accountId,
'USER_GROUP_A',
[typistUserId_1],
);
await createCheckoutPermissions(source, taskId, typistUserId_1);
await createCheckoutPermissions(source, taskId, undefined, userGroupId);
const service = module.get<TasksService>(TasksService);
const NotificationHubService = module.get<NotificationhubService>(
NotificationhubService,
);
await service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[{ typistName: 'typist-user-2', typistUserId: typistUserId_2 }],
'author-user-external-id',
['admin'],
);
const permisions = await getCheckoutPermissions(source, taskId);
expect(permisions.length).toEqual(1);
expect(permisions[0]).toEqual({
id: 3,
task_id: taskId,
user_id: typistUserId_2,
user_group_id: null,
});
const resultTask = await getTask(source, taskId);
// 通知処理が想定通りの引数で呼ばれているか確認
expect(NotificationHubService.notify).toHaveBeenCalledWith(
makeContext('trackingId'),
[`user_${typistUserId_2}`],
{
authorId: 'MY_AUTHOR_ID',
filename: 'x',
priority: 'High',
uploadedAt: resultTask?.file?.uploaded_at.toISOString(),
},
);
});
it('タスクのチェックアウト権限を変更できる。(グループ指定)', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId_1 } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: typistUserId_2 } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-2-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Uploaded',
);
const { userGroupId: userGroupId_1 } = await createUserGroup(
source,
accountId,
'USER_GROUP_A',
[typistUserId_1],
);
const { userGroupId: userGroupId_2 } = await createUserGroup(
source,
accountId,
'USER_GROUP_B',
[typistUserId_2],
);
await createCheckoutPermissions(source, taskId, typistUserId_1);
await createCheckoutPermissions(source, taskId, undefined, userGroupId_1);
const service = module.get<TasksService>(TasksService);
const NotificationHubService = module.get<NotificationhubService>(
NotificationhubService,
);
await service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[{ typistName: 'USER_GROUP_B', typistGroupId: userGroupId_2 }],
'author-user-external-id',
['admin'],
);
const permisions = await getCheckoutPermissions(source, taskId);
expect(permisions.length).toEqual(1);
expect(permisions[0]).toEqual({
id: 3,
task_id: taskId,
user_id: null,
user_group_id: userGroupId_2,
});
const resultTask = await getTask(source, taskId);
// 通知処理が想定通りの引数で呼ばれているか確認
expect(NotificationHubService.notify).toHaveBeenCalledWith(
makeContext('trackingId'),
[`user_${typistUserId_2}`],
{
authorId: 'MY_AUTHOR_ID',
filename: 'x',
priority: 'High',
uploadedAt: resultTask?.file?.uploaded_at.toISOString(),
},
);
});
it('タスクのチェックアウト権限を変更できる。(チェックアウト権限を外す)', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId_1 } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Uploaded',
);
const { userGroupId } = await createUserGroup(
source,
accountId,
'USER_GROUP_A',
[typistUserId_1],
);
await createCheckoutPermissions(source, taskId, typistUserId_1);
await createCheckoutPermissions(source, taskId, undefined, userGroupId);
const service = module.get<TasksService>(TasksService);
await service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[],
'author-user-external-id',
['admin'],
);
const permisions = await getCheckoutPermissions(source, taskId);
expect(permisions.length).toEqual(0);
});
it('ユーザーが存在しない場合、タスクのチェックアウト権限を変更できない', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId_1 } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Uploaded',
);
const { userGroupId } = await createUserGroup(
source,
accountId,
'USER_GROUP_A',
[typistUserId_1],
);
await createCheckoutPermissions(source, taskId, typistUserId_1);
await createCheckoutPermissions(source, taskId, undefined, userGroupId);
const service = module.get<TasksService>(TasksService);
try {
await service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[{ typistName: 'not-exist-user', typistUserId: 999 }],
'author-user-external-id',
['admin'],
);
fail();
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010204'));
} else {
fail();
}
}
});
it('ユーザーがメール認証されていない場合、タスクのチェックアウト権限を変更できない', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId_1 } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id_1',
role: 'typist',
});
const { id: typistUserId_2 } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id_2',
role: 'typist',
email_verified: false,
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Uploaded',
);
const { userGroupId } = await createUserGroup(
source,
accountId,
'USER_GROUP_A',
[typistUserId_1],
);
await createCheckoutPermissions(source, taskId, typistUserId_1);
await createCheckoutPermissions(source, taskId, undefined, userGroupId);
const service = module.get<TasksService>(TasksService);
try {
await service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[{ typistName: 'not-verified-user', typistUserId: typistUserId_2 }],
'author-user-external-id',
['admin'],
);
fail();
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010204'));
} else {
fail();
}
}
});
it('ユーザーグループが存在しない場合、タスクのチェックアウト権限を変更できない', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId_1 } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Uploaded',
);
const { userGroupId } = await createUserGroup(
source,
accountId,
'USER_GROUP_A',
[typistUserId_1],
);
await createCheckoutPermissions(source, taskId, typistUserId_1);
await createCheckoutPermissions(source, taskId, undefined, userGroupId);
const service = module.get<TasksService>(TasksService);
try {
await service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[{ typistName: 'not-exist-user-group', typistGroupId: 999 }],
'author-user-external-id',
['admin'],
),
fail();
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010204'));
} else {
fail();
}
}
});
it('タスクが存在しない場合、タスクのチェックアウト権限を変更できない', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const service = module.get<TasksService>(TasksService);
try {
await service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[{ typistName: 'typist-user', typistUserId: typistUserId }],
'author-user-external-id',
['admin'],
),
fail();
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010601'));
} else {
fail();
}
}
});
it('タスクのステータスがUploadedでない場合、タスクのチェックアウト権限を変更できない', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Inprogress',
);
const service = module.get<TasksService>(TasksService);
try {
await service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[{ typistName: 'typist-user', typistUserId: typistUserId }],
'author-user-external-id',
['admin'],
),
fail();
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010601'));
} else {
fail();
}
}
});
it('ユーザーのRoleがAuthorでタスクのAuthorIDと自身のAuthorIDが一致しない場合、タスクのチェックアウト権限を変更できない', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
await createTask(
source,
accountId,
authorUserId,
'OTHER_AUTHOR_ID',
'',
'01',
'00000001',
'Uploaded',
);
const service = module.get<TasksService>(TasksService);
try {
await service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[{ typistName: 'typist-user', typistUserId: typistUserId }],
'author-user-external-id',
['author'],
),
fail();
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010601'));
} else {
fail();
}
}
});
it('通知に失敗した場合、エラーとなる', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
notificationhubServiceMockValue.notify = new Error('Notify Error.');
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId_1 } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: typistUserId_2 } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-2-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Uploaded',
);
const { userGroupId } = await createUserGroup(
source,
accountId,
'USER_GROUP_A',
[typistUserId_1],
);
await createCheckoutPermissions(source, taskId, typistUserId_1);
await createCheckoutPermissions(source, taskId, undefined, userGroupId);
const service = module.get<TasksService>(TasksService);
try {
await service.changeCheckoutPermission(
makeContext('trackingId'),
1,
[{ typistName: 'typist-user-2', typistUserId: typistUserId_2 }],
'author-user-external-id',
['admin'],
),
fail();
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
});
});
describe('checkout', () => {
let source: DataSource | null = null;
beforeEach(async () => {
source = new DataSource({
type: 'sqlite',
database: ':memory:',
logging: false,
entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
synchronize: true, // trueにすると自動的にmigrationが行われるため注意
});
return source.initialize();
});
afterEach(async () => {
if (!source) return;
await source.destroy();
source = null;
});
it('ユーザーのRoleがTypistで、タスクのチェックアウト権限が個人指定である時、タスクをチェックアウトできる', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Uploaded',
);
const { userGroupId } = await createUserGroup(
source,
accountId,
'USER_GROUP_A',
[typistUserId],
);
await createCheckoutPermissions(source, taskId, typistUserId);
await createCheckoutPermissions(source, taskId, undefined, userGroupId);
const service = module.get<TasksService>(TasksService);
const initTask = await getTask(source, taskId);
await service.checkout(
makeContext('trackingId'),
1,
['typist'],
'typist-user-external-id',
);
const resultTask = await getTask(source, taskId);
const permisions = await getCheckoutPermissions(source, taskId);
expect(resultTask?.status).toEqual('InProgress');
expect(resultTask?.typist_user_id).toEqual(typistUserId);
expect(resultTask?.started_at).not.toEqual(initTask?.started_at);
expect(permisions.length).toEqual(1);
expect(permisions[0]).toEqual({
id: 3,
task_id: 1,
user_id: 1,
user_group_id: null,
});
});
it('ユーザーのRoleがTypistで、タスクのチェックアウト権限がグループ指定である時、タスクをチェックアウトできる', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Uploaded',
);
const { userGroupId } = await createUserGroup(
source,
accountId,
'USER_GROUP_A',
[typistUserId],
);
await createCheckoutPermissions(source, taskId, typistUserId);
await createCheckoutPermissions(source, taskId, undefined, userGroupId);
const service = module.get<TasksService>(TasksService);
const initTask = await getTask(source, taskId);
await service.checkout(
makeContext('trackingId'),
1,
['typist'],
'typist-user-external-id',
);
const resultTask = await getTask(source, taskId);
const permisions = await getCheckoutPermissions(source, taskId);
expect(resultTask?.status).toEqual('InProgress');
expect(resultTask?.typist_user_id).toEqual(typistUserId);
expect(resultTask?.started_at).not.toEqual(initTask?.started_at);
expect(permisions.length).toEqual(1);
expect(permisions[0]).toEqual({
id: 3,
task_id: 1,
user_id: 1,
user_group_id: null,
});
});
it('ユーザーのRoleがTypistで、タスクのステータスがPendingである時、タスクをチェックアウトできる', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Pending',
);
await createCheckoutPermissions(source, taskId, typistUserId);
const service = module.get<TasksService>(TasksService);
const initTask = await getTask(source, taskId);
await service.checkout(
makeContext('trackingId'),
1,
['typist'],
'typist-user-external-id',
);
const resultTask = await getTask(source, taskId);
const permisions = await getCheckoutPermissions(source, taskId);
expect(resultTask?.status).toEqual('InProgress');
expect(resultTask?.typist_user_id).toEqual(typistUserId);
//タスクの元々のステータスがPending,Inprogressの場合、文字起こし開始時刻は更新されない
expect(resultTask?.started_at).toEqual(initTask?.started_at);
expect(permisions.length).toEqual(1);
expect(permisions[0]).toEqual({
id: 2,
task_id: 1,
user_id: 1,
user_group_id: null,
});
});
it('ユーザーのRoleがTypistで、対象のタスクのStatus[Uploaded,Inprogress,Pending]以外の時、タスクをチェックアウトできない', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
author_id: 'MY_AUTHOR_ID',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Backup',
);
const service = module.get<TasksService>(TasksService);
try {
await service.checkout(
makeContext('trackingId'),
1,
['typist'],
'typist-user-external-id',
);
fail();
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010601'));
} else {
fail();
}
}
});
it('ユーザーのRoleがTypistで、チェックアウト権限が存在しない時、タスクをチェックアウトできない', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
author_id: 'MY_AUTHOR_ID',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Uploaded',
);
const service = module.get<TasksService>(TasksService);
try {
await service.checkout(
makeContext('trackingId'),
1,
['typist'],
'typist-user-external-id',
);
fail();
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010602'));
} else {
fail();
}
}
});
it('ユーザーのRoleがTypistで、既にチェックアウト中のタスクInProgressがある時、タスクをチェックアウトできない', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
TASK_STATUS.IN_PROGRESS,
typistUserId,
);
const { taskId, audioFileId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000002',
TASK_STATUS.UPLOADED,
);
await createCheckoutPermissions(source, taskId, typistUserId);
const service = module.get<TasksService>(TasksService);
try {
await service.checkout(
makeContext('trackingId'),
audioFileId,
['typist'],
'typist-user-external-id',
);
fail();
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010601'));
} else {
fail();
}
}
});
it('ユーザーのRoleがTypistで、別ユーザーによってチェックアウト中のタスクInProgressがある時、タスクをチェックアウトできる', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId1 } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id1',
role: 'typist',
});
const { id: typistUserId2 } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id2',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
TASK_STATUS.IN_PROGRESS,
typistUserId1,
);
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000002',
TASK_STATUS.UPLOADED,
);
await createCheckoutPermissions(source, taskId, typistUserId2);
const service = module.get<TasksService>(TasksService);
await service.checkout(
makeContext('trackingId'),
2,
['typist'],
'typist-user-external-id2',
);
const resultTask = await getTask(source, taskId);
const permisions = await getCheckoutPermissions(source, taskId);
expect(resultTask?.status).toEqual(TASK_STATUS.IN_PROGRESS);
expect(resultTask?.typist_user_id).toEqual(typistUserId2);
expect(permisions.length).toBe(1);
expect(permisions[0].task_id).toBe(taskId);
expect(permisions[0].user_id).toBe(typistUserId2);
});
it('ユーザーのRoleがAuthorで、アップロードした音声ファイルに紐づいたタスクをチェックアウトできる(Uploaded)', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Uploaded',
);
const service = module.get<TasksService>(TasksService);
expect(
await service.checkout(
makeContext('trackingId'),
1,
['author'],
'author-user-external-id',
),
).toEqual(undefined);
});
it('ユーザーのRoleがAuthorで、アップロードした音声ファイルに紐づいたタスクをチェックアウトできる(Finished)', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Uploaded',
);
const service = module.get<TasksService>(TasksService);
expect(
await service.checkout(
makeContext('trackingId'),
1,
['author'],
'author-user-external-id',
),
).toEqual(undefined);
});
it('ユーザーのRoleがAuthorで、アップロードした音声ファイルに紐づいたタスクが存在しない場合、タスクをチェックアウトできない', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const service = module.get<TasksService>(TasksService);
try {
await service.checkout(
makeContext('trackingId'),
1,
['author'],
'author-user-external-id',
),
fail();
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.NOT_FOUND);
expect(e.getResponse()).toEqual(makeErrorResponse('E010601'));
} else {
fail();
}
}
});
it('ユーザーのRoleがAuthorで、音声ファイルに紐づいたタスクでユーザーと一致するAuthorIDでない場合、タスクをチェックアウトできない', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
await createTask(
source,
accountId,
authorUserId,
'OTHOR_AUTHOR',
'',
'01',
'00000001',
'Uploaded',
);
const service = module.get<TasksService>(TasksService);
try {
await service.checkout(
makeContext('trackingId'),
1,
['author'],
'author-user-external-id',
);
fail();
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010602'));
} else {
fail();
}
}
});
it('ユーザーのRoleに[Typist,author]が設定されていない時、タスクをチェックアウトできない', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
await makeTestUser(source, {
account_id: accountId,
external_id: 'none-user-external-id',
role: 'none',
author_id: 'MY_AUTHOR_ID',
});
const service = module.get<TasksService>(TasksService);
try {
await service.checkout(
makeContext('trackingId'),
1,
['none'],
'none-user-external-id',
);
fail();
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010602'));
} else {
fail();
}
}
});
});
describe('checkin', () => {
let source: DataSource | null = null;
beforeEach(async () => {
source = new DataSource({
type: 'sqlite',
database: ':memory:',
logging: false,
entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
synchronize: true, // trueにすると自動的にmigrationが行われるため注意
});
return source.initialize();
});
afterEach(async () => {
if (!source) return;
await source.destroy();
source = null;
});
it('API実行者が文字起こし実行中のタスクである場合、タスクをチェックインできる', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'InProgress',
typistUserId,
);
await createCheckoutPermissions(source, taskId, typistUserId);
const service = module.get<TasksService>(TasksService);
const initTask = await getTask(source, taskId);
await service.checkin(
makeContext('trackingId'),
1,
'typist-user-external-id',
);
const resultTask = await getTask(source, taskId);
expect(resultTask?.status).toEqual('Finished');
expect(resultTask?.finished_at).not.toEqual(initTask?.finished_at);
});
it('タスクのステータスがInprogressでない時、タスクをチェックインできない', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Uploaded',
typistUserId,
);
await createCheckoutPermissions(source, taskId, typistUserId);
const service = module.get<TasksService>(TasksService);
await expect(
service.checkin(makeContext('trackingId'), 1, 'typist-user-external-id'),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010601'), HttpStatus.BAD_REQUEST),
);
});
it('API実行者が文字起こし実行中のタスクでない場合、タスクをチェックインできない', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: anotherTypistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'another-typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'InProgress',
// API実行者のタスクではないため、typist_user_idは設定しない
);
await createCheckoutPermissions(source, taskId, anotherTypistUserId);
const service = module.get<TasksService>(TasksService);
await expect(
service.checkin(makeContext('trackingId'), 1, 'typist-user-external-id'),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010601'), HttpStatus.BAD_REQUEST),
);
});
it('タスクがない時、タスクをチェックインできない', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const service = module.get<TasksService>(TasksService);
await expect(
service.checkin(makeContext('trackingId'), 1, 'typist-user-external-id'),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010603'), HttpStatus.NOT_FOUND),
);
});
});
describe('suspend', () => {
let source: DataSource | null = null;
beforeEach(async () => {
source = new DataSource({
type: 'sqlite',
database: ':memory:',
logging: false,
entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
synchronize: true, // trueにすると自動的にmigrationが行われるため注意
});
return source.initialize();
});
afterEach(async () => {
if (!source) return;
await source.destroy();
source = null;
});
it('API実行者が文字起こし実行中のタスクである場合、タスクを中断できる', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'InProgress',
typistUserId,
);
const service = module.get<TasksService>(TasksService);
await service.suspend(
makeContext('trackingId'),
1,
'typist-user-external-id',
);
const resultTask = await getTask(source, taskId);
expect(resultTask?.status).toEqual('Pending');
});
it('タスクのステータスがInprogressでない時、タスクを中断できない', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Uploaded',
typistUserId,
);
await createCheckoutPermissions(source, taskId, typistUserId);
const service = module.get<TasksService>(TasksService);
await expect(
service.suspend(makeContext('trackingId'), 1, 'typist-user-external-id'),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010601'), HttpStatus.BAD_REQUEST),
);
});
it('API実行者が文字起こし実行中のタスクでない場合、タスクを中断できない', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: anotherTypistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'another-typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'InProgress',
anotherTypistUserId,
);
await createCheckoutPermissions(source, taskId, anotherTypistUserId);
const service = module.get<TasksService>(TasksService);
await expect(
service.checkin(makeContext('trackingId'), 1, 'typist-user-external-id'),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010601'), HttpStatus.BAD_REQUEST),
);
});
it('タスクがない時、タスクを中断できない', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const service = module.get<TasksService>(TasksService);
await expect(
service.checkin(makeContext('trackingId'), 1, 'typist-user-external-id'),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010603'), HttpStatus.NOT_FOUND),
);
});
});
describe('cancel', () => {
let source: DataSource | null = null;
beforeEach(async () => {
source = new DataSource({
type: 'sqlite',
database: ':memory:',
logging: false,
entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
synchronize: true, // trueにすると自動的にmigrationが行われるため注意
});
return source.initialize();
});
afterEach(async () => {
if (!source) return;
await source.destroy();
source = null;
});
it('API実行者のRoleがTypistの場合、自身が文字起こし実行中のタスクをキャンセルできる', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'InProgress',
typistUserId,
);
await createCheckoutPermissions(source, taskId, typistUserId);
const service = module.get<TasksService>(TasksService);
await service.cancel(
makeContext('trackingId'),
1,
'typist-user-external-id',
['typist', 'standard'],
);
const resultTask = await getTask(source, taskId);
const permisions = await getCheckoutPermissions(source, taskId);
expect(resultTask?.status).toEqual('Uploaded');
expect(resultTask?.typist_user_id).toEqual(null);
expect(permisions.length).toEqual(0);
});
it('API実行者のRoleがTypistの場合、自身が文字起こし中断しているタスクをキャンセルできる', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Pending',
typistUserId,
);
await createCheckoutPermissions(source, taskId, typistUserId);
const service = module.get<TasksService>(TasksService);
await service.cancel(
makeContext('trackingId'),
1,
'typist-user-external-id',
['typist', 'standard'],
);
const resultTask = await getTask(source, taskId);
const permisions = await getCheckoutPermissions(source, taskId);
expect(resultTask?.status).toEqual('Uploaded');
expect(resultTask?.typist_user_id).toEqual(null);
expect(permisions.length).toEqual(0);
});
it('API実行者のRoleがAdminの場合、文字起こし実行中のタスクをキャンセルできる', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'InProgress',
typistUserId,
);
await createCheckoutPermissions(source, taskId, typistUserId);
const service = module.get<TasksService>(TasksService);
await service.cancel(
makeContext('trackingId'),
1,
'typist-user-external-id',
['admin', 'author'],
);
const resultTask = await getTask(source, taskId);
const permisions = await getCheckoutPermissions(source, taskId);
expect(resultTask?.status).toEqual('Uploaded');
expect(resultTask?.typist_user_id).toEqual(null);
expect(permisions.length).toEqual(0);
});
it('API実行者のRoleがAdminの場合、文字起こし中断しているタスクをキャンセルできる', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Pending',
typistUserId,
);
await createCheckoutPermissions(source, taskId, typistUserId);
const service = module.get<TasksService>(TasksService);
await service.cancel(
makeContext('trackingId'),
1,
'typist-user-external-id',
['admin', 'author'],
);
const resultTask = await getTask(source, taskId);
const permisions = await getCheckoutPermissions(source, taskId);
expect(resultTask?.status).toEqual('Uploaded');
expect(resultTask?.typist_user_id).toEqual(null);
expect(permisions.length).toEqual(0);
});
it('タスクのステータスが[Inprogress,Pending]でない時、タスクをキャンセルできない', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'Uploaded',
typistUserId,
);
await createCheckoutPermissions(source, taskId, typistUserId);
const service = module.get<TasksService>(TasksService);
await expect(
service.cancel(makeContext('trackingId'), 1, 'typist-user-external-id', [
'admin',
'author',
]),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010601'), HttpStatus.BAD_REQUEST),
);
});
it('API実行者のRoleがTypistの場合、他人が文字起こし実行中のタスクをキャンセルできない', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: anotherTypistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'another-typist-user-external-id',
role: 'typist',
});
const { id: authorUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
'InProgress',
anotherTypistUserId,
);
await createCheckoutPermissions(source, taskId, anotherTypistUserId);
const service = module.get<TasksService>(TasksService);
await expect(
service.cancel(makeContext('trackingId'), 1, 'typist-user-external-id', [
'typist',
'standard',
]),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010601'), HttpStatus.BAD_REQUEST),
);
});
it('タスクがない時、タスクをキャンセルできない', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const service = module.get<TasksService>(TasksService);
await expect(
service.cancel(makeContext('trackingId'), 1, 'typist-user-external-id', [
'typist',
'standard',
]),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010603'), HttpStatus.NOT_FOUND),
);
});
it('API実行者のRoleがTypistの場合、自身が文字起こし実行中のタスクをキャンセルし、そのタスクの自動ルーティングを行う', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
const { id: typistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { id: authorUserId, author_id } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'AUTHOR_ID',
});
//ワークタイプIDを作成
await createWorktype(source, accountId, '01');
// テンプレートファイルを作成
const { id: templateFileId } = await createTemplateFile(
source,
accountId,
'template-file-name',
'https://example.com',
);
// ワークフローを作成
const { id: workflowId } = await createWorkflow(
source,
accountId,
authorUserId,
undefined,
templateFileId,
);
// ワークフロータイピストを作成
await createWorkflowTypist(source, workflowId, typistUserId);
const { taskId } = await createTask(
source,
accountId,
authorUserId,
author_id ?? '',
'',
'01',
'00000001',
'InProgress',
typistUserId,
);
await createCheckoutPermissions(source, taskId, typistUserId);
const service = module.get<TasksService>(TasksService);
const NotificationHubService = module.get<NotificationhubService>(
NotificationhubService,
);
await service.cancel(
makeContext('trackingId'),
1,
'typist-user-external-id',
['typist', 'standard'],
);
const resultTask = await getTask(source, taskId);
const permisions = await getCheckoutPermissions(source, taskId);
expect(resultTask?.status).toEqual('Uploaded');
expect(resultTask?.typist_user_id).toEqual(null);
// タスクのテンプレートファイルIDを確認
expect(resultTask?.template_file_id).toEqual(templateFileId);
// タスクのチェックアウト権限が想定通りワークフローで設定されているのユーザーIDで作成されているか確認
expect(permisions.length).toEqual(1);
expect(permisions[0].user_id).toEqual(typistUserId);
// 通知処理が想定通りの引数で呼ばれているか確認
expect(NotificationHubService.notify).toHaveBeenCalledWith(
makeContext('trackingId'),
[`user_${typistUserId}`],
{
authorId: 'AUTHOR_ID',
filename: 'x',
priority: 'High',
uploadedAt: resultTask?.file?.uploaded_at.toISOString(),
},
);
});
it('API実行者のRoleがAdminの場合、自身が文字起こし実行中のタスクをキャンセルし、そのタスクの自動ルーティングを行うAPI実行者のAuthorIDと音声ファイルに紐づくWorkType', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
// タスクの文字起こし担当者
const { id: typistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
// 自動ルーティングされるタイピストユーザーを作成
const { id: autoRoutingTypistUserId } = await makeTestUser(source, {
account_id: accountId,
external_id: 'auto-routing-typist-user-external-id',
role: 'typist',
});
// API実行者
const {
id: myAuthorUserId,
external_id,
role,
} = await makeTestUser(source, {
account_id: accountId,
external_id: 'my-author-user-external-id',
role: 'author admin',
author_id: 'MY_AUTHOR_ID',
});
// 音声ファイルのアップロード者
const { id: authorUserId, author_id } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'AUTHOR_ID',
});
//ワークタイプIDを作成
const { id: workTypeId, custom_worktype_id } = await createWorktype(
source,
accountId,
'01',
);
// テンプレートファイルを作成
const { id: templateFileId } = await createTemplateFile(
source,
accountId,
'template-file-name',
'https://example.com',
);
// ワークフローを作成
const { id: workflowId } = await createWorkflow(
source,
accountId,
myAuthorUserId,
workTypeId,
templateFileId,
);
// ワークフロータイピストを作成
await createWorkflowTypist(source, workflowId, autoRoutingTypistUserId);
const { taskId } = await createTask(
source,
accountId,
authorUserId,
author_id ?? '',
custom_worktype_id,
'01',
'00000001',
'InProgress',
typistUserId,
);
await createCheckoutPermissions(source, taskId, typistUserId);
const service = module.get<TasksService>(TasksService);
const NotificationHubService = module.get<NotificationhubService>(
NotificationhubService,
);
await service.cancel(
makeContext('trackingId'),
1,
external_id,
role.split(' ') as Roles[],
);
const resultTask = await getTask(source, taskId);
const permisions = await getCheckoutPermissions(source, taskId);
expect(resultTask?.status).toEqual('Uploaded');
expect(resultTask?.typist_user_id).toEqual(null);
// タスクのテンプレートファイルIDを確認
expect(resultTask?.template_file_id).toEqual(templateFileId);
// タスクのチェックアウト権限が想定通りワークフローで設定されているのユーザーIDで作成されているか確認
expect(permisions.length).toEqual(1);
expect(permisions[0].user_id).toEqual(autoRoutingTypistUserId);
// 通知処理が想定通りの引数で呼ばれているか確認
expect(NotificationHubService.notify).toHaveBeenCalledWith(
makeContext('trackingId'),
[`user_${autoRoutingTypistUserId}`],
{
authorId: 'AUTHOR_ID',
filename: 'x',
priority: 'High',
uploadedAt: resultTask?.file?.uploaded_at.toISOString(),
},
);
});
it('API実行者のRoleがTypistの場合、自身が文字起こし実行中のタスクをキャンセルするが、一致するワークフローがない場合は自動ルーティングを行うことができない', async () => {
if (!source) fail();
const notificationhubServiceMockValue =
makeDefaultNotificationhubServiceMockValue();
const module = await makeTaskTestingModuleWithNotificaiton(
source,
notificationhubServiceMockValue,
);
if (!module) fail();
const { id: accountId } = await makeTestSimpleAccount(source);
// タスクの文字起こし担当者
const {
id: typistUserId,
external_id,
role,
} = await makeTestUser(source, {
account_id: accountId,
external_id: 'typist-user-external-id',
role: 'typist',
});
// 音声ファイルのアップロード者
const { id: authorUserId, author_id } = await makeTestUser(source, {
account_id: accountId,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'AUTHOR_ID',
});
const { taskId } = await createTask(
source,
accountId,
authorUserId,
author_id ?? '',
'custom_worktype_id',
'01',
'00000001',
'InProgress',
typistUserId,
);
await createCheckoutPermissions(source, taskId, typistUserId);
const service = module.get<TasksService>(TasksService);
const NotificationHubService = module.get<NotificationhubService>(
NotificationhubService,
);
await service.cancel(
makeContext('trackingId'),
1,
external_id,
role.split(' ') as Roles[],
);
const resultTask = await getTask(source, taskId);
const permisions = await getCheckoutPermissions(source, taskId);
expect(resultTask?.status).toEqual('Uploaded');
expect(resultTask?.typist_user_id).toEqual(null);
// タスクのチェックアウト権限が削除されていることを確認
expect(permisions.length).toEqual(0);
// 通知処理が想定通りの引数で呼ばれていないか確認
expect(NotificationHubService.notify).not.toHaveBeenCalled();
});
});
describe('backup', () => {
let source: DataSource | null = null;
beforeEach(async () => {
source = new DataSource({
type: 'sqlite',
database: ':memory:',
logging: false,
entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
synchronize: true, // trueにすると自動的にmigrationが行われるため注意
});
return source.initialize();
});
afterEach(async () => {
if (!source) return;
await source.destroy();
source = null;
});
it('文字起こし完了のタスクをバックアップできる', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
const { account, admin } = await makeTestAccount(source);
const { id: authorUserId } = await makeTestUser(source, {
account_id: account.id,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { id: typistUserId } = await makeTestUser(source, {
account_id: account.id,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { taskId, audioFileId } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
TASK_STATUS.FINISHED,
typistUserId,
);
// 作成したデータを確認
{
const task = await getTask(source, taskId);
expect(task?.status).toBe(TASK_STATUS.FINISHED);
expect(task?.is_job_number_enabled).toBe(true);
}
const service = module.get<TasksService>(TasksService);
await service.backup(
makeContext(admin.external_id),
audioFileId,
admin.external_id,
);
// バックアップしたデータを確認
{
const task = await getTask(source, taskId);
expect(task?.status).toBe(TASK_STATUS.BACKUP);
expect(task?.is_job_number_enabled).toBe(false);
}
});
it('文字起こしバックアップ済みのタスクをバックアップできる', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
const { account, admin } = await makeTestAccount(source);
const { id: authorUserId } = await makeTestUser(source, {
account_id: account.id,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { id: typistUserId } = await makeTestUser(source, {
account_id: account.id,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { taskId, audioFileId } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
TASK_STATUS.BACKUP,
typistUserId,
false,
);
// 作成したデータを確認
{
const task = await getTask(source, taskId);
expect(task?.status).toBe(TASK_STATUS.BACKUP);
expect(task?.is_job_number_enabled).toBe(false);
}
const service = module.get<TasksService>(TasksService);
await service.backup(
makeContext(admin.external_id),
audioFileId,
admin.external_id,
);
// バックアップしたデータを確認
{
const task = await getTask(source, taskId);
expect(task?.status).toBe(TASK_STATUS.BACKUP);
expect(task?.is_job_number_enabled).toBe(false);
}
});
it('タスクのステータスが[Finished,Backup]でない時、エラーを返却する', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
const { account, admin } = await makeTestAccount(source);
const { id: authorUserId } = await makeTestUser(source, {
account_id: account.id,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { id: typistUserId } = await makeTestUser(source, {
account_id: account.id,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { taskId, audioFileId } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
TASK_STATUS.IN_PROGRESS,
typistUserId,
);
// 作成したデータを確認
{
const task = await getTask(source, taskId);
expect(task?.status).toBe(TASK_STATUS.IN_PROGRESS);
expect(task?.is_job_number_enabled).toBe(true);
}
const service = module.get<TasksService>(TasksService);
try {
await service.backup(
makeContext(admin.external_id),
audioFileId,
admin.external_id,
);
fail();
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010601'));
} else {
fail();
}
}
});
it('指定タスクが存在しない時、エラーを返却する', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
const { account, admin } = await makeTestAccount(source);
const { id: authorUserId } = await makeTestUser(source, {
account_id: account.id,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { id: typistUserId } = await makeTestUser(source, {
account_id: account.id,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { taskId } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
TASK_STATUS.FINISHED,
typistUserId,
);
// 作成したデータを確認
{
const task = await getTask(source, taskId);
expect(task?.status).toBe(TASK_STATUS.FINISHED);
expect(task?.is_job_number_enabled).toBe(true);
}
const service = module.get<TasksService>(TasksService);
try {
await service.backup(
makeContext(admin.external_id),
9999, // 存在しないタスクID
admin.external_id,
);
fail();
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.NOT_FOUND);
expect(e.getResponse()).toEqual(makeErrorResponse('E010603'));
} else {
fail();
}
}
});
it('DBアクセスに失敗した場合、エラーを返却する', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
const { account, admin } = await makeTestAccount(source);
const { id: authorUserId } = await makeTestUser(source, {
account_id: account.id,
external_id: 'author-user-external-id',
role: 'author',
author_id: 'MY_AUTHOR_ID',
});
const { id: typistUserId } = await makeTestUser(source, {
account_id: account.id,
external_id: 'typist-user-external-id',
role: 'typist',
});
const { taskId, audioFileId } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
TASK_STATUS.FINISHED,
typistUserId,
);
// 作成したデータを確認
{
const task = await getTask(source, taskId);
expect(task?.status).toBe(TASK_STATUS.FINISHED);
expect(task?.is_job_number_enabled).toBe(true);
}
const service = module.get<TasksService>(TasksService);
//DBアクセスに失敗するようにする
const tasksService = module.get<TasksRepositoryService>(
TasksRepositoryService,
);
tasksService.backup = jest.fn().mockRejectedValue('DB failed');
try {
await service.backup(
makeContext(admin.external_id),
audioFileId,
admin.external_id,
);
fail();
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
});
});
describe('getNextTask', () => {
let source: DataSource | null = null;
beforeEach(async () => {
source = new DataSource({
type: 'sqlite',
database: ':memory:',
logging: false,
entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
synchronize: true, // trueにすると自動的にmigrationが行われるため注意
});
return source.initialize();
});
afterEach(async () => {
if (!source) return;
await source.destroy();
source = null;
});
it('次タスクを取得できるJobNumber順', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const { id: authorUserId } = await makeTestUser(source, {
account_id: account.id,
author_id: 'AUTHOR_ID',
external_id: 'author-user-external-id',
role: USER_ROLES.AUTHOR,
});
const { id: typistUserId, external_id: typistExternalId } =
await makeTestUser(source, {
account_id: account.id,
external_id: 'typist-user-external-id',
role: USER_ROLES.TYPIST,
});
await createSortCriteria(source, typistUserId, 'JOB_NUMBER', 'ASC');
const { taskId: taskId1 } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
TASK_STATUS.UPLOADED,
);
await createCheckoutPermissions(source, taskId1, typistUserId);
const { taskId: taskId3, audioFileId: audioFileId3 } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000003',
TASK_STATUS.UPLOADED,
);
await createCheckoutPermissions(source, taskId3, typistUserId);
const { taskId: taskId2, audioFileId: audioFileId2 } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000002',
TASK_STATUS.UPLOADED,
);
await createCheckoutPermissions(source, taskId2, typistUserId);
const service = module.get<TasksService>(TasksService);
const context = makeContext(admin.external_id);
const nextAudioFileId = await service.getNextTask(
context,
typistExternalId,
audioFileId2,
);
// 実行結果が正しいか確認
{
expect(nextAudioFileId).toEqual(audioFileId3);
}
});
it('次タスクを取得できるJobNumber順優先度', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const { id: authorUserId } = await makeTestUser(source, {
account_id: account.id,
author_id: 'AUTHOR_ID',
external_id: 'author-user-external-id',
role: USER_ROLES.AUTHOR,
});
const { id: typistUserId, external_id: typistExternalId } =
await makeTestUser(source, {
account_id: account.id,
external_id: 'typist-user-external-id',
role: USER_ROLES.TYPIST,
});
await createSortCriteria(source, typistUserId, 'JOB_NUMBER', 'ASC');
const { taskId: taskId1, audioFileId: audioFileId1 } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'',
'00',
'00000001',
TASK_STATUS.UPLOADED,
);
await createCheckoutPermissions(source, taskId1, typistUserId);
const { taskId: taskId3, audioFileId: audioFileId3 } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'',
'00',
'00000003',
TASK_STATUS.UPLOADED,
);
await createCheckoutPermissions(source, taskId3, typistUserId);
const { taskId: taskId2 } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000002',
TASK_STATUS.UPLOADED,
);
await createCheckoutPermissions(source, taskId2, typistUserId);
const service = module.get<TasksService>(TasksService);
const context = makeContext(admin.external_id);
const nextAudioFileId = await service.getNextTask(
context,
typistExternalId,
audioFileId1,
);
// 実行結果が正しいか確認
{
expect(nextAudioFileId).toEqual(audioFileId3);
}
});
it('次タスクを取得できるJobNumber順、先頭', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const { id: authorUserId } = await makeTestUser(source, {
account_id: account.id,
author_id: 'AUTHOR_ID',
external_id: 'author-user-external-id',
role: USER_ROLES.AUTHOR,
});
const { id: typistUserId, external_id: typistExternalId } =
await makeTestUser(source, {
account_id: account.id,
external_id: 'typist-user-external-id',
role: USER_ROLES.TYPIST,
});
await createSortCriteria(source, typistUserId, 'JOB_NUMBER', 'ASC');
const { taskId: taskId1, audioFileId: audioFileId1 } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000001',
TASK_STATUS.UPLOADED,
);
await createCheckoutPermissions(source, taskId1, typistUserId);
const { taskId: taskId3, audioFileId: audioFileId3 } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000003',
TASK_STATUS.UPLOADED,
);
await createCheckoutPermissions(source, taskId3, typistUserId);
const { taskId: taskId2 } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'',
'01',
'00000002',
TASK_STATUS.UPLOADED,
);
await createCheckoutPermissions(source, taskId2, typistUserId);
const service = module.get<TasksService>(TasksService);
const context = makeContext(admin.external_id);
const nextAudioFileId = await service.getNextTask(
context,
typistExternalId,
audioFileId3,
);
// 実行結果が正しいか確認
{
expect(nextAudioFileId).toEqual(audioFileId1);
}
});
it('次タスクを取得できるWorktype順', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const { id: authorUserId } = await makeTestUser(source, {
account_id: account.id,
author_id: 'AUTHOR_ID',
external_id: 'author-user-external-id',
role: USER_ROLES.AUTHOR,
});
const { id: typistUserId, external_id: typistExternalId } =
await makeTestUser(source, {
account_id: account.id,
external_id: 'typist-user-external-id',
role: USER_ROLES.TYPIST,
});
await createSortCriteria(source, typistUserId, 'WORK_TYPE', 'ASC');
const { taskId: taskId1 } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'worktype1',
'01',
'00000001',
TASK_STATUS.UPLOADED,
);
await createCheckoutPermissions(source, taskId1, typistUserId);
const { taskId: taskId3, audioFileId: audioFileId3 } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'worktype2',
'01',
'00000003',
TASK_STATUS.UPLOADED,
);
await createCheckoutPermissions(source, taskId3, typistUserId);
const { taskId: taskId2, audioFileId: audioFileId2 } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'worktype3',
'01',
'00000002',
TASK_STATUS.UPLOADED,
);
await createCheckoutPermissions(source, taskId2, typistUserId);
const service = module.get<TasksService>(TasksService);
const context = makeContext(admin.external_id);
const nextAudioFileId = await service.getNextTask(
context,
typistExternalId,
audioFileId3,
);
// 実行結果が正しいか確認
{
expect(nextAudioFileId).toEqual(audioFileId2);
}
});
it('次タスクを取得できるStatus順', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const { id: authorUserId } = await makeTestUser(source, {
account_id: account.id,
author_id: 'AUTHOR_ID',
external_id: 'author-user-external-id',
role: USER_ROLES.AUTHOR,
});
const { id: typistUserId, external_id: typistExternalId } =
await makeTestUser(source, {
account_id: account.id,
external_id: 'typist-user-external-id',
role: USER_ROLES.TYPIST,
});
await createSortCriteria(source, typistUserId, 'STATUS', 'ASC');
const { taskId: taskId1, audioFileId: audioFileId1 } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'worktype1',
'01',
'00000001',
TASK_STATUS.UPLOADED,
);
await createCheckoutPermissions(source, taskId1, typistUserId);
const { taskId: taskId3 } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'worktype2',
'01',
'00000003',
TASK_STATUS.UPLOADED,
);
await createCheckoutPermissions(source, taskId3, typistUserId);
const { taskId: taskId2, audioFileId: audioFileId2 } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'worktype3',
'01',
'00000002',
TASK_STATUS.PENDING,
);
await createCheckoutPermissions(source, taskId2, typistUserId);
const service = module.get<TasksService>(TasksService);
const context = makeContext(admin.external_id);
const nextAudioFileId = await service.getNextTask(
context,
typistExternalId,
audioFileId2,
);
// 実行結果が正しいか確認
{
expect(nextAudioFileId).toEqual(audioFileId1);
}
});
it('次タスクが存在しない場合undefinedを返すJobNumber順', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const { id: authorUserId } = await makeTestUser(source, {
account_id: account.id,
author_id: 'AUTHOR_ID',
external_id: 'author-user-external-id',
role: USER_ROLES.AUTHOR,
});
const { id: typistUserId, external_id: typistExternalId } =
await makeTestUser(source, {
account_id: account.id,
external_id: 'typist-user-external-id',
role: USER_ROLES.TYPIST,
});
await createSortCriteria(source, typistUserId, 'JOB_NUMBER', 'ASC');
const { taskId: taskId1, audioFileId: audioFileId1 } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'worktype1',
'01',
'00000001',
TASK_STATUS.UPLOADED,
);
await createCheckoutPermissions(source, taskId1, typistUserId);
const service = module.get<TasksService>(TasksService);
const context = makeContext(admin.external_id);
const nextAudioFileId = await service.getNextTask(
context,
typistExternalId,
audioFileId1,
);
// 実行結果が正しいか確認
{
expect(nextAudioFileId).toEqual(undefined);
}
});
it('指定タスクが存在しない場合エラーを返すJobNumber順', async () => {
if (!source) fail();
const module = await makeTestingModule(source);
if (!module) fail();
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const { id: authorUserId } = await makeTestUser(source, {
account_id: account.id,
author_id: 'AUTHOR_ID',
external_id: 'author-user-external-id',
role: USER_ROLES.AUTHOR,
});
const { id: typistUserId, external_id: typistExternalId } =
await makeTestUser(source, {
account_id: account.id,
external_id: 'typist-user-external-id',
role: USER_ROLES.TYPIST,
});
await createSortCriteria(source, typistUserId, 'WORK_TYPE', 'ASC');
const { taskId: taskId1, audioFileId: audioFileId1 } = await createTask(
source,
account.id,
authorUserId,
'MY_AUTHOR_ID',
'worktype1',
'01',
'00000001',
TASK_STATUS.UPLOADED,
);
await createCheckoutPermissions(source, taskId1, typistUserId);
const service = module.get<TasksService>(TasksService);
const context = makeContext(admin.external_id);
// 実行結果が正しいか確認
try {
await service.getNextTask(context, typistExternalId, audioFileId1 + 1);
fail();
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010603'));
} else {
fail();
}
}
});
});