## 概要 [Task2767: [PBI1220残]退避テーブル対応(月の途中で退会したアカウントの集計対応)](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/2767) アカウント削除時に以下のテーブルの削除対象データを退避する処理を追加しました。 ・ライセンステーブル ・ライセンス割り当て履歴テーブル ## レビューポイント なし ## UIの変更 なし ## 動作確認状況 UT,ローカル動作確認を実施済み ## 補足 なし
5579 lines
175 KiB
TypeScript
5579 lines
175 KiB
TypeScript
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、子1:1、子2:2)
|
||
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→子1:10ライセンス、子4→子2:10ライセンス)
|
||
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,
|
||
);
|
||
});
|
||
|
||
// 有効期限が迫っていないライセンスを追加(子2:Unallocatedを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);
|
||
});
|
||
});
|