OMDSCloud/dictation_server/src/features/accounts/accounts.service.spec.ts
makabe.t 5b1c3a0e99 Merged PR 361: API実装(TypistGroup取得API)
## 概要
[Task2461: API実装(TypistGroup取得API)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2461)

- TypistGroup取得APIとテストを実装しました。

## レビューポイント
- DBからの取得ロジックに問題はないか
- テストケースは十分か

## UIの変更
- なし

## 動作確認状況
- ローカルで確認
2023-08-29 06:25:15 +00:00

2779 lines
89 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,
} from './test/accounts.service.mock';
import { makeDefaultConfigValue } from '../users/test/users.service.mock';
import {
createLicense,
createLicenseOrder,
createLicenseSetExpiryDateAndStatus,
getSortCriteria,
getTypistGroup,
getTypistGroupMember,
createTypistGroup,
} from './test/utility';
import { DataSource } from 'typeorm';
import { makeTestingModule } from '../../common/test/modules';
import {
makeTestAccount,
getAccount,
getAccounts,
getUserFromExternalId,
getUsers,
makeTestUser,
} from '../../common/test/utility';
import { AccountsService } from './accounts.service';
import { Context, makeContext } from '../../common/log';
import { TIERS, USER_ROLES } 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';
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 service = await makeAccountsServiceMock(
accountsRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cParam,
configMockValue,
sendGridMockValue,
blobStorageMockValue,
licensesRepositoryMockValue,
);
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 service = await makeAccountsServiceMock(
accountsRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cParam,
configMockValue,
sendGridMockValue,
blobStorageMockValue,
licensesRepositoryMockValue,
);
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 service = await makeAccountsServiceMock(
accountsRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cParam,
configMockValue,
sendGridMockValue,
blobStorageMockValue,
licensesRepositoryMockValue,
);
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 service = await makeAccountsServiceMock(
accountsRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cParam,
configMockValue,
sendGridMockValue,
blobStorageMockValue,
licensesRepositoryMockValue,
);
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 service = await makeAccountsServiceMock(
accountsRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cParam,
configMockValue,
sendGridMockValue,
blobStorageMockValue,
licensesRepositoryMockValue,
);
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 service = await makeAccountsServiceMock(
accountsRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cParam,
configMockValue,
sendGridMockValue,
blobStorageMockValue,
licensesRepositoryMockValue,
);
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 service = await makeAccountsServiceMock(
accountsRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cParam,
configMockValue,
sendGridMockValue,
blobStorageMockValue,
licensesRepositoryMockValue,
);
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 service = await makeAccountsServiceMock(
accountsRepositoryMockValue,
usersRepositoryMockValue,
userGroupsRepositoryMockValue,
adb2cParam,
configMockValue,
sendGridMockValue,
blobStorageMockValue,
licensesRepositoryMockValue,
);
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, parentAccountId);
await createLicense(source, parentAccountId);
await createLicense(source, parentAccountId);
await createLicense(source, childAccountId1);
await createLicense(source, childAccountId2);
await createLicense(source, childAccountId2);
// ライセンス注文を追加子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 createLicense(source, childAccountId1);
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 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,
);
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, parentAccountId);
await createLicense(source, parentAccountId);
await createLicense(source, parentAccountId);
// 子から親への注文を作成する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, parentAccountId);
await createLicense(source, parentAccountId);
await createLicense(source, parentAccountId);
// 子から親への注文を作成する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, parentAccountId);
await createLicense(source, parentAccountId);
await createLicense(source, parentAccountId);
// 子から親への注文を作成する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 { id: typistGroupId } = await createTypistGroup(
source,
account.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 service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
const typistGroup = await service.getTypistGroup(
context,
admin.external_id,
typistGroupId,
);
//実行結果を確認
{
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';
await createTypistGroup(source, account.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 service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
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 { id: typistGroupId } = await createTypistGroup(
source,
account.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 service = module.get<AccountsService>(AccountsService);
const context = makeContext(admin.external_id);
//DBアクセスに失敗するようにする
const typistGroupService = module.get<UserGroupsRepositoryService>(
UserGroupsRepositoryService,
);
typistGroupService.getTypistGroup = jest
.fn()
.mockRejectedValue('DB failed');
try {
await service.getTypistGroup(context, admin.external_id, typistGroupId);
} catch (e) {
if (e instanceof HttpException) {
expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
} else {
fail();
}
}
});
});