From f34d4e9b0e8943067661db81b60fed2c2629eae7 Mon Sep 17 00:00:00 2001
From: "kaoru.ohtaka" <ockacru+git@gmail.com>
Date: Sun, 14 Apr 2024 06:23:25 +0900
Subject: [PATCH 1/2] test: increase test coverage

---
 src/bin/args-options.ts                       |  38 +++++
 src/bin/pnpm-license-exporter.ts              |  38 +----
 .../build-exported-pnpm-package-info.test.ts  |  41 ++++++
 .../utils/build-exported-pnpm-package-info.ts |   9 ++
 .../utils/find-license-dirent.test.ts         |  35 +++++
 .../utils/find-license-dirent.ts              |   7 +
 .../utils/search-license.util.test.ts         | 108 ++++++++++++++
 .../utils/search-license.util.ts              |  12 +-
 .../utils/write-licenses.test.ts              | 138 ++++++++++++++++++
 .../export-license/utils/write-licenses.ts    |   2 +-
 vitest.config.ts                              |   9 +-
 11 files changed, 388 insertions(+), 49 deletions(-)
 create mode 100644 src/bin/args-options.ts
 create mode 100644 src/pnpm/export-license/utils/build-exported-pnpm-package-info.test.ts
 create mode 100644 src/pnpm/export-license/utils/build-exported-pnpm-package-info.ts
 create mode 100644 src/pnpm/export-license/utils/find-license-dirent.test.ts
 create mode 100644 src/pnpm/export-license/utils/find-license-dirent.ts
 create mode 100644 src/pnpm/export-license/utils/search-license.util.test.ts
 create mode 100644 src/pnpm/export-license/utils/write-licenses.test.ts

diff --git a/src/bin/args-options.ts b/src/bin/args-options.ts
new file mode 100644
index 0000000..ba5c88f
--- /dev/null
+++ b/src/bin/args-options.ts
@@ -0,0 +1,38 @@
+import type { ParseArgsConfig } from 'node:util';
+
+export const argsOptions = {
+  output: {
+    type: 'string',
+    multiple: false,
+    short: 'o',
+    default: './licenses.json',
+  },
+  pretty: {
+    type: 'boolean',
+    multiple: false,
+    short: 'p',
+    default: false,
+  },
+  recursive: {
+    type: 'boolean',
+    multiple: false,
+    short: 'r',
+    default: false,
+  },
+  dev: {
+    type: 'boolean',
+    multiple: false,
+    short: 'd',
+    default: false,
+  },
+  'no-prod': {
+    type: 'boolean',
+    multiple: false,
+    default: false,
+  },
+  'no-optional': {
+    type: 'boolean',
+    multiple: false,
+    default: false,
+  },
+} satisfies ParseArgsConfig['options'];
\ No newline at end of file
diff --git a/src/bin/pnpm-license-exporter.ts b/src/bin/pnpm-license-exporter.ts
index 01e8d13..102cae7 100644
--- a/src/bin/pnpm-license-exporter.ts
+++ b/src/bin/pnpm-license-exporter.ts
@@ -3,43 +3,7 @@
 import { execSync } from 'node:child_process';
 import { parseArgs, ParseArgsConfig } from 'node:util';
 import { writeLicenses } from '../pnpm/export-license';
