Skip to content

Commit

Permalink
test: increase test coverage (#32)
Browse files Browse the repository at this point in the history
* test: increase test coverage

* ci: add a test ci
  • Loading branch information
kkkaoru authored Apr 14, 2024
1 parent f8fdcb5 commit 5bfd908
Show file tree
Hide file tree
Showing 12 changed files with 420 additions and 49 deletions.
32 changes: 32 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -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
38 changes: 38 additions & 0 deletions src/bin/args-options.ts
Original file line number Diff line number Diff line change
@@ -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'];
38 changes: 1 addition & 37 deletions src/bin/pnpm-license-exporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
});
});
Original file line number Diff line number Diff line change
@@ -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 };
}
35 changes: 35 additions & 0 deletions src/pnpm/export-license/utils/find-license-dirent.test.ts
Original file line number Diff line number Diff line change
@@ -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);
});
7 changes: 7 additions & 0 deletions src/pnpm/export-license/utils/find-license-dirent.ts
Original file line number Diff line number Diff line change
@@ -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'));
}
108 changes: 108 additions & 0 deletions src/pnpm/export-license/utils/search-license.util.test.ts
Original file line number Diff line number Diff line change
@@ -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);
})
12 changes: 5 additions & 7 deletions src/pnpm/export-license/utils/search-license.util.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
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;
}
const licenseTxt = await readLicense({
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));
}
Loading

0 comments on commit 5bfd908

Please sign in to comment.