Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/test-unit-shared.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Unit tests - React Native Legal Shared package

on:
pull_request:
branches:
- main
paths:
- '.github/workflows/test-unit-shared.yml'
- 'packages/shared/**/*.[tj]sx?'

push:
branches:
- main

workflow_dispatch:

concurrency: ${{ github.workflow }}-${{ github.ref }}

jobs:
unit-test-shared:
name: Run unit tests for @callstack/react-native-legal-shared
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup
uses: ./.github/actions/setup

- name: Run unit tests
run: yarn workspace @callstack/react-native-legal-shared test
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@

---

![E2E tests - Android](https://github.com/callstackincubator/react-native-legal/actions/workflows/test-e2e-android.yaml/badge.svg)
![E2E tests - iOS](https://github.com/callstackincubator/react-native-legal/actions/workflows/test-e2e-ios.yaml/badge.svg)
![Release](https://github.com/callstackincubator/react-native-legal/actions/workflows/release.yml/badge.svg)
![Deploy Docs](https://github.com/callstackincubator/react-native-legal/actions/workflows/deploy-docs.yml/badge.svg)
![Integration tests - License Kit (Node)](https://github.com/callstackincubator/react-native-legal/actions/workflows/test-integration-node.yml/badge.svg)
![Unit tests - React Native Legal Shared](https://github.com/callstackincubator/react-native-legal/actions/workflows/test-unit-shared.yml/badge.svg)
![E2E tests - Android](https://github.com/callstackincubator/react-native-legal/actions/workflows/test-e2e-android.yaml/badge.svg)
![E2E tests - iOS](https://github.com/callstackincubator/react-native-legal/actions/workflows/test-e2e-ios.yaml/badge.svg)

- [Documentation](#documentation)
- [Installation](#installation)
Expand Down
26 changes: 13 additions & 13 deletions docs/docs/docs/standalone-cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -68,24 +68,24 @@ Exit codes:
- `1` - strong copyleft licenses found
- `2` - weak copyleft licenses found (if `--error-on-weak` is set)

| Flag / Option | Description | Default |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------- |
| `--tm, --transitive-deps-mode [mode]` | Controls, which transitive dependencies are included: <ul><li>`'all'`</li> <li>`'from-external-only'` (only transitive dependencies of direct dependencies specified by non-workspace:... specifiers)</li> <li>`'from-workspace-only'` (only transitive dependencies of direct dependencies specified by `workspace:` specifier)</li> <li>`'none'`</li></ul> | `'all'` |
| `--dm, --dev-deps-mode [mode]` | <ul><li>`'root-only'` (only direct devDependencies from the scanned project's root package.json)</li> <li>`'none'`</li></ul> | `'root-only'` |
| `--root [path]` | Path to the root of your project | Current working directory |
| `--error-on-weak` | Exit with error code if weak copyleft licenses are found | `false` |
| Flag / Option | Description | Default |
| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
| `--tm, --transitive-deps-mode [mode]` | Controls, which transitive dependencies are included: <ul><li>`'all'`</li> <li>`'from-external-only'` (only transitive dependencies of direct dependencies specified by non-workspace:... specifiers)</li> <li>`'from-workspace-only'` (only direct dependencies of direct dependencies specified by `workspace:` specifier)</li> <li>`'none'`</li></ul> | `'all'` |
| `--dm, --dev-deps-mode [mode]` | <ul><li>`'root-only'` (only direct devDependencies from the scanned project's root package.json)</li> <li>`'none'`</li></ul> | `'root-only'` |
| `--root [path]` | Path to the root of your project | Current working directory |
| `--error-on-weak` | Exit with error code if weak copyleft licenses are found | `false` |

#### Command: `report`

Generates a licenses report in the specified format. The output can be written to `stdout` (default) or a file.

| Flag / Option | Description | Default |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------- |
| `--tm, --transitive-deps-mode [mode]` | Controls, which transitive dependencies are included: <ul><li>`'all'`</li> <li>`'from-external-only'` (only transitive dependencies of direct dependencies specified by non-workspace:... specifiers)</li> <li>`'from-workspace-only'` (only transitive dependencies of direct dependencies specified by `workspace:` specifier)</li> <li>`'none'`</li></ul> | `'all'` |
| `--dm, --dev-deps-mode [mode]` | <ul><li>`'root-only'` (only direct devDependencies from the scanned project's root package.json)</li> <li>`'none'`</li></ul> | `'root-only'` |
| `--root [path]` | Path to the root of your project | Current working directory |
| `--format [type]` | Output format, one of: `'json'`, `'about-json'` (AboutLibraries-compatible), `'text'`, `'markdown'` | `'json'` |
| `--output [path]` | Where to write the output - either `'stdout'` or a path to an output file | `'stdout'` |
| Flag / Option | Description | Default |
| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
| `--tm, --transitive-deps-mode [mode]` | Controls, which transitive dependencies are included: <ul><li>`'all'`</li> <li>`'from-external-only'` (only transitive dependencies of direct dependencies specified by non-workspace:... specifiers)</li> <li>`'from-workspace-only'` (only direct dependencies of direct dependencies specified by `workspace:` specifier)</li> <li>`'none'`</li></ul> | `'all'` |
| `--dm, --dev-deps-mode [mode]` | <ul><li>`'root-only'` (only direct devDependencies from the scanned project's root package.json)</li> <li>`'none'`</li></ul> | `'root-only'` |
| `--root [path]` | Path to the root of your project | Current working directory |
| `--format [type]` | Output format, one of: `'json'`, `'about-json'` (AboutLibraries-compatible), `'text'`, `'markdown'` | `'json'` |
| `--output [path]` | Where to write the output - either `'stdout'` or a path to an output file | `'stdout'` |

#### Command: `help`

Expand Down
153 changes: 153 additions & 0 deletions examples/node-example/__tests__/report.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import child_process from 'node:child_process';

import {
dependencies as licenseKitDependenciesObj,
devDependencies as licenseKitDevDependenciesObj,
} from '../../../packages/license-kit/package.json';
import {
dependencies as sharedDependenciesObj,
devDependencies as sharedDevDependenciesObj,
} from '../../../packages/shared/package.json';
import { dependencies as dependenciesObj, devDependencies as devDependenciesObj } from '../package.json';

const dependencies = Object.keys(dependenciesObj).sort();
const devDependencies = Object.keys(devDependenciesObj).sort();
const licenseKitDependencies = Object.keys(licenseKitDependenciesObj).sort();
const licenseKitDevDependencies = Object.keys(licenseKitDevDependenciesObj).sort();
const sharedDependencies = Object.keys(sharedDependenciesObj).sort();
const sharedDevDependencies = Object.keys(sharedDevDependenciesObj).sort();

async function runReportCommandForJsonOutput(args: string[] = []) {
const command = `yarn workspace license-kit-node-example report${args ? ` ${args.join(' ')}` : ''}`;

const output = await new Promise<string>((resolve) => {
child_process.exec(command, (_, stdout) => {
resolve(stdout);
});
});

return JSON.parse(output);
}

describe('license-kit report', () => {
it('including transitive deps, with dev deps with default settings', async () => {
const json = await runReportCommandForJsonOutput();

expect(json['dhtmlx-gantt'].type).toMatch('GPL-2.0');
expect(json['is-even'].content).toMatch('MIT License');
expect(json['is-even'].type).toMatch('MIT');
expect(json.mariadb.content).toMatch('GNU LESSER GENERAL PUBLIC LICENSE');
expect(json.mariadb.type).toMatch('LGPL-2.1-or-later');
expect(json.zustand.content).toMatch('MIT License');
expect(json.zustand.type).toMatch('MIT');
});

it('without transitive deps and without dev deps', async () => {
const json = await runReportCommandForJsonOutput(['--dev-deps-mode', 'none', '--transitive-deps-mode', 'none']);

expect(Object.keys(json).toSorted()).toEqual(dependencies.toSorted());
});

it('without transitive deps and with root-only dev deps', async () => {
const json = await runReportCommandForJsonOutput([
'--dev-deps-mode',
'root-only',
'--transitive-deps-mode',
'none',
]);

expect(Object.keys(json).toSorted()).toEqual(Array.from(new Set([...dependencies, ...devDependencies])).toSorted());
});

it('with root-only dev deps and with transitive dependencies of workspace-specifier-only dependencies', async () => {
const json = await runReportCommandForJsonOutput([
'--dev-deps-mode',
'root-only',
'--transitive-deps-mode',
'from-workspace-only',
]);

expect(Object.keys(json).toSorted()).toEqual(
Array.from(new Set([...dependencies, ...devDependencies, ...licenseKitDependencies])).toSorted(),
);
});

it('without dev deps and with transitive dependencies of external dependencies only', async () => {
const json = await runReportCommandForJsonOutput([
'--dev-deps-mode',
'none',
'--transitive-deps-mode',
'from-external-only',
]);

const resultKeys = Object.keys(json);

expect(resultKeys.toSorted()).toEqual([
'@types/geojson',
'@types/node',
'denque',
'dhtmlx-gantt',
'iconv-lite',
'is-even',
'is-number',
'is-odd',
'lru-cache',
'mariadb',
'safer-buffer',
'undici-types',
'yallist',
'zustand',
]);

expect(resultKeys).not.toIncludeAllMembers(licenseKitDependencies);
expect(resultKeys).not.toIncludeAllMembers(licenseKitDevDependencies);
});

it('with root-only dev deps and with transitive dependencies of external dependencies only', async () => {
const json = await runReportCommandForJsonOutput([
'--dev-deps-mode',
'root-only',
'--transitive-deps-mode',
'from-external-only',
]);

const resultKeys = Object.keys(json);

expect(resultKeys).toContain('license-kit');

// this time, the result should also include all dependencies of the direct devDependencies of the root package.json
expect(resultKeys.length).toBeGreaterThan(200);
expect(resultKeys).toIncludeAllMembers([
'@babel/plugin-transform-async-to-generator',
'@babel/plugin-transform-block-scoped-functions',
'@babel/plugin-transform-block-scoping',
'@babel/plugin-transform-class-properties',
'@babel/helper-create-class-features-plugin',
'@babel/helper-member-expression-to-functions',
]);

expect(resultKeys).not.toIncludeAllMembers(licenseKitDependencies);
expect(resultKeys).not.toIncludeAllMembers(licenseKitDevDependencies);

// note: sharedDependencies should not be included, yet they contain glob, which is a transitive dependency of something else
expect(resultKeys).not.toIncludeAllMembers(sharedDevDependencies);
});

it('with root-only dev deps and with all transitive dependencies', async () => {
const json = await runReportCommandForJsonOutput(['--dev-deps-mode', 'root-only', '--transitive-deps-mode', 'all']);

const resultKeys = Object.keys(json);

// this time, the result should also include all transitive dependencies of direct devDependencies of the root package.json,
// such as that of license-kit itself (which is a direct devDependency of the root package.json)
expect(resultKeys.length).toBeGreaterThan(300);
expect(resultKeys).toContain('license-kit');
expect(resultKeys).toContain('@callstack/react-native-legal-shared');

expect(resultKeys).toIncludeAllMembers(licenseKitDependencies);
expect(resultKeys).not.toIncludeAllMembers(licenseKitDevDependencies);

expect(resultKeys).toIncludeAllMembers(sharedDependencies);
expect(resultKeys).not.toIncludeAllMembers(sharedDevDependencies);
});
});
1 change: 1 addition & 0 deletions examples/node-example/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="jest-extended" />
1 change: 1 addition & 0 deletions examples/node-example/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/** @type {import('jest').Config} */
const config = {
testEnvironment: 'node',
setupFilesAfterEnv: ['jest-extended/all'],
};

module.exports = config;
1 change: 1 addition & 0 deletions examples/node-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@types/jest": "^29.5.5",
"babel-jest": "^29.7.0",
"jest": "^29.7.0",
"jest-extended": "^6.0.0",
"license-kit": "workspace:*"
}
}
21 changes: 0 additions & 21 deletions examples/node-example/test/report.spec.ts

This file was deleted.

Loading
Loading