Skip to content

Commit

Permalink
Support debug flag on format and lint (#367)
Browse files Browse the repository at this point in the history
This can clue you in on which files ESLint and Prettier are formatting
and linting, which can in turn inform your `.eslintignore` and
`.prettierignore` files.
  • Loading branch information
72636c authored Feb 24, 2021
1 parent de02a2a commit 78c9a48
Show file tree
Hide file tree
Showing 8 changed files with 249 additions and 9 deletions.
5 changes: 5 additions & 0 deletions .changeset/nice-apricots-turn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'skuba': minor
---

**format, lint:** Support `--debug` flag
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ Apply automatic fixes to code quality and flag issues that require manual interv

This script should be run locally before pushing code to a remote branch.

| Option | Description |
| :-------- | :-------------------------- |
| `--debug` | Enable debug console output |

### `skuba help`

```shell
Expand Down Expand Up @@ -221,6 +225,10 @@ Check for code quality issues.

This script should be run in CI to verify that [`skuba format`] was applied and triaged locally.

| Option | Description |
| :-------- | :-------------------------- |
| `--debug` | Enable debug console output |

### `skuba node`

Run a TypeScript source file, or open a REPL if none is provided:
Expand Down
100 changes: 100 additions & 0 deletions src/cli/format.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import execa from 'execa';

import { hasStringProp } from '../utils/validation';

import { format } from './format';

jest.mock('execa');

const execaCalls = () =>
((execa as unknown) as jest.Mock<typeof execa>).mock.calls
.flat(2)
.map((val) =>
Array.isArray(val) || !hasStringProp(val, 'localDir')
? val
: { ...val, localDir: 'REDACTED' },
);

describe('format', () => {
const consoleLog = jest.spyOn(global.console, 'log').mockReturnValue();

const consoleLogCalls = () => consoleLog.mock.calls.flat(2);

afterEach(jest.clearAllMocks);

const oldProcessArgv = process.argv;
afterAll(() => (process.argv = oldProcessArgv));

it('handles no flags', async () => {
process.argv = [];

await expect(format()).resolves.toBeUndefined();

expect(execaCalls()).toMatchInlineSnapshot(`
Array [
"eslint",
"--ext=js,ts,tsx",
"--fix",
".",
Object {
"localDir": "REDACTED",
"preferLocal": true,
"stdio": "inherit",
},
"prettier",
"--write",
".",
Object {
"localDir": "REDACTED",
"preferLocal": true,
"stdio": "inherit",
},
]
`);

expect(consoleLogCalls()).toMatchInlineSnapshot(`
Array [
"✔ ESLint",
"✔ Prettier",
]
`);
});

it('handles debug flag', async () => {
process.argv = ['something', '--dEbUg', 'else'];

await expect(format()).resolves.toBeUndefined();

expect(execaCalls()).toMatchInlineSnapshot(`
Array [
"eslint",
"--debug",
"--ext=js,ts,tsx",
"--fix",
".",
Object {
"localDir": "REDACTED",
"preferLocal": true,
"stdio": "inherit",
},
"prettier",
"--loglevel",
"debug",
"--write",
".",
Object {
"localDir": "REDACTED",
"preferLocal": true,
"stdio": "inherit",
},
]
`);

expect(consoleLogCalls()).toMatchInlineSnapshot(`
Array [
"✔ ESLint",
"✔ Prettier",
]
`);
});
});
18 changes: 16 additions & 2 deletions src/cli/format.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
import { hasDebugFlag } from '../utils/args';
import { exec } from '../utils/exec';
import { log } from '../utils/logging';

export const format = async () => {
await exec('eslint', '--ext=js,ts,tsx', '--fix', '.');
const debug = hasDebugFlag();

await exec(
'eslint',
...(debug ? ['--debug'] : []),
'--ext=js,ts,tsx',
'--fix',
'.',
);
log.ok('✔ ESLint');

await exec('prettier', '--write', '.');
await exec(
'prettier',
...(debug ? ['--loglevel', 'debug'] : []),
'--write',
'.',
);
log.ok('✔ Prettier');
};
86 changes: 85 additions & 1 deletion src/cli/lint.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,88 @@
import { internalLint } from './lint';
import concurrently from 'concurrently';

import { internalLint, lint } from './lint';

jest.mock('concurrently');

const concurrentlyCalls = () =>
((concurrently as unknown) as jest.Mock<typeof concurrently>).mock.calls
.flat(2)
.map(({ env, maxProcesses, ...rest }) => ({
...(typeof env !== 'undefined' && { env: 'REDACTED' }),
...(typeof maxProcesses !== 'undefined' && { maxProcesses: 'REDACTED' }),
...rest,
}));

describe('lint', () => {
afterEach(jest.clearAllMocks);

const oldProcessArgv = process.argv;
afterAll(() => (process.argv = oldProcessArgv));

it('handles no flags', async () => {
process.argv = [];

await expect(lint()).resolves.toBeUndefined();

expect(concurrentlyCalls()).toMatchInlineSnapshot(`
Array [
Object {
"command": "eslint --ext=js,ts,tsx --report-unused-disable-directives .",
"env": "REDACTED",
"name": "ESLint ",
"prefixColor": "magenta",
},
Object {
"command": "tsc --noEmit",
"env": "REDACTED",
"name": "tsc ",
"prefixColor": "blue",
},
Object {
"command": "prettier --check .",
"env": "REDACTED",
"name": "Prettier",
"prefixColor": "cyan",
},
Object {
"maxProcesses": "REDACTED",
},
]
`);
});

it('handles debug flag', async () => {
process.argv = ['something', '--DeBuG', 'else'];

await expect(lint()).resolves.toBeUndefined();

expect(concurrentlyCalls()).toMatchInlineSnapshot(`
Array [
Object {
"command": "eslint --debug --ext=js,ts,tsx --report-unused-disable-directives .",
"env": "REDACTED",
"name": "ESLint ",
"prefixColor": "magenta",
},
Object {
"command": "tsc --extendedDiagnostics --noEmit",
"env": "REDACTED",
"name": "tsc ",
"prefixColor": "blue",
},
Object {
"command": "prettier --check --loglevel debug .",
"env": "REDACTED",
"name": "Prettier",
"prefixColor": "cyan",
},
Object {
"maxProcesses": "REDACTED",
},
]
`);
});
});

describe('internalLint', () => {
it('passes on skuba itself', () =>
Expand Down
21 changes: 16 additions & 5 deletions src/cli/lint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,30 @@ import path from 'path';
import chalk from 'chalk';
import fs from 'fs-extra';

import { hasDebugFlag } from '../utils/args';
import { execConcurrently } from '../utils/exec';
import { getConsumerManifest } from '../utils/manifest';

const externalLint = () =>
interface Options {
debug: boolean;
}

const externalLint = ({ debug }: Options) =>
execConcurrently([
{
command: 'eslint --ext=js,ts,tsx --report-unused-disable-directives .',
command: `eslint${
debug ? ' --debug' : ''
} --ext=js,ts,tsx --report-unused-disable-directives .`,
name: 'ESLint',
prefixColor: 'magenta',
},
{
command: 'tsc --noEmit',
command: `tsc${debug ? ' --extendedDiagnostics' : ''} --noEmit`,
name: 'tsc',
prefixColor: 'blue',
},
{
command: 'prettier --check .',
command: `prettier --check${debug ? ' --loglevel debug' : ''} .`,
name: 'Prettier',
prefixColor: 'cyan',
},
Expand Down Expand Up @@ -51,7 +58,11 @@ export const internalLint = async () => {
};

export const lint = async () => {
await externalLint();
const opts: Options = {
debug: hasDebugFlag(),
};

await externalLint(opts);

await internalLint();
};
17 changes: 16 additions & 1 deletion src/utils/args.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
import { parseProcessArgs, parseRunArgs } from './args';
import { hasDebugFlag, parseProcessArgs, parseRunArgs } from './args';

describe('hasDebugFlag', () => {
test.each`
description | args | expected
${'no args'} | ${[]} | ${false}
${'unrelated args'} | ${['something', 'else']} | ${false}
${'single dash'} | ${['-debug']} | ${false}
${'matching lowercase arg'} | ${['--debug']} | ${true}
${'matching uppercase arg'} | ${['--DEBUG']} | ${true}
${'matching spongebob arg'} | ${['--dEBuG']} | ${true}
${'matching arg among others'} | ${['something', '--debug', 'else']} | ${true}
`('$description => $expected', ({ args, expected }) =>
expect(hasDebugFlag(args)).toBe(expected),
);
});

describe('parseProcessArgs', () => {
it('parses a macOS command with args', () => {
Expand Down
3 changes: 3 additions & 0 deletions src/utils/args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import assert from 'assert';

import { COMMAND_ALIASES } from './command';

export const hasDebugFlag = (args = process.argv) =>
args.some((arg) => arg.toLocaleLowerCase() === '--debug');

/**
* Parse process arguments.
*
Expand Down

0 comments on commit 78c9a48

Please sign in to comment.