-
-export const argsOptions = {
-  output: {
-    type: 'string',
-    multiple: false,
-    short: 'o',
-    default: './licenses.json',
-  },
-  pretty: {
-    type: 'boolean',
-    multiple: false,
-    short: 'p',
-    default: false,
-  },
-  recursive: {
-    type: 'boolean',
-    multiple: false,
-    short: 'r',
-    default: false,
-  },
-  dev: {
-    type: 'boolean',
-    multiple: false,
-    short: 'd',
-    default: false,
-  },
-  'no-prod': {
-    type: 'boolean',
-    multiple: false,
-    default: false,
-  },
-  'no-optional': {
-    type: 'boolean',
-    multiple: false,
-    default: false,
-  },
-} satisfies ParseArgsConfig['options'];
+import { argsOptions } from './args-options';
 
 const nodeLinkerSetting = (
   JSON.parse(execSync('pnpm config list --json').toString('utf8')) as {
diff --git a/src/pnpm/export-license/utils/build-exported-pnpm-package-info.test.ts b/src/pnpm/export-license/utils/build-exported-pnpm-package-info.test.ts
new file mode 100644
index 0000000..9d3fdf6
--- /dev/null
+++ b/src/pnpm/export-license/utils/build-exported-pnpm-package-info.test.ts
@@ -0,0 +1,41 @@
+import { nextLicense } from '../../../license-txt';
+import { buildExportedPnpmPackageInfo } from './build-exported-pnpm-package-info';
+
+test('should return package info without licenseTxt', () => {
+  expect(buildExportedPnpmPackageInfo({
+      name: '@ampproject/remapping',
+      version: '2.2.0',
+      path: '/Users/luco/ghq/sucomado-frontend/node_modules/.pnpm/@ampproject+remapping@2.2.0/node_modules/@ampproject/remapping',
+      license: 'Apache-2.0',
+      author: 'Justin Ridgewell',
+      homepage: 'https://github.com/ampproject/remapping#readme',
+      description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+    }, undefined)).toStrictEqual({
+      name: '@ampproject/remapping',
+      version: '2.2.0',
+      license: 'Apache-2.0',
+      author: 'Justin Ridgewell',
+      homepage: 'https://github.com/ampproject/remapping#readme',
+      description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+  });
+});
+
+test('should return package info with licenseTxt', () => {
+    expect(buildExportedPnpmPackageInfo({
+      name: '@ampproject/remapping',
+      version: '2.2.0',
+      path: '/Users/luco/ghq/sucomado-frontend/node_modules/.pnpm/@ampproject+remapping@2.2.0/node_modules/@ampproject/remapping',
+      license: 'Apache-2.0',
+      author: 'Justin Ridgewell',
+      homepage: 'https://github.com/ampproject/remapping#readme',
+      description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+    }, nextLicense)).toStrictEqual({
+      name: '@ampproject/remapping',
+      version: '2.2.0',
+      license: 'Apache-2.0',
+      author: 'Justin Ridgewell',
+      homepage: 'https://github.com/ampproject/remapping#readme',
+      description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+      licenseTxt: nextLicense,
+  });
+});
\ No newline at end of file
diff --git a/src/pnpm/export-license/utils/build-exported-pnpm-package-info.ts b/src/pnpm/export-license/utils/build-exported-pnpm-package-info.ts
new file mode 100644
index 0000000..1d42cf8
--- /dev/null
+++ b/src/pnpm/export-license/utils/build-exported-pnpm-package-info.ts
@@ -0,0 +1,9 @@
+import type { PnpmPackageInfo, ExportedPnpmPackageInfo } from '../types/export-licenses.types';
+
+export function buildExportedPnpmPackageInfo(pnpmPackage: PnpmPackageInfo, licenseTxt: undefined | string): ExportedPnpmPackageInfo {
+  // remove path property
+  const { path, ...PnpmPackageInfo } = pnpmPackage;
+  return licenseTxt === undefined
+    ? PnpmPackageInfo
+    : { ...PnpmPackageInfo, licenseTxt };
+}
\ No newline at end of file
diff --git a/src/pnpm/export-license/utils/find-license-dirent.test.ts b/src/pnpm/export-license/utils/find-license-dirent.test.ts
new file mode 100644
index 0000000..d5f6b7a
--- /dev/null
+++ b/src/pnpm/export-license/utils/find-license-dirent.test.ts
@@ -0,0 +1,35 @@
+import { Mock } from 'vitest';
+import { findLicenseDirent } from './find-license-dirent';
+import { readdir } from 'node:fs/promises';
+
+vitest.mock('node:fs/promises', () => ({
+  readdir: vitest.fn().mockResolvedValue([
+    {
+      name: 'LICENSE.md',
+      parentPath: '/Users/mock/luco-inc/pnpm-license-exporter/node_modules/.pnpm/vitest@1.5.0_@types+node@20.12.7/node_modules/vitest/',
+      path: '/Users/mock/luco-inc/pnpm-license-exporter/node_modules/.pnpm/vitest@1.5.0_@types+node@20.12.7/node_modules/vitest/',
+    },
+    {
+      name: 'README.md',
+      parentPath: '/Users/mock/luco-inc/pnpm-license-exporter/node_modules/.pnpm/vitest@1.5.0_@types+node@20.12.7/node_modules/vitest/',
+      path: '/Users/mock/luco-inc/pnpm-license-exporter/node_modules/.pnpm/vitest@1.5.0_@types+node@20.12.7/node_modules/vitest/',
+    }
+  ])
+}));
+
+test('should return license dirent', async () => {
+  expect(await findLicenseDirent('/Users/mock/luco-inc/pnpm-license-exporter/node_modules/.pnpm/vitest@1.5.0_@types+node@20.12.7/node_modules/vitest')).toStrictEqual({
+    name: 'LICENSE.md',
+    parentPath: '/Users/mock/luco-inc/pnpm-license-exporter/node_modules/.pnpm/vitest@1.5.0_@types+node@20.12.7/node_modules/vitest/',
+    path: '/Users/mock/luco-inc/pnpm-license-exporter/node_modules/.pnpm/vitest@1.5.0_@types+node@20.12.7/node_modules/vitest/'
+  });
+});
+
+test('should return undefined', async () => {
+  (readdir as Mock).mockResolvedValue([{
+    name: 'README.md',
+    parentPath: '/Users/mock/luco-inc/pnpm-license-exporter/node_modules/.pnpm/vitest@1.5.0_@types+node@20.12.7/node_modules/vitest/',
+    path: '/Users/mock/luco-inc/pnpm-license-exporter/node_modules/.pnpm/vitest@1.5.0_@types+node@20.12.7/node_modules/vitest/',
+  }]);
+  expect(await findLicenseDirent('/Users/mock/luco-inc/pnpm-license-exporter/node_modules/.pnpm/vitest@1.5.0_@types+node@20.12.7/node_modules/vitest')).toBe(undefined);
+});
\ No newline at end of file
diff --git a/src/pnpm/export-license/utils/find-license-dirent.ts b/src/pnpm/export-license/utils/find-license-dirent.ts
new file mode 100644
index 0000000..0cbe428
--- /dev/null
+++ b/src/pnpm/export-license/utils/find-license-dirent.ts
@@ -0,0 +1,7 @@
+import type { Dirent } from 'node:fs';
+import { readdir } from 'node:fs/promises';
+
+export async function findLicenseDirent(pnpmPackagePath: string): Promise<Dirent | undefined> {
+  const dirents = await readdir(pnpmPackagePath, { withFileTypes: true });
+  return dirents.find((dirent) => dirent.name.toLowerCase().includes('license'));
+}
\ No newline at end of file
diff --git a/src/pnpm/export-license/utils/search-license.util.test.ts b/src/pnpm/export-license/utils/search-license.util.test.ts
new file mode 100644
index 0000000..c0a93d1
--- /dev/null
+++ b/src/pnpm/export-license/utils/search-license.util.test.ts
@@ -0,0 +1,108 @@
+import { mockPnpmPackages } from '../mocks/mock-pnpm-packages';
+import { searchLicense } from './search-license.util';
+import { findLicenseDirent } from './find-license-dirent';
+import { buildExportedPnpmPackageInfo } from './build-exported-pnpm-package-info';
+import { readLicense } from './read-license.util';
+import { Mock } from 'vitest';
+import { nextLicense } from '../../../license-txt';
+
+vitest.mock('./find-license-dirent', () => ({
+  findLicenseDirent: vitest.fn().mockResolvedValue({
+    name: 'LICENSE.md',
+    parentPath: '/Users/mock/luco-inc/pnpm-license-exporter/node_modules/.pnpm/vitest@1.5.0_@types+node@20.12.7/node_modules/vitest/',
+    path: '/Users/mock/luco-inc/pnpm-license-exporter/node_modules/.pnpm/vitest@1.5.0_@types+node@20.12.7/node_modules/vitest/'
+  })
+}));
+
+vitest.mock('./build-exported-pnpm-package-info', () => ({
+  buildExportedPnpmPackageInfo: vitest.fn().mockImplementation(()=> ({
+    name: '@ampproject/remapping',
+    version: '2.2.0',
+    license: 'Apache-2.0',
+    author: 'Justin Ridgewell',
+    homepage: 'https://github.com/ampproject/remapping#readme',
+    description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+  }))
+}));
+
+vitest.mock('./read-license.util', () => ({
+  readLicense: vitest.fn().mockResolvedValue(undefined)
+}));
+
+test('should return licenses', async () => {
+  expect(await searchLicense([
+    mockPnpmPackages['Apache-2.0'][0],
+    mockPnpmPackages.MIT[0],
+    mockPnpmPackages.MIT[1],
+  ])).toStrictEqual([
+    {
+      name: '@ampproject/remapping',
+      version: '2.2.0',
+      license: 'Apache-2.0',
+      author: 'Justin Ridgewell',
+      homepage: 'https://github.com/ampproject/remapping#readme',
+      description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+    },
+    {
+      name: '@ampproject/remapping',
+      version: '2.2.0',
+      license: 'Apache-2.0',
+      author: 'Justin Ridgewell',
+      homepage: 'https://github.com/ampproject/remapping#readme',
+      description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+    },
+    {
+      name: '@ampproject/remapping',
+      version: '2.2.0',
+      license: 'Apache-2.0',
+      author: 'Justin Ridgewell',
+      homepage: 'https://github.com/ampproject/remapping#readme',
+      description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+    },
+  ])
+  expect(findLicenseDirent).toHaveBeenCalledTimes(3);
+  expect(readLicense).toHaveBeenCalledTimes(3);
+  expect(buildExportedPnpmPackageInfo).toHaveBeenCalledTimes(3);
+});
+
+test('should using pnpm package in args', async () => {
+  (readLicense as Mock).mockResolvedValue(nextLicense);
+  (buildExportedPnpmPackageInfo as Mock).mockResolvedValue({
+      name: '@ampproject/remapping',
+      version: '2.2.0',
+      license: 'Apache-2.0',
+      author: 'Justin Ridgewell',
+      homepage: 'https://github.com/ampproject/remapping#readme',
+      description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+      licenseTxt: nextLicense,
+  });
+
+  expect(await searchLicense([mockPnpmPackages['Apache-2.0'][0]])).toStrictEqual([
+    {
+      name: '@ampproject/remapping',
+      version: '2.2.0',
+      license: 'Apache-2.0',
+      author: 'Justin Ridgewell',
+      homepage: 'https://github.com/ampproject/remapping#readme',
+      description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+      licenseTxt: nextLicense,
+    }
+  ]);
+  expect(findLicenseDirent).toHaveBeenCalledTimes(1);
+  expect(findLicenseDirent).toHaveBeenCalledWith('/Users/luco/ghq/sucomado-frontend/node_modules/.pnpm/@ampproject+remapping@2.2.0/node_modules/@ampproject/remapping');
+  expect(readLicense).toHaveBeenCalledTimes(1);
+  expect(readLicense).toHaveBeenCalledWith({
+    name: '@ampproject/remapping',
+    licensePath: '/Users/luco/ghq/sucomado-frontend/node_modules/.pnpm/@ampproject+remapping@2.2.0/node_modules/@ampproject/remapping/LICENSE.md',
+  });
+  expect(buildExportedPnpmPackageInfo).toHaveBeenCalledTimes(1);
+  expect(buildExportedPnpmPackageInfo).toHaveBeenCalledWith({
+    name: '@ampproject/remapping',
+    version: '2.2.0',
+    license: 'Apache-2.0',
+    author: 'Justin Ridgewell',
+    homepage: 'https://github.com/ampproject/remapping#readme',
+    description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+    path: "/Users/luco/ghq/sucomado-frontend/node_modules/.pnpm/@ampproject+remapping@2.2.0/node_modules/@ampproject/remapping"
+  }, nextLicense);
+})
\ No newline at end of file
diff --git a/src/pnpm/export-license/utils/search-license.util.ts b/src/pnpm/export-license/utils/search-license.util.ts
index 5bf4f79..50c471b 100644
--- a/src/pnpm/export-license/utils/search-license.util.ts
+++ b/src/pnpm/export-license/utils/search-license.util.ts
@@ -1,12 +1,12 @@
-import { readdir } from 'node:fs/promises';
 import type { PnpmPackageInfo, ExportedPnpmPackageInfo } from '../types/export-licenses.types';
 import { readLicense } from './read-license.util';
+import { findLicenseDirent } from './find-license-dirent';
+import { buildExportedPnpmPackageInfo } from './build-exported-pnpm-package-info';
 
-export function searchLicense(packages: PnpmPackageInfo[]) {
+export function searchLicense(packages: PnpmPackageInfo[]): Promise<(ExportedPnpmPackageInfo|undefined)[]> {
   return Promise.all(
     packages.map(async (pnpmPackage): Promise<ExportedPnpmPackageInfo | undefined> => {
-      const dirents = await readdir(pnpmPackage.path, { withFileTypes: true });
-      const licenseDirent = dirents.find((dirent) => dirent.name.toLowerCase().includes('license'));
+      const licenseDirent = await findLicenseDirent(pnpmPackage.path);
       if (licenseDirent === undefined) {
         return undefined;
       }
@@ -14,9 +14,7 @@ export function searchLicense(packages: PnpmPackageInfo[]) {
         name: pnpmPackage.name,
         licensePath: `${pnpmPackage.path}/${licenseDirent.name}`,
       });
-      // remove path property
-      const { path, ...PnpmPackageInfo } = pnpmPackage;
-      return licenseTxt === undefined ? PnpmPackageInfo : { ...PnpmPackageInfo, licenseTxt };
+      return buildExportedPnpmPackageInfo(pnpmPackage, licenseTxt);
     }),
   ).then((licenses) => licenses.filter(Boolean));
 }
diff --git a/src/pnpm/export-license/utils/write-licenses.test.ts b/src/pnpm/export-license/utils/write-licenses.test.ts
new file mode 100644
index 0000000..200b7bf
--- /dev/null
+++ b/src/pnpm/export-license/utils/write-licenses.test.ts
@@ -0,0 +1,138 @@
+import { writeLicenses } from './write-licenses';
+import { writeFile, mkdir } from 'node:fs/promises';
+import { generateFlatPnpmPackages } from './generate-flat-pnpm-packages.util';
+import { searchLicense } from './search-license.util';
+import path from 'node:path';
+import { mockPnpmPackages } from '../mocks/mock-pnpm-packages';
+import { Mock } from 'vitest';
+
+vi.mock('node:path', () => ({
+  ...vi.importActual('node:path'),
+  default: {
+    dirname: vi.fn().mockReturnValue('src/licenses'),
+  }
+}));
+vi.mock('node:fs/promises', () => ({
+  ...vi.importActual('node:fs/promises'),
+  writeFile: vi.fn().mockResolvedValue(undefined),
+  mkdir: vi.fn().mockResolvedValue(undefined),
+}));
+vi.mock('./generate-flat-pnpm-packages.util', () => ({
+  generateFlatPnpmPackages: vi.fn().mockImplementation(()=> [
+    mockPnpmPackages['Apache-2.0'][0],
+    mockPnpmPackages.MIT[0],
+    mockPnpmPackages.MIT[1],
+  ])
+}));
+vi.mock('./search-license.util', () => ({
+  searchLicense: vi.fn().mockResolvedValue([
+    {
+      name: '@ampproject/remapping',
+      version: '2.2.0',
+      license: 'Apache-2.0',
+      author: 'Justin Ridgewell',
+      homepage: 'https://github.com/ampproject/remapping#readme',
+      description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+    },
+    {
+      name: '@ampproject/remapping',
+      version: '2.2.0',
+      license: 'Apache-2.0',
+      author: 'Justin Ridgewell',
+      homepage: 'https://github.com/ampproject/remapping#readme',
+      description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+    },
+    {
+      name: '@ampproject/remapping',
+      version: '2.2.0',
+      license: 'Apache-2.0',
+      author: 'Justin Ridgewell',
+      homepage: 'https://github.com/ampproject/remapping#readme',
+      description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+    },
+  ]),
+}));
+
+test('should write licenses', async () => {
+  await writeLicenses({});
+  expect(generateFlatPnpmPackages).toHaveBeenCalledTimes(1);
+  expect(generateFlatPnpmPackages).toHaveBeenCalledWith({
+    dev: false,
+    noOptional: false,
+    noProd: false,
+    recursive: false,
+  });
+  expect(searchLicense).toHaveBeenCalledTimes(1);
+  expect(searchLicense).toHaveBeenCalledWith([
+    mockPnpmPackages['Apache-2.0'][0],
+    mockPnpmPackages.MIT[0],
+    mockPnpmPackages.MIT[1],
+  ]);
+  expect(path.dirname).toHaveBeenCalledTimes(1);
+  expect(path.dirname).toHaveBeenCalledWith('./licenses.json');
+  expect(mkdir).toHaveBeenCalledTimes(1);
+  expect(mkdir).toHaveBeenCalledWith('src/licenses', { recursive: true });
+  expect(writeFile).toHaveBeenCalledTimes(1);
+  expect(writeFile).toHaveBeenCalledWith('./licenses.json', JSON.stringify([
+    {
+      name: '@ampproject/remapping',
+      version: '2.2.0',
+      license: 'Apache-2.0',
+      author: 'Justin Ridgewell',
+      homepage: 'https://github.com/ampproject/remapping#readme',
+      description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+    },
+    {
+      name: '@ampproject/remapping',
+      version: '2.2.0',
+      license: 'Apache-2.0',
+      author: 'Justin Ridgewell',
+      homepage: 'https://github.com/ampproject/remapping#readme',
+      description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+    },
+    {
+      name: '@ampproject/remapping',
+      version: '2.2.0',
+      license: 'Apache-2.0',
+      author: 'Justin Ridgewell',
+      homepage: 'https://github.com/ampproject/remapping#readme',
+      description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+    },
+  ], undefined, undefined));
+});
+
+test('should not a make directory', async () => {
+  (path.dirname as Mock).mockReturnValue('');
+  await writeLicenses({});
+  expect(mkdir).toHaveBeenCalledTimes(0);
+})
+
+test('should pretty', async () => {
+  await writeLicenses({ pretty: true });
+  expect(writeFile).toHaveBeenCalledWith('./licenses.json', JSON.stringify([
+    {
+      name: '@ampproject/remapping',
+      version: '2.2.0',
+      license: 'Apache-2.0',
+      author: 'Justin Ridgewell',
+      homepage: 'https://github.com/ampproject/remapping#readme',
+      description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+    },
+    {
+      name: '@ampproject/remapping',
+      version: '2.2.0',
+      license: 'Apache-2.0',
+      author: 'Justin Ridgewell',
+      homepage: 'https://github.com/ampproject/remapping#readme',
+      description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+    },
+    {
+      name: '@ampproject/remapping',
+      version: '2.2.0',
+      license: 'Apache-2.0',
+      author: 'Justin Ridgewell',
+      homepage: 'https://github.com/ampproject/remapping#readme',
+      description: 'Remap sequential sourcemaps through transformations to point at the original source code',
+    },
+  ], undefined, 2));
+})
\ No newline at end of file
diff --git a/src/pnpm/export-license/utils/write-licenses.ts b/src/pnpm/export-license/utils/write-licenses.ts
index b8d03ae..5d2a16e 100644
--- a/src/pnpm/export-license/utils/write-licenses.ts
+++ b/src/pnpm/export-license/utils/write-licenses.ts
@@ -2,7 +2,7 @@ import { writeFile, mkdir } from 'node:fs/promises';
 
 import { generateFlatPnpmPackages } from './generate-flat-pnpm-packages.util';
 import { searchLicense } from './search-license.util';
-import { argsOptions } from '../../../bin/pnpm-license-exporter';
+import { argsOptions } from '../../../bin/args-options';
 import path from 'node:path';
 
 type argType = {
diff --git a/vitest.config.ts b/vitest.config.ts
index ce5a2a6..8e63989 100644
--- a/vitest.config.ts
+++ b/vitest.config.ts
@@ -7,12 +7,13 @@ export default defineConfig({
       enabled: true,
       provider: 'v8',
       thresholds: {
-        statements: 76.66,
-        branches: 50,
-        functions: 25,
-        lines: 76.66,
+        statements: 98.74,
+        branches: 81.25,
+        functions: 100,
+        lines: 98.74,
         autoUpdate: true,
       },
+      exclude: ['**/*/index.ts', '**/*/*.types.ts', '**/*/*.d.ts', '**/*/*.js','*.cjs', 'apps', 'src/bin', '**/const/*.*'],
     },
     clearMocks: true,
   },

From 1c955b09daba1cd6f5fcc796c27a3c5225d3cb98 Mon Sep 17 00:00:00 2001
From: "kaoru.ohtaka" <ockacru+git@gmail.com>
Date: Sun, 14 Apr 2024 06:26:33 +0900
Subject: [PATCH 2/2] ci: add a test ci

---
 .github/workflows/test.yml | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)
 create mode 100644 .github/workflows/test.yml

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 0000000..282aa40
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,32 @@
+name: Test jobs
+on:
+  pull_request:
+    types: [opened, synchronize, reopened, ready_for_review]
+jobs:
+  test:
+    runs-on: ubuntu-22.04
+    steps:
+      - name: Checkout code
+        uses: actions/checkout@v4
+      - name: Use Node.js
+        uses: actions/setup-node@v4
+        with:
+          node-version-file: ./.node-version
+      - name: Enable corepack
+        run: corepack enable
+      - name: Get pnpm store directory
+        id: pnpm-cache
+        shell: bash
+        run: |
+          echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
+      - uses: actions/cache@v3
+        name: Setup pnpm cache
+        with:
+          path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
+          key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
+          restore-keys: |
+            ${{ runner.os }}-pnpm-store-
+      - name: Install dependencies
+        run: pnpm i --frozen-lockfile
+      - name: Test
+        run: pnpm run test