OMDSCloud/dictation_server/src/features/accounts/accounts.service.spec.ts
oura.a aef6a35a7d Merged PR 466: [PBI1220残]退避テーブル対応(月の途中で退会したアカウントの集計対応)
## 概要
[Task2767: [PBI1220残]退避テーブル対応(月の途中で退会したアカウントの集計対応)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2767)

アカウント削除時に以下のテーブルの削除対象データを退避する処理を追加しました。
・ライセンステーブル
・ライセンス割り当て履歴テーブル

## レビューポイント
なし

## UIの変更
なし

## 動作確認状況
UT,ローカル動作確認を実施済み

## 補足
なし
2023-10-06 06:04:11 +00:00

5579 lines
175 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 { HttpException, HttpStatus } from '@nestjs/common';
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
import {
makeAccountsServiceMock,
makeBlobStorageServiceMockValue,
makeDefaultAccountsRepositoryMockValue,
makeDefaultAdB2cMockValue,
makeDefaultLicensesRepositoryMockValue,
makeDefaultSendGridlValue,
makeDefaultUserGroupsRepositoryMockValue,
makeDefaultUsersRepositoryMockValue,
makeDefaultWorktypesRepositoryMockValue,
} from './test/accounts.service.mock';
import { makeDefaultConfigValue } from '../users/test/users.service.mock';
import {
createLicense,
createLicenseOrder,
createLicenseSetExpiryDateAndStatus,
createOptionItems,
createWorktype,
getOptionItems,
getSortCriteria,
getTypistGroup,
getTypistGroupMember,
getWorktypes,
} from './test/utility';
import { DataSource } from 'typeorm';
import { makeTestingModule } from '../../common/test/modules';
import {
makeTestAccount,
getAccount,
getAccounts,
getUserFromExternalId,
getUsers,
makeTestUser,
makeHierarchicalAccounts,
getUser,
getUserArchive,
} from '../../common/test/utility';
import { AccountsService } from './accounts.service';
import { Context, makeContext } from '../../common/log';
import {
ADB2C_SIGN_IN_TYPE,
LICENSE_ALLOCATED_STATUS,
LICENSE_ISSUE_STATUS,
LICENSE_TYPE,
OPTION_ITEM_VALUE_TYPE,
TIERS,
USER_ROLES,
WORKTYPE_MAX_COUNT,
} from '../../constants';
import { License } from '../../repositories/licenses/entity/license.entity';
import {
overrideAccountsRepositoryService,
overrideAdB2cService,
overrideBlobstorageService,
overrideSendgridService,
} from '../../common/test/overrides';
import { AdB2cService } from '../../gateways/adb2c/adb2c.service';
import { BlobstorageService } from '../../gateways/blobstorage/blobstorage.service';
import { UserGroupsRepositoryService } from '../../repositories/user_groups/user_groups.repository.service';
import {
createLicenseAllocationHistory,
createOrder,
getLicenseArchive,
getLicenseAllocationHistoryArchive,
selectLicense,
selectOrderLicense,
} from '../licenses/test/utility';
import { WorktypesRepositoryService } from '../../repositories/worktypes/worktypes.repository.service';
import { AdB2cUser } from '../../gateways/adb2c/types/types';
import { Worktype } from '../../repositories/worktypes/entity/worktype.entity';
import { AccountsRepositoryService } from '../../repositories/accounts/accounts.repository.service';
import { UsersRepositoryService } from '../../repositories/users/users.repository.service';
describe('createAccount', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('アカウントを作成できる', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const externalId = 'test_external_id';
const companyName = 'test_company_name';
const country = 'US';
const dealerAccountId = 1;
const email = 'dummy@example.com';
const password = 'dummy_password';
const username = 'dummy_username';
const role = 'none';
const acceptedTermsVersion = '1.0.0';
overrideAdB2cService(service, {
createUser: async () => {
return { sub: externalId };
},
});
overrideSendgridService(service, {
sendMail: async () => {
return;
},
createMailContentFromEmailConfirm: async () => {
return { html: '', text: '', subject: '' };
},
});
overrideBlobstorageService(service, {
createContainer: async () => {
return;
},
});
const { accountId, externalUserId, userId } = await service.createAccount(
makeContext('uuid'),
companyName,
country,
dealerAccountId,
email,
password,
username,
role,
acceptedTermsVersion,
);
// 作成したアカウントのIDが返ってくるか確認
expect(accountId).toBe(1);
expect(externalUserId).toBe(externalId);
expect(userId).toBe(1);
// DB内が想定通りになっているか確認
const account = await getAccount(source, accountId);
const user = await getUserFromExternalId(source, externalUserId);
expect(account.company_name).toBe(companyName);
expect(account.country).toBe(country);
expect(account.parent_account_id).toBe(dealerAccountId);
expect(account.tier).toBe(TIERS.TIER5);
expect(account.primary_admin_user_id).toBe(user.id);
expect(account.secondary_admin_user_id).toBe(null);
expect(user.accepted_terms_version).toBe(acceptedTermsVersion);
expect(user.account_id).toBe(accountId);
expect(user.role).toBe(role);
});
it('アカウントを作成がAzure AD B2Cへの通信失敗によって失敗すると500エラーが発生する', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
overrideAdB2cService(service, {
createUser: async () => {
throw new Error();
},
});
overrideSendgridService(service, {
sendMail: async () => {
return;
},
createMailContentFromEmailConfirm: async () => {
return { html: '', text: '', subject: '' };
},
});
const companyName = 'test_company_name';
const country = 'US';
const dealerAccountId = 1;
const email = 'dummy@example.com';
const password = 'dummy_password';
const username = 'dummy_username';
const role = 'admin none';
const acceptedTermsVersion = '1.0.0';
overrideAdB2cService(service, {
createUser: async () => {
throw new Error();
},
});
overrideSendgridService(service, {});
overrideBlobstorageService(service, {});
try {
await service.createAccount(
makeContext('uuid'),
companyName,
country,
dealerAccountId,
email,
password,
username,
role,
acceptedTermsVersion,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
// DB内が想定通りになっているか確認
const accounts = await getAccounts(source);
expect(accounts.length).toBe(0);
const users = await getUsers(source);
expect(users.length).toBe(0);
});
it('アカウントを作成がメールアドレス重複によって失敗すると400エラーが発生する', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
overrideAdB2cService(service, {
createUser: async () => {
// EmailのConflictエラーを返す
return { reason: 'email', message: 'dummy' };
},
});
overrideSendgridService(service, {
sendMail: async () => {
return;
},
createMailContentFromEmailConfirm: async () => {
return { html: '', text: '', subject: '' };
},
});
const companyName = 'test_company_name';
const country = 'US';
const dealerAccountId = 1;
const email = 'dummy@example.com';
const password = 'dummy_password';
const username = 'dummy_username';
const role = 'admin none';
const acceptedTermsVersion = '1.0.0';
overrideAdB2cService(service, {
createUser: async () => {
// EmailのConflictエラーを返す
return { reason: 'email', message: 'dummy' };
},
});
overrideSendgridService(service, {});
overrideBlobstorageService(service, {});
try {
await service.createAccount(
makeContext('uuid'),
companyName,
country,
dealerAccountId,
email,
password,
username,
role,
acceptedTermsVersion,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010301'));
} else {
fail();
}
}
// DB内が想定通りになっているか確認
const accounts = await getAccounts(source);
expect(accounts.length).toBe(0);
const users = await getUsers(source);
expect(users.length).toBe(0);
});
it('アカウントを作成がDBへの通信失敗によって500エラーが発生した場合、リカバリ処理としてADB2Cユーザーを削除され、500エラーが返却される', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const b2cService = module.get<AdB2cService>(AdB2cService);
const externalId = 'test_external_id';
const companyName = 'test_company_name';
const country = 'US';
const dealerAccountId = 1;
const email = 'dummy@example.com';
const password = 'dummy_password';
const username = 'dummy_username';
const role = 'none';
const acceptedTermsVersion = '1.0.0';
overrideAdB2cService(service, {
createUser: async () => {
return { sub: externalId };
},
deleteUser: jest.fn(),
});
overrideSendgridService(service, {});
overrideAccountsRepositoryService(service, {
createAccount: async () => {
throw new Error();
},
});
try {
await service.createAccount(
makeContext('uuid'),
companyName,
country,
dealerAccountId,
email,
password,
username,
role,
acceptedTermsVersion,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
// DB内が想定通りになっているか確認
// DBのデータ作成で失敗しているので、DB内は空
const accounts = await getAccounts(source);
expect(accounts.length).toBe(0);
const users = await getUsers(source);
expect(users.length).toBe(0);
const sortCriteria = await getSortCriteria(source);
expect(sortCriteria.length).toBe(0);
// ADB2Cユーザー削除メソッドが呼ばれているか確認
expect(b2cService.deleteUser).toBeCalledWith(
externalId,
makeContext('uuid'),
);
});
it('アカウントを作成がDBへの通信失敗によって500エラーが発生した場合、リカバリ処理が実行されるが、ADB2Cユーザー削除で失敗した場合、500エラーが返却される', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const b2cService = module.get<AdB2cService>(AdB2cService);
const externalId = 'test_external_id';
const companyName = 'test_company_name';
const country = 'US';
const dealerAccountId = 1;
const email = 'dummy@dummy.dummy';
const password = 'dummy_password';
const username = 'dummy_username';
const role = 'none';
const acceptedTermsVersion = '1.0.0';
overrideAdB2cService(service, {
createUser: async () => {
return { sub: externalId };
},
deleteUser: jest.fn().mockRejectedValue(new Error()),
});
overrideSendgridService(service, {});
overrideAccountsRepositoryService(service, {
createAccount: async () => {
throw new Error();
},
});
try {
await service.createAccount(
makeContext('uuid'),
companyName,
country,
dealerAccountId,
email,
password,
username,
role,
acceptedTermsVersion,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
// DB内が想定通りになっているか確認
// DBのデータ作成で失敗しているので、DB内は空
const accounts = await getAccounts(source);
expect(accounts.length).toBe(0);
const users = await getUsers(source);
expect(users.length).toBe(0);
const sortCriteria = await getSortCriteria(source);
expect(sortCriteria.length).toBe(0);
// ADB2Cユーザー削除メソッドが呼ばれているか確認
expect(b2cService.deleteUser).toBeCalledWith(
externalId,
makeContext('uuid'),
);
});
it('アカウントを作成がBlobStorageへの通信失敗によって500エラーが発生した場合、リカバリ処理としてADB2C,DB上のデータが削除され、500エラーが返却される', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const b2cService = module.get<AdB2cService>(AdB2cService);
b2cService.deleteUser = jest.fn(); // リカバリ処理の確認のため、deleteUserをモック化
const externalId = 'test_external_id';
const companyName = 'test_company_name';
const country = 'US';
const dealerAccountId = 1;
const email = 'dummy@dummy.dummy';
const password = 'dummy_password';
const username = 'dummy_username';
const role = 'none';
const acceptedTermsVersion = '1.0.0';
overrideAdB2cService(service, {
createUser: async () => {
return { sub: externalId };
},
deleteUser: async () => {
return;
},
});
overrideSendgridService(service, {});
overrideBlobstorageService(service, {
createContainer: async () => {
throw new Error();
},
});
try {
await service.createAccount(
makeContext('uuid'),
companyName,
country,
dealerAccountId,
email,
password,
username,
role,
acceptedTermsVersion,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
// DB内が想定通りになっているか確認
// リカバリ処理が走っているため、アカウント・ユーザーは削除されている
const accounts = await getAccounts(source);
expect(accounts.length).toBe(0);
const users = await getUsers(source);
expect(users.length).toBe(0);
const sortCriteria = await getSortCriteria(source);
expect(sortCriteria.length).toBe(0);
// ADB2Cユーザー削除メソッドが呼ばれているか確認
expect(b2cService.deleteUser).toBeCalledWith(
externalId,
makeContext('uuid'),
);
});
it('アカウントを作成がBlobStorageへの通信失敗によって500エラーが発生した場合、リカバリ処理が実行されるが、そのリカバリ処理に失敗した場合、500エラーが返却される', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const b2cService = module.get<AdB2cService>(AdB2cService);
const externalId = 'test_external_id';
const companyName = 'test_company_name';
const country = 'US';
const dealerAccountId = 1;
const email = 'dummy@dummy.dummy';
const password = 'dummy_password';
const username = 'dummy_username';
const role = 'none';
const acceptedTermsVersion = '1.0.0';
overrideAdB2cService(service, {
createUser: async () => {
return { sub: externalId };
},
deleteUser: jest.fn().mockRejectedValue(new Error()),
});
overrideSendgridService(service, {});
overrideBlobstorageService(service, {
createContainer: async () => {
throw new Error();
},
});
overrideAccountsRepositoryService(service, {
deleteAccount: async () => {
throw new Error();
},
});
try {
await service.createAccount(
makeContext('uuid'),
companyName,
country,
dealerAccountId,
email,
password,
username,
role,
acceptedTermsVersion,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
// DB内が想定通りになっているか確認
// DB上のデータのリカバリ処理に失敗したため、DB上のデータは削除されない
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
const users = await getUsers(source);
expect(users.length).toBe(1);
const sortCriteria = await getSortCriteria(source);
expect(sortCriteria.length).toBe(1);
// ADB2Cユーザー削除メソッドが呼ばれているか確認
expect(b2cService.deleteUser).toBeCalledWith(
externalId,
makeContext('uuid'),
);
});
it('アカウントを作成がSendGridへの通信失敗によって500エラーが発生した場合、リカバリ処理としてADB2C,DB上のデータとBlobストレージのコンテナが削除され、500エラーが返却される', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const b2cService = module.get<AdB2cService>(AdB2cService);
const blobstorageService =
module.get<BlobstorageService>(BlobstorageService);
const externalId = 'test_external_id';
const companyName = 'test_company_name';
const country = 'US';
const dealerAccountId = 1;
const email = 'dummy@dummy.dummy';
const password = 'dummy_password';
const username = 'dummy_username';
const role = 'none';
const acceptedTermsVersion = '1.0.0';
overrideAdB2cService(service, {
createUser: async (
_context: Context,
_email: string,
_password: string,
_username: string,
) => {
// ユーザー作成時に指定したパラメータが正しく渡されていることを確認
expect(email).toEqual(_email);
expect(username).toEqual(_username);
return { sub: externalId };
},
deleteUser: jest.fn(),
});
overrideSendgridService(service, {
sendMail: async () => {
throw new Error();
},
createMailContentFromEmailConfirm: async () => {
return {
html: 'dummy_html',
subject: 'dummy_subject',
text: 'dummy_text',
};
},
});
overrideBlobstorageService(service, {
createContainer: async () => {
return;
},
deleteContainer: jest.fn(),
});
overrideAccountsRepositoryService(service, {});
try {
await service.createAccount(
makeContext('uuid'),
companyName,
country,
dealerAccountId,
email,
password,
username,
role,
acceptedTermsVersion,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
// DB内が想定通りになっているか確認
// リカバリ処理によってADB2C,DB上のデータとBlobストレージのコンテナが削除される
const accounts = await getAccounts(source);
expect(accounts.length).toBe(0);
const users = await getUsers(source);
expect(users.length).toBe(0);
const sortCriteria = await getSortCriteria(source);
expect(sortCriteria.length).toBe(0);
// ADB2Cユーザー削除メソッドが呼ばれているか確認
expect(b2cService.deleteUser).toBeCalledWith(
externalId,
makeContext('uuid'),
);
// Blobストレージのコンテナ削除メソッドが呼ばれているか確認
expect(blobstorageService.deleteContainer).toBeCalledWith(
makeContext('uuid'),
1, //新規作成したアカウントのID
country,
);
});
it('アカウントを作成がSendGridへの通信失敗によって500エラーが発生した場合、リカバリ処理が実行されるが、そのリカバリ処理に失敗した場合、500エラーが返却される', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const b2cService = module.get<AdB2cService>(AdB2cService);
const blobstorageService =
module.get<BlobstorageService>(BlobstorageService);
const externalId = 'test_external_id';
const companyName = 'test_company_name';
const country = 'US';
const dealerAccountId = 1;
const email = 'dummy@dummy.dummy';
const password = 'dummy_password';
const username = 'dummy_username';
const role = 'none';
const acceptedTermsVersion = '1.0.0';
overrideAdB2cService(service, {
createUser: async () => {
return { sub: externalId };
},
deleteUser: jest.fn().mockRejectedValue(new Error()),
});
overrideSendgridService(service, {
sendMail: async () => {
throw new Error();
},
createMailContentFromEmailConfirm: async () => {
return {
html: 'dummy_html',
subject: 'dummy_subject',
text: 'dummy_text',
};
},
});
overrideBlobstorageService(service, {
createContainer: async () => {
return;
},
deleteContainer: jest
.fn()
.mockRejectedValue(new Error('BlobStorage Error')),
});
overrideAccountsRepositoryService(service, {
deleteAccount: async () => {
throw new Error();
},
});
try {
await service.createAccount(
makeContext('uuid'),
companyName,
country,
dealerAccountId,
email,
password,
username,
role,
acceptedTermsVersion,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
// DB内が想定通りになっているか確認
// リカバリ処理によってADB2C,DB上のデータとBlobストレージのコンテナが削除されない
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
const users = await getUsers(source);
expect(users.length).toBe(1);
const sortCriteria = await getSortCriteria(source);
expect(sortCriteria.length).toBe(1);
// ADB2Cユーザー削除メソッドが呼ばれているか確認
expect(b2cService.deleteUser).toBeCalledWith(
externalId,
makeContext('uuid'),
);
// Blobストレージのコンテナ削除メソッドが呼ばれているか確認
expect(blobstorageService.deleteContainer).toBeCalledWith(
makeContext('uuid'),
1, //新規作成したアカウントのID
country,
);
});
});
describe('createPartnerAccount', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('パートナーを追加できる', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const adminExternalId = 'ADMIN0001';
// 第一階層のアカウントを作成
const { account: parent } = await makeTestAccount(
source,
{ tier: 1 },
{ external_id: adminExternalId },
);
const context = makeContext('uuid');
const companyName = 'test_company_name';
const country = 'US';
const email = 'partner@example.com';
const adminName = 'partner_admin';
const pertnerExternalId = 'PARTNER0001';
overrideAdB2cService(service, {
createUser: async () => {
return { sub: pertnerExternalId };
},
});
overrideSendgridService(service, {
createMailContentFromEmailConfirmForNormalUser: async () => {
return { html: '', text: '', subject: '' };
},
sendMail: async () => {
return;
},
});
overrideBlobstorageService(service, {
createContainer: async () => {
return;
},
});
// DB上に用意されたデータが想定通りであるか確認
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
}
const { accountId } = await service.createPartnerAccount(
context,
companyName,
country,
email,
adminName,
adminExternalId,
parent.tier,
);
// DB上に作成されたデータが想定通りであるか確認
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(2);
const createdUser = await getUserFromExternalId(
source,
pertnerExternalId,
);
const createdAccount = await getAccount(source, accountId);
expect(createdAccount.company_name).toBe(companyName);
expect(createdAccount.country).toBe(country);
expect(createdAccount.parent_account_id).toBe(parent.id);
expect(createdAccount.tier).toBe(2);
expect(createdAccount.primary_admin_user_id).toBe(createdUser.id);
expect(createdAccount.secondary_admin_user_id).toBe(null);
}
});
it('Azure AD B2Cへの接続に失敗した結果アカウントの追加に失敗した場合、エラーとなる(500エラー)', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const adminExternalId = 'ADMIN0001';
// 第一階層のアカウントを作成
const { account: parent } = await makeTestAccount(
source,
{ tier: 1 },
{ external_id: adminExternalId },
);
const context = makeContext('uuid');
const companyName = 'test_company_name';
const country = 'US';
const email = 'partner@example.com';
const adminName = 'partner_admin';
overrideAdB2cService(service, {
createUser: async () => {
throw new Error();
},
});
overrideSendgridService(service, {
createMailContentFromEmailConfirmForNormalUser: async () => {
return { html: '', text: '', subject: '' };
},
sendMail: async () => {
return;
},
});
overrideBlobstorageService(service, {
createContainer: async () => {
return;
},
});
// DB上に用意されたデータが想定通りであるか確認
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
const users = await getUsers(source);
expect(users.length).toBe(1);
}
try {
await service.createPartnerAccount(
context,
companyName,
country,
email,
adminName,
adminExternalId,
parent.tier,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
// DB上に作成されたデータが想定通りであるか確認
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
const users = await getUsers(source);
expect(users.length).toBe(1);
}
});
it('DBへの通信失敗によって500エラーが発生した場合、リカバリ処理としてADB2Cユーザーを削除され、500エラーが返却される', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const b2cService = module.get<AdB2cService>(AdB2cService);
const adminExternalId = 'ADMIN0001';
// 第一階層のアカウントを作成
const { account: parent } = await makeTestAccount(
source,
{ tier: 1 },
{ external_id: adminExternalId },
);
const context = makeContext('uuid');
const companyName = 'test_company_name';
const country = 'US';
const email = 'partner@example.com';
const adminName = 'partner_admin';
const partnerExternalId = 'partner_external_id';
overrideAdB2cService(service, {
createUser: async () => {
return { sub: partnerExternalId };
},
deleteUser: jest.fn(),
});
overrideSendgridService(service, {
createMailContentFromEmailConfirmForNormalUser: async () => {
return { html: '', text: '', subject: '' };
},
sendMail: async () => {
return;
},
});
overrideAccountsRepositoryService(service, {
createAccount: async () => {
throw new Error('DB Error');
},
});
overrideBlobstorageService(service, {
createContainer: async () => {
return;
},
});
// DB上に用意されたデータが想定通りであるか確認
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
const users = await getUsers(source);
expect(users.length).toBe(1);
}
try {
await service.createPartnerAccount(
context,
companyName,
country,
email,
adminName,
adminExternalId,
parent.tier,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
// DB上に作成されたデータが想定通りであるか確認
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
expect(accounts[0].tier).toBe(1);
const users = await getUsers(source);
expect(users.length).toBe(1);
expect(users[0].external_id).toBe(adminExternalId);
// ADB2Cユーザー削除メソッドが呼ばれているか確認
expect(b2cService.deleteUser).toBeCalledWith(partnerExternalId, context);
}
});
it('DBへの通信失敗によって500エラーが発生した場合、リカバリ処理が実行されるが、ADB2Cユーザー削除で失敗した場合、500エラーが返却される', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const b2cService = module.get<AdB2cService>(AdB2cService);
const adminExternalId = 'ADMIN0001';
// 第一階層のアカウントを作成
const { account: parent } = await makeTestAccount(
source,
{ tier: 1 },
{ external_id: adminExternalId },
);
const context = makeContext('uuid');
const companyName = 'test_company_name';
const country = 'US';
const email = 'partner@example.com';
const adminName = 'partner_admin';
const partnerExternalId = 'partner_external_id';
overrideAdB2cService(service, {
createUser: async () => {
return { sub: partnerExternalId };
},
deleteUser: jest.fn().mockRejectedValue(new Error('ADB2C Error')),
});
overrideSendgridService(service, {
createMailContentFromEmailConfirmForNormalUser: async () => {
return { html: '', text: '', subject: '' };
},
sendMail: async () => {
return;
},
});
overrideAccountsRepositoryService(service, {
createAccount: async () => {
throw new Error('DB Error');
},
});
overrideBlobstorageService(service, {
createContainer: async () => {
return;
},
});
// DB上に用意されたデータが想定通りであるか確認
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
const users = await getUsers(source);
expect(users.length).toBe(1);
}
try {
await service.createPartnerAccount(
context,
companyName,
country,
email,
adminName,
adminExternalId,
parent.tier,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
// DB上に作成されたデータが想定通りであるか確認
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
expect(accounts[0].tier).toBe(1);
const users = await getUsers(source);
expect(users.length).toBe(1);
expect(users[0].external_id).toBe(adminExternalId);
// ADB2Cユーザー削除メソッドが呼ばれているか確認
expect(b2cService.deleteUser).toBeCalledWith(partnerExternalId, context);
}
});
it('BlobStorageへの通信失敗が原因でアカウントの追加に失敗した場合、リカバリ処理としてADB2C,DB上のデータが削除され、500エラーが返却される', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const b2cService = module.get<AdB2cService>(AdB2cService);
const parentExternalId = 'parent_external_id';
// 第一階層のアカウントを作成
const { account: parent } = await makeTestAccount(
source,
{ tier: 1 },
{ external_id: parentExternalId },
);
const context = makeContext(parentExternalId);
const partnerExternalId = 'partner_external_id';
const companyName = 'partner_company_name';
const country = 'US';
const email = 'partner@example.com';
const username = 'partner_username';
overrideAdB2cService(service, {
createUser: async () => {
return { sub: partnerExternalId };
},
deleteUser: jest.fn(),
});
overrideSendgridService(service, {
sendMail: async () => {
return;
},
createMailContentFromEmailConfirmForNormalUser: async () => {
return { html: '', text: '', subject: '' };
},
});
overrideBlobstorageService(service, {
createContainer: async () => {
throw new Error();
},
});
// DB上に用意されたデータが想定通りであるか確認
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
}
try {
await service.createPartnerAccount(
context,
companyName,
country,
email,
username,
parentExternalId,
TIERS.TIER1,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
expect(accounts[0].tier).toBe(parent.tier);
const users = await getUsers(source);
expect(users.length).toBe(1);
expect(users[0].external_id).toBe(parentExternalId);
// ADB2Cユーザー削除メソッドが呼ばれているか確認
expect(b2cService.deleteUser).toBeCalledWith(partnerExternalId, context);
}
});
it('BlobStorageへの通信失敗が原因でアカウントの追加に失敗した場合、リカバリ処理が実行されるが、そのリカバリ処理に失敗した場合、500エラーが返却される', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const b2cService = module.get<AdB2cService>(AdB2cService);
const parentExternalId = 'parent_external_id';
// 第一階層のアカウントを作成
const { account: parent } = await makeTestAccount(
source,
{ tier: 1 },
{ external_id: parentExternalId },
);
const context = makeContext(parentExternalId);
const partnerExternalId = 'partner_external_id';
const companyName = 'partner_company_name';
const country = 'US';
const email = 'partner@example.com';
const username = 'partner_username';
overrideAdB2cService(service, {
createUser: async () => {
return { sub: partnerExternalId };
},
deleteUser: jest.fn().mockRejectedValue(new Error('ADB2C Error')),
});
overrideSendgridService(service, {
sendMail: async () => {
return;
},
createMailContentFromEmailConfirmForNormalUser: async () => {
return { html: '', text: '', subject: '' };
},
});
overrideAccountsRepositoryService(service, {
deleteAccount: jest.fn().mockRejectedValue(new Error('DB Error')),
});
overrideBlobstorageService(service, {
createContainer: async () => {
throw new Error();
},
});
// DB上に用意されたデータが想定通りであるか確認
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
}
try {
await service.createPartnerAccount(
context,
companyName,
country,
email,
username,
parentExternalId,
TIERS.TIER1,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
{
// DB上に作成されたデータが想定通りであるか確認
// リカバリ処理が失敗した場合、DB上のデータは削除されない
const accounts = await getAccounts(source);
expect(accounts.length).toBe(2);
expect(accounts[0].tier).toBe(parent.tier);
expect(accounts[1].tier).toBe(parent.tier + 1);
const users = await getUsers(source);
expect(users.length).toBe(2);
expect(users[0].external_id).toBe(parentExternalId);
expect(users[1].external_id).toBe(partnerExternalId);
// ADB2Cユーザー削除メソッドが呼ばれているか確認
expect(b2cService.deleteUser).toBeCalledWith(partnerExternalId, context);
}
});
it('SendGridへの通信失敗によって500エラーが発生した場合、リカバリ処理としてADB2C,DB上のデータ,コンテナが削除され、500エラーが返却される', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const b2cService = module.get<AdB2cService>(AdB2cService);
const blobstorageService =
module.get<BlobstorageService>(BlobstorageService);
const parentExternalId = 'parent_external_id';
// 第一階層のアカウントを作成
const { account: parent } = await makeTestAccount(
source,
{ tier: 1 },
{ external_id: parentExternalId },
);
const context = makeContext(parentExternalId);
const partnerExternalId = 'partner_external_id';
const companyName = 'partner_company_name';
const country = 'US';
const email = 'partner@example.com';
const username = 'partner_username';
overrideAdB2cService(service, {
createUser: async () => {
return { sub: partnerExternalId };
},
deleteUser: jest.fn(),
});
overrideSendgridService(service, {
sendMail: async () => {
throw new Error();
},
createMailContentFromEmailConfirmForNormalUser: async () => {
return { html: '', text: '', subject: '' };
},
});
overrideBlobstorageService(service, {
createContainer: async () => {
return;
},
deleteContainer: jest.fn(),
});
// DB上に用意されたデータが想定通りであるか確認
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
}
try {
await service.createPartnerAccount(
context,
companyName,
country,
email,
username,
parentExternalId,
TIERS.TIER1,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
{
// DB上に作成されたデータが想定通りであるか確認
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
expect(accounts[0].tier).toBe(parent.tier);
const users = await getUsers(source);
expect(users.length).toBe(1);
expect(users[0].external_id).toBe(parentExternalId);
// ADB2Cユーザー削除メソッドが呼ばれているか確認
expect(b2cService.deleteUser).toBeCalledWith(partnerExternalId, context);
// コンテナ削除メソッドが呼ばれているか確認
expect(blobstorageService.deleteContainer).toBeCalledWith(
context,
2, //新規作成したパートナーのアカウントID
country,
);
}
});
it('SendGridへの通信失敗によって500エラーが発生した場合、リカバリ処理が実行されるが、そのリカバリ処理に失敗した場合、500エラーが返却される', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const b2cService = module.get<AdB2cService>(AdB2cService);
const blobstorageService =
module.get<BlobstorageService>(BlobstorageService);
const parentExternalId = 'parent_external_id';
// 第一階層のアカウントを作成
const { account: parent } = await makeTestAccount(
source,
{ tier: 1 },
{ external_id: parentExternalId },
);
const context = makeContext(parentExternalId);
const partnerExternalId = 'partner_external_id';
const companyName = 'partner_company_name';
const country = 'US';
const email = 'partner@example.com';
const username = 'partner_username';
overrideAdB2cService(service, {
createUser: async () => {
return { sub: partnerExternalId };
},
deleteUser: jest.fn().mockRejectedValue(new Error('ADB2C Error')),
});
overrideSendgridService(service, {
sendMail: async () => {
throw new Error();
},
createMailContentFromEmailConfirmForNormalUser: async () => {
return { html: '', text: '', subject: '' };
},
});
overrideAccountsRepositoryService(service, {
deleteAccount: jest.fn().mockRejectedValue(new Error('DB Error')),
});
overrideBlobstorageService(service, {
createContainer: async () => {
return;
},
deleteContainer: jest.fn().mockRejectedValue(new Error('Blob Error')),
});
// DB上に用意されたデータが想定通りであるか確認
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
}
try {
await service.createPartnerAccount(
context,
companyName,
country,
email,
username,
parentExternalId,
TIERS.TIER1,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
{
// DB上に作成されたデータが想定通りであるか確認
// リカバリ処理が失敗したため、DB上のデータは削除されていない
const accounts = await getAccounts(source);
expect(accounts.length).toBe(2);
expect(accounts[0].tier).toBe(parent.tier);
expect(accounts[1].tier).toBe(parent.tier + 1);
const users = await getUsers(source);
expect(users.length).toBe(2);
expect(users[0].external_id).toBe(parentExternalId);
expect(users[1].external_id).toBe(partnerExternalId);
// ADB2Cユーザー削除メソッドが呼ばれているか確認
expect(b2cService.deleteUser).toBeCalledWith(partnerExternalId, context);
// コンテナ削除メソッドが呼ばれているか確認
expect(blobstorageService.deleteContainer).toBeCalledWith(
context,
2, //新規作成したパートナーのアカウントID
country,
);
}
});
it('既に登録済みのメールアドレスが原因でアカウントの追加に失敗した場合、エラーとなる(400エラー)', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const adminExternalId = 'ADMIN0001';
// 第一階層のアカウントを作成
const { account: parent } = await makeTestAccount(
source,
{ tier: 1 },
{ external_id: adminExternalId },
);
const context = makeContext('uuid');
const companyName = 'test_company_name';
const country = 'US';
const email = 'partner@example.com';
const adminName = 'partner_admin';
overrideAdB2cService(service, {
createUser: async () => {
// Conflictエラーを返す
return { reason: 'email', message: 'dummy' };
},
});
overrideSendgridService(service, {
createMailContentFromEmailConfirmForNormalUser: async () => {
return { html: '', text: '', subject: '' };
},
sendMail: async () => {
return;
},
});
overrideBlobstorageService(service, {
createContainer: async () => {
return;
},
});
// DB上に用意されたデータが想定通りであるか確認
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
const users = await getUsers(source);
expect(users.length).toBe(1);
}
try {
await service.createPartnerAccount(
context,
companyName,
country,
email,
adminName,
adminExternalId,
parent.tier,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toBe(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010301'));
} else {
fail();
}
}
// DB上に作成されたデータが想定通りであるか確認
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
const users = await getUsers(source);
expect(users.length).toBe(1);
}
});
});
describe('AccountsService', () => {
it('アカウントに紐づくライセンス情報を取得する', async () => {
const accountId = 1;
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
const userGroupsRepositoryMockValue =
makeDefaultUserGroupsRepositoryMockValue();
const adb2cParam = makeDefaultAdB2cMockValue();
const accountsRepositoryMockValue =
makeDefaultAccountsRepositoryMockValue();
const configMockValue = makeDefaultConfigValue();
const sendGridMockValue = makeDefaultSendGridlValue();
const blobStorageMockValue = makeBlobStorageServiceMockValue();
const licensesRepositoryMockValue =
makeDefaultLicensesRepositoryMockValue();
const worktypesRepositoryMockValue =
makeDefaultWorktypesRepositoryMockValue();
const service = await makeAccountsServiceMock(
accountsRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cParam,
configMockValue,
sendGridMockValue,
blobStorageMockValue,
licensesRepositoryMockValue,
worktypesRepositoryMockValue,
);
expect(await service.getLicenseSummary(accountId)).toEqual(
expectedAccountLisenceCounts,
);
});
it('ライセンス情報が取得できない場合、エラーとなる', async () => {
const accountId = 1;
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
const userGroupsRepositoryMockValue =
makeDefaultUserGroupsRepositoryMockValue();
const adb2cParam = makeDefaultAdB2cMockValue();
const accountsRepositoryMockValue =
makeDefaultAccountsRepositoryMockValue();
accountsRepositoryMockValue.getLicenseSummaryInfo = null;
const configMockValue = makeDefaultConfigValue();
const sendGridMockValue = makeDefaultSendGridlValue();
const blobStorageMockValue = makeBlobStorageServiceMockValue();
const licensesRepositoryMockValue =
makeDefaultLicensesRepositoryMockValue();
const worktypesRepositoryMockValue =
makeDefaultWorktypesRepositoryMockValue();
const service = await makeAccountsServiceMock(
accountsRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cParam,
configMockValue,
sendGridMockValue,
blobStorageMockValue,
licensesRepositoryMockValue,
worktypesRepositoryMockValue,
);
await expect(service.getLicenseSummary(accountId)).rejects.toEqual(
new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
),
);
});
it('アカウントに紐づくタイピストユーザーを取得できる', async () => {
const externalId = 'externalId';
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
const userGroupsRepositoryMockValue =
makeDefaultUserGroupsRepositoryMockValue();
const adb2cParam = makeDefaultAdB2cMockValue();
const accountsRepositoryMockValue =
makeDefaultAccountsRepositoryMockValue();
const configMockValue = makeDefaultConfigValue();
const sendGridMockValue = makeDefaultSendGridlValue();
const blobStorageMockValue = makeBlobStorageServiceMockValue();
const licensesRepositoryMockValue =
makeDefaultLicensesRepositoryMockValue();
const worktypesRepositoryMockValue =
makeDefaultWorktypesRepositoryMockValue();
const service = await makeAccountsServiceMock(
accountsRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cParam,
configMockValue,
sendGridMockValue,
blobStorageMockValue,
licensesRepositoryMockValue,
worktypesRepositoryMockValue,
);
expect(await service.getTypists(externalId)).toEqual([
{ id: 1, name: 'Typist1' },
{ id: 2, name: 'Typist2' },
{ id: 3, name: 'Typist3' },
]);
});
it('ユーザー取得に失敗した場合、エラーとなる', async () => {
const externalId = 'externalId';
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
usersRepositoryMockValue.findTypistUsers = new Error();
const userGroupsRepositoryMockValue =
makeDefaultUserGroupsRepositoryMockValue();
const adb2cParam = makeDefaultAdB2cMockValue();
const accountsRepositoryMockValue =
makeDefaultAccountsRepositoryMockValue();
const configMockValue = makeDefaultConfigValue();
const sendGridMockValue = makeDefaultSendGridlValue();
const blobStorageMockValue = makeBlobStorageServiceMockValue();
const licensesRepositoryMockValue =
makeDefaultLicensesRepositoryMockValue();
const worktypesRepositoryMockValue =
makeDefaultWorktypesRepositoryMockValue();
const service = await makeAccountsServiceMock(
accountsRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cParam,
configMockValue,
sendGridMockValue,
blobStorageMockValue,
licensesRepositoryMockValue,
worktypesRepositoryMockValue,
);
await expect(service.getTypists(externalId)).rejects.toEqual(
new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
),
);
});
it('ADB2Cからのユーザーの取得に失敗した場合、エラーとなる', async () => {
const externalId = 'externalId';
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
const userGroupsRepositoryMockValue =
makeDefaultUserGroupsRepositoryMockValue();
const adb2cParam = makeDefaultAdB2cMockValue();
adb2cParam.getUsers = new Error();
const accountsRepositoryMockValue =
makeDefaultAccountsRepositoryMockValue();
const configMockValue = makeDefaultConfigValue();
const sendGridMockValue = makeDefaultSendGridlValue();
const blobStorageMockValue = makeBlobStorageServiceMockValue();
const licensesRepositoryMockValue =
makeDefaultLicensesRepositoryMockValue();
const worktypesRepositoryMockValue =
makeDefaultWorktypesRepositoryMockValue();
const service = await makeAccountsServiceMock(
accountsRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cParam,
configMockValue,
sendGridMockValue,
blobStorageMockValue,
licensesRepositoryMockValue,
worktypesRepositoryMockValue,
);
await expect(service.getTypists(externalId)).rejects.toEqual(
new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
),
);
});
it('アカウントに紐づくユーザーグループを取得できる', async () => {
const externalId = 'externalId';
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
const adb2cParam = makeDefaultAdB2cMockValue();
const accountsRepositoryMockValue =
makeDefaultAccountsRepositoryMockValue();
const userGroupsRepositoryMockValue =
makeDefaultUserGroupsRepositoryMockValue();
const configMockValue = makeDefaultConfigValue();
const sendGridMockValue = makeDefaultSendGridlValue();
const blobStorageMockValue = makeBlobStorageServiceMockValue();
const licensesRepositoryMockValue =
makeDefaultLicensesRepositoryMockValue();
const worktypesRepositoryMockValue =
makeDefaultWorktypesRepositoryMockValue();
const service = await makeAccountsServiceMock(
accountsRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cParam,
configMockValue,
sendGridMockValue,
blobStorageMockValue,
licensesRepositoryMockValue,
worktypesRepositoryMockValue,
);
expect(await service.getTypistGroups(externalId)).toEqual([
{ id: 1, name: 'GroupA' },
{ id: 2, name: 'GroupB' },
]);
});
it('ユーザーの取得に失敗した場合、エラーとなること', async () => {
const externalId = 'externalId';
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
usersRepositoryMockValue.findUserByExternalId = new Error('DB failed');
const adb2cParam = makeDefaultAdB2cMockValue();
const accountsRepositoryMockValue =
makeDefaultAccountsRepositoryMockValue();
const userGroupsRepositoryMockValue =
makeDefaultUserGroupsRepositoryMockValue();
const configMockValue = makeDefaultConfigValue();
const sendGridMockValue = makeDefaultSendGridlValue();
const blobStorageMockValue = makeBlobStorageServiceMockValue();
const licensesRepositoryMockValue =
makeDefaultLicensesRepositoryMockValue();
const worktypesRepositoryMockValue =
makeDefaultWorktypesRepositoryMockValue();
const service = await makeAccountsServiceMock(
accountsRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cParam,
configMockValue,
sendGridMockValue,
blobStorageMockValue,
licensesRepositoryMockValue,
worktypesRepositoryMockValue,
);
await expect(service.getTypistGroups(externalId)).rejects.toEqual(
new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
),
);
});
it('ユーザーグループの取得に失敗した場合、エラーとなること', async () => {
const externalId = 'externalId';
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
const adb2cParam = makeDefaultAdB2cMockValue();
const accountsRepositoryMockValue =
makeDefaultAccountsRepositoryMockValue();
const userGroupsRepositoryMockValue =
makeDefaultUserGroupsRepositoryMockValue();
userGroupsRepositoryMockValue.getUserGroups = new Error('DB failed');
const configMockValue = makeDefaultConfigValue();
const sendGridMockValue = makeDefaultSendGridlValue();
const blobStorageMockValue = makeBlobStorageServiceMockValue();
const licensesRepositoryMockValue =
makeDefaultLicensesRepositoryMockValue();
const worktypesRepositoryMockValue =
makeDefaultWorktypesRepositoryMockValue();
const service = await makeAccountsServiceMock(
accountsRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cParam,
configMockValue,
sendGridMockValue,
blobStorageMockValue,
licensesRepositoryMockValue,
worktypesRepositoryMockValue,
);
await expect(service.getTypistGroups(externalId)).rejects.toEqual(
new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
),
);
});
});
const expectedAccountLisenceCounts = {
totalLicense: 1,
allocatedLicense: 2,
reusableLicense: 3,
freeLicense: 4,
expiringWithin14daysLicense: 5,
issueRequesting: 6,
numberOfRequesting: 7,
shortage: 0,
storageSize: 0,
usedSize: 0,
isStorageAvailable: false,
};
describe('getPartnerAccount', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('パラメータのアカウント自身と子アカウントに紐つくライセンス情報を取得する', async () => {
const module = await makeTestingModule(source);
// 親アカウントと子アカウント2つ作成
const { id: parentAccountId } = (
await makeTestAccount(source, {
parent_account_id: 0,
tier: 1,
company_name: 'PARENTCORP',
})
).account;
const { id: childAccountId1 } = (
await makeTestAccount(source, {
parent_account_id: parentAccountId,
tier: 2,
company_name: 'CHILDCORP1',
})
).account;
const { id: childAccountId2 } = (
await makeTestAccount(source, {
parent_account_id: parentAccountId,
tier: 2,
company_name: 'CHILDCORP2',
})
).account;
// 第二にリクエストを投げる用の第三を作成
const { id: childAccountId3 } = (
await makeTestAccount(source, {
parent_account_id: childAccountId1,
tier: 3,
company_name: 'CHILDCORP3',
})
).account;
const { id: childAccountId4 } = (
await makeTestAccount(source, {
parent_account_id: childAccountId2,
tier: 3,
company_name: 'CHILDCORP4',
})
).account;
// 所有ライセンスを追加3、子11、子22
await createLicense(
source,
1,
null,
parentAccountId,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
1,
null,
null,
);
await createLicense(
source,
2,
null,
parentAccountId,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
1,
null,
null,
);
await createLicense(
source,
3,
null,
parentAccountId,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
1,
null,
null,
);
await createLicense(
source,
4,
null,
childAccountId1,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
2,
null,
null,
);
await createLicense(
source,
5,
null,
childAccountId2,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
3,
null,
null,
);
await createLicense(
source,
6,
null,
childAccountId2,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
3,
null,
null,
);
// ライセンス注文を追加子1→親10ライセンス、子2→親5ライセンス
await createLicenseOrder(
source,
childAccountId1,
parentAccountId,
10,
'TEST222',
);
await createLicenseOrder(source, childAccountId2, parentAccountId, 5);
// ライセンス注文を追加子3→子110ライセンス、子4→子210ライセンス
await createLicenseOrder(source, childAccountId3, childAccountId1, 10);
await createLicenseOrder(source, childAccountId4, childAccountId2, 10);
const service = module.get<AccountsService>(AccountsService);
const accountId = parentAccountId;
const offset = 0;
const limit = 20;
const response = await service.getPartnerLicenses(limit, offset, accountId);
expect(response.total).toBe(2);
expect(response.ownPartnerLicense.companyName).toBe('PARENTCORP');
expect(response.ownPartnerLicense.tier).toBe(1);
expect(response.ownPartnerLicense.stockLicense).toBe(3);
expect(response.ownPartnerLicense.issuedRequested).toBe(15);
expect(response.ownPartnerLicense.shortage).toBe(12);
expect(response.childrenPartnerLicenses[0].companyName).toBe('CHILDCORP1');
expect(response.childrenPartnerLicenses[0].tier).toBe(2);
expect(response.childrenPartnerLicenses[0].stockLicense).toBe(1);
expect(response.childrenPartnerLicenses[0].issueRequesting).toBe(10);
expect(response.childrenPartnerLicenses[0].shortage).toBe(9);
expect(response.childrenPartnerLicenses[1].companyName).toBe('CHILDCORP2');
expect(response.childrenPartnerLicenses[1].tier).toBe(2);
expect(response.childrenPartnerLicenses[1].stockLicense).toBe(2);
expect(response.childrenPartnerLicenses[1].shortage).toBe(8);
});
});
describe('getPartnerAccount', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('パラメータのアカウント自身と子アカウントに紐つくライセンス情報を取得する(第五のshortage確認)', async () => {
const module = await makeTestingModule(source);
// 親アカウントと子アカウント2つ作成
const { id: parentAccountId } = (
await makeTestAccount(source, {
parent_account_id: 0,
tier: 4,
company_name: 'PARENTCORP',
})
).account;
const { id: childAccountId1 } = (
await makeTestAccount(source, {
parent_account_id: parentAccountId,
tier: 5,
company_name: 'CHILDCORP1',
})
).account;
const { id: childAccountId2 } = (
await makeTestAccount(source, {
parent_account_id: parentAccountId,
tier: 5,
company_name: 'CHILDCORP2',
})
).account;
const { id: childAccountId3 } = (
await makeTestAccount(source, {
parent_account_id: parentAccountId,
tier: 5,
company_name: 'CHILDCORP3',
})
).account;
// 有効期限が14日後のライセンスを追加5ライセンス
const expiryDate = new Date();
expiryDate.setDate(expiryDate.getDate() + 14);
expiryDate.setHours(23, 59, 59, 999);
for (let i = 0; i < 5; i++) {
await createLicenseSetExpiryDateAndStatus(
source,
childAccountId1,
expiryDate,
'Allocated',
);
await createLicenseSetExpiryDateAndStatus(
source,
childAccountId2,
expiryDate,
'Allocated',
);
}
// 有効期限が15日後のライセンスを追加
expiryDate.setDate(expiryDate.getDate() + 15);
expiryDate.setHours(23, 59, 59, 999);
await createLicenseSetExpiryDateAndStatus(
source,
childAccountId3,
expiryDate,
'Allocated',
);
// 有効期限が迫っていないライセンスを追加子1各ステータスのライセンスを1つずつ、計4つ
const status = ['Unallocated', 'Allocated', 'Reusable', 'Deleted'];
status.forEach(async (element) => {
await createLicenseSetExpiryDateAndStatus(
source,
childAccountId1,
new Date(2500, 1, 1, 23, 59, 59),
element,
);
});
// 有効期限が迫っていないライセンスを追加子2Unallocatedを10件
for (let i = 0; i < 10; i++) {
await createLicenseSetExpiryDateAndStatus(
source,
childAccountId2,
new Date(2500, 1, 1, 23, 59, 59),
'Unallocated',
);
}
// 有効期限未設定のライセンスを1件追加子1
await createLicenseSetExpiryDateAndStatus(
source,
childAccountId1,
null,
'Unallocated',
);
const service = module.get<AccountsService>(AccountsService);
const accountId = parentAccountId;
const offset = 0;
const limit = 20;
const response = await service.getPartnerLicenses(limit, offset, accountId);
// 有効期限間近5件 有効期限間近でない3件'Unallocated', 'Allocated', 'Reusable' 有効期限未設定1件  9件
expect(response.childrenPartnerLicenses[0].stockLicense).toBe(9);
// 有効期限間近5件 - {有効期限間近でない未割当2件'Unallocated', 'Reusable' 有効期限未設定1件}  2件
expect(response.childrenPartnerLicenses[0].shortage).toBe(2);
// 有効期限間近5件 有効期限間近でない10件  15件
expect(response.childrenPartnerLicenses[1].stockLicense).toBe(15);
// 有効期限間近5件- 有効期限間近でない未割当10件'Unallocated'  有効期限未設定1件  -5件  0件
expect(response.childrenPartnerLicenses[1].shortage).toBe(0);
expect(response.childrenPartnerLicenses[2].stockLicense).toBe(1);
// 有効期限が15日後のものはshortageにカウントされない
expect(response.childrenPartnerLicenses[2].shortage).toBe(0);
});
});
describe('getOrderHistories', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('指定したアカウントIDの注文履歴情報を取得できる', async () => {
const module = await makeTestingModule(source);
const targetAccountId = 10;
const targetParentAccountId = 14;
const now = new Date(); // 現在の時刻を取得
// 注文履歴情報の作成
await createLicenseOrder(
source,
targetAccountId,
targetParentAccountId,
10,
'TEST001',
new Date(now.getTime() + 60 * 60 * 1000),
);
await createLicenseOrder(
source,
targetAccountId,
targetParentAccountId,
10,
'TEST002',
new Date(now.getTime() + 60 * 60 * 1000 * 2),
);
await createLicenseOrder(
source,
targetAccountId,
targetParentAccountId,
10,
'TEST003',
new Date(now.getTime() + 60 * 60 * 1000 * 3),
);
await createLicenseOrder(
source,
targetAccountId,
targetParentAccountId,
10,
'TEST004',
new Date(now.getTime() + 60 * 60 * 1000 * 4),
);
await createLicenseOrder(
source,
targetAccountId,
targetParentAccountId,
10,
'TEST005',
new Date(now.getTime() + 60 * 60 * 1000 * 5),
);
const service = module.get<AccountsService>(AccountsService);
const accountId = targetAccountId;
const offset = 1;
const limit = 2;
const response = await service.getOrderHistories(limit, offset, accountId);
expect(response.total).toBe(5);
expect(response.orderHistories[0].poNumber).toBe('TEST004');
expect(response.orderHistories[1].poNumber).toBe('TEST003');
});
it('注文履歴情報の取得に失敗した場合、エラーとなる', async () => {
const limit = 0;
const offset = 0;
const accountId = 0;
const worktypesRepositoryMockValue =
makeDefaultWorktypesRepositoryMockValue();
const usersRepositoryMockValue = makeDefaultUsersRepositoryMockValue();
usersRepositoryMockValue.findTypistUsers = new Error();
const userGroupsRepositoryMockValue =
makeDefaultUserGroupsRepositoryMockValue();
const adb2cParam = makeDefaultAdB2cMockValue();
const accountsRepositoryMockValue =
makeDefaultAccountsRepositoryMockValue();
const configMockValue = makeDefaultConfigValue();
const sendGridMockValue = makeDefaultSendGridlValue();
const blobStorageMockValue = makeBlobStorageServiceMockValue();
const licensesRepositoryMockValue =
makeDefaultLicensesRepositoryMockValue();
licensesRepositoryMockValue.getLicenseOrderHistoryInfo = new Error(
'DB failed',
);
const service = await makeAccountsServiceMock(
accountsRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cParam,
configMockValue,
sendGridMockValue,
blobStorageMockValue,
licensesRepositoryMockValue,
worktypesRepositoryMockValue,
);
await expect(
service.getOrderHistories(limit, offset, accountId),
).rejects.toEqual(
new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
),
);
});
});
describe('issueLicense', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('指定した注文を発行済みにする', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const now = new Date();
// 親と子アカウントを作成する
const { id: parentAccountId } = (
await makeTestAccount(source, {
parent_account_id: 0,
tier: 2,
company_name: 'PARENTCORP',
})
).account;
const { id: childAccountId } = (
await makeTestAccount(source, {
parent_account_id: parentAccountId,
tier: 3,
company_name: 'CHILDCORP1',
})
).account;
// 親と子のユーザーを作成する
const { external_id: externalId } = await makeTestUser(source, {
account_id: parentAccountId,
external_id: 'userId-parent',
role: 'admin',
});
// 親のライセンスを作成する3個
await createLicense(
source,
1,
null,
parentAccountId,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
1,
null,
null,
);
await createLicense(
source,
2,
null,
parentAccountId,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
1,
null,
null,
);
await createLicense(
source,
3,
null,
parentAccountId,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
1,
null,
null,
);
// 子から親への注文を作成する2個
await createLicenseOrder(
source,
childAccountId,
parentAccountId,
2,
'TEST001',
new Date(now.getTime() + 60 * 60 * 1000),
);
const context = makeContext('userId-parent');
// 注文を発行済みにする
await service.issueLicense(
context,
childAccountId,
externalId,
2,
'TEST001',
);
const issuedLicenses = await source.getRepository(License).find({
where: {
account_id: childAccountId,
status: 'Unallocated',
type: 'NORMAL',
},
});
expect(issuedLicenses.length).toEqual(2);
});
it('既に注文が発行済みの場合、エラーとなる', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const now = new Date();
// 親と子アカウントを作成する
const { id: parentAccountId } = (
await makeTestAccount(source, {
parent_account_id: 0,
tier: 2,
company_name: 'PARENTCORP',
})
).account;
const { id: childAccountId } = (
await makeTestAccount(source, {
parent_account_id: parentAccountId,
tier: 3,
company_name: 'CHILDCORP1',
})
).account;
// 親と子のユーザーを作成する
const { external_id: externalId } = await makeTestUser(source, {
account_id: parentAccountId,
external_id: 'userId-parent',
role: 'admin',
});
// 親のライセンスを作成する3個
await createLicense(
source,
1,
null,
parentAccountId,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
1,
null,
null,
);
await createLicense(
source,
2,
null,
parentAccountId,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
1,
null,
null,
);
await createLicense(
source,
3,
null,
parentAccountId,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
1,
null,
null,
);
// 子から親への注文を作成する2個
await createLicenseOrder(
source,
childAccountId,
parentAccountId,
2,
'TEST001',
new Date(now.getTime() + 60 * 60 * 1000),
);
const context = makeContext('userId-parent');
// 注文を発行済みにする
await service.issueLicense(
context,
childAccountId,
externalId,
2,
'TEST001',
);
//再度同じ処理を行う
await expect(
service.issueLicense(context, childAccountId, externalId, 2, 'TEST001'),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010803'), HttpStatus.BAD_REQUEST),
);
});
it('ライセンスが不足している場合、エラーとなる', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const now = new Date();
// 親と子アカウントを作成する
const { id: parentAccountId } = (
await makeTestAccount(source, {
parent_account_id: 0,
tier: 2,
company_name: 'PARENTCORP',
})
).account;
const { id: childAccountId } = (
await makeTestAccount(source, {
parent_account_id: parentAccountId,
tier: 3,
company_name: 'CHILDCORP1',
})
).account;
// 親と子のユーザーを作成する
const { external_id: externalId } = await makeTestUser(source, {
account_id: parentAccountId,
external_id: 'userId-parent',
role: 'admin',
});
// 親のライセンスを作成する3個
await createLicense(
source,
1,
null,
parentAccountId,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
1,
null,
null,
);
await createLicense(
source,
2,
null,
parentAccountId,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
1,
null,
null,
);
await createLicense(
source,
3,
null,
parentAccountId,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
1,
null,
null,
);
// 子から親への注文を作成する4個
await createLicenseOrder(
source,
childAccountId,
parentAccountId,
4,
'TEST001',
new Date(now.getTime() + 60 * 60 * 1000),
);
const context = makeContext('userId-parent');
// 注文を発行済みにする
await expect(
service.issueLicense(context, childAccountId, externalId, 2, 'TEST001'),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010804'), HttpStatus.BAD_REQUEST),
);
});
});
describe('getDealers', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('Dealerを取得できる', async () => {
const module = await makeTestingModule(source);
const { id: accountId_1 } = (
await makeTestAccount(source, {
parent_account_id: 1,
tier: TIERS.TIER4,
country: 'JP',
company_name: 'DEALER_1',
})
).account;
const { id: accountId_2 } = (
await makeTestAccount(source, {
parent_account_id: 2,
tier: TIERS.TIER4,
country: 'JP',
company_name: 'DEALER_2',
})
).account;
const { id: accountId_3 } = (
await makeTestAccount(source, {
parent_account_id: 3,
tier: TIERS.TIER4,
country: 'JP',
company_name: 'DEALER_3',
})
).account;
const service = module.get<AccountsService>(AccountsService);
expect(await service.getDealers()).toEqual({
dealers: [
{
country: 'JP',
id: accountId_1,
name: 'DEALER_1',
},
{
country: 'JP',
id: accountId_2,
name: 'DEALER_2',
},
{
country: 'JP',
id: accountId_3,
name: 'DEALER_3',
},
],
});
});
it('0件でもDealerを取得できる', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
expect(await service.getDealers()).toEqual({
dealers: [],
});
});
});
describe('createTypistGroup', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('TypistGroupを作成できる', async () => {
const module = await makeTestingModule(source);
const adminExternalId = 'admin-external-id';
// 第五階層のアカウント作成
const { id: accountId } = (
await makeTestAccount(
source,
{ tier: 5 },
{ external_id: adminExternalId },
)
).account;
// 作成したアカウントにユーザーを3名追加する
const typiptUserExternalIds = [
'typist-user-external-id1',
'typist-user-external-id2',
'typist-user-external-id3',
];
const userIds: number[] = [];
for (const typiptUserExternalId of typiptUserExternalIds) {
const { id: userId } = await makeTestUser(source, {
account_id: accountId,
external_id: typiptUserExternalId,
role: 'typist',
});
userIds.push(userId);
}
//作成したデータを確認
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
expect(accounts[0].id).toBe(accountId);
const users = await getUsers(source);
expect(users.length).toBe(4);
}
const service = module.get<AccountsService>(AccountsService);
const typistGroupName = 'typist-group-name';
const typistUserIds = userIds;
const context = makeContext(adminExternalId);
await service.createTypistGroup(
context,
adminExternalId,
typistGroupName,
typistUserIds,
);
//実行結果を確認
{
const typistGroups = await getTypistGroup(source, accountId);
expect(typistGroups.length).toBe(1);
expect(typistGroups[0].name).toBe(typistGroupName);
const typistGroupUsers = await getTypistGroupMember(
source,
typistGroups[0].id,
);
expect(typistGroupUsers.length).toBe(3);
expect(typistGroupUsers.map((user) => user.user_id)).toEqual(userIds);
}
});
it('typistIdsにRole:typist以外のユーザーが含まれていた場合、400エラーを返却する', async () => {
const module = await makeTestingModule(source);
const adminExternalId = 'admin-external-id';
// 第五階層のアカウント作成
const { id: accountId } = (
await makeTestAccount(
source,
{ tier: 5 },
{ external_id: adminExternalId },
)
).account;
// 作成したアカウントにユーザーを3名追加する
const typiptUserExternalIds = [
'typist-user-external-id1',
'typist-user-external-id2',
'typist-user-external-id3',
];
const userIds: number[] = [];
for (const typiptUserExternalId of typiptUserExternalIds) {
const { id: userId } = await makeTestUser(source, {
account_id: accountId,
external_id: typiptUserExternalId,
role:
typiptUserExternalId === 'typist-user-external-id3'
? 'none'
: 'typist', //typist-user-external-id3のみRole:none,
});
userIds.push(userId);
}
//作成したデータを確認
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
expect(accounts[0].id).toBe(accountId);
const users = await getUsers(source);
expect(users.length).toBe(4);
expect(users.filter((user) => user.role === 'typist').length).toBe(2);
}
const service = module.get<AccountsService>(AccountsService);
const typistGroupName = 'typist-group-name';
const typistUserIds = userIds;
const context = makeContext(adminExternalId);
await expect(
service.createTypistGroup(
context,
adminExternalId,
typistGroupName,
typistUserIds,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010204'), HttpStatus.BAD_REQUEST),
);
});
it('typistIdsに存在しないユーザーが含まれていた場合、400エラーを返却する', async () => {
const module = await makeTestingModule(source);
const adminExternalId = 'admin-external-id';
// 第五階層のアカウント作成
const { id: accountId } = (
await makeTestAccount(
source,
{ tier: 5 },
{ external_id: adminExternalId },
)
).account;
// 作成したアカウントにユーザーを3名追加する
const typiptUserExternalIds = [
'typist-user-external-id1',
'typist-user-external-id2',
'typist-user-external-id3',
];
const userIds: number[] = [];
for (const typiptUserExternalId of typiptUserExternalIds) {
const { id: userId } = await makeTestUser(source, {
account_id: accountId,
external_id: typiptUserExternalId,
role: 'typist',
});
userIds.push(userId);
}
//作成したデータを確認
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
expect(accounts[0].id).toBe(accountId);
const users = await getUsers(source);
expect(users.length).toBe(4);
}
const service = module.get<AccountsService>(AccountsService);
const typistGroupName = 'typist-group-name';
const typistUserIds = [...userIds, 9999]; //存在しないユーザーIDを追加
const context = makeContext(adminExternalId);
await expect(
service.createTypistGroup(
context,
adminExternalId,
typistGroupName,
typistUserIds,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010204'), HttpStatus.BAD_REQUEST),
);
});
it('DBアクセスに失敗した場合、500エラーを返却する', async () => {
const module = await makeTestingModule(source);
const adminExternalId = 'admin-external-id';
// 第五階層のアカウント作成
const { id: accountId } = (
await makeTestAccount(
source,
{ tier: 5 },
{ external_id: adminExternalId },
)
).account;
// 作成したアカウントにユーザーを3名追加する
const typiptUserExternalIds = [
'typist-user-external-id1',
'typist-user-external-id2',
'typist-user-external-id3',
];
const userIds: number[] = [];
for (const typiptUserExternalId of typiptUserExternalIds) {
const { id: userId } = await makeTestUser(source, {
account_id: accountId,
external_id: typiptUserExternalId,
role: 'typist',
});
userIds.push(userId);
}
//作成したデータを確認
{
const accounts = await getAccounts(source);
expect(accounts.length).toBe(1);
expect(accounts[0].id).toBe(accountId);
const users = await getUsers(source);
expect(users.length).toBe(4);
}
const service = module.get<AccountsService>(AccountsService);
const typistGroupName = 'typist-group-name';
const typistUserIds = userIds;
const context = makeContext(adminExternalId);
//DBアクセスに失敗するようにする
const typistGroupService = module.get<UserGroupsRepositoryService>(
UserGroupsRepositoryService,
);
typistGroupService.createTypistGroup = jest
.fn()
.mockRejectedValue('DB failed');
await expect(
service.createTypistGroup(
context,
adminExternalId,
typistGroupName,
typistUserIds,
),
).rejects.toEqual(
new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
),
);
});
});
describe('getTypistGroup', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('指定したIDのTypistGroupを取得できる', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
// 作成したアカウントにユーザーを3名追加する
const typiptUserExternalIds = [
'typist-user-external-id1',
'typist-user-external-id2',
'typist-user-external-id3',
];
const userIds: number[] = [];
for (const typiptUserExternalId of typiptUserExternalIds) {
const { id: userId } = await makeTestUser(source, {
account_id: account.id,
external_id: typiptUserExternalId,
role: USER_ROLES.TYPIST,
});
userIds.push(userId);
}
// アカウントにタイピストグループを作成する
const typistGroupName = 'typist-group-name';
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
await service.createTypistGroup(
context,
admin.external_id,
typistGroupName,
userIds,
);
//作成したデータを確認
const group = await getTypistGroup(source, account.id);
{
expect(group.length).toBe(1);
expect(group[0].name).toBe(typistGroupName);
const groupUsers = await getTypistGroupMember(source, group[0].id);
expect(groupUsers.length).toBe(3);
expect(groupUsers.map((user) => user.user_id)).toEqual(userIds);
}
const typistGroup = await service.getTypistGroup(
context,
admin.external_id,
group[0].id,
);
//実行結果を確認
{
const typistGroups = await getTypistGroup(source, account.id);
expect(typistGroups.length).toBe(1);
expect(typistGroup.typistGroupName).toBe(typistGroupName);
expect(typistGroup.typistIds.length).toBe(3);
expect(typistGroup.typistIds).toEqual(userIds);
}
});
it('指定したタイピストグループIDのタイピストグループが存在しない場合、400エラーを返却する', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
// 作成したアカウントにユーザーを3名追加する
const typiptUserExternalIds = [
'typist-user-external-id1',
'typist-user-external-id2',
'typist-user-external-id3',
];
const userIds: number[] = [];
for (const typiptUserExternalId of typiptUserExternalIds) {
const { id: userId } = await makeTestUser(source, {
account_id: account.id,
external_id: typiptUserExternalId,
role: USER_ROLES.TYPIST,
});
userIds.push(userId);
}
// アカウントにタイピストグループを作成する
const typistGroupName = 'typist-group-name';
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
await service.createTypistGroup(
context,
admin.external_id,
typistGroupName,
userIds,
);
//作成したデータを確認
{
const group = await getTypistGroup(source, account.id);
expect(group.length).toBe(1);
expect(group[0].name).toBe(typistGroupName);
const groupUsers = await getTypistGroupMember(source, group[0].id);
expect(groupUsers.length).toBe(3);
expect(groupUsers.map((user) => user.user_id)).toEqual(userIds);
}
try {
await service.getTypistGroup(context, admin.external_id, 999);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010908'));
} else {
fail();
}
}
});
it('DBアクセスに失敗した場合、500エラーを返却する', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
// 作成したアカウントにユーザーを3名追加する
const typiptUserExternalIds = [
'typist-user-external-id1',
'typist-user-external-id2',
'typist-user-external-id3',
];
const userIds: number[] = [];
for (const typiptUserExternalId of typiptUserExternalIds) {
const { id: userId } = await makeTestUser(source, {
account_id: account.id,
external_id: typiptUserExternalId,
role: USER_ROLES.TYPIST,
});
userIds.push(userId);
}
// アカウントにタイピストグループを作成する
const typistGroupName = 'typist-group-name';
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
await service.createTypistGroup(
context,
admin.external_id,
typistGroupName,
userIds,
);
//作成したデータを確認
const group = await getTypistGroup(source, account.id);
{
expect(group.length).toBe(1);
expect(group[0].name).toBe(typistGroupName);
const groupUsers = await getTypistGroupMember(source, group[0].id);
expect(groupUsers.length).toBe(3);
expect(groupUsers.map((user) => user.user_id)).toEqual(userIds);
}
//DBアクセスに失敗するようにする
const typistGroupService = module.get<UserGroupsRepositoryService>(
UserGroupsRepositoryService,
);
typistGroupService.getTypistGroup = jest
.fn()
.mockRejectedValue('DB failed');
try {
await service.getTypistGroup(context, admin.external_id, group[0].id);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
});
});
describe('updateTypistGroup', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('TypistGroupを更新できる', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
// 作成したアカウントにユーザーを3名追加する
const typiptUserExternalIds = [
'typist-user-external-id1',
'typist-user-external-id2',
'typist-user-external-id3',
];
const userIds: number[] = [];
for (const typiptUserExternalId of typiptUserExternalIds) {
const { id: userId } = await makeTestUser(source, {
account_id: account.id,
external_id: typiptUserExternalId,
role: USER_ROLES.TYPIST,
});
userIds.push(userId);
}
const service = module.get<AccountsService>(AccountsService);
const typistUserIds = [userIds[1]];
const context = makeContext(admin.external_id);
const typistGroupName = 'typist-group-name';
await service.createTypistGroup(
context,
admin.external_id,
typistGroupName,
[userIds[0]],
);
//作成したデータを確認
const group = await getTypistGroup(source, account.id);
{
const group = await getTypistGroup(source, account.id);
expect(group.length).toBe(1);
expect(group[0].name).toBe(typistGroupName);
const groupUsers = await getTypistGroupMember(source, group[0].id);
expect(groupUsers.length).toBe(1);
expect(groupUsers[0].user_group_id).toEqual(group[0].id);
expect(groupUsers[0].user_id).toEqual(userIds[0]);
}
const updateTypistGroupName = 'typist-group-name-update';
await service.updateTypistGroup(
context,
admin.external_id,
group[0].id,
updateTypistGroupName,
typistUserIds,
);
//実行結果を確認
{
const typistGroups = await getTypistGroup(source, account.id);
expect(typistGroups.length).toBe(1);
expect(typistGroups[0].name).toBe(updateTypistGroupName);
const typistGroupUsers = await getTypistGroupMember(
source,
typistGroups[0].id,
);
expect(typistGroupUsers.length).toBe(1);
expect(typistGroupUsers[0].user_id).toEqual(userIds[1]);
}
});
it('typistIdsにRole:typist以外のユーザーが含まれていた場合、400エラーを返却する', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
// 作成したアカウントにユーザーを3名追加する
const typiptUserExternalIds = [
'typist-user-external-id1',
'typist-user-external-id2',
'typist-user-external-id3',
];
const userIds: number[] = [];
for (const typiptUserExternalId of typiptUserExternalIds) {
const { id: userId } = await makeTestUser(source, {
account_id: account.id,
external_id: typiptUserExternalId,
role:
typiptUserExternalId === 'typist-user-external-id3'
? USER_ROLES.NONE
: USER_ROLES.TYPIST, //typist-user-external-id3のみRole:none
});
userIds.push(userId);
}
const typistGroupName = 'typist-group-name';
const service = module.get<AccountsService>(AccountsService);
const typistUserIds = [userIds[2]];
const context = makeContext(admin.external_id);
await service.createTypistGroup(
context,
admin.external_id,
typistGroupName,
[userIds[0]],
);
//作成したデータを確認
const group = await getTypistGroup(source, account.id);
{
expect(group.length).toBe(1);
expect(group[0].name).toBe(typistGroupName);
const groupUsers = await getTypistGroupMember(source, group[0].id);
expect(groupUsers.length).toBe(1);
expect(groupUsers[0].user_group_id).toEqual(group[0].id);
expect(groupUsers[0].user_id).toEqual(userIds[0]);
}
const updateTypistGroupName = 'typist-group-name-update';
try {
await service.updateTypistGroup(
context,
admin.external_id,
group[0].id,
updateTypistGroupName,
typistUserIds,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010204'));
} else {
fail();
}
}
});
it('typistIdsに存在しないユーザーが含まれていた場合、400エラーを返却する', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
// 作成したアカウントにユーザーを3名追加する
const typiptUserExternalIds = [
'typist-user-external-id1',
'typist-user-external-id2',
'typist-user-external-id3',
];
const userIds: number[] = [];
for (const typiptUserExternalId of typiptUserExternalIds) {
const { id: userId } = await makeTestUser(source, {
account_id: account.id,
external_id: typiptUserExternalId,
role: USER_ROLES.TYPIST,
});
userIds.push(userId);
}
const typistGroupName = 'typist-group-name';
const service = module.get<AccountsService>(AccountsService);
const typistUserIds = [999];
const context = makeContext(admin.external_id);
await service.createTypistGroup(
context,
admin.external_id,
typistGroupName,
[userIds[0]],
);
//作成したデータを確認
const group = await getTypistGroup(source, account.id);
{
expect(group.length).toBe(1);
expect(group[0].name).toBe(typistGroupName);
const groupUsers = await getTypistGroupMember(source, group[0].id);
expect(groupUsers.length).toBe(1);
expect(groupUsers[0].user_group_id).toEqual(group[0].id);
expect(groupUsers[0].user_id).toEqual(userIds[0]);
}
const updateTypistGroupName = 'typist-group-name-update';
try {
await service.updateTypistGroup(
context,
admin.external_id,
group[0].id,
updateTypistGroupName,
typistUserIds,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010204'));
} else {
fail();
}
}
});
it('タイピストグループが存在しない場合、400エラーを返却する', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
// 作成したアカウントにユーザーを3名追加する
const typiptUserExternalIds = [
'typist-user-external-id1',
'typist-user-external-id2',
'typist-user-external-id3',
];
const userIds: number[] = [];
for (const typiptUserExternalId of typiptUserExternalIds) {
const { id: userId } = await makeTestUser(source, {
account_id: account.id,
external_id: typiptUserExternalId,
role: USER_ROLES.TYPIST,
});
userIds.push(userId);
}
const typistGroupName = 'typist-group-name';
const service = module.get<AccountsService>(AccountsService);
const typistUserIds = [userIds[1]];
const context = makeContext(admin.external_id);
await service.createTypistGroup(
context,
admin.external_id,
typistGroupName,
[userIds[0]],
);
//作成したデータを確認
const group = await getTypistGroup(source, account.id);
{
expect(group.length).toBe(1);
expect(group[0].name).toBe(typistGroupName);
const groupUsers = await getTypistGroupMember(source, group[0].id);
expect(groupUsers.length).toBe(1);
expect(groupUsers[0].user_group_id).toEqual(group[0].id);
expect(groupUsers[0].user_id).toEqual(userIds[0]);
}
const updateTypistGroupName = 'typist-group-name-update';
try {
await service.updateTypistGroup(
context,
admin.external_id,
999,
updateTypistGroupName,
typistUserIds,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E010908'));
} else {
fail();
}
}
});
it('DBアクセスに失敗した場合、500エラーを返却する', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
// 作成したアカウントにユーザーを3名追加する
const typiptUserExternalIds = [
'typist-user-external-id1',
'typist-user-external-id2',
'typist-user-external-id3',
];
const userIds: number[] = [];
for (const typiptUserExternalId of typiptUserExternalIds) {
const { id: userId } = await makeTestUser(source, {
account_id: account.id,
external_id: typiptUserExternalId,
role: USER_ROLES.TYPIST,
});
userIds.push(userId);
}
const typistGroupName = 'typist-group-name';
const service = module.get<AccountsService>(AccountsService);
const typistUserIds = [userIds[1]];
const context = makeContext(admin.external_id);
await service.createTypistGroup(
context,
admin.external_id,
typistGroupName,
[userIds[0]],
);
//作成したデータを確認
const group = await getTypistGroup(source, account.id);
{
const group = await getTypistGroup(source, account.id);
expect(group.length).toBe(1);
expect(group[0].name).toBe(typistGroupName);
const groupUsers = await getTypistGroupMember(source, group[0].id);
expect(groupUsers.length).toBe(1);
expect(groupUsers[0].user_group_id).toEqual(group[0].id);
expect(groupUsers[0].user_id).toEqual(userIds[0]);
}
const updateTypistGroupName = 'typist-group-name-update';
//DBアクセスに失敗するようにする
const typistGroupService = module.get<UserGroupsRepositoryService>(
UserGroupsRepositoryService,
);
typistGroupService.updateTypistGroup = jest
.fn()
.mockRejectedValue('DB failed');
try {
await service.updateTypistGroup(
context,
admin.external_id,
group[0].id,
updateTypistGroupName,
typistUserIds,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
});
});
describe('getWorktypes', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('アカウント内のWorktypeを取得できる', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
await createWorktype(source, account.id, 'worktype1', 'description1', true);
await createWorktype(source, account.id, 'worktype2');
//作成したデータを確認
const worktypes = await getWorktypes(source, account.id);
const accounts = await getAccounts(source);
{
expect(worktypes.length).toBe(2);
expect(worktypes[0].custom_worktype_id).toBe('worktype1');
expect(worktypes[1].custom_worktype_id).toBe('worktype2');
expect(worktypes[0].description).toBe('description1');
expect(worktypes[1].description).toBeNull();
expect(accounts.length).toBe(1);
expect(accounts[0].active_worktype_id).toBe(worktypes[0].id);
}
const resWorktypes = await service.getWorktypes(context, admin.external_id);
//実行結果を確認
{
expect(resWorktypes.worktypes.length).toBe(2);
expect(resWorktypes.worktypes[0].worktypeId).toBe('worktype1');
expect(resWorktypes.worktypes[1].worktypeId).toBe('worktype2');
expect(resWorktypes.worktypes[0].description).toBe('description1');
expect(resWorktypes.worktypes[1].description).toBe(undefined);
expect(resWorktypes.active).toBe(worktypes[0].id);
}
});
it('アカウント内のWorktypeを取得できる0件', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const resWorktypes = await service.getWorktypes(context, admin.external_id);
//実行結果を確認
{
expect(resWorktypes.worktypes.length).toBe(0);
}
});
it('DBアクセスに失敗した場合、500エラーを返却する', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
await createWorktype(source, account.id, 'worktype1', 'description1');
await createWorktype(source, account.id, 'worktype2');
//作成したデータを確認
const worktypes = await getWorktypes(source, account.id);
{
expect(worktypes.length).toBe(2);
expect(worktypes[0].custom_worktype_id).toBe('worktype1');
expect(worktypes[1].custom_worktype_id).toBe('worktype2');
expect(worktypes[0].description).toBe('description1');
expect(worktypes[1].description).toBeNull();
}
//DBアクセスに失敗するようにする
const worktypeService = module.get<WorktypesRepositoryService>(
WorktypesRepositoryService,
);
worktypeService.getWorktypes = jest.fn().mockRejectedValue('DB failed');
try {
await service.getWorktypes(context, admin.external_id);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
});
});
describe('createWorktype', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('Worktypeを作成できる', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
// Worktypeが未登録であることを確認
{
const worktypes = await getWorktypes(source, account.id);
const optionItems = await getOptionItems(source);
expect(worktypes.length).toBe(0);
expect(optionItems.length).toBe(0);
}
await service.createWorktype(
context,
admin.external_id,
'worktype1',
'description1',
);
//実行結果を確認
{
const worktypes = await getWorktypes(source, account.id);
const optionItems = await getOptionItems(source, worktypes[0].id);
expect(worktypes.length).toBe(1);
expect(worktypes[0].custom_worktype_id).toBe('worktype1');
expect(worktypes[0].description).toBe('description1');
expect(optionItems.length).toBe(10);
expect(optionItems[0].item_label).toBe('');
expect(optionItems[0].default_value_type).toBe(
OPTION_ITEM_VALUE_TYPE.DEFAULT,
);
expect(optionItems[0].initial_value).toBe('');
}
});
it('WorktypeIDが登録済みのWorktypeIDと重複した場合、400エラーとなること', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const worktypeId = 'worktype1';
await createWorktype(source, account.id, worktypeId);
//作成したデータを確認
{
const worktypes = await getWorktypes(source, account.id);
expect(worktypes.length).toBe(1);
expect(worktypes[0].custom_worktype_id).toBe(worktypeId);
}
try {
await service.createWorktype(context, admin.external_id, worktypeId);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E011001'));
} else {
fail();
}
}
});
it('WorktypeIDがすでに最大登録数20件まで登録されている場合、400エラーとなること', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
// あらかじめ最大登録数分のWorktypeを登録する
for (let i = 0; i < WORKTYPE_MAX_COUNT; i++) {
await createWorktype(source, account.id, `worktype${i + 1}`);
}
//作成したデータを確認
{
const worktypes = await getWorktypes(source, account.id);
expect(worktypes.length).toBe(WORKTYPE_MAX_COUNT);
}
try {
await service.createWorktype(context, admin.external_id, 'newWorktypeID');
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E011002'));
} else {
fail();
}
}
});
it('DBアクセスに失敗した場合、500エラーを返却する', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
//DBアクセスに失敗するようにする
const worktypeService = module.get<WorktypesRepositoryService>(
WorktypesRepositoryService,
);
worktypeService.createWorktype = jest.fn().mockRejectedValue('DB failed');
try {
await service.createWorktype(context, admin.external_id, 'worktype1');
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
});
});
describe('updateWorktype', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('Worktypeを更新できる', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const worktype = new Worktype();
worktype.custom_worktype_id = 'worktypeID1';
worktype.description = 'description1';
await createWorktype(
source,
account.id,
worktype.custom_worktype_id,
worktype.description,
);
// Worktypeを確認
const worktypes = await getWorktypes(source, account.id);
{
expect(worktypes.length).toBe(1);
expect(worktypes[0].custom_worktype_id).toBe(worktype.custom_worktype_id);
expect(worktypes[0].description).toBe(worktype.description);
}
const updateWorktypeId = 'updateWorktypeID';
const updateDescription = 'updateDescription';
await service.updateWorktype(
context,
admin.external_id,
worktypes[0].id,
updateWorktypeId,
updateDescription,
);
//実行結果を確認
{
const worktypes = await getWorktypes(source, account.id);
expect(worktypes.length).toBe(1);
expect(worktypes[0].custom_worktype_id).toBe(updateWorktypeId);
expect(worktypes[0].description).toBe(updateDescription);
}
});
it('指定したIDが登録されていない場合、400エラーとなること', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const worktype = new Worktype();
worktype.custom_worktype_id = 'worktypeID1';
worktype.description = 'description1';
await createWorktype(
source,
account.id,
worktype.custom_worktype_id,
worktype.description,
);
// Worktypeを確認
{
const worktypes = await getWorktypes(source, account.id);
expect(worktypes.length).toBe(1);
expect(worktypes[0].custom_worktype_id).toBe(worktype.custom_worktype_id);
expect(worktypes[0].description).toBe(worktype.description);
}
try {
await service.updateWorktype(
context,
admin.external_id,
999,
'newWorktypeID',
'newDescription',
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E011003'));
} else {
fail();
}
}
});
it('WorktypeIDが登録済みのWorktypeIDと重複した場合、400エラーとなること', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const worktype1 = new Worktype();
worktype1.custom_worktype_id = 'worktypeID1';
worktype1.description = 'description1';
const worktype2 = new Worktype();
worktype2.custom_worktype_id = 'worktypeID2';
worktype2.description = 'description2';
await createWorktype(
source,
account.id,
worktype1.custom_worktype_id,
worktype1.description,
);
await createWorktype(
source,
account.id,
worktype2.custom_worktype_id,
worktype2.description,
);
//作成したデータを確認
const worktypes = await getWorktypes(source, account.id);
{
expect(worktypes.length).toBe(2);
expect(worktypes[0].custom_worktype_id).toBe(
worktype1.custom_worktype_id,
);
expect(worktypes[0].description).toBe(worktype1.description);
expect(worktypes[1].custom_worktype_id).toBe(
worktype2.custom_worktype_id,
);
expect(worktypes[1].description).toBe(worktype2.description);
}
try {
await service.updateWorktype(
context,
admin.external_id,
worktypes[0].id,
worktype2.custom_worktype_id,
worktype2.description,
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E011001'));
} else {
fail();
}
}
});
it('WorktypeIDが登録済みの指定IDのWorktypeIDと重複した場合でも更新できること', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const worktype = new Worktype();
worktype.custom_worktype_id = 'worktypeID1';
worktype.description = 'description1';
await createWorktype(
source,
account.id,
worktype.custom_worktype_id,
worktype.description,
);
// Worktypeを確認
const worktypes = await getWorktypes(source, account.id);
{
expect(worktypes.length).toBe(1);
expect(worktypes[0].custom_worktype_id).toBe(worktype.custom_worktype_id);
expect(worktypes[0].description).toBe(worktype.description);
}
const updateDescription = 'updateDescription';
await service.updateWorktype(
context,
admin.external_id,
worktypes[0].id,
worktype.custom_worktype_id,
updateDescription,
);
//実行結果を確認
{
const worktypes = await getWorktypes(source, account.id);
expect(worktypes.length).toBe(1);
expect(worktypes[0].custom_worktype_id).toBe(worktype.custom_worktype_id);
expect(worktypes[0].description).toBe(updateDescription);
}
});
it('DBアクセスに失敗した場合、500エラーを返却する', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const worktype = new Worktype();
worktype.custom_worktype_id = 'worktypeID1';
worktype.description = 'description1';
await createWorktype(
source,
account.id,
worktype.custom_worktype_id,
worktype.description,
);
// Worktypeを確認
const worktypes = await getWorktypes(source, account.id);
{
expect(worktypes.length).toBe(1);
expect(worktypes[0].custom_worktype_id).toBe(worktype.custom_worktype_id);
expect(worktypes[0].description).toBe(worktype.description);
}
//DBアクセスに失敗するようにする
const worktypeService = module.get<WorktypesRepositoryService>(
WorktypesRepositoryService,
);
worktypeService.updateWorktype = jest.fn().mockRejectedValue('DB failed');
try {
await service.updateWorktype(
context,
admin.external_id,
worktypes[0].id,
'newWorktype',
'newDescription',
);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
});
});
describe('getOptionItems', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('指定WorktypeIDに紐づいたOptionItemを取得できる', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const worktype = await createWorktype(source, account.id, 'worktype1');
const optionItems = await createOptionItems(source, worktype.id);
//作成したデータを確認
{
expect(optionItems.length).toBe(10);
expect(optionItems[0].item_label).toBe('');
expect(optionItems[0].default_value_type).toBe(
OPTION_ITEM_VALUE_TYPE.DEFAULT,
);
expect(optionItems[0].initial_value).toBe('');
}
const resOptionItems = await service.getOptionItems(
context,
admin.external_id,
worktype.id,
);
//実行結果を確認
{
expect(resOptionItems.optionItems.length).toBe(10);
expect(resOptionItems.optionItems.map((x) => x.id)).toEqual(
optionItems.map((x) => x.id),
);
expect(resOptionItems.optionItems[0].itemLabel).toBe('');
expect(resOptionItems.optionItems[0].defaultValueType).toBe(
OPTION_ITEM_VALUE_TYPE.DEFAULT,
);
expect(resOptionItems.optionItems[0].initialValue).toBe('');
}
});
it('WorktypeIDが存在しない場合、400エラーとなること', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const worktype = await createWorktype(source, account.id, 'worktype1');
const optionItems = await createOptionItems(source, worktype.id);
//作成したデータを確認
{
expect(optionItems.length).toBe(10);
expect(optionItems[0].item_label).toBe('');
expect(optionItems[0].default_value_type).toBe(
OPTION_ITEM_VALUE_TYPE.DEFAULT,
);
expect(optionItems[0].initial_value).toBe('');
}
try {
await service.getOptionItems(context, admin.external_id, 999);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E011003'));
} else {
fail();
}
}
});
it('DBアクセスに失敗した場合、500エラーを返却する', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const worktype = await createWorktype(source, account.id, 'worktype1');
const optionItems = await createOptionItems(source, worktype.id);
//作成したデータを確認
{
expect(optionItems.length).toBe(10);
expect(optionItems[0].item_label).toBe('');
expect(optionItems[0].default_value_type).toBe(
OPTION_ITEM_VALUE_TYPE.DEFAULT,
);
expect(optionItems[0].initial_value).toBe('');
}
//DBアクセスに失敗するようにする
const worktypesService = module.get<WorktypesRepositoryService>(
WorktypesRepositoryService,
);
worktypesService.getOptionItems = jest.fn().mockRejectedValue('DB failed');
try {
await service.getOptionItems(context, admin.external_id, worktype.id);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
});
});
describe('updateOptionItems', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('指定WorktypeIDに紐づいたOptionItemを更新できる', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const worktype = await createWorktype(source, account.id, 'worktype1');
const optionItems = await createOptionItems(source, worktype.id);
//作成したデータを確認
{
expect(optionItems.length).toBe(10);
expect(optionItems[0].item_label).toBe('');
expect(optionItems[0].default_value_type).toBe(
OPTION_ITEM_VALUE_TYPE.DEFAULT,
);
expect(optionItems[0].initial_value).toBe('');
expect(optionItems[1].item_label).toBe('');
expect(optionItems[1].default_value_type).toBe(
OPTION_ITEM_VALUE_TYPE.DEFAULT,
);
expect(optionItems[1].initial_value).toBe('');
expect(optionItems[2].item_label).toBe('');
expect(optionItems[2].default_value_type).toBe(
OPTION_ITEM_VALUE_TYPE.DEFAULT,
);
expect(optionItems[2].initial_value).toBe('');
expect(optionItems[3].item_label).toBe('');
expect(optionItems[3].default_value_type).toBe(
OPTION_ITEM_VALUE_TYPE.DEFAULT,
);
expect(optionItems[3].initial_value).toBe('');
}
await service.updateOptionItems(context, admin.external_id, worktype.id, [
{
itemLabel: 'itemLabel1',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: 'initialValue1',
},
{
itemLabel: 'itemLabel2',
defaultValueType: OPTION_ITEM_VALUE_TYPE.BLANK,
initialValue: '',
},
{
itemLabel: 'itemLabel3',
defaultValueType: OPTION_ITEM_VALUE_TYPE.LAST_INPUT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.BLANK,
initialValue: 'initialValue4',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
]);
//実行結果を確認
{
const resOptionItems = await getOptionItems(source, worktype.id);
expect(resOptionItems.length).toBe(10);
expect(resOptionItems[0].item_label).toBe('itemLabel1');
expect(resOptionItems[0].default_value_type).toBe(
OPTION_ITEM_VALUE_TYPE.DEFAULT,
);
expect(resOptionItems[0].initial_value).toBe('initialValue1');
expect(resOptionItems[1].item_label).toBe('itemLabel2');
expect(resOptionItems[1].default_value_type).toBe(
OPTION_ITEM_VALUE_TYPE.BLANK,
);
expect(resOptionItems[1].initial_value).toBe('');
expect(resOptionItems[2].item_label).toBe('itemLabel3');
expect(resOptionItems[2].default_value_type).toBe(
OPTION_ITEM_VALUE_TYPE.LAST_INPUT,
);
expect(resOptionItems[2].initial_value).toBe('');
expect(resOptionItems[3].item_label).toBe('');
expect(resOptionItems[3].default_value_type).toBe(
OPTION_ITEM_VALUE_TYPE.BLANK,
);
expect(resOptionItems[3].initial_value).toBe('');
}
});
it('WorktypeIDが存在しない場合、400エラーとなること', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const worktype = await createWorktype(source, account.id, 'worktype1');
const optionItems = await createOptionItems(source, worktype.id);
//作成したデータを確認
{
expect(optionItems.length).toBe(10);
expect(optionItems[0].item_label).toBe('');
expect(optionItems[0].default_value_type).toBe(
OPTION_ITEM_VALUE_TYPE.DEFAULT,
);
expect(optionItems[0].initial_value).toBe('');
}
try {
await service.updateOptionItems(context, admin.external_id, 999, [
{
itemLabel: 'itemLabel1',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: 'initialValue1',
},
{
itemLabel: 'itemLabel2',
defaultValueType: OPTION_ITEM_VALUE_TYPE.BLANK,
initialValue: '',
},
{
itemLabel: 'itemLabel3',
defaultValueType: OPTION_ITEM_VALUE_TYPE.LAST_INPUT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
]);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E011003'));
} else {
fail();
}
}
});
it('DBアクセスに失敗した場合、500エラーを返却する', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const worktype = await createWorktype(source, account.id, 'worktype1');
const optionItems = await createOptionItems(source, worktype.id);
//作成したデータを確認
{
expect(optionItems.length).toBe(10);
expect(optionItems[0].item_label).toBe('');
expect(optionItems[0].default_value_type).toBe(
OPTION_ITEM_VALUE_TYPE.DEFAULT,
);
expect(optionItems[0].initial_value).toBe('');
}
//DBアクセスに失敗するようにする
const worktypesService = module.get<WorktypesRepositoryService>(
WorktypesRepositoryService,
);
worktypesService.updateOptionItems = jest
.fn()
.mockRejectedValue('DB failed');
try {
await service.updateOptionItems(context, admin.external_id, worktype.id, [
{
itemLabel: 'itemLabel1',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: 'initialValue1',
},
{
itemLabel: 'itemLabel2',
defaultValueType: OPTION_ITEM_VALUE_TYPE.BLANK,
initialValue: '',
},
{
itemLabel: 'itemLabel3',
defaultValueType: OPTION_ITEM_VALUE_TYPE.LAST_INPUT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
{
itemLabel: '',
defaultValueType: OPTION_ITEM_VALUE_TYPE.DEFAULT,
initialValue: '',
},
]);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
});
});
describe('updateActiveWorktype', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('アカウントのActiveWorktypeIDを指定WorktypeIDに更新できるNULL⇒ID設定', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const worktype = await createWorktype(source, account.id, 'worktype1');
//作成したデータを確認
{
const beforeAccount = await getAccount(source, account.id);
expect(beforeAccount.active_worktype_id).toBe(null);
}
await service.updateActiveWorktype(context, admin.external_id, worktype.id);
//実行結果を確認
{
const { active_worktype_id } = await getAccount(source, account.id);
expect(active_worktype_id).toBe(worktype.id);
}
});
it('アカウントのActiveWorktypeIDを指定WorktypeIDに更新できる別のWorkTypeIDを設定', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const worktype1 = await createWorktype(
source,
account.id,
'worktype1',
'description1',
true,
);
const worktype2 = await createWorktype(source, account.id, 'worktype2');
//作成したデータを確認
{
const beforeAccount = await getAccount(source, account.id);
expect(beforeAccount.active_worktype_id).toBe(worktype1.id);
}
await service.updateActiveWorktype(
context,
admin.external_id,
worktype2.id,
);
//実行結果を確認
{
const { active_worktype_id } = await getAccount(source, account.id);
expect(active_worktype_id).toBe(worktype2.id);
}
});
it('アカウントのActiveWorktypeIDをNULLに更新できるWorkTypeID⇒NULL', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const worktype1 = await createWorktype(
source,
account.id,
'worktype1',
'description1',
true,
);
//作成したデータを確認
{
const beforeAccount = await getAccount(source, account.id);
expect(beforeAccount.active_worktype_id).toBe(worktype1.id);
}
await service.updateActiveWorktype(context, admin.external_id, undefined);
//実行結果を確認
{
const { active_worktype_id } = await getAccount(source, account.id);
expect(active_worktype_id).toBe(null);
}
});
it('自アカウント内に指定されたIDのWorktypeIDが存在しない場合、400エラーとなることWorkTypeIDが存在しない場合', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
await createWorktype(source, account.id, 'worktype1');
//作成したデータを確認
{
const beforeAccount = await getAccount(source, account.id);
expect(beforeAccount.active_worktype_id).toBe(null);
}
try {
await service.updateActiveWorktype(context, admin.external_id, 999);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E011003'));
} else {
fail();
}
}
});
it('自アカウント内に指定されたIDのWorktypeIDが存在しない場合、400エラーとなることWorkTypeIDが別アカウントの場合', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const { account: otherAccount } = await makeTestAccount(source, {
tier: 5,
});
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
await createWorktype(source, account.id, 'worktype1');
await createWorktype(source, otherAccount.id, 'worktype2');
//作成したデータを確認
{
const beforeAccount = await getAccount(source, account.id);
const worktype1 = await getWorktypes(source, account.id);
const worktype2 = await getWorktypes(source, otherAccount.id);
expect(beforeAccount.active_worktype_id).toBe(null);
expect(worktype1.length).toBe(1);
expect(worktype1[0].custom_worktype_id).toBe('worktype1');
expect(worktype2.length).toBe(1);
expect(worktype2[0].custom_worktype_id).toBe('worktype2');
}
try {
await service.updateActiveWorktype(context, admin.external_id, 999);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
expect(e.getResponse()).toEqual(makeErrorResponse('E011003'));
} else {
fail();
}
}
});
it('DBアクセスに失敗した場合、500エラーを返却する', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
await createWorktype(source, account.id, 'worktype1');
//作成したデータを確認
{
const beforeAccount = await getAccount(source, account.id);
expect(beforeAccount.active_worktype_id).toBe(null);
}
//DBアクセスに失敗するようにする
const accountsRepositoryService = module.get<AccountsRepositoryService>(
AccountsRepositoryService,
);
accountsRepositoryService.updateActiveWorktypeId = jest
.fn()
.mockRejectedValue('DB failed');
try {
await service.updateActiveWorktype(context, admin.external_id, 999);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
});
});
describe('ライセンス発行キャンセル', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('ライセンス発行のキャンセルが完了する(第一階層で実行)', async () => {
const module = await makeTestingModule(source);
const { tier1Accounts: tier1Accounts, tier4Accounts: tier4Accounts } =
await makeHierarchicalAccounts(source);
const tier5Accounts = await makeTestAccount(source, {
parent_account_id: tier4Accounts[0].account.id,
tier: 5,
});
const poNumber = 'CANCEL_TEST';
const date = new Date();
date.setDate(date.getDate() - 10);
await createOrder(
source,
poNumber,
tier5Accounts.account.id,
tier5Accounts.account.parent_account_id,
date,
1,
LICENSE_ISSUE_STATUS.ISSUED,
);
date.setDate(date.getDate() + 10);
// 発行時に論理削除されたライセンス情報
await createLicense(
source,
1,
date,
tier5Accounts.account.id,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
null,
date,
1,
);
const service = module.get<AccountsService>(AccountsService);
await service.cancelIssue(
makeContext('trackingId'),
tier1Accounts[0].users[0].external_id,
poNumber,
tier5Accounts.account.id,
);
// 発行待ちに戻した注文の状態確認
const orderRecord = await selectOrderLicense(
source,
tier5Accounts.account.id,
poNumber,
);
expect(orderRecord.orderLicense.issued_at).toBe(null);
expect(orderRecord.orderLicense.status).toBe(
LICENSE_ISSUE_STATUS.ISSUE_REQUESTING,
);
// 未割当に戻したライセンスの状態確認
const licenseRecord = await selectLicense(source, 1);
expect(licenseRecord.license.status).toBe(
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
);
expect(licenseRecord.license.delete_order_id).toBe(null);
expect(licenseRecord.license.deleted_at).toBe(null);
});
it('ライセンス発行のキャンセルが完了する(第二階層で実行)', async () => {
const module = await makeTestingModule(source);
const { tier2Accounts: tier2Accounts, tier4Accounts: tier4Accounts } =
await makeHierarchicalAccounts(source);
const tier5Accounts = await makeTestAccount(source, {
parent_account_id: tier4Accounts[0].account.id,
tier: 5,
});
const poNumber = 'CANCEL_TEST';
const date = new Date();
date.setDate(date.getDate() - 10);
await createOrder(
source,
poNumber,
tier5Accounts.account.id,
tier5Accounts.account.parent_account_id,
date,
1,
LICENSE_ISSUE_STATUS.ISSUED,
);
date.setDate(date.getDate() + 10);
// 発行時に論理削除されたライセンス情報
await createLicense(
source,
1,
date,
tier5Accounts.account.id,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
null,
date,
1,
);
const service = module.get<AccountsService>(AccountsService);
await service.cancelIssue(
makeContext('trackingId'),
tier2Accounts[0].users[0].external_id,
poNumber,
tier5Accounts.account.id,
);
// 発行待ちに戻した注文の状態確認
const orderRecord = await selectOrderLicense(
source,
tier5Accounts.account.id,
poNumber,
);
expect(orderRecord.orderLicense.issued_at).toBe(null);
expect(orderRecord.orderLicense.status).toBe(
LICENSE_ISSUE_STATUS.ISSUE_REQUESTING,
);
// 未割当に戻したライセンスの状態確認
const licenseRecord = await selectLicense(source, 1);
expect(licenseRecord.license.status).toBe(
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
);
expect(licenseRecord.license.delete_order_id).toBe(null);
expect(licenseRecord.license.deleted_at).toBe(null);
});
it('キャンセル対象の発行が存在しない場合エラー', async () => {
const module = await makeTestingModule(source);
const { tier1Accounts: tier1Accounts, tier4Accounts: tier4Accounts } =
await makeHierarchicalAccounts(source);
const tier5Accounts = await makeTestAccount(source, {
parent_account_id: tier4Accounts[0].account.id,
tier: 5,
});
const poNumber = 'CANCEL_TEST';
const service = module.get<AccountsService>(AccountsService);
await expect(
service.cancelIssue(
makeContext('trackingId'),
tier1Accounts[0].users[0].external_id,
poNumber,
tier5Accounts.account.id,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010809'), HttpStatus.BAD_REQUEST),
);
});
it('キャンセル対象の発行が14日より経過していた場合エラー', async () => {
const module = await makeTestingModule(source);
const { tier1Accounts: tier1Accounts, tier4Accounts: tier4Accounts } =
await makeHierarchicalAccounts(source);
const tier5Accounts = await makeTestAccount(source, {
parent_account_id: tier4Accounts[0].account.id,
tier: 5,
});
const poNumber = 'CANCEL_TEST';
const date = new Date();
date.setDate(date.getDate() - 15);
await createOrder(
source,
poNumber,
tier5Accounts.account.id,
tier5Accounts.account.parent_account_id,
date,
1,
LICENSE_ISSUE_STATUS.ISSUED,
);
await createLicense(
source,
1,
date,
tier5Accounts.account.id,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
1,
null,
null,
);
const service = module.get<AccountsService>(AccountsService);
await expect(
service.cancelIssue(
makeContext('trackingId'),
tier1Accounts[0].users[0].external_id,
poNumber,
tier5Accounts.account.id,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010810'), HttpStatus.BAD_REQUEST),
);
});
it('キャンセル対象の発行のライセンスが使われていた場合エラー', async () => {
const module = await makeTestingModule(source);
const { tier1Accounts: tier1Accounts, tier4Accounts: tier4Accounts } =
await makeHierarchicalAccounts(source);
const tier5Accounts = await makeTestAccount(source, {
parent_account_id: tier4Accounts[0].account.id,
tier: 5,
});
const poNumber = 'CANCEL_TEST';
const date = new Date();
date.setDate(date.getDate() - 14);
await createOrder(
source,
poNumber,
tier5Accounts.account.id,
tier5Accounts.account.parent_account_id,
date,
1,
LICENSE_ISSUE_STATUS.ISSUED,
);
await createLicense(
source,
1,
date,
tier5Accounts.account.id,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.ALLOCATED,
null,
1,
null,
null,
);
const service = module.get<AccountsService>(AccountsService);
await expect(
service.cancelIssue(
makeContext('trackingId'),
tier1Accounts[0].users[0].external_id,
poNumber,
tier5Accounts.account.id,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010811'), HttpStatus.BAD_REQUEST),
);
});
it('自身のパートナー以外の発行をキャンセルしようとした場合、エラー', async () => {
const module = await makeTestingModule(source);
const { tier1Accounts: tier1Accounts } = await makeHierarchicalAccounts(
source,
);
const tier5Accounts = await makeTestAccount(source, {
parent_account_id: 100,
tier: 5,
});
const poNumber = 'CANCEL_TEST';
const date = new Date();
date.setDate(date.getDate() - 14);
await createOrder(
source,
poNumber,
tier5Accounts.account.id,
tier5Accounts.account.parent_account_id,
date,
1,
LICENSE_ISSUE_STATUS.ISSUED,
);
await createLicense(
source,
1,
date,
tier5Accounts.account.id,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
1,
null,
null,
);
const service = module.get<AccountsService>(AccountsService);
await expect(
service.cancelIssue(
makeContext('trackingId'),
tier1Accounts[0].users[0].external_id,
poNumber,
tier5Accounts.account.id,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E000108'), HttpStatus.UNAUTHORIZED),
);
});
});
describe('パートナー一覧取得', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('パートナー一覧を取得する', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const { tier1Accounts: tier1Accounts, tier2Accounts: tier2Accounts } =
await makeHierarchicalAccounts(source);
const tier1Difference = await makeTestAccount(source, {
tier: 1,
});
const tier2_3 = await makeTestAccount(
source,
{
parent_account_id: tier1Accounts[0].account.id,
tier: 2,
},
{},
true,
false,
);
const tier2_4 = await makeTestAccount(
source,
{
parent_account_id: tier1Accounts[0].account.id,
tier: 2,
},
{},
true,
true,
);
await makeTestAccount(source, {
parent_account_id: tier1Difference.account.id,
tier: 2,
});
const adb2cReturn = [
{
id: tier2Accounts[0].users[0].external_id,
displayName: 'partner1',
identities: [
{
signInType: ADB2C_SIGN_IN_TYPE.EAMILADDRESS,
issuer: 'issuer',
issuerAssignedId: 'partner1@example.com',
},
],
},
{
id: tier2Accounts[1].users[0].external_id,
displayName: 'partner2',
identities: [
{
signInType: ADB2C_SIGN_IN_TYPE.EAMILADDRESS,
issuer: 'issuer',
issuerAssignedId: 'partner2@example.com',
},
],
},
] as AdB2cUser[];
overrideAdB2cService(service, {
getUsers: async (_context: Context, _externalIds: string[]) => {
return adb2cReturn;
},
});
const partners = await service.getPartners(
makeContext('trackingId'),
tier1Accounts[0].users[0].external_id,
15,
0,
);
// 違うアカウントのパートナーは取得していないこと
expect(partners.total).toBe(4);
// 会社名の昇順に取得できていること
expect(partners.partners[0].name).toBe(
tier2Accounts[1].account.company_name,
);
expect(partners.partners[1].name).toBe(
tier2Accounts[0].account.company_name,
);
expect(partners.partners[2].name).toBe(tier2_3.account.company_name);
expect(partners.partners[3].name).toBe(tier2_4.account.company_name);
expect(partners.partners[0].email).toBe('partner2@example.com');
expect(partners.partners[1].email).toBe('partner1@example.com');
expect(partners.partners[2].email).toBeUndefined;
expect(partners.partners[3].email).toBeUndefined;
expect(partners.partners[0].tier).toBe(tier2Accounts[1].account.tier);
expect(partners.partners[0].country).toBe(tier2Accounts[1].account.country);
expect(partners.partners[0].accountId).toBe(tier2Accounts[1].account.id);
expect(partners.partners[0].tier).toBe(tier2Accounts[1].account.tier);
expect(partners.partners[0].primaryAdmin).toBe('partner2');
expect(partners.partners[0].dealerManagement).toBe(
tier2Accounts[1].account.delegation_permission,
);
});
it('パートナー一覧を取得する(パートナーが0件の場合)', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const account = await makeTestAccount(source, {
tier: 1,
});
const adb2cReturn = [{}] as AdB2cUser[];
overrideAdB2cService(service, {
getUsers: async (_context: Context, _externalIds: string[]) => {
return adb2cReturn;
},
});
const partners = await service.getPartners(
makeContext('trackingId'),
account.admin.external_id,
15,
0,
);
// 結果が0件で成功となること
expect(partners.total).toBe(0);
});
});
describe('アカウント情報更新', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('アカウント情報を更新する(第五階層が実行/セカンダリ管理者ユーザがnull', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const { tier4Accounts: tier4Accounts } = await makeHierarchicalAccounts(
source,
);
const tier5Accounts = await makeTestAccount(source, {
parent_account_id: tier4Accounts[0].account.id,
tier: 5,
});
await service.updateAccountInfo(
makeContext('trackingId'),
tier5Accounts.admin.external_id,
tier5Accounts.account.tier,
true,
tier5Accounts.admin.id,
tier4Accounts[0].account.id,
undefined,
);
// DB内が想定通りになっているか確認
const account = await getAccount(source, tier5Accounts.account.id);
expect(account.parent_account_id).toBe(tier4Accounts[0].account.id);
expect(account.delegation_permission).toBe(true);
expect(account.primary_admin_user_id).toBe(tier5Accounts.admin.id);
expect(account.secondary_admin_user_id).toBe(null);
});
it('アカウント情報を更新する(第五階層以外が実行)', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const { tier3Accounts: tier3Accounts, tier4Accounts: tier4Accounts } =
await makeHierarchicalAccounts(source);
const adduser = await makeTestUser(source, {
account_id: tier4Accounts[0].account.id,
external_id: 'typist-user-external-id',
role: 'typist',
});
await service.updateAccountInfo(
makeContext('trackingId'),
tier4Accounts[0].users[0].external_id,
tier4Accounts[0].account.tier,
false,
tier4Accounts[0].users[0].id,
tier3Accounts[0].account.id,
adduser.id,
);
// DB内が想定通りになっているか確認
const account = await getAccount(source, tier4Accounts[0].account.id);
expect(account.parent_account_id).toBe(tier3Accounts[0].account.id);
expect(account.delegation_permission).toBe(false);
expect(account.primary_admin_user_id).toBe(tier4Accounts[0].users[0].id);
expect(account.secondary_admin_user_id).toBe(adduser.id);
});
it('アカウント情報を更新する(ディーラーアカウントが未入力)', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const { tier3Accounts: tier3Accounts, tier4Accounts: tier4Accounts } =
await makeHierarchicalAccounts(source);
const adduser = await makeTestUser(source, {
account_id: tier4Accounts[0].account.id,
external_id: 'typist-user-external-id',
role: 'typist',
});
await service.updateAccountInfo(
makeContext('trackingId'),
tier4Accounts[0].users[0].external_id,
tier4Accounts[0].account.tier,
false,
tier4Accounts[0].users[0].id,
undefined,
adduser.id,
);
// DB内が想定通りになっているか確認
const account = await getAccount(source, tier4Accounts[0].account.id);
expect(account.parent_account_id).toBe(null);
expect(account.delegation_permission).toBe(false);
expect(account.primary_admin_user_id).toBe(tier4Accounts[0].users[0].id);
expect(account.secondary_admin_user_id).toBe(adduser.id);
});
it('アカウント情報の更新に失敗する(ディーラー未存在)', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const { tier4Accounts: tier4Accounts } = await makeHierarchicalAccounts(
source,
);
const adduser = await makeTestUser(source, {
account_id: tier4Accounts[0].account.id,
external_id: 'typist-user-external-id',
role: 'typist',
});
await expect(
service.updateAccountInfo(
makeContext('trackingId'),
tier4Accounts[0].users[0].external_id,
tier4Accounts[0].account.tier,
false,
tier4Accounts[0].users[0].id,
123,
adduser.id,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010502'), HttpStatus.BAD_REQUEST),
);
});
it('アカウント情報の更新に失敗する(プライマリ管理者ユーザ未存在)', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const { tier4Accounts: tier4Accounts } = await makeHierarchicalAccounts(
source,
);
const tier5Accounts = await makeTestAccount(source, {
parent_account_id: tier4Accounts[0].account.id,
tier: 5,
});
await expect(
service.updateAccountInfo(
makeContext('trackingId'),
tier5Accounts.admin.external_id,
tier5Accounts.account.tier,
true,
999,
tier4Accounts[0].account.id,
tier4Accounts[1].users[0].id,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010502'), HttpStatus.BAD_REQUEST),
);
});
it('アカウント情報の更新に失敗する(セカンダリ管理者ユーザ未存在)', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const { tier4Accounts: tier4Accounts } = await makeHierarchicalAccounts(
source,
);
const tier5Accounts = await makeTestAccount(source, {
parent_account_id: tier4Accounts[0].account.id,
tier: 5,
});
await expect(
service.updateAccountInfo(
makeContext('trackingId'),
tier5Accounts.admin.external_id,
tier5Accounts.account.tier,
true,
tier4Accounts[0].users[0].id,
tier4Accounts[0].account.id,
999,
),
).rejects.toEqual(
new HttpException(makeErrorResponse('E010502'), HttpStatus.BAD_REQUEST),
);
});
});
describe('getAccountInfo', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('パラメータのユーザに対応するアカウント情報を取得できる', async () => {
const module = await makeTestingModule(source);
const { tier4Accounts: tier4Accounts } = await makeHierarchicalAccounts(
source,
);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, {
parent_account_id: tier4Accounts[0].account.id,
});
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const accountResponse = await service.getAccountInfo(
context,
admin.external_id,
);
//実行結果を確認
{
expect(accountResponse.account.accountId).toBe(account.id);
expect(accountResponse.account.companyName).toBe(account.company_name);
expect(accountResponse.account.country).toBe(account.country);
expect(accountResponse.account.delegationPermission).toBe(
account.delegation_permission,
);
expect(accountResponse.account.parentAccountId).toBe(
account.parent_account_id,
);
expect(accountResponse.account.primaryAdminUserId).toBe(
account.primary_admin_user_id,
);
expect(accountResponse.account.secondryAdminUserId).toBe(undefined);
expect(accountResponse.account.tier).toBe(account.tier);
expect(accountResponse.account.parentAccountName).toBe(
tier4Accounts[0].account.company_name,
);
}
});
});
describe('getAuthors', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('アカウント内のAuthorユーザーの一覧を取得できる', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { account, admin } = await makeTestAccount(source, { tier: 5 });
const { id: userId1 } = await makeTestUser(source, {
account_id: account.id,
role: USER_ROLES.AUTHOR,
author_id: 'AUTHOR_ID_1',
});
const { id: userId2 } = await makeTestUser(source, {
account_id: account.id,
role: USER_ROLES.AUTHOR,
author_id: 'AUTHOR_ID_2',
});
const { id: userId3 } = await makeTestUser(source, {
account_id: account.id,
role: USER_ROLES.TYPIST,
});
// 作成したデータを確認
{
const users = await getUsers(source);
expect(users.length).toBe(4);
expect(users[1].id).toBe(userId1);
expect(users[2].id).toBe(userId2);
expect(users[3].id).toBe(userId3);
}
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const authors = await service.getAuthors(context, admin.external_id);
//実行結果を確認
{
expect(authors.length).toBe(2);
expect(authors[0].id).toBe(userId1);
expect(authors[0].authorId).toBe('AUTHOR_ID_1');
expect(authors[1].id).toBe(userId2);
expect(authors[1].authorId).toBe('AUTHOR_ID_2');
}
});
it('アカウント内のAuthorユーザーの一覧を取得できる0件', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { admin } = await makeTestAccount(source, { tier: 5 });
// 作成したデータを確認
{
const users = await getUsers(source);
expect(users.length).toBe(1);
}
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const authors = await service.getAuthors(context, admin.external_id);
//実行結果を確認
{
expect(authors.length).toBe(0);
}
});
it('DBアクセスに失敗した場合、500エラーとなる', async () => {
const module = await makeTestingModule(source);
// 第五階層のアカウント作成
const { admin } = await makeTestAccount(source, { tier: 5 });
const service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
//DBアクセスに失敗するようにする
const usersService = module.get<UsersRepositoryService>(
UsersRepositoryService,
);
usersService.findAuthorUsers = jest.fn().mockRejectedValue('DB failed');
//実行結果を確認
try {
await service.getAuthors(context, admin.external_id);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
});
});
describe('deleteAccountAndData', () => {
let source: DataSource = 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 () => {
await source.destroy();
source = null;
});
it('アカウント情報が削除されること', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
// 第五階層のアカウント作成
const tier4Accounts = await makeHierarchicalAccounts(source);
const { account: account1, admin: admin1 } = await makeTestAccount(source, {
parent_account_id: tier4Accounts.tier4Accounts[0].account.id,
});
const account = account1;
const admin = admin1;
const context = makeContext(admin.external_id);
// 第五階層のアカウント作成
const tier5Accounts = await makeTestAccount(source, {
parent_account_id: account.id,
tier: 5,
});
// ユーザの作成
const user = await makeTestUser(source, {
account_id: tier5Accounts.account.id,
});
// ライセンス作成
await createLicense(
source,
1,
new Date(),
tier5Accounts.account.id,
LICENSE_TYPE.NORMAL,
LICENSE_ALLOCATED_STATUS.UNALLOCATED,
null,
user.id,
null,
null,
);
await createLicenseAllocationHistory(
source,
1,
user.id,
1,
tier5Accounts.account.id,
'NONE',
);
// ADB2Cユーザーの削除成功
overrideAdB2cService(service, {
deleteUsers: jest.fn(),
});
// blobstorageコンテナの削除成功
overrideBlobstorageService(service, {
deleteContainer: jest.fn(),
});
// アカウント情報の削除
await service.deleteAccountAndData(
context,
tier5Accounts.admin.external_id,
tier5Accounts.account.id,
);
// DB内が想定通りになっているか確認
const accountRecord = await getAccount(source, tier5Accounts.account.id);
expect(accountRecord).toBe(null);
const userRecord = await getUser(source, user.id);
expect(userRecord).toBe(null);
const UserArchive = await getUserArchive(source);
expect(UserArchive.length).toBe(2);
const LicenseArchive = await getLicenseArchive(source);
expect(LicenseArchive.length).toBe(1);
const LicenseAllocationHistoryArchive =
await getLicenseAllocationHistoryArchive(source);
expect(LicenseAllocationHistoryArchive.length).toBe(1);
});
it('アカウントの削除に失敗した場合はエラーを返す', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const loggerSpy = jest.spyOn(service['logger'], 'log').mockImplementation();
// 第五階層のアカウント作成
const tier4Accounts = await makeHierarchicalAccounts(source);
const { account: account1, admin: admin1 } = await makeTestAccount(source, {
parent_account_id: tier4Accounts.tier4Accounts[0].account.id,
});
const account = account1;
const admin = admin1;
const context = makeContext(admin.external_id);
// 第五階層のアカウント作成
const tier5Accounts = await makeTestAccount(source, {
parent_account_id: account.id,
tier: 5,
});
// ユーザの作成
const user = await makeTestUser(source, {
account_id: tier5Accounts.account.id,
});
// アカウント情報の削除失敗
overrideAccountsRepositoryService(service, {
deleteAccountAndInsertArchives: jest.fn().mockRejectedValue(new Error()),
});
// ADB2Cユーザーの削除成功
overrideAdB2cService(service, {
deleteUsers: jest.fn(),
});
// blobstorageコンテナの削除成功
overrideBlobstorageService(service, {
deleteContainer: jest.fn(),
});
// アカウント情報の削除に失敗することを確認
await expect(
service.deleteAccountAndData(
context,
tier5Accounts.admin.external_id,
tier5Accounts.account.id,
),
).rejects.toEqual(
new HttpException(
makeErrorResponse('E009999'),
HttpStatus.INTERNAL_SERVER_ERROR,
),
);
// loggerSpyがスパイしているlogger.logメソッドが出力したログを確認目視確認用
const logs = loggerSpy.mock.calls.map((call) => call[0]);
console.log(logs);
// DB内が削除されていないことを確認
const accountRecord = await getAccount(source, tier5Accounts.account.id);
expect(accountRecord.id).not.toBeNull();
const userRecord = await getUser(source, user.id);
expect(userRecord.id).not.toBeNull();
});
it('ADB2Cユーザーの削除失敗時は、MANUAL_RECOVERY_REQUIREDを出して処理続行', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const loggerSpy = jest.spyOn(service['logger'], 'log').mockImplementation();
// 第五階層のアカウント作成
const tier4Accounts = await makeHierarchicalAccounts(source);
const { account: account1, admin: admin1 } = await makeTestAccount(source, {
parent_account_id: tier4Accounts.tier4Accounts[0].account.id,
});
const account = account1;
const admin = admin1;
const context = makeContext(admin.external_id);
// 第五階層のアカウント作成
const tier5Accounts = await makeTestAccount(source, {
parent_account_id: account.id,
tier: 5,
});
// ユーザの作成
const user = await makeTestUser(source, {
account_id: tier5Accounts.account.id,
});
// ADB2Cユーザーの削除失敗
overrideAdB2cService(service, {
deleteUsers: jest.fn().mockRejectedValue(new Error()),
});
// blobstorageコンテナの削除成功
overrideBlobstorageService(service, {
deleteContainer: jest.fn(),
});
// 処理自体は成功することを確認
expect(
await service.deleteAccountAndData(
context,
tier5Accounts.admin.external_id,
tier5Accounts.account.id,
),
).toEqual(undefined);
// loggerSpyがスパイしているlogger.logメソッドが出力したログを確認目視確認用
const logs = loggerSpy.mock.calls.map((call) => call[0]);
console.log(logs);
// DB内が想定通りになっているか確認
const accountRecord = await getAccount(source, tier5Accounts.account.id);
expect(accountRecord).toBe(null);
const userRecord = await getUser(source, user.id);
expect(userRecord).toBe(null);
});
it('blobstorageコンテナを削除で失敗した場合は、MANUAL_RECOVERY_REQUIRED出して正常終了', async () => {
const module = await makeTestingModule(source);
const service = module.get<AccountsService>(AccountsService);
const loggerSpy = jest.spyOn(service['logger'], 'log').mockImplementation();
// 第五階層のアカウント作成
const tier4Accounts = await makeHierarchicalAccounts(source);
const { account: account1, admin: admin1 } = await makeTestAccount(source, {
parent_account_id: tier4Accounts.tier4Accounts[0].account.id,
});
const account = account1;
const admin = admin1;
const context = makeContext(admin.external_id);
// 第五階層のアカウント作成
const tier5Accounts = await makeTestAccount(source, {
parent_account_id: account.id,
tier: 5,
});
// ユーザの作成
const user = await makeTestUser(source, {
account_id: tier5Accounts.account.id,
});
// ADB2Cユーザーの削除成功
overrideAdB2cService(service, {
deleteUsers: jest.fn(),
});
// blobstorageコンテナの削除失敗
overrideBlobstorageService(service, {
deleteContainer: jest.fn().mockRejectedValue(new Error()),
});
// 処理自体は成功することを確認
expect(
await service.deleteAccountAndData(
context,
tier5Accounts.admin.external_id,
tier5Accounts.account.id,
),
).toEqual(undefined);
// loggerSpyがスパイしているlogger.logメソッドが出力したログを確認目視確認用
const logs = loggerSpy.mock.calls.map((call) => call[0]);
console.log(logs);
// DB内が想定通りになっているか確認
const accountRecord = await getAccount(source, tier5Accounts.account.id);
expect(accountRecord).toBe(null);
const userRecord = await getUser(source, user.id);
expect(userRecord).toBe(null);
});
});