## 概要 [Task2836: 修正②(files,licenses , Repositoiesのlicenses)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2836) - feature - files - licenses - repositories - licenses - users - worktypes - entity - licenses - audio_files - audio_option_item - checkout_permission - アクセストークンをそのままService層に渡している箇所を修正し、必要なパラメータのみ渡すように修正 - クライアントの型生成 - 割り当て可能ライセンス取得APIのIFが変わったため ## レビューポイント - ## UIの変更 - Before/Afterのスクショなど - スクショ置き場 ## 動作確認状況 - ローカルでテストが通ることを確認 ## 補足 - 相談、参考資料などがあれば
1097 lines
32 KiB
TypeScript
1097 lines
32 KiB
TypeScript
import { HttpException, HttpStatus } from '@nestjs/common';
|
||
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
|
||
import {
|
||
makeBlobstorageServiceMockValue,
|
||
makeDefaultTasksRepositoryMockValue,
|
||
makeDefaultUsersRepositoryMockValue,
|
||
makeFilesServiceMock,
|
||
} from './test/files.service.mock';
|
||
import { DataSource } from 'typeorm';
|
||
import { createTask, makeTestingModuleWithBlob } from './test/utility';
|
||
import { FilesService } from './files.service';
|
||
import { makeContext } from '../../common/log';
|
||
import {
|
||
makeTestAccount,
|
||
makeTestSimpleAccount,
|
||
makeTestUser,
|
||
} from '../../common/test/utility';
|
||
import { makeTestingModule } from '../../common/test/modules';
|
||
import { overrideBlobstorageService } from '../../common/test/overrides';
|
||
import {
|
||
createTemplateFile,
|
||
getTemplateFiles,
|
||
} from '../templates/test/utility';
|
||
import { TemplateFilesRepositoryService } from '../../repositories/template_files/template_files.repository.service';
|
||
|
||
describe('音声ファイルアップロードURL取得', () => {
|
||
it('アップロードSASトークンが乗っているURLを返却する', async () => {
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
const userRepoParam = makeDefaultUsersRepositoryMockValue();
|
||
const taskRepoParam = makeDefaultTasksRepositoryMockValue();
|
||
const service = await makeFilesServiceMock(
|
||
blobParam,
|
||
userRepoParam,
|
||
taskRepoParam,
|
||
);
|
||
|
||
expect(
|
||
await service.publishUploadSas(
|
||
makeContext('trackingId'),
|
||
'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
|
||
),
|
||
).toEqual('https://blob-storage?sas-token');
|
||
});
|
||
|
||
it('アカウント専用コンテナが無い場合でも、コンテナ作成しURLを返却する', async () => {
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
const userRepoParam = makeDefaultUsersRepositoryMockValue();
|
||
const taskRepoParam = makeDefaultTasksRepositoryMockValue();
|
||
|
||
blobParam.containerExists = false;
|
||
|
||
const service = await makeFilesServiceMock(
|
||
blobParam,
|
||
userRepoParam,
|
||
taskRepoParam,
|
||
);
|
||
|
||
expect(
|
||
await service.publishUploadSas(
|
||
makeContext('trackingId'),
|
||
'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
|
||
),
|
||
).toEqual('https://blob-storage?sas-token');
|
||
});
|
||
|
||
it('ユーザー情報の取得に失敗した場合、例外エラーを返却する', async () => {
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
const taskRepoParam = makeDefaultTasksRepositoryMockValue();
|
||
|
||
const service = await makeFilesServiceMock(
|
||
blobParam,
|
||
{
|
||
findUserByExternalId: new Error(''),
|
||
},
|
||
taskRepoParam,
|
||
);
|
||
|
||
await expect(
|
||
service.publishUploadSas(
|
||
makeContext('trackingId'),
|
||
'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
|
||
),
|
||
).rejects.toEqual(
|
||
new HttpException(makeErrorResponse('E009999'), HttpStatus.UNAUTHORIZED),
|
||
);
|
||
});
|
||
|
||
it('コンテナ作成に失敗した場合、例外エラーを返却する', async () => {
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
const taskRepoParam = makeDefaultTasksRepositoryMockValue();
|
||
|
||
const service = await makeFilesServiceMock(
|
||
blobParam,
|
||
{
|
||
findUserByExternalId: new Error(''),
|
||
},
|
||
taskRepoParam,
|
||
);
|
||
blobParam.publishUploadSas = new Error('Azure service down');
|
||
|
||
await expect(
|
||
service.publishUploadSas(
|
||
makeContext('trackingId'),
|
||
'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx',
|
||
),
|
||
).rejects.toEqual(
|
||
new HttpException(makeErrorResponse('E009999'), HttpStatus.UNAUTHORIZED),
|
||
);
|
||
});
|
||
});
|
||
|
||
describe('タスク作成', () => {
|
||
it('文字起こしタスクを作成できる', async () => {
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
const userRepoParam = makeDefaultUsersRepositoryMockValue();
|
||
const taskRepoParam = makeDefaultTasksRepositoryMockValue();
|
||
const service = await makeFilesServiceMock(
|
||
blobParam,
|
||
userRepoParam,
|
||
taskRepoParam,
|
||
);
|
||
|
||
expect(
|
||
await service.uploadFinished(
|
||
makeContext('trackingId'),
|
||
'userId',
|
||
'http://blob/url/file.zip',
|
||
'AUTHOR_01',
|
||
'file.zip',
|
||
'11:22:33',
|
||
'2023-05-26T11:22:33.444',
|
||
'2023-05-26T11:22:33.444',
|
||
'2023-05-26T11:22:33.444',
|
||
256,
|
||
'01',
|
||
'DS2',
|
||
'comment',
|
||
'workTypeID',
|
||
optionItemList,
|
||
false,
|
||
),
|
||
).toEqual({ jobNumber: '00000001' });
|
||
});
|
||
|
||
it('日付フォーマットが不正な場合、エラーを返却する', async () => {
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
const userRepoParam = makeDefaultUsersRepositoryMockValue();
|
||
const taskRepoParam = makeDefaultTasksRepositoryMockValue();
|
||
const service = await makeFilesServiceMock(
|
||
blobParam,
|
||
userRepoParam,
|
||
taskRepoParam,
|
||
);
|
||
|
||
await expect(
|
||
service.uploadFinished(
|
||
makeContext('trackingId'),
|
||
'userId',
|
||
'http://blob/url/file.zip',
|
||
'AUTHOR_01',
|
||
'file.zip',
|
||
'11:22:33',
|
||
'yyyy-05-26T11:22:33.444',
|
||
'2023-05-26T11:22:33.444',
|
||
'2023-05-26T11:22:33.444',
|
||
256,
|
||
'01',
|
||
'DS2',
|
||
'comment',
|
||
'workTypeID',
|
||
optionItemList,
|
||
false,
|
||
),
|
||
).rejects.toEqual(
|
||
new HttpException(makeErrorResponse('E010001'), HttpStatus.BAD_REQUEST),
|
||
);
|
||
});
|
||
|
||
it('オプションアイテムが10個ない場合、エラーを返却する', async () => {
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
const userRepoParam = makeDefaultUsersRepositoryMockValue();
|
||
const taskRepoParam = makeDefaultTasksRepositoryMockValue();
|
||
const service = await makeFilesServiceMock(
|
||
blobParam,
|
||
userRepoParam,
|
||
taskRepoParam,
|
||
);
|
||
|
||
await expect(
|
||
service.uploadFinished(
|
||
makeContext('trackingId'),
|
||
'userId',
|
||
'http://blob/url/file.zip',
|
||
'AUTHOR_01',
|
||
'file.zip',
|
||
'11:22:33',
|
||
'2023-05-26T11:22:33.444',
|
||
'2023-05-26T11:22:33.444',
|
||
'2023-05-26T11:22:33.444',
|
||
256,
|
||
'01',
|
||
'DS2',
|
||
'comment',
|
||
'workTypeID',
|
||
[
|
||
{
|
||
optionItemLabel: 'label_01',
|
||
optionItemValue: 'value_01',
|
||
},
|
||
],
|
||
false,
|
||
),
|
||
).rejects.toEqual(
|
||
new HttpException(makeErrorResponse('E010001'), HttpStatus.BAD_REQUEST),
|
||
);
|
||
});
|
||
|
||
it('タスク追加でユーザー情報の取得に失敗した場合、エラーを返却する', async () => {
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
const taskRepoParam = makeDefaultTasksRepositoryMockValue();
|
||
|
||
const service = await makeFilesServiceMock(
|
||
blobParam,
|
||
{
|
||
findUserByExternalId: new Error(''),
|
||
},
|
||
taskRepoParam,
|
||
);
|
||
|
||
await expect(
|
||
service.uploadFinished(
|
||
makeContext('trackingId'),
|
||
'userId',
|
||
'http://blob/url/file.zip',
|
||
'AUTHOR_01',
|
||
'file.zip',
|
||
'11:22:33',
|
||
'2023-05-26T11:22:33.444',
|
||
'2023-05-26T11:22:33.444',
|
||
'2023-05-26T11:22:33.444',
|
||
256,
|
||
'01',
|
||
'DS2',
|
||
'comment',
|
||
'workTypeID',
|
||
optionItemList,
|
||
false,
|
||
),
|
||
).rejects.toEqual(
|
||
new HttpException(
|
||
makeErrorResponse('E009999'),
|
||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||
),
|
||
);
|
||
});
|
||
|
||
it('タスクのDBへの追加に失敗した場合、エラーを返却する', async () => {
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
const userRepoParam = makeDefaultUsersRepositoryMockValue();
|
||
const service = await makeFilesServiceMock(blobParam, userRepoParam, {
|
||
create: new Error(''),
|
||
getTasksFromAccountId: new Error(),
|
||
});
|
||
|
||
await expect(
|
||
service.uploadFinished(
|
||
makeContext('trackingId'),
|
||
'userId',
|
||
'http://blob/url/file.zip',
|
||
'AUTHOR_01',
|
||
'file.zip',
|
||
'11:22:33',
|
||
'2023-05-26T11:22:33.444',
|
||
'2023-05-26T11:22:33.444',
|
||
'2023-05-26T11:22:33.444',
|
||
256,
|
||
'01',
|
||
'DS2',
|
||
'comment',
|
||
'workTypeID',
|
||
optionItemList,
|
||
false,
|
||
),
|
||
).rejects.toEqual(
|
||
new HttpException(
|
||
makeErrorResponse('E009999'),
|
||
HttpStatus.INTERNAL_SERVER_ERROR,
|
||
),
|
||
);
|
||
});
|
||
});
|
||
|
||
describe('音声ファイルダウンロードURL取得', () => {
|
||
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('ダウンロードSASトークンが乗っているURLを取得できる', async () => {
|
||
if (!source) fail();
|
||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||
const {
|
||
external_id: externalId,
|
||
id: userId,
|
||
author_id: authorId,
|
||
} = await makeTestUser(source, {
|
||
account_id: accountId,
|
||
external_id: 'author-user-external-id',
|
||
role: 'author',
|
||
author_id: 'AUTHOR_ID',
|
||
});
|
||
const url = `https://saodmsusdev.blob.core.windows.net/account-${accountId}/${userId}`;
|
||
|
||
const { audioFileId } = await createTask(
|
||
source,
|
||
accountId,
|
||
url,
|
||
'test.zip',
|
||
'InProgress',
|
||
undefined,
|
||
authorId ?? '',
|
||
);
|
||
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
blobParam.publishDownloadSas = `${url}?sas-token`;
|
||
blobParam.fileExists = true;
|
||
|
||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||
if (!module) fail();
|
||
const service = module.get<FilesService>(FilesService);
|
||
|
||
expect(
|
||
await service.publishAudioFileDownloadSas(
|
||
makeContext('trackingId'),
|
||
externalId,
|
||
audioFileId,
|
||
),
|
||
).toEqual(`${url}?sas-token`);
|
||
});
|
||
|
||
it('Typistの場合、タスクのステータスが[Inprogress,Pending]以外でエラー', async () => {
|
||
if (!source) fail();
|
||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||
const { external_id: externalId, id: userId } = 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: 'AUTHOR_ID',
|
||
});
|
||
|
||
const url = `https://saodmsusdev.blob.core.windows.net/account-${accountId}/${authorUserId}`;
|
||
|
||
const { audioFileId } = await createTask(
|
||
source,
|
||
accountId,
|
||
url,
|
||
'test.zip',
|
||
'Finished',
|
||
userId,
|
||
);
|
||
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
blobParam.publishDownloadSas = `${url}?sas-token`;
|
||
blobParam.fileExists = true;
|
||
|
||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||
if (!module) fail();
|
||
const service = module.get<FilesService>(FilesService);
|
||
|
||
await expect(
|
||
service.publishAudioFileDownloadSas(
|
||
makeContext('trackingId'),
|
||
externalId,
|
||
audioFileId,
|
||
),
|
||
).rejects.toEqual(
|
||
new HttpException(makeErrorResponse('E010603'), HttpStatus.BAD_REQUEST),
|
||
);
|
||
});
|
||
|
||
it('Typistの場合、自身が担当するタスクでない場合エラー', async () => {
|
||
if (!source) fail();
|
||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||
const { external_id: externalId } = await makeTestUser(source, {
|
||
account_id: accountId,
|
||
external_id: 'typist-user-external-id',
|
||
role: 'typist',
|
||
});
|
||
const { id: otherId } = await makeTestUser(source, {
|
||
account_id: accountId,
|
||
external_id: 'other-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: 'AUTHOR_ID',
|
||
});
|
||
const url = `https://saodmsusdev.blob.core.windows.net/account-${accountId}/${authorUserId}`;
|
||
|
||
const { audioFileId } = await createTask(
|
||
source,
|
||
accountId,
|
||
url,
|
||
'test.zip',
|
||
'InProgress',
|
||
otherId,
|
||
);
|
||
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
blobParam.publishDownloadSas = `${url}?sas-token`;
|
||
blobParam.fileExists = true;
|
||
|
||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||
if (!module) fail();
|
||
const service = module.get<FilesService>(FilesService);
|
||
|
||
await expect(
|
||
service.publishTemplateFileDownloadSas(
|
||
makeContext('tracking'),
|
||
externalId,
|
||
audioFileId,
|
||
),
|
||
).rejects.toEqual(
|
||
new HttpException(makeErrorResponse('E010603'), HttpStatus.BAD_REQUEST),
|
||
);
|
||
});
|
||
|
||
it('Authorの場合、自身が登録したタスクでない場合エラー', async () => {
|
||
if (!source) fail();
|
||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||
const { external_id: externalId, id: userId } = await makeTestUser(source, {
|
||
account_id: accountId,
|
||
external_id: 'author-user-external-id',
|
||
role: 'author',
|
||
author_id: 'AUTHOR_ID',
|
||
});
|
||
const url = `https://saodmsusdev.blob.core.windows.net/account-${accountId}/${userId}`;
|
||
|
||
const { audioFileId } = await createTask(
|
||
source,
|
||
accountId,
|
||
url,
|
||
'test.zip',
|
||
'InProgress',
|
||
undefined,
|
||
'OTHOR_ID',
|
||
);
|
||
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
blobParam.publishDownloadSas = `${url}?sas-token`;
|
||
blobParam.fileExists = true;
|
||
|
||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||
if (!module) fail();
|
||
const service = module.get<FilesService>(FilesService);
|
||
|
||
await expect(
|
||
service.publishAudioFileDownloadSas(
|
||
makeContext('trackingId'),
|
||
externalId,
|
||
audioFileId,
|
||
),
|
||
).rejects.toEqual(
|
||
new HttpException(makeErrorResponse('E010603'), HttpStatus.BAD_REQUEST),
|
||
);
|
||
});
|
||
|
||
it('Taskが存在しない場合はエラーとなる', async () => {
|
||
if (!source) fail();
|
||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||
const { external_id: externalId } = await makeTestUser(source, {
|
||
account_id: accountId,
|
||
external_id: 'author-user-external-id',
|
||
role: 'author',
|
||
author_id: 'AUTHOR_ID',
|
||
});
|
||
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
|
||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||
if (!module) fail();
|
||
const service = module.get<FilesService>(FilesService);
|
||
|
||
await expect(
|
||
service.publishAudioFileDownloadSas(
|
||
makeContext('trackingId'),
|
||
externalId,
|
||
1,
|
||
),
|
||
).rejects.toEqual(
|
||
new HttpException(makeErrorResponse('E010603'), HttpStatus.BAD_REQUEST),
|
||
);
|
||
});
|
||
|
||
it('blobストレージにファイルが存在しない場合はエラーとなる', async () => {
|
||
if (!source) fail();
|
||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||
const {
|
||
external_id: externalId,
|
||
id: userId,
|
||
author_id: authorId,
|
||
} = await makeTestUser(source, {
|
||
account_id: accountId,
|
||
external_id: 'author-user-external-id',
|
||
role: 'author',
|
||
author_id: 'AUTHOR_ID',
|
||
});
|
||
const url = `https://saodmsusdev.blob.core.windows.net/account-${accountId}/${userId}`;
|
||
|
||
const { audioFileId } = await createTask(
|
||
source,
|
||
accountId,
|
||
url,
|
||
'test.zip',
|
||
'InProgress',
|
||
undefined,
|
||
authorId ?? '',
|
||
);
|
||
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
blobParam.publishDownloadSas = `${url}?sas-token`;
|
||
blobParam.fileExists = false;
|
||
|
||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||
if (!module) fail();
|
||
const service = module.get<FilesService>(FilesService);
|
||
|
||
await expect(
|
||
service.publishAudioFileDownloadSas(
|
||
makeContext('trackingId'),
|
||
externalId,
|
||
audioFileId,
|
||
),
|
||
).rejects.toEqual(
|
||
new HttpException(makeErrorResponse('E010701'), HttpStatus.BAD_REQUEST),
|
||
);
|
||
});
|
||
});
|
||
|
||
describe('テンプレートファイルダウンロードURL取得', () => {
|
||
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('ダウンロードSASトークンが乗っているURLを取得できる', async () => {
|
||
if (!source) fail();
|
||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||
const { external_id: externalId, author_id: authorId } = await makeTestUser(
|
||
source,
|
||
{
|
||
account_id: accountId,
|
||
external_id: 'author-user-external-id',
|
||
role: 'author',
|
||
author_id: 'AUTHOR_ID',
|
||
},
|
||
);
|
||
const url = `https://saodmsusdev.blob.core.windows.net/account-${accountId}/Templates`;
|
||
|
||
const { audioFileId } = await createTask(
|
||
source,
|
||
accountId,
|
||
url,
|
||
'test.zip',
|
||
'InProgress',
|
||
undefined,
|
||
authorId ?? '',
|
||
);
|
||
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
blobParam.publishDownloadSas = `${url}?sas-token`;
|
||
blobParam.fileExists = true;
|
||
|
||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||
if (!module) fail();
|
||
const service = module.get<FilesService>(FilesService);
|
||
|
||
expect(
|
||
await service.publishTemplateFileDownloadSas(
|
||
makeContext('tracking'),
|
||
externalId,
|
||
audioFileId,
|
||
),
|
||
).toEqual(`${url}?sas-token`);
|
||
});
|
||
|
||
it('Typistの場合、タスクのステータスが[Inprogress,Pending]以外でエラー', async () => {
|
||
if (!source) fail();
|
||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||
const { external_id: externalId, id: userId } = await makeTestUser(source, {
|
||
account_id: accountId,
|
||
external_id: 'typist-user-external-id',
|
||
role: 'typist',
|
||
author_id: undefined,
|
||
});
|
||
const url = `https://saodmsusdev.blob.core.windows.net/account-${accountId}/Templates`;
|
||
|
||
const { audioFileId } = await createTask(
|
||
source,
|
||
accountId,
|
||
url,
|
||
'test.zip',
|
||
'Finished',
|
||
userId,
|
||
);
|
||
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
blobParam.publishDownloadSas = `${url}?sas-token`;
|
||
blobParam.fileExists = true;
|
||
|
||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||
if (!module) fail();
|
||
const service = module.get<FilesService>(FilesService);
|
||
|
||
await expect(
|
||
service.publishTemplateFileDownloadSas(
|
||
makeContext('tracking'),
|
||
externalId,
|
||
audioFileId,
|
||
),
|
||
).rejects.toEqual(
|
||
new HttpException(makeErrorResponse('E010603'), HttpStatus.BAD_REQUEST),
|
||
);
|
||
});
|
||
|
||
it('Typistの場合、自身が担当するタスクでない場合エラー', async () => {
|
||
if (!source) fail();
|
||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||
const { external_id: externalId } = await makeTestUser(source, {
|
||
account_id: accountId,
|
||
external_id: 'typist-user-external-id',
|
||
role: 'typist',
|
||
author_id: undefined,
|
||
});
|
||
const { id: otherId } = await makeTestUser(source, {
|
||
account_id: accountId,
|
||
external_id: 'other-typist-user-external-id',
|
||
role: 'typist',
|
||
author_id: undefined,
|
||
});
|
||
const url = `https://saodmsusdev.blob.core.windows.net/account-${accountId}/Templates`;
|
||
|
||
const { audioFileId } = await createTask(
|
||
source,
|
||
accountId,
|
||
url,
|
||
'test.zip',
|
||
'InProgress',
|
||
otherId,
|
||
);
|
||
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
blobParam.publishDownloadSas = `${url}?sas-token`;
|
||
blobParam.fileExists = true;
|
||
|
||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||
if (!module) fail();
|
||
const service = module.get<FilesService>(FilesService);
|
||
|
||
await expect(
|
||
service.publishTemplateFileDownloadSas(
|
||
makeContext('tracking'),
|
||
externalId,
|
||
audioFileId,
|
||
),
|
||
).rejects.toEqual(
|
||
new HttpException(makeErrorResponse('E010603'), HttpStatus.BAD_REQUEST),
|
||
);
|
||
});
|
||
|
||
it('Authorの場合、自身が登録したタスクでない場合エラー', async () => {
|
||
if (!source) fail();
|
||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||
const { external_id: externalId } = await makeTestUser(source, {
|
||
account_id: accountId,
|
||
external_id: 'author-user-external-id',
|
||
role: 'author',
|
||
author_id: 'AUTHOR_ID',
|
||
});
|
||
const url = `https://saodmsusdev.blob.core.windows.net/account-${accountId}/Templates`;
|
||
|
||
const { audioFileId } = await createTask(
|
||
source,
|
||
accountId,
|
||
url,
|
||
'test.zip',
|
||
'InProgress',
|
||
undefined,
|
||
'OTHOR_ID',
|
||
);
|
||
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
blobParam.publishDownloadSas = `${url}?sas-token`;
|
||
blobParam.fileExists = true;
|
||
|
||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||
if (!module) fail();
|
||
const service = module.get<FilesService>(FilesService);
|
||
|
||
await expect(
|
||
service.publishTemplateFileDownloadSas(
|
||
makeContext('tracking'),
|
||
externalId,
|
||
audioFileId,
|
||
),
|
||
).rejects.toEqual(
|
||
new HttpException(makeErrorResponse('E010603'), HttpStatus.BAD_REQUEST),
|
||
);
|
||
});
|
||
|
||
it('Taskが存在しない場合はエラーとなる', async () => {
|
||
if (!source) fail();
|
||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||
const { external_id: externalId } = await makeTestUser(source, {
|
||
account_id: accountId,
|
||
external_id: 'author-user-external-id',
|
||
role: 'author',
|
||
author_id: 'AUTHOR_ID',
|
||
});
|
||
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
|
||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||
if (!module) fail();
|
||
const service = module.get<FilesService>(FilesService);
|
||
|
||
await expect(
|
||
service.publishTemplateFileDownloadSas(
|
||
makeContext('tracking'),
|
||
externalId,
|
||
1,
|
||
),
|
||
).rejects.toEqual(
|
||
new HttpException(makeErrorResponse('E010603'), HttpStatus.BAD_REQUEST),
|
||
);
|
||
});
|
||
|
||
it('blobストレージにファイルが存在しない場合はエラーとなる', async () => {
|
||
if (!source) fail();
|
||
const { id: accountId } = await makeTestSimpleAccount(source);
|
||
const { external_id: externalId, author_id: authorId } = await makeTestUser(
|
||
source,
|
||
{
|
||
account_id: accountId,
|
||
external_id: 'author-user-external-id',
|
||
role: 'author',
|
||
author_id: 'AUTHOR_ID',
|
||
},
|
||
);
|
||
const url = `https://saodmsusdev.blob.core.windows.net/account-${accountId}/Templates`;
|
||
|
||
const { audioFileId } = await createTask(
|
||
source,
|
||
accountId,
|
||
url,
|
||
'test.zip',
|
||
'InProgress',
|
||
undefined,
|
||
authorId ?? '',
|
||
);
|
||
|
||
const blobParam = makeBlobstorageServiceMockValue();
|
||
blobParam.publishDownloadSas = `${url}?sas-token`;
|
||
blobParam.fileExists = false;
|
||
|
||
const module = await makeTestingModuleWithBlob(source, blobParam);
|
||
if (!module) fail();
|
||
const service = module.get<FilesService>(FilesService);
|
||
|
||
await expect(
|
||
service.publishTemplateFileDownloadSas(
|
||
makeContext('tracking'),
|
||
externalId,
|
||
audioFileId,
|
||
),
|
||
).rejects.toEqual(
|
||
new HttpException(makeErrorResponse('E010701'), HttpStatus.BAD_REQUEST),
|
||
);
|
||
});
|
||
});
|
||
|
||
describe('publishTemplateFileUploadSas', () => {
|
||
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('テンプレートファイルアップロードSASトークンが乗っているURLを取得できる', async () => {
|
||
if (!source) fail();
|
||
const module = await makeTestingModule(source);
|
||
if (!module) fail();
|
||
const service = module.get<FilesService>(FilesService);
|
||
// 第五階層のアカウント作成
|
||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||
|
||
const context = makeContext(admin.external_id);
|
||
const baseUrl = `https://saodmsusdev.blob.core.windows.net/account-${account.id}/Templates`;
|
||
|
||
//SASトークンを返却する
|
||
overrideBlobstorageService(service, {
|
||
containerExists: async () => true,
|
||
publishTemplateUploadSas: async () => `${baseUrl}?sas-token`,
|
||
});
|
||
|
||
const url = await service.publishTemplateFileUploadSas(
|
||
context,
|
||
admin.external_id,
|
||
);
|
||
|
||
expect(url).toBe(`${baseUrl}?sas-token`);
|
||
});
|
||
|
||
it('blobストレージにコンテナが存在しない場合はエラーとなる', async () => {
|
||
if (!source) fail();
|
||
const module = await makeTestingModule(source);
|
||
if (!module) fail();
|
||
const service = module.get<FilesService>(FilesService);
|
||
// 第五階層のアカウント作成
|
||
const { admin } = await makeTestAccount(source, { tier: 5 });
|
||
|
||
const context = makeContext(admin.external_id);
|
||
|
||
//Blobコンテナ存在チェックに失敗するようにする
|
||
overrideBlobstorageService(service, {
|
||
containerExists: async () => false,
|
||
publishTemplateUploadSas: async () => '',
|
||
});
|
||
|
||
try {
|
||
await service.publishTemplateFileUploadSas(context, admin.external_id);
|
||
} catch (e) {
|
||
if (e instanceof HttpException) {
|
||
expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
|
||
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
|
||
} else {
|
||
fail();
|
||
}
|
||
}
|
||
});
|
||
|
||
it('SASトークンの取得に失敗した場合はエラーとなる', async () => {
|
||
if (!source) fail();
|
||
const module = await makeTestingModule(source);
|
||
if (!module) fail();
|
||
const service = module.get<FilesService>(FilesService);
|
||
// 第五階層のアカウント作成
|
||
const { admin } = await makeTestAccount(source, { tier: 5 });
|
||
|
||
const context = makeContext(admin.external_id);
|
||
|
||
//BlobのSASトークン生成に失敗するようにする
|
||
overrideBlobstorageService(service, {
|
||
containerExists: async () => true,
|
||
publishTemplateUploadSas: async () => {
|
||
throw new Error('blob failed');
|
||
},
|
||
});
|
||
|
||
try {
|
||
await service.publishTemplateFileUploadSas(context, admin.external_id);
|
||
} catch (e) {
|
||
if (e instanceof HttpException) {
|
||
expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
|
||
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
|
||
} else {
|
||
fail();
|
||
}
|
||
}
|
||
});
|
||
});
|
||
|
||
describe('templateUploadFinished', () => {
|
||
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('アップロード完了後のテンプレートファイル情報をDBに保存できる(新規追加)', async () => {
|
||
if (!source) fail();
|
||
const module = await makeTestingModule(source);
|
||
if (!module) fail();
|
||
const service = module.get<FilesService>(FilesService);
|
||
// 第五階層のアカウント作成
|
||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||
const context = makeContext(admin.external_id);
|
||
|
||
const fileName = 'test.docs';
|
||
const url = `https://blob.url/account-${account.id}/Templates`;
|
||
|
||
// 事前にDBを確認
|
||
{
|
||
const templates = await getTemplateFiles(source, account.id);
|
||
expect(templates.length).toBe(0);
|
||
}
|
||
|
||
await service.templateUploadFinished(
|
||
context,
|
||
admin.external_id,
|
||
url,
|
||
fileName,
|
||
);
|
||
|
||
//実行結果を確認
|
||
{
|
||
const templates = await getTemplateFiles(source, account.id);
|
||
expect(templates.length).toBe(1);
|
||
expect(templates[0].file_name).toBe(fileName);
|
||
expect(templates[0].url).toBe(url);
|
||
}
|
||
});
|
||
|
||
it('アップロード完了後のテンプレートファイル情報をDBに保存できる(更新)', async () => {
|
||
if (!source) fail();
|
||
const module = await makeTestingModule(source);
|
||
if (!module) fail();
|
||
const service = module.get<FilesService>(FilesService);
|
||
// 第五階層のアカウント作成
|
||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||
const context = makeContext(admin.external_id);
|
||
|
||
const fileName = 'test.docs';
|
||
const url = `https://blob.url/account-${account.id}/Templates`;
|
||
|
||
await createTemplateFile(source, account.id, fileName, url);
|
||
|
||
// 事前にDBを確認
|
||
{
|
||
const templates = await getTemplateFiles(source, account.id);
|
||
expect(templates.length).toBe(1);
|
||
expect(templates[0].file_name).toBe(fileName);
|
||
expect(templates[0].url).toBe(url);
|
||
}
|
||
|
||
const updateUrl = `https://blob.update.url/account-${account.id}/Templates`;
|
||
|
||
await service.templateUploadFinished(
|
||
context,
|
||
admin.external_id,
|
||
updateUrl,
|
||
fileName,
|
||
);
|
||
|
||
//実行結果を確認
|
||
{
|
||
const templates = await getTemplateFiles(source, account.id);
|
||
expect(templates.length).toBe(1);
|
||
expect(templates[0].file_name).toBe(fileName);
|
||
expect(templates[0].url).toBe(updateUrl);
|
||
}
|
||
});
|
||
|
||
it('DBへの保存に失敗した場合はエラーとなる', async () => {
|
||
if (!source) fail();
|
||
const module = await makeTestingModule(source);
|
||
if (!module) fail();
|
||
const service = module.get<FilesService>(FilesService);
|
||
// 第五階層のアカウント作成
|
||
const { account, admin } = await makeTestAccount(source, { tier: 5 });
|
||
const context = makeContext(admin.external_id);
|
||
|
||
const fileName = 'test.docs';
|
||
const url = `https://blob.url/account-${account.id}/Templates`;
|
||
|
||
// 事前にDBを確認
|
||
{
|
||
const templates = await getTemplateFiles(source, account.id);
|
||
expect(templates.length).toBe(0);
|
||
}
|
||
|
||
//DBアクセスに失敗するようにする
|
||
const templatesService = module.get<TemplateFilesRepositoryService>(
|
||
TemplateFilesRepositoryService,
|
||
);
|
||
templatesService.upsertTemplateFile = jest
|
||
.fn()
|
||
.mockRejectedValue('DB failed');
|
||
|
||
try {
|
||
await service.templateUploadFinished(
|
||
context,
|
||
admin.external_id,
|
||
url,
|
||
fileName,
|
||
);
|
||
} catch (e) {
|
||
if (e instanceof HttpException) {
|
||
expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
|
||
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
|
||
} else {
|
||
fail();
|
||
}
|
||
}
|
||
});
|
||
});
|
||
|
||
const optionItemList = [
|
||
{
|
||
optionItemLabel: 'label_01',
|
||
optionItemValue: 'value_01',
|
||
},
|
||
{
|
||
optionItemLabel: 'label_02',
|
||
optionItemValue: 'value_02',
|
||
},
|
||
{
|
||
optionItemLabel: 'label_03',
|
||
optionItemValue: 'value_03',
|
||
},
|
||
{
|
||
optionItemLabel: 'label_04',
|
||
optionItemValue: 'value_04',
|
||
},
|
||
{
|
||
optionItemLabel: 'label_05',
|
||
optionItemValue: 'value_05',
|
||
},
|
||
{
|
||
optionItemLabel: 'label_06',
|
||
optionItemValue: 'value_06',
|
||
},
|
||
{
|
||
optionItemLabel: 'label_07',
|
||
optionItemValue: 'value_07',
|
||
},
|
||
{
|
||
optionItemLabel: 'label_08',
|
||
optionItemValue: 'value_08',
|
||
},
|
||
{
|
||
optionItemLabel: 'label_09',
|
||
optionItemValue: 'value_09',
|
||
},
|
||
{
|
||
optionItemLabel: 'label_10',
|
||
optionItemValue: 'value_10',
|
||
},
|
||
];
|