import { DataSource } from 'typeorm';
import { makeTestingModule } from '../../common/test/modules';
import { makeTestAccount, makeTestUser } from '../../common/test/utility';
import { makeContext } from '../../common/log';
import { WorkflowsService } from './workflows.service';
import { USER_ROLES } from '../../constants';
import { createTemplateFile } from '../templates/test/utility';
import { createWorktype } from '../accounts/test/utility';
import {
  createWorkflow,
  createWorkflowTypist,
  getAllWorkflowTypists,
  getAllWorkflows,
  getWorkflowTypists,
  getWorkflows,
} from './test/utility';
import { createUserGroup } from '../users/test/utility';
import { overrideAdB2cService } from '../../common/test/overrides';
import { WorkflowsRepositoryService } from '../../repositories/workflows/workflows.repository.service';
import { HttpException, HttpStatus } from '@nestjs/common';
import { makeErrorResponse } from '../../common/error/makeErrorResponse';
import { truncateAllTable } from '../../common/test/init';

describe('getWorkflows', () => {
  let source: DataSource | null = null;
  beforeAll(async () => {
    if (source == null) {
      source = await (async () => {
        const s = new DataSource({
          type: 'mysql',
          host: 'test_mysql_db',
          port: 3306,
          username: 'user',
          password: 'password',
          database: 'odms',
          entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
          synchronize: false, // trueにすると自動的にmigrationが行われるため注意
        });
        return await s.initialize();
      })();
    }
  });

  beforeEach(async () => {
    if (source) {
      await truncateAllTable(source);
    }
  });

  afterAll(async () => {
    await source?.destroy();
    source = null;
  });

  it('アカウント内のWorkflow一覧を取得できる', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId1 } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'BBBBB',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: authorId2 } = await makeTestUser(source, {
      external_id: 'author2',
      author_id: 'AAAAA',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: authorId3 } = await makeTestUser(source, {
      external_id: 'author3',
      author_id: 'CCCCC',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });

    const { id: typistId, external_id: typistExternalId } = await makeTestUser(
      source,
      {
        external_id: 'typist1',
        account_id: account.id,
        role: USER_ROLES.TYPIST,
      },
    );
    const { userGroupId } = await createUserGroup(
      source,
      account.id,
      'group1',
      [typistId],
    );

    const { id: worktypeId1 } = await createWorktype(
      source,
      account.id,
      'worktype2',
    );

    const { id: worktypeId2 } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    const { id: templateId1 } = await createTemplateFile(
      source,
      account.id,
      'fileName1',
      'url1',
    );

    const workflow1 = await createWorkflow(
      source,
      account.id,
      authorId1,
      worktypeId2,
      templateId1,
    );
    const workflow2 = await createWorkflow(
      source,
      account.id,
      authorId2,
      undefined,
      templateId1,
    );
    const workflow3 = await createWorkflow(
      source,
      account.id,
      authorId3,
      worktypeId1,
      undefined,
    );
    const workflow4 = await createWorkflow(
      source,
      account.id,
      authorId3,
      worktypeId2,
      undefined,
    );

    await createWorkflowTypist(source, workflow1.id, typistId, undefined);
    await createWorkflowTypist(source, workflow2.id, undefined, userGroupId);
    await createWorkflowTypist(source, workflow3.id, undefined, userGroupId);
    await createWorkflowTypist(source, workflow4.id, undefined, userGroupId);

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      expect(workflows.length).toBe(4);
      expect(workflows[0].id).toBe(workflow1.id);
      expect(workflows[0].author_id).toBe(authorId1);
      expect(workflows[0].worktype_id).toBe(worktypeId2);
      expect(workflows[0].template_id).toBe(templateId1);

      expect(workflows[1].id).toBe(workflow2.id);
      expect(workflows[1].author_id).toBe(authorId2);
      expect(workflows[1].worktype_id).toBe(null);
      expect(workflows[1].template_id).toBe(templateId1);

      expect(workflows[2].id).toBe(workflow3.id);
      expect(workflows[2].author_id).toBe(authorId3);
      expect(workflows[2].worktype_id).toBe(worktypeId1);
      expect(workflows[2].template_id).toBe(null);

      expect(workflows[3].id).toBe(workflow4.id);
      expect(workflows[3].author_id).toBe(authorId3);
      expect(workflows[3].worktype_id).toBe(worktypeId2);
      expect(workflows[3].template_id).toBe(null);
    }

    overrideAdB2cService(service, {
      getUsers: async () => [{ id: typistExternalId, displayName: 'typist1' }],
    });

    const resWorkflows = await service.getWorkflows(context, admin.external_id);

    //実行結果を確認
    {
      expect(resWorkflows.length).toBe(4);

      expect(resWorkflows[0].id).toBe(workflow2.id);
      expect(resWorkflows[0].author.id).toBe(authorId2);
      expect(resWorkflows[0].author.authorId).toBe('AAAAA');
      expect(resWorkflows[0].worktype).toBe(undefined);
      expect(resWorkflows[0].template?.id).toBe(templateId1);
      expect(resWorkflows[0].template?.fileName).toBe('fileName1');
      expect(resWorkflows[0].typists.length).toBe(1);
      expect(resWorkflows[0].typists[0].typistGroupId).toBe(userGroupId);
      expect(resWorkflows[0].typists[0].typistName).toBe('group1');

      expect(resWorkflows[1].id).toBe(workflow1.id);
      expect(resWorkflows[1].author.id).toBe(authorId1);
      expect(resWorkflows[1].author.authorId).toBe('BBBBB');
      expect(resWorkflows[1].worktype?.id).toBe(worktypeId2);
      expect(resWorkflows[1].worktype?.worktypeId).toBe('worktype1');
      expect(resWorkflows[1].template?.id).toBe(templateId1);
      expect(resWorkflows[1].template?.fileName).toBe('fileName1');
      expect(resWorkflows[1].typists.length).toBe(1);
      expect(resWorkflows[1].typists[0].typistUserId).toBe(typistId);
      expect(resWorkflows[1].typists[0].typistName).toBe('typist1');

      expect(resWorkflows[2].id).toBe(workflow4.id);
      expect(resWorkflows[2].author.id).toBe(authorId3);
      expect(resWorkflows[2].author.authorId).toBe('CCCCC');
      expect(resWorkflows[2].worktype?.id).toBe(worktypeId2);
      expect(resWorkflows[2].worktype?.worktypeId).toBe('worktype1');
      expect(resWorkflows[2].template).toBe(undefined);
      expect(resWorkflows[2].typists.length).toBe(1);
      expect(resWorkflows[2].typists[0].typistGroupId).toBe(userGroupId);
      expect(resWorkflows[2].typists[0].typistName).toBe('group1');

      expect(resWorkflows[3].id).toBe(workflow3.id);
      expect(resWorkflows[3].author.id).toBe(authorId3);
      expect(resWorkflows[3].author.authorId).toBe('CCCCC');
      expect(resWorkflows[3].worktype?.id).toBe(worktypeId1);
      expect(resWorkflows[3].worktype?.worktypeId).toBe('worktype2');
      expect(resWorkflows[3].template).toBe(undefined);
      expect(resWorkflows[3].typists.length).toBe(1);
      expect(resWorkflows[3].typists[0].typistGroupId).toBe(userGroupId);
      expect(resWorkflows[3].typists[0].typistName).toBe('group1');
    }
  });

  it('アカウント内のWorkflow一覧を取得できる（0件）', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { admin } = await makeTestAccount(source, { tier: 5 });

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    overrideAdB2cService(service, {
      getUsers: async () => [],
    });

    const resWorkflows = await service.getWorkflows(context, admin.external_id);

    //実行結果を確認
    {
      expect(resWorkflows.length).toBe(0);
    }
  });

  it('DBアクセスに失敗した場合、500エラーを返却する', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { admin } = await makeTestAccount(source, { tier: 5 });

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //DBアクセスに失敗するようにする
    const templatesService = module.get<WorkflowsRepositoryService>(
      WorkflowsRepositoryService,
    );
    templatesService.getWorkflows = jest.fn().mockRejectedValue('DB failed');

    //実行結果を確認
    try {
      await service.getWorkflows(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('createWorkflows', () => {
  let source: DataSource | null = null;
  beforeAll(async () => {
    if (source == null) {
      source = await (async () => {
        const s = new DataSource({
          type: 'mysql',
          host: 'test_mysql_db',
          port: 3306,
          username: 'user',
          password: 'password',
          database: 'odms',
          entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
          synchronize: false, // trueにすると自動的にmigrationが行われるため注意
        });
        return await s.initialize();
      })();
    }
  });

  beforeEach(async () => {
    if (source) {
      await truncateAllTable(source);
    }
  });

  afterAll(async () => {
    await source?.destroy();
    source = null;
  });
  it('アカウント内にWorkflowを作成できる（WorktypeIDあり、テンプレートファイルあり）', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const { id: worktypeId } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    const { id: templateId } = await createTemplateFile(
      source,
      account.id,
      'fileName1',
      'url1',
    );

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(0);
      expect(workflowTypists.length).toBe(0);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    await service.createWorkflow(
      context,
      admin.external_id,
      authorId,
      [
        {
          typistId: typistId,
        },
      ],
      worktypeId,
      templateId,
    );

    //実行結果を確認
    {
      const workflows = await getWorkflows(source, account.id);
      expect(workflows.length).toBe(1);
      expect(workflows[0].account_id).toBe(account.id);
      expect(workflows[0].author_id).toBe(authorId);
      expect(workflows[0].worktype_id).toBe(worktypeId);
      expect(workflows[0].template_id).toBe(templateId);

      const workflowTypists = await getWorkflowTypists(source, workflows[0].id);
      expect(workflowTypists.length).toBe(1);
      expect(workflowTypists[0].typist_id).toBe(typistId);
      expect(workflowTypists[0].typist_group_id).toBe(null);
    }
  });

  it('アカウント内にWorkflowを作成できる（WorktypeIDなし、テンプレートファイルあり）', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const { id: templateId } = await createTemplateFile(
      source,
      account.id,
      'fileName1',
      'url1',
    );

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(0);
      expect(workflowTypists.length).toBe(0);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    await service.createWorkflow(
      context,
      admin.external_id,
      authorId,
      [
        {
          typistId: typistId,
        },
      ],
      undefined,
      templateId,
    );

    //実行結果を確認
    {
      const workflows = await getWorkflows(source, account.id);
      expect(workflows.length).toBe(1);
      expect(workflows[0].account_id).toBe(account.id);
      expect(workflows[0].author_id).toBe(authorId);
      expect(workflows[0].worktype_id).toBe(null);
      expect(workflows[0].template_id).toBe(templateId);

      const workflowTypists = await getWorkflowTypists(source, workflows[0].id);
      expect(workflowTypists.length).toBe(1);
      expect(workflowTypists[0].typist_id).toBe(typistId);
      expect(workflowTypists[0].typist_group_id).toBe(null);
    }
  });

  it('アカウント内にWorkflowを作成できる（WorktypeIDあり、テンプレートファイルなし）', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const { id: worktypeId } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(0);
      expect(workflowTypists.length).toBe(0);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    await service.createWorkflow(
      context,
      admin.external_id,
      authorId,
      [
        {
          typistId: typistId,
        },
      ],
      worktypeId,
      undefined,
    );

    //実行結果を確認
    {
      const workflows = await getWorkflows(source, account.id);
      expect(workflows.length).toBe(1);
      expect(workflows[0].account_id).toBe(account.id);
      expect(workflows[0].author_id).toBe(authorId);
      expect(workflows[0].worktype_id).toBe(worktypeId);
      expect(workflows[0].template_id).toBe(null);

      const workflowTypists = await getWorkflowTypists(source, workflows[0].id);
      expect(workflowTypists.length).toBe(1);
      expect(workflowTypists[0].typist_id).toBe(typistId);
      expect(workflowTypists[0].typist_group_id).toBe(null);
    }
  });

  it('アカウント内にWorkflowを作成できる（WorktypeIDなし、テンプレートファイルなし）', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(0);
      expect(workflowTypists.length).toBe(0);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    await service.createWorkflow(
      context,
      admin.external_id,
      authorId,
      [
        {
          typistId: typistId,
        },
      ],
      undefined,
      undefined,
    );

    //実行結果を確認
    {
      const workflows = await getWorkflows(source, account.id);
      expect(workflows.length).toBe(1);
      expect(workflows[0].account_id).toBe(account.id);
      expect(workflows[0].author_id).toBe(authorId);
      expect(workflows[0].worktype_id).toBe(null);
      expect(workflows[0].template_id).toBe(null);

      const workflowTypists = await getWorkflowTypists(source, workflows[0].id);
      expect(workflowTypists.length).toBe(1);
      expect(workflowTypists[0].typist_id).toBe(typistId);
      expect(workflowTypists[0].typist_group_id).toBe(null);
    }
  });

  it('アカウント内にWorkflowを作成できる（WorktypeIDなし、テンプレートファイルなし、同一AuthorIDのワークフローあり）', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const { id: worktypeId } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(0);
      expect(workflowTypists.length).toBe(0);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    // 同一AuthorIDのワークフローを作成
    await service.createWorkflow(
      context,
      admin.external_id,
      authorId,
      [
        {
          typistId: typistId,
        },
      ],
      worktypeId,
      undefined,
    );

    await service.createWorkflow(
      context,
      admin.external_id,
      authorId,
      [
        {
          typistId: typistId,
        },
      ],
      undefined,
      undefined,
    );

    //実行結果を確認
    {
      const workflows = await getWorkflows(source, account.id);
      workflows.sort((a, b) => a.id - b.id);
      expect(workflows.length).toBe(2);
      expect(workflows[1].account_id).toBe(account.id);
      expect(workflows[1].author_id).toBe(authorId);
      expect(workflows[1].worktype_id).toBe(null);
      expect(workflows[1].template_id).toBe(null);

      const workflowTypists = await getWorkflowTypists(source, workflows[1].id);
      expect(workflowTypists.length).toBe(1);
      expect(workflowTypists[0].typist_id).toBe(typistId);
      expect(workflowTypists[0].typist_group_id).toBe(null);
    }
  });

  it('Authorがメール未認証の場合、400エラーとなること', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
      email_verified: false,
    });
    const { id: typistId } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(0);
      expect(workflowTypists.length).toBe(0);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');
    //実行結果を確認
    try {
      await service.createWorkflow(
        context,
        admin.external_id,
        authorId,
        [{ typistId: typistId }],
        undefined,
        undefined,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E010204'));
      } else {
        fail();
      }
    }
  });

  it('DBにAuthorが存在しない場合、400エラーとなること', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });

    const { id: typistId } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const { id: worktypeId } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    const { id: templateId } = await createTemplateFile(
      source,
      account.id,
      'fileName1',
      'url1',
    );

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(0);
      expect(workflowTypists.length).toBe(0);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //実行結果を確認
    try {
      await service.createWorkflow(
        context,
        admin.external_id,
        0,
        [
          {
            typistId: typistId,
          },
        ],
        worktypeId,
        templateId,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E010204'));
      } else {
        fail();
      }
    }
  });

  it('DBにWorktypeIDが存在しない場合、400エラーとなること', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const { id: templateId } = await createTemplateFile(
      source,
      account.id,
      'fileName1',
      'url1',
    );

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(0);
      expect(workflowTypists.length).toBe(0);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //実行結果を確認
    try {
      await service.createWorkflow(
        context,
        admin.external_id,
        authorId,
        [
          {
            typistId: typistId,
          },
        ],
        9999,
        templateId,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E011003'));
      } else {
        fail();
      }
    }
  });

  it('DBにテンプレートファイルが存在しない場合、400エラーとなること', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const { id: worktypeId } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(0);
      expect(workflowTypists.length).toBe(0);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //実行結果を確認
    try {
      await service.createWorkflow(
        context,
        admin.external_id,
        authorId,
        [
          {
            typistId: typistId,
          },
        ],
        worktypeId,
        9999,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E012001'));
      } else {
        fail();
      }
    }
  });

  it('DBにルーティング候補ユーザーが存在しない場合、400エラーとなること', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });

    const { id: worktypeId } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    const { id: templateId } = await createTemplateFile(
      source,
      account.id,
      'fileName1',
      'url1',
    );

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(0);
      expect(workflowTypists.length).toBe(0);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //実行結果を確認
    try {
      await service.createWorkflow(
        context,
        admin.external_id,
        authorId,
        [
          {
            typistId: 9999,
          },
        ],
        worktypeId,
        templateId,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E010204'));
      } else {
        fail();
      }
    }
  });

  it('ルーティング候補ユーザーがメール未認証の場合、400エラーとなること', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
      email_verified: false,
    });

    const { id: worktypeId } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    const { id: templateId } = await createTemplateFile(
      source,
      account.id,
      'fileName1',
      'url1',
    );

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(0);
      expect(workflowTypists.length).toBe(0);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //実行結果を確認
    try {
      await service.createWorkflow(
        context,
        admin.external_id,
        authorId,
        [
          {
            typistId: typistId,
          },
        ],
        worktypeId,
        templateId,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E010204'));
      } else {
        fail();
      }
    }
  });

  it('DBにルーティング候補グループが存在しない場合、400エラーとなること', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });

    const { id: worktypeId } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    const { id: templateId } = await createTemplateFile(
      source,
      account.id,
      'fileName1',
      'url1',
    );

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(0);
      expect(workflowTypists.length).toBe(0);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //実行結果を確認
    try {
      await service.createWorkflow(
        context,
        admin.external_id,
        authorId,
        [
          {
            typistGroupId: 9999,
          },
        ],
        worktypeId,
        templateId,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E010908'));
      } else {
        fail();
      }
    }
  });

  it('DBにAuthorIDとWorktypeIDのペアがすでに存在する場合、400エラーとなること', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const { id: worktypeId } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    const { id: templateId } = await createTemplateFile(
      source,
      account.id,
      'fileName1',
      'url1',
    );

    await createWorkflow(source, account.id, authorId, worktypeId, templateId);

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      expect(workflows.length).toBe(1);
      expect(workflows[0].account_id).toBe(account.id);
      expect(workflows[0].author_id).toBe(authorId);
      expect(workflows[0].worktype_id).toBe(worktypeId);
      expect(workflows[0].template_id).toBe(templateId);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //実行結果を確認
    try {
      await service.createWorkflow(
        context,
        admin.external_id,
        authorId,
        [
          {
            typistId: typistId,
          },
        ],
        worktypeId,
        templateId,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E013001'));
      } else {
        fail();
      }
    }
  });

  it('DBアクセスに失敗した場合、500エラーを返却する', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const { id: worktypeId } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    const { id: templateId } = await createTemplateFile(
      source,
      account.id,
      'fileName1',
      'url1',
    );

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(0);
      expect(workflowTypists.length).toBe(0);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //DBアクセスに失敗するようにする
    const templatesService = module.get<WorkflowsRepositoryService>(
      WorkflowsRepositoryService,
    );
    templatesService.createtWorkflows = jest
      .fn()
      .mockRejectedValue('DB failed');

    //実行結果を確認
    try {
      await service.createWorkflow(
        context,
        admin.external_id,
        authorId,
        [
          {
            typistId: typistId,
          },
        ],
        worktypeId,
        templateId,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
        expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
      } else {
        fail();
      }
    }
  });
});

