import { ConfigModule, ConfigService } from '@nestjs/config'; import { Test, TestingModule } from '@nestjs/testing'; import { Aadb2cUser, B2cMetadata, JwkSignKey } from '../../../common/token'; import { AdB2cService, ConflictError, } from '../../../gateways/adb2c/adb2c.service'; import { CryptoService } from '../../../gateways/crypto/crypto.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 { UsersService } from '../users.service'; export type CryptoMockValue = { getPublicKey: string | Error; }; export type UsersRepositoryMockValue = { updateUserVerified: undefined | Error; findUserById: User | Error; createNormalUser: User | Error; findSameAccountUsers: User[] | Error; findUserByExternalId: User | Error; }; export type AdB2cMockValue = { getMetaData: B2cMetadata | Error; getSignKeySets: JwkSignKey[] | Error; changePassword: { sub: string } | Error; createUser: string | ConflictError | Error; getUser: Aadb2cUser | Error; }; export type SendGridMockValue = { createMailContentFromEmailConfirm: { subject: string; text: string; html: string; }; createMailContentFromEmailConfirmForNormalUser: | { subject: string; text: string; html: string } | Error; sendMail: undefined | Error; }; 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: { displayName: 'Hanako Sato', mail: 'hanako@sample.com', }, }; }; export const makeSendGridServiceMock = (value: SendGridMockValue) => { const { createMailContentFromEmailConfirm, sendMail } = value; return { createMailContentFromEmailConfirm: createMailContentFromEmailConfirm instanceof Error ? jest .fn, []>() .mockRejectedValue(createMailContentFromEmailConfirm) : jest .fn, []>() .mockResolvedValue(createMailContentFromEmailConfirm), sendMail: sendMail instanceof Error ? jest.fn, []>().mockRejectedValue(sendMail) : jest.fn, []>().mockResolvedValue(sendMail), }; }; export const makeAdB2cServiceMock = (value: AdB2cMockValue) => { const { getMetaData, getSignKeySets, changePassword, createUser, getUser } = 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), }; }; export type ConfigMockValue = { get: string | Error; }; export const makeUsersServiceMock = async ( cryptoMockValue: CryptoMockValue, usersRepositoryMockValue: UsersRepositoryMockValue, adB2cMockValue: AdB2cMockValue, sendGridMockValue: SendGridMockValue, configMockValue: ConfigMockValue, ): Promise => { const module: TestingModule = await Test.createTestingModule({ providers: [UsersService], imports: [ ConfigModule.forRoot({ ignoreEnvFile: true, ignoreEnvVars: true, }), ], }) .useMocker((token) => { switch (token) { case CryptoService: return makeCryptoServiceMock(cryptoMockValue); case UsersRepositoryService: return makeUsersRepositoryMock(usersRepositoryMockValue); case AdB2cService: return makeAdB2cServiceMock(adB2cMockValue); case SendGridService: return makeSendGridMock(sendGridMockValue); case ConfigService: return makeConfigMock(configMockValue); } }) .compile(); return module.get(UsersService); }; export const makeCryptoServiceMock = (value: CryptoMockValue) => { const { getPublicKey } = value; return { getPublicKey: getPublicKey instanceof Error ? jest.fn, []>().mockRejectedValue(getPublicKey) : jest.fn, []>().mockResolvedValue(getPublicKey), }; }; class authorIdError extends Error { constructor(public code: string, e?: string) { super(e); } } export const makeUsersRepositoryMock = (value: UsersRepositoryMockValue) => { const { updateUserVerified, findUserById, createNormalUser, findSameAccountUsers, findUserByExternalId, } = 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), }; }; export const makeSendGridMock = (value: SendGridMockValue) => { const { sendMail, createMailContentFromEmailConfirmForNormalUser } = value; return { sendMail: sendMail instanceof Error ? jest.fn, []>().mockRejectedValue(sendMail) : jest.fn, []>().mockResolvedValue(sendMail), createMailContentFromEmailConfirmForNormalUser: createMailContentFromEmailConfirmForNormalUser instanceof Error ? jest .fn, []>() .mockRejectedValue(createMailContentFromEmailConfirmForNormalUser) : jest .fn, []>() .mockResolvedValue(createMailContentFromEmailConfirmForNormalUser), }; }; export const makeConfigMock = (value: ConfigMockValue) => { const { get } = value; return { get: get instanceof Error ? jest.fn, []>().mockRejectedValue(get) : jest.fn, []>().mockResolvedValue(get), }; }; export const makeDefaultCryptoMockValue = (): CryptoMockValue => { return { getPublicKey: [ '-----BEGIN PUBLIC KEY-----', 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5IZZNgDew9eGmuFTezwd', 'HYLSaJvUPPIKYoiOeVLD1paWNI517Vkaoh0ngprcKOdv6T1N07V4igK7mOim2zY3', 'yCTR6wcWR3PfFJrl9vh5SOo79koZoJb27YiM4jtxfx2dezzp0T2GoNR5rRolPUbW', 'FJXnDe0DVXYXpJLb4LAlF2XAyYX0SYKUVUsJnzm5k4xbXtnwPwVbpm0EdswBE6qS', 'fiL9zWk9dvHoKzSnfSDzDFoFcEoVchawzYXf/MM1YR4wo5XyzECc6Q5Ah4z522//', 'mBNNaDHv83Yuw3mGShT73iJ0JQdkTturshv2Ecma38r6ftrIwNYXw4VVatJM8+GO', 'OQIDAQAB', '-----END PUBLIC KEY-----', ].join('\n'), }; }; export const makeDefaultSendGridlValue = (): SendGridMockValue => { return { sendMail: undefined, createMailContentFromEmailConfirm: { subject: '', text: '', html: '' }, createMailContentFromEmailConfirmForNormalUser: { subject: 'test', text: 'test', html: 'test', }, }; }; export const makeDefaultConfigValue = (): ConfigMockValue => { return { get: `test@example.co.jp`, }; }; // 個別のテストケースに対応してそれぞれの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_terms_version = '1.0'; user1.email_verified = true; user1.auto_renew = false; user1.license_alert = false; user1.notification = false; user1.deleted_at = null; user1.created_by = 'test'; user1.created_at = new Date(); user1.updated_by = null; user1.updated_at = null; 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_terms_version = '1.0'; user2.email_verified = true; user2.auto_renew = false; user2.license_alert = false; user2.notification = false; user2.deleted_at = null; user2.created_by = 'test'; user2.created_at = new Date(); user2.updated_by = null; user2.updated_at = null; return { updateUserVerified: undefined, findUserById: newUser, createNormalUser: newUser, findSameAccountUsers: [user1, user2], findUserByExternalId: newUser, }; };