import { ConfigModule, ConfigService } from '@nestjs/config'; import { Test, TestingModule } from '@nestjs/testing'; import { B2cMetadata, JwkSignKey } from '../../../common/token'; import { AdB2cService, ConflictError, } from '../../../gateways/adb2c/adb2c.service'; import { SendGridService } from '../../../gateways/sendgrid/sendgrid.service'; import { User } from '../../../repositories/users/entity/user.entity'; import { UsersRepositoryService } from '../../../repositories/users/users.repository.service'; import { LicensesRepositoryService } from '../../../repositories/licenses/licenses.repository.service'; import { UsersService } from '../users.service'; import { SortCriteria } from '../../../repositories/sort_criteria/entity/sort_criteria.entity'; import { SortCriteriaRepositoryService } from '../../../repositories/sort_criteria/sort_criteria.repository.service'; import { SortDirection, TaskListSortableAttribute, } from '../../../common/types/sort'; import { AdB2cUser } from '../../../gateways/adb2c/types/types'; import { ADB2C_SIGN_IN_TYPE } from '../../../constants'; import { AccountsRepositoryService } from '../../../repositories/accounts/accounts.repository.service'; export type SortCriteriaRepositoryMockValue = { updateSortCriteria: SortCriteria | Error; getSortCriteria: SortCriteria | Error; }; export type UsersRepositoryMockValue = { updateUserVerified: undefined | Error; findUserById: User | Error; createNormalUser: User | Error; findSameAccountUsers: User[] | Error; findUserByExternalId: User | Error; existsAuthorId: boolean | Error; }; export type LicensesRepositoryMockValue = { // empty }; export type AdB2cMockValue = { getMetaData: B2cMetadata | Error; getSignKeySets: JwkSignKey[] | Error; changePassword: { sub: string } | Error; createUser: string | ConflictError | Error; getUser: AdB2cUser | Error; getUsers: AdB2cUser[] | Error; }; export type SendGridMockValue = { sendMail: undefined | Error; }; export type ConfigMockValue = { get: string | Error; }; export const makeUsersServiceMock = async ( usersRepositoryMockValue: UsersRepositoryMockValue, licensesRepositoryMockValue: LicensesRepositoryMockValue | null, adB2cMockValue: AdB2cMockValue, sendGridMockValue: SendGridMockValue, configMockValue: ConfigMockValue, sortCriteriaRepositoryMockValue: SortCriteriaRepositoryMockValue, ): Promise => { const module: TestingModule = await Test.createTestingModule({ providers: [UsersService], imports: [ ConfigModule.forRoot({ envFilePath: ['.env.local', '.env'], }), ], }) .useMocker((token) => { switch (token) { case AccountsRepositoryService: return {}; case UsersRepositoryService: return makeUsersRepositoryMock(usersRepositoryMockValue); case LicensesRepositoryService: return makeLicensesRepositoryMock(); case AdB2cService: return makeAdB2cServiceMock(adB2cMockValue); case SendGridService: return makeSendGridMock(sendGridMockValue); case ConfigService: return makeConfigMock(configMockValue); case SortCriteriaRepositoryService: return makeSortCriteriaRepositoryMock( sortCriteriaRepositoryMockValue, ); } }) .compile(); return module.get(UsersService); }; export const makeSortCriteriaRepositoryMock = ( value: SortCriteriaRepositoryMockValue, ) => { const { updateSortCriteria, getSortCriteria } = value; return { updateSortCriteria: updateSortCriteria instanceof Error ? jest .fn< Promise, [number, TaskListSortableAttribute, SortDirection] >() .mockRejectedValue(updateSortCriteria) : jest .fn< Promise, [number, TaskListSortableAttribute, SortDirection] >() .mockResolvedValue(updateSortCriteria), getSortCriteria: getSortCriteria instanceof Error ? jest.fn, [number]>().mockRejectedValue(getSortCriteria) : jest .fn, [number]>() .mockResolvedValue(getSortCriteria), }; }; export const makeSendGridServiceMock = (value: SendGridMockValue) => { const { sendMail } = value; return { sendMail: sendMail instanceof Error ? jest.fn, []>().mockRejectedValue(sendMail) : jest.fn, []>().mockResolvedValue(sendMail), }; }; export const makeAdB2cServiceMock = (value: AdB2cMockValue) => { const { getMetaData, getSignKeySets, changePassword, createUser, getUser, getUsers, } = value; return { getMetaData: getMetaData instanceof Error ? jest.fn, []>().mockRejectedValue(getMetaData) : jest.fn, []>().mockResolvedValue(getMetaData), getSignKeySets: getSignKeySets instanceof Error ? jest.fn, []>().mockRejectedValue(getSignKeySets) : jest .fn, []>() .mockResolvedValue(getSignKeySets), changePassword: changePassword instanceof Error ? jest.fn, []>().mockRejectedValue(changePassword) : jest .fn, []>() .mockResolvedValue(changePassword), createUser: createUser instanceof Error ? jest.fn, []>().mockRejectedValue(createUser) : jest .fn, []>() .mockResolvedValue(createUser), getUser: getUser instanceof Error ? jest .fn, []>() .mockRejectedValue(getUser) : jest .fn, []>() .mockResolvedValue(getUser), getUsers: getUsers instanceof Error ? jest.fn, []>().mockRejectedValue(getUsers) : jest.fn, []>().mockResolvedValue(getUsers), }; }; class authorIdError extends Error { constructor(public code: string, e?: string) { super(e); } } export const makeUsersRepositoryMock = (value: UsersRepositoryMockValue) => { const { updateUserVerified, findUserById, createNormalUser, findSameAccountUsers, findUserByExternalId, existsAuthorId, } = value; const aIdError = new authorIdError('ER_DUP_ENTRY'); return { updateUserVerified: updateUserVerified instanceof Error ? jest.fn, []>().mockRejectedValue(updateUserVerified) : jest.fn, []>().mockResolvedValue(updateUserVerified), findUserById: findUserById instanceof Error ? jest.fn, []>().mockRejectedValue(findUserById) : jest.fn, []>().mockResolvedValue(findUserById), createNormalUser: createNormalUser instanceof Error ? createNormalUser.name == 'ER_DUP_ENTRY' ? jest.fn, []>().mockRejectedValue(aIdError) : jest.fn, []>().mockRejectedValue(createNormalUser) : jest.fn, []>().mockResolvedValue(createNormalUser), findSameAccountUsers: findSameAccountUsers instanceof Error ? jest .fn, []>() .mockRejectedValue(findSameAccountUsers) : jest .fn, []>() .mockResolvedValue(findSameAccountUsers), findUserByExternalId: findUserByExternalId instanceof Error ? jest.fn, []>().mockRejectedValue(findUserByExternalId) : jest.fn, []>().mockResolvedValue(findUserByExternalId), existsAuthorId: existsAuthorId instanceof Error ? jest.fn, []>().mockRejectedValue(existsAuthorId) : jest.fn, []>().mockResolvedValue(existsAuthorId), }; }; export const makeLicensesRepositoryMock = (): LicensesRepositoryMockValue => { return { // empty }; }; export const makeSendGridMock = (value: SendGridMockValue) => { const { sendMail } = value; return { sendMail: sendMail instanceof Error ? jest.fn, []>().mockRejectedValue(sendMail) : jest.fn, []>().mockResolvedValue(sendMail), }; }; export const makeConfigMock = (value: ConfigMockValue) => { const { get } = value; return { get: get instanceof Error ? jest.fn, []>().mockRejectedValue(get) : jest.fn, []>().mockResolvedValue(get), }; }; export const makeDefaultSendGridlValue = (): SendGridMockValue => { return { sendMail: undefined }; }; export const makeDefaultConfigValue = (): ConfigMockValue => { return { get: `test@example.com`, }; }; export const makeDefaultSortCriteriaRepositoryMockValue = (): SortCriteriaRepositoryMockValue => { const sortCriteria = new SortCriteria(); { sortCriteria.id = 1; sortCriteria.direction = 'ASC'; sortCriteria.parameter = 'JOB_NUMBER'; sortCriteria.user_id = 1; } return { updateSortCriteria: sortCriteria, getSortCriteria: sortCriteria, }; }; export const makeDefaultAdB2cMockValue = (): AdB2cMockValue => { return { getMetaData: { issuer: 'issuer', }, getSignKeySets: [ { kid: 'kid', nbf: 1111111111, use: 'sig', kty: 'RSA', e: 'e', n: 'n', }, ], changePassword: { sub: 'TEST9999', }, createUser: '001', getUser: { id: 'xxxx-xxxxx-xxxxx-xxxx', displayName: 'Hanako Sato', }, getUsers: AdB2cMockUsers, }; }; // 個別のテストケースに対応してそれぞれのMockを用意するのは無駄が多いのでテストケース内で個別の値を設定する export const makeDefaultUsersRepositoryMockValue = (): UsersRepositoryMockValue => { const newUser = new User(); newUser.id = 111; const user1 = new User(); user1.id = 2; user1.external_id = 'ede66c43-9b9d-4222-93ed-5f11c96e08e2'; user1.account_id = 1234567890123456; user1.role = 'none'; user1.author_id = '6cce347f-0cf1-a15e-19ab-d00988b643f9'; user1.accepted_eula_version = '1.0'; user1.accepted_dpa_version = '1.0'; user1.email_verified = true; user1.auto_renew = false; user1.notification = false; user1.encryption = false; user1.prompt = false; user1.deleted_at = null; user1.created_by = 'test'; user1.created_at = new Date(); user1.updated_by = null; user1.updated_at = new Date(); const user2 = new User(); user2.id = 3; user2.external_id = '698176dc-4028-4638-a452-f00bf62a7781'; user2.account_id = 1234567890123456; user2.role = 'none'; user2.author_id = '551c4077-5b55-a38c-2c55-cd1edd537aa8'; user2.accepted_eula_version = '1.0'; user2.accepted_dpa_version = '1.0'; user2.email_verified = true; user2.auto_renew = false; user2.notification = false; user2.encryption = false; user2.prompt = false; user2.deleted_at = null; user2.created_by = 'test'; user2.created_at = new Date(); user2.updated_by = null; user2.updated_at = new Date(); return { updateUserVerified: undefined, findUserById: newUser, createNormalUser: newUser, findSameAccountUsers: [user1, user2], findUserByExternalId: newUser, existsAuthorId: false, }; }; const AdB2cMockUsers: AdB2cUser[] = [ { id: 'external_id1', displayName: 'test1', identities: [ { signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS, issuer: 'issuer', issuerAssignedId: 'test1@mail.com', }, ], }, { id: 'external_id2', displayName: 'test2', identities: [ { signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS, issuer: 'issuer', issuerAssignedId: 'test2@mail.com', }, ], }, { id: 'external_id3', displayName: 'test3', identities: [ { signInType: ADB2C_SIGN_IN_TYPE.EMAILADDRESS, issuer: 'issuer', issuerAssignedId: 'test3@mail.com', }, ], }, ];