describe('updateWorkflow', () => {
  let source: DataSource | null = null;
  beforeAll(async () => {
    if (source == null) {
      source = await (async () => {
        const s = new DataSource({
          type: 'mysql',
          host: 'test_mysql_db',
          port: 3306,
          username: 'user',
          password: 'password',
          database: 'odms',
          entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
          synchronize: false, // trueにすると自動的にmigrationが行われるため注意
        });
        return await s.initialize();
      })();
    }
  });

  beforeEach(async () => {
    if (source) {
      await truncateAllTable(source);
    }
  });

  afterAll(async () => {
    await source?.destroy();
    source = null;
  });

  it('アカウント内のWorkflowを更新できる（WorktypeIDあり、テンプレートファイルあり）', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId1 } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: authorId2 } = await makeTestUser(source, {
      external_id: 'author2',
      author_id: 'AUTHOR2',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId1 } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });
    const { id: typistId2 } = await makeTestUser(source, {
      external_id: 'typist12',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const { id: worktypeId } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    const { id: templateId } = await createTemplateFile(
      source,
      account.id,
      'fileName1',
      'url1',
    );

    const preWorkflow = await createWorkflow(
      source,
      account.id,
      authorId1,
      undefined,
      undefined,
    );
    await createWorkflowTypist(source, preWorkflow.id, typistId1);

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(1);
      expect(workflows[0].id).toBe(preWorkflow.id);
      expect(workflows[0].account_id).toBe(account.id);
      expect(workflows[0].author_id).toBe(authorId1);
      expect(workflows[0].worktype_id).toBe(null);
      expect(workflows[0].template_id).toBe(null);
      expect(workflowTypists.length).toBe(1);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    await service.updateWorkflow(
      context,
      admin.external_id,
      preWorkflow.id,
      authorId2,
      [
        {
          typistId: typistId2,
        },
      ],
      worktypeId,
      templateId,
    );

    //実行結果を確認
    {
      const workflows = await getWorkflows(source, account.id);
      expect(workflows.length).toBe(1);
      expect(workflows[0].account_id).toBe(account.id);
      expect(workflows[0].author_id).toBe(authorId2);
      expect(workflows[0].worktype_id).toBe(worktypeId);
      expect(workflows[0].template_id).toBe(templateId);

      const workflowTypists = await getWorkflowTypists(source, workflows[0].id);
      expect(workflowTypists.length).toBe(1);
      expect(workflowTypists[0].typist_id).toBe(typistId2);
    }
  });

  it('アカウント内にWorkflowを作成できる（WorktypeIDなし、テンプレートファイルあり）', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId1 } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: authorId2 } = await makeTestUser(source, {
      external_id: 'author2',
      author_id: 'AUTHOR2',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId1 } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });
    const { id: typistId2 } = await makeTestUser(source, {
      external_id: 'typist12',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const { id: templateId } = await createTemplateFile(
      source,
      account.id,
      'fileName1',
      'url1',
    );

    const preWorkflow = await createWorkflow(
      source,
      account.id,
      authorId1,
      undefined,
      undefined,
    );
    await createWorkflowTypist(source, preWorkflow.id, typistId1);

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(1);
      expect(workflows[0].id).toBe(preWorkflow.id);
      expect(workflows[0].account_id).toBe(account.id);
      expect(workflows[0].author_id).toBe(authorId1);
      expect(workflows[0].worktype_id).toBe(null);
      expect(workflows[0].template_id).toBe(null);
      expect(workflowTypists.length).toBe(1);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    await service.updateWorkflow(
      context,
      admin.external_id,
      preWorkflow.id,
      authorId2,
      [
        {
          typistId: typistId2,
        },
      ],
      undefined,
      templateId,
    );

    //実行結果を確認
    {
      const workflows = await getWorkflows(source, account.id);
      expect(workflows.length).toBe(1);
      expect(workflows[0].account_id).toBe(account.id);
      expect(workflows[0].author_id).toBe(authorId2);
      expect(workflows[0].worktype_id).toBe(null);
      expect(workflows[0].template_id).toBe(templateId);

      const workflowTypists = await getWorkflowTypists(source, workflows[0].id);
      expect(workflowTypists.length).toBe(1);
      expect(workflowTypists[0].typist_id).toBe(typistId2);
    }
  });

  it('アカウント内にWorkflowを作成できる（WorktypeIDあり、テンプレートファイルなし）', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId1 } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: authorId2 } = await makeTestUser(source, {
      external_id: 'author2',
      author_id: 'AUTHOR2',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId1 } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });
    const { id: typistId2 } = await makeTestUser(source, {
      external_id: 'typist12',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const { id: worktypeId } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    const preWorkflow = await createWorkflow(
      source,
      account.id,
      authorId1,
      undefined,
      undefined,
    );
    await createWorkflowTypist(source, preWorkflow.id, typistId1);

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(1);
      expect(workflows[0].id).toBe(preWorkflow.id);
      expect(workflows[0].account_id).toBe(account.id);
      expect(workflows[0].author_id).toBe(authorId1);
      expect(workflows[0].worktype_id).toBe(null);
      expect(workflows[0].template_id).toBe(null);
      expect(workflowTypists.length).toBe(1);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    await service.updateWorkflow(
      context,
      admin.external_id,
      preWorkflow.id,
      authorId2,
      [
        {
          typistId: typistId2,
        },
      ],
      worktypeId,
      undefined,
    );

    //実行結果を確認
    {
      const workflows = await getWorkflows(source, account.id);
      expect(workflows.length).toBe(1);
      expect(workflows[0].account_id).toBe(account.id);
      expect(workflows[0].author_id).toBe(authorId2);
      expect(workflows[0].worktype_id).toBe(worktypeId);
      expect(workflows[0].template_id).toBe(null);

      const workflowTypists = await getWorkflowTypists(source, workflows[0].id);
      expect(workflowTypists.length).toBe(1);
      expect(workflowTypists[0].typist_id).toBe(typistId2);
    }
  });

  it('アカウント内にWorkflowを作成できる（WorktypeIDなし、テンプレートファイルなし）', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId1 } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: authorId2 } = await makeTestUser(source, {
      external_id: 'author2',
      author_id: 'AUTHOR2',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId1 } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });
    const { id: typistId2 } = await makeTestUser(source, {
      external_id: 'typist12',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const preWorkflow = await createWorkflow(
      source,
      account.id,
      authorId1,
      undefined,
      undefined,
    );
    await createWorkflowTypist(source, preWorkflow.id, typistId1);

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(1);
      expect(workflows[0].id).toBe(preWorkflow.id);
      expect(workflows[0].account_id).toBe(account.id);
      expect(workflows[0].author_id).toBe(authorId1);
      expect(workflows[0].worktype_id).toBe(null);
      expect(workflows[0].template_id).toBe(null);
      expect(workflowTypists.length).toBe(1);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    await service.updateWorkflow(
      context,
      admin.external_id,
      preWorkflow.id,
      authorId2,
      [
        {
          typistId: typistId2,
        },
      ],
      undefined,
      undefined,
    );

    //実行結果を確認
    {
      const workflows = await getWorkflows(source, account.id);
      expect(workflows.length).toBe(1);
      expect(workflows[0].account_id).toBe(account.id);
      expect(workflows[0].author_id).toBe(authorId2);
      expect(workflows[0].worktype_id).toBe(null);
      expect(workflows[0].template_id).toBe(null);

      const workflowTypists = await getWorkflowTypists(source, workflows[0].id);
      expect(workflowTypists.length).toBe(1);
      expect(workflowTypists[0].typist_id).toBe(typistId2);
    }
  });

  it('アカウント内にWorkflowを作成できる（WorktypeIDなし、テンプレートファイルなし、同一AuthorIDのワークフローあり）', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId1 } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: authorId2 } = await makeTestUser(source, {
      external_id: 'author2',
      author_id: 'AUTHOR2',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId1 } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });
    const { id: typistId2 } = await makeTestUser(source, {
      external_id: 'typist12',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });
    const { id: worktypeId } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );
    // 更新対象のワークフローを作成
    const preWorkflow1 = await createWorkflow(
      source,
      account.id,
      authorId1,
      undefined,
      undefined,
    );
    // 同一AuthorIDのワークフローを作成
    const preWorkflow2 = await createWorkflow(
      source,
      account.id,
      authorId2, // 更新するAuthorIDと同じ
      worktypeId,
      undefined,
    );

    await createWorkflowTypist(source, preWorkflow1.id, typistId1);
    await createWorkflowTypist(source, preWorkflow2.id, typistId1);

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      workflows.sort((a, b) => a.id - b.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(2);
      expect(workflows[0].id).toBe(preWorkflow1.id);
      expect(workflows[0].account_id).toBe(account.id);
      expect(workflows[0].author_id).toBe(authorId1);
      expect(workflows[0].worktype_id).toBe(null);
      expect(workflows[0].template_id).toBe(null);
      expect(workflows[1].id).toBe(preWorkflow2.id);
      expect(workflows[1].account_id).toBe(account.id);
      expect(workflows[1].author_id).toBe(authorId2);
      expect(workflows[1].worktype_id).toBe(worktypeId);
      expect(workflows[1].template_id).toBe(null);
      expect(workflowTypists.length).toBe(2);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    await service.updateWorkflow(
      context,
      admin.external_id,
      preWorkflow1.id,
      authorId2,
      [
        {
          typistId: typistId2,
        },
      ],
      undefined,
      undefined,
    );

    //実行結果を確認
    {
      const workflows = await getWorkflows(source, account.id);
      workflows.sort((a, b) => a.id - b.id);
      expect(workflows.length).toBe(2);
      expect(workflows[1].account_id).toBe(account.id);
      expect(workflows[1].author_id).toBe(authorId2);
      expect(workflows[1].worktype_id).toBe(null);
      expect(workflows[1].template_id).toBe(null);

      const workflowTypists = await getWorkflowTypists(source, workflows[1].id);
      expect(workflowTypists.length).toBe(1);
      expect(workflowTypists[0].typist_id).toBe(typistId2);
    }
  });

  it('Authorがメール未認証の場合、400エラーとなること', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId1 } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: authorId2 } = await makeTestUser(source, {
      external_id: 'author2',
      author_id: 'AUTHOR2',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
      email_verified: false,
    });
    const { id: typistId1 } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const preWorkflow = await createWorkflow(
      source,
      account.id,
      authorId1,
      undefined,
      undefined,
    );
    await createWorkflowTypist(source, preWorkflow.id, typistId1);

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(1);
      expect(workflows[0].id).toBe(preWorkflow.id);
      expect(workflows[0].account_id).toBe(account.id);
      expect(workflows[0].author_id).toBe(authorId1);
      expect(workflows[0].worktype_id).toBe(null);
      expect(workflows[0].template_id).toBe(null);
      expect(workflowTypists.length).toBe(1);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //実行結果を確認
    try {
      await service.updateWorkflow(
        context,
        admin.external_id,
        preWorkflow.id,
        authorId2,
        [{ typistId: typistId1 }],
        undefined,
        undefined,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E010204'));
      } else {
        fail();
      }
    }
  });

  it('DBにWorkflowが存在しない場合、400エラーとなること', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId1 } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId1 } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //実行結果を確認
    try {
      await service.updateWorkflow(
        context,
        admin.external_id,
        9999,
        authorId1,
        [
          {
            typistId: typistId1,
          },
        ],
        undefined,
        undefined,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E013002'));
      } else {
        fail();
      }
    }
  });
  it('DBにAuthorが存在しない場合、400エラーとなること', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId1 } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId1 } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const { id: worktypeId } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    const { id: templateId } = await createTemplateFile(
      source,
      account.id,
      'fileName1',
      'url1',
    );

    const preWorkflow = await createWorkflow(
      source,
      account.id,
      authorId1,
      undefined,
      undefined,
    );
    await createWorkflowTypist(source, preWorkflow.id, typistId1);

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      expect(workflows.length).toBe(1);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //実行結果を確認
    try {
      await service.updateWorkflow(
        context,
        admin.external_id,
        preWorkflow.id,
        9999,
        [
          {
            typistId: typistId1,
          },
        ],
        worktypeId,
        templateId,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E010204'));
      } else {
        fail();
      }
    }
  });

  it('DBにWorktypeIDが存在しない場合、400エラーとなること', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId1 } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId1 } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const { id: templateId } = await createTemplateFile(
      source,
      account.id,
      'fileName1',
      'url1',
    );

    const preWorkflow = await createWorkflow(
      source,
      account.id,
      authorId1,
      undefined,
      undefined,
    );
    await createWorkflowTypist(source, preWorkflow.id, typistId1);

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      expect(workflows.length).toBe(1);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //実行結果を確認
    try {
      await service.updateWorkflow(
        context,
        admin.external_id,
        preWorkflow.id,
        authorId1,
        [
          {
            typistId: typistId1,
          },
        ],
        9999,
        templateId,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E011003'));
      } else {
        fail();
      }
    }
  });

  it('DBにテンプレートファイルが存在しない場合、400エラーとなること', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId1 } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId1 } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const { id: worktypeId } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    const preWorkflow = await createWorkflow(
      source,
      account.id,
      authorId1,
      undefined,
      undefined,
    );
    await createWorkflowTypist(source, preWorkflow.id, typistId1);

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      expect(workflows.length).toBe(1);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //実行結果を確認
    try {
      await service.updateWorkflow(
        context,
        admin.external_id,
        preWorkflow.id,
        authorId1,
        [
          {
            typistId: typistId1,
          },
        ],
        worktypeId,
        9999,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E012001'));
      } else {
        fail();
      }
    }
  });

  it('DBにルーティング候補ユーザーが存在しない場合、400エラーとなること', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId1 } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId1 } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const { id: worktypeId } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    const { id: templateId } = await createTemplateFile(
      source,
      account.id,
      'fileName1',
      'url1',
    );

    const preWorkflow = await createWorkflow(
      source,
      account.id,
      authorId1,
      undefined,
      undefined,
    );
    await createWorkflowTypist(source, preWorkflow.id, typistId1);

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      expect(workflows.length).toBe(1);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //実行結果を確認
    try {
      await service.updateWorkflow(
        context,
        admin.external_id,
        preWorkflow.id,
        authorId1,
        [
          {
            typistId: 9999,
          },
        ],
        worktypeId,
        templateId,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E010204'));
      } else {
        fail();
      }
    }
  });

  it('Dルーティング候補ユーザーがメール未認証の場合、400エラーとなること', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId1 } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId1 } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });
    const { id: typistId2 } = await makeTestUser(source, {
      external_id: 'typist2',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
      email_verified: false,
    });

    const { id: worktypeId } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    const { id: templateId } = await createTemplateFile(
      source,
      account.id,
      'fileName1',
      'url1',
    );

    const preWorkflow = await createWorkflow(
      source,
      account.id,
      authorId1,
      undefined,
      undefined,
    );
    await createWorkflowTypist(source, preWorkflow.id, typistId1);

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      expect(workflows.length).toBe(1);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //実行結果を確認
    try {
      await service.updateWorkflow(
        context,
        admin.external_id,
        preWorkflow.id,
        authorId1,
        [
          {
            typistId: typistId2,
          },
        ],
        worktypeId,
        templateId,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E010204'));
      } else {
        fail();
      }
    }
  });

  it('DBにルーティング候補グループが存在しない場合、400エラーとなること', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId1 } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId1 } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const { id: worktypeId } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    const { id: templateId } = await createTemplateFile(
      source,
      account.id,
      'fileName1',
      'url1',
    );

    const preWorkflow = await createWorkflow(
      source,
      account.id,
      authorId1,
      undefined,
      undefined,
    );
    await createWorkflowTypist(source, preWorkflow.id, typistId1);

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      expect(workflows.length).toBe(1);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //実行結果を確認
    try {
      await service.updateWorkflow(
        context,
        admin.external_id,
        preWorkflow.id,
        authorId1,
        [
          {
            typistGroupId: 9999,
          },
        ],
        worktypeId,
        templateId,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E010908'));
      } else {
        fail();
      }
    }
  });

  it('DBにAuthorIDとWorktypeIDのペアがすでに存在する場合、400エラーとなること', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId1 } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId1 } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });
    const { id: worktypeId1 } = await createWorktype(
      source,
      account.id,
      'worktype1',
    );

    await createWorkflow(source, account.id, authorId1, worktypeId1, undefined);

    const preWorkflow = await createWorkflow(
      source,
      account.id,
      authorId1,
      undefined,
      undefined,
    );
    await createWorkflowTypist(source, preWorkflow.id, typistId1);

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      expect(workflows.length).toBe(2);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //実行結果を確認
    try {
      await service.updateWorkflow(
        context,
        admin.external_id,
        preWorkflow.id,
        authorId1,
        [
          {
            typistId: typistId1,
          },
        ],
        worktypeId1,
        undefined,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E013001'));
      } else {
        fail();
      }
    }
  });

  it('DBアクセスに失敗した場合、500エラーを返却する', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId1 } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId1 } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const preWorkflow = await createWorkflow(
      source,
      account.id,
      authorId1,
      undefined,
      undefined,
    );
    await createWorkflowTypist(source, preWorkflow.id, typistId1);

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(1);
      expect(workflows[0].id).toBe(preWorkflow.id);
      expect(workflows[0].account_id).toBe(account.id);
      expect(workflows[0].author_id).toBe(authorId1);
      expect(workflows[0].worktype_id).toBe(null);
      expect(workflows[0].template_id).toBe(null);
      expect(workflowTypists.length).toBe(1);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //DBアクセスに失敗するようにする
    const workflowsRepositoryService = module.get<WorkflowsRepositoryService>(
      WorkflowsRepositoryService,
    );
    workflowsRepositoryService.updatetWorkflow = jest
      .fn()
      .mockRejectedValue('DB failed');

    //実行結果を確認
    try {
      await service.updateWorkflow(
        context,
        admin.external_id,
        preWorkflow.id,
        authorId1,
        [
          {
            typistId: typistId1,
          },
        ],
        undefined,
        undefined,
      );
      fail();
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
        expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
      } else {
        fail();
      }
    }
  });
});

describe('deleteWorkflows', () => {
  let source: DataSource | null = null;
  beforeAll(async () => {
    if (source == null) {
      source = await (async () => {
        const s = new DataSource({
          type: 'mysql',
          host: 'test_mysql_db',
          port: 3306,
          username: 'user',
          password: 'password',
          database: 'odms',
          entities: [__dirname + '/../../**/*.entity{.ts,.js}'],
          synchronize: false, // trueにすると自動的にmigrationが行われるため注意
        });
        return await s.initialize();
      })();
    }
  });

  beforeEach(async () => {
    if (source) {
      await truncateAllTable(source);
    }
  });

  afterAll(async () => {
    await source?.destroy();
    source = null;
  });

  it('アカウント内のWorkflowを削除できる', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const workflow = await createWorkflow(
      source,
      account.id,
      authorId,
      undefined,
      undefined,
    );
    await createWorkflowTypist(source, workflow.id, typistId);

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(1);
      expect(workflowTypists.length).toBe(1);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    await service.deleteWorkflow(context, admin.external_id, workflow.id);

    //実行結果を確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(0);
      expect(workflowTypists.length).toBe(0);
    }
  });

  it('アカウント内のWorkflowを削除できる（複数ワークフローがある場合）', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId1 } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: authorId2 } = await makeTestUser(source, {
      external_id: 'author2',
      author_id: 'AUTHOR2',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const workflow1 = await createWorkflow(source, account.id, authorId1);
    await createWorkflowTypist(source, workflow1.id, typistId);
    const workflow2 = await createWorkflow(source, account.id, authorId2);
    await createWorkflowTypist(source, workflow2.id, typistId);

    //作成したデータを確認
    {
      const workflows = await getAllWorkflows(source);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(2);
      expect(workflowTypists.length).toBe(2);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    await service.deleteWorkflow(context, admin.external_id, workflow1.id);

    //実行結果を確認
    {
      const workflows = await getAllWorkflows(source);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(1);
      expect(workflows[0].id).toBe(workflow2.id);
      expect(workflowTypists.length).toBe(1);
      expect(workflowTypists[0].workflow_id).toBe(workflow2.id);
    }
  });

  it('指定されたワークフローが存在しない場合、400エラーを返却する', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const workflow = await createWorkflow(
      source,
      account.id,
      authorId,
      undefined,
      undefined,
    );
    await createWorkflowTypist(source, workflow.id, typistId);

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(1);
      expect(workflowTypists.length).toBe(1);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //実行結果を確認
    try {
      await service.deleteWorkflow(context, admin.external_id, 9999);
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E013002'));
      } else {
        fail();
      }
    }
  });

  it('指定されたワークフローが存在しない場合、400エラーを返却する（ログインユーザーのアカウント外）', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const workflow = await createWorkflow(
      source,
      account.id,
      authorId,
      undefined,
      undefined,
    );
    await createWorkflowTypist(source, workflow.id, typistId);

    const { account: otherAccount } = await makeTestAccount(source, {
      tier: 5,
    });
    const { id: otherAauthorId } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: otherAccount.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: otherTypistId } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: otherAccount.id,
      role: USER_ROLES.TYPIST,
    });

    const otherWorkflow = await createWorkflow(
      source,
      otherAccount.id,
      otherAauthorId,
      undefined,
      undefined,
    );
    await createWorkflowTypist(source, otherWorkflow.id, otherTypistId);

    //作成したデータを確認
    {
      const workflows = await getAllWorkflows(source);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(2);
      expect(workflowTypists.length).toBe(2);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //実行結果を確認
    try {
      await service.deleteWorkflow(
        context,
        admin.external_id,
        otherWorkflow.id,
      );
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.BAD_REQUEST);
        expect(e.getResponse()).toEqual(makeErrorResponse('E013002'));
      } else {
        fail();
      }
    }
  });

  it('DBアクセスに失敗した場合、500エラーを返却する', async () => {
    if (!source) fail();
    const module = await makeTestingModule(source);
    if (!module) fail();
    // 第五階層のアカウント作成
    const { account, admin } = await makeTestAccount(source, { tier: 5 });
    const { id: authorId } = await makeTestUser(source, {
      external_id: 'author1',
      author_id: 'AUTHOR1',
      account_id: account.id,
      role: USER_ROLES.AUTHOR,
    });
    const { id: typistId } = await makeTestUser(source, {
      external_id: 'typist1',
      account_id: account.id,
      role: USER_ROLES.TYPIST,
    });

    const workflow = await createWorkflow(
      source,
      account.id,
      authorId,
      undefined,
      undefined,
    );
    await createWorkflowTypist(source, workflow.id, typistId);

    //作成したデータを確認
    {
      const workflows = await getWorkflows(source, account.id);
      const workflowTypists = await getAllWorkflowTypists(source);
      expect(workflows.length).toBe(1);
      expect(workflowTypists.length).toBe(1);
    }

    const service = module.get<WorkflowsService>(WorkflowsService);
    const context = makeContext(admin.external_id, 'requestId');

    //DBアクセスに失敗するようにする
    const workflowsRepositoryService = module.get<WorkflowsRepositoryService>(
      WorkflowsRepositoryService,
    );
    workflowsRepositoryService.deleteWorkflow = jest
      .fn()
      .mockRejectedValue('DB failed');

    //実行結果を確認
    try {
      await service.deleteWorkflow(context, admin.external_id, workflow.id);
    } catch (e) {
      if (e instanceof HttpException) {
        expect(e.getStatus()).toEqual(HttpStatus.INTERNAL_SERVER_ERROR);
        expect(e.getResponse()).toEqual(makeErrorResponse('E009999'));
      } else {
        fail();
      }
    }
  });
});
