From 4d987151ef754106a6ae57ce5a54d88e62ddee79 Mon Sep 17 00:00:00 2001 From: Daniel Stockman <5605+evocateur@users.noreply.github.com> Date: Thu, 6 Jan 2022 11:44:04 -0800 Subject: [PATCH 1/3] fix: Resolve config modules with ESM createRequire() ES modules do not have require() available, we must construct it first. This fixes the CLI when passing `--config my-config-package`, broken in v12.0.0. The tests didn't catch this because Jest still doesn't support mocking ESM, and there's really no way to write a test for this right now. I wasn't able to get the automatic `test/__mocks__/resolveConfig.js` to work, probably a race condition between the module parser and the mocker. --- jest.config.js | 7 ++++++- lib/loadConfig.js | 10 ++-------- lib/resolveConfig.js | 15 +++++++++++++++ test/index.spec.js | 10 ++++++++++ test/index2.spec.js | 11 +++++++++++ test/integration.test.js | 10 ++++++++++ test/loadConfig.spec.js | 11 +++++++++++ 7 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 lib/resolveConfig.js diff --git a/jest.config.js b/jest.config.js index b7568c554..878a1825a 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,6 +1,11 @@ const config = { collectCoverage: true, - collectCoverageFrom: ['lib/**/*.js'], + collectCoverageFrom: [ + 'lib/**/*.js', + // Avoid ESM import.meta parse error. + // (Can't measure coverage anyway, it's always mocked) + '!lib/resolveConfig.js', + ], moduleDirectories: ['node_modules'], setupFiles: ['./testSetup.js'], snapshotSerializers: ['jest-snapshot-serializer-ansi'], diff --git a/lib/loadConfig.js b/lib/loadConfig.js index 76493447d..626a6da02 100644 --- a/lib/loadConfig.js +++ b/lib/loadConfig.js @@ -6,6 +6,8 @@ import debug from 'debug' import { lilconfig } from 'lilconfig' import YAML from 'yaml' +import { resolveConfig } from './resolveConfig' + const debugLog = debug('lint-staged:loadConfig') /** @@ -49,14 +51,6 @@ const loaders = { noExt: yamlParse, } -const resolveConfig = (configPath) => { - try { - return require.resolve(configPath) - } catch { - return configPath - } -} - /** * @param {object} options * @param {string} [options.configPath] - Explicit path to a config file diff --git a/lib/resolveConfig.js b/lib/resolveConfig.js new file mode 100644 index 000000000..0b9f357c1 --- /dev/null +++ b/lib/resolveConfig.js @@ -0,0 +1,15 @@ +import { createRequire } from 'module' + +/** + * require() does not exist for ESM, so we must create it to use require.resolve(). + * @see https://nodejs.org/api/module.html#modulecreaterequirefilename + */ +const require = createRequire(import.meta.url) + +export function resolveConfig(configPath) { + try { + return require.resolve(configPath) + } catch { + return configPath + } +} diff --git a/test/index.spec.js b/test/index.spec.js index 004ef7444..81bd5193d 100644 --- a/test/index.spec.js +++ b/test/index.spec.js @@ -28,6 +28,16 @@ jest.mock('url', () => ({ jest.mock('../lib/getStagedFiles') jest.mock('../lib/gitWorkflow') +jest.mock('../lib/resolveConfig', () => ({ + /** Unfortunately necessary due to non-ESM tests. */ + resolveConfig: (configPath) => { + try { + return require.resolve(configPath) + } catch { + return configPath + } + }, +})) jest.mock('../lib/validateOptions', () => ({ validateOptions: jest.fn().mockImplementation(async () => {}), })) diff --git a/test/index2.spec.js b/test/index2.spec.js index 8712feff5..41de135f3 100644 --- a/test/index2.spec.js +++ b/test/index2.spec.js @@ -4,6 +4,17 @@ import { Listr } from 'listr2' import makeConsoleMock from 'consolemock' jest.mock('listr2') +jest.mock('../lib/resolveConfig', () => ({ + /** Unfortunately necessary due to non-ESM tests. */ + resolveConfig: (configPath) => { + try { + return require.resolve(configPath) + } catch { + return configPath + } + }, +})) + jest.mock('../lib/resolveGitRepo') import lintStaged from '../lib/index' diff --git a/test/integration.test.js b/test/integration.test.js index cc9c2da11..1048f8148 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -7,6 +7,16 @@ import normalize from 'normalize-path' jest.unmock('lilconfig') jest.unmock('execa') +jest.mock('../lib/resolveConfig', () => ({ + /** Unfortunately necessary due to non-ESM tests. */ + resolveConfig: (configPath) => { + try { + return require.resolve(configPath) + } catch { + return configPath + } + }, +})) import { execGit as execGitBase } from '../lib/execGit' import lintStaged from '../lib/index' diff --git a/test/loadConfig.spec.js b/test/loadConfig.spec.js index 33272e610..2123012ae 100644 --- a/test/loadConfig.spec.js +++ b/test/loadConfig.spec.js @@ -1,3 +1,14 @@ +jest.mock('../lib/resolveConfig', () => ({ + /** Unfortunately necessary due to non-ESM tests. */ + resolveConfig: (configPath) => { + try { + return require.resolve(configPath) + } catch { + return configPath + } + }, +})) + import { dynamicImport } from '../lib/loadConfig.js' describe('dynamicImport', () => { From 74b39f5b6e8d2e247f95906b4649f121fcb45f53 Mon Sep 17 00:00:00 2001 From: Daniel Stockman <5605+evocateur@users.noreply.github.com> Date: Thu, 6 Jan 2022 14:04:15 -0800 Subject: [PATCH 2/3] test(integration): Respect global init.defaultBranch git config --- test/integration.test.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/test/integration.test.js b/test/integration.test.js index 1048f8148..d044a3a13 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -98,6 +98,9 @@ describe('lint-staged', () => { const globalConsoleTemp = console +// Tests should be resilient to `git config init.defaultBranch` that is _not_ "master" +let defaultBranchName = 'UNSET' + describe('lint-staged', () => { beforeAll(() => { console = makeConsoleMock() @@ -114,6 +117,10 @@ describe('lint-staged', () => { await appendFile('README.md', '# Test\n') await execGit(['add', 'README.md']) await execGit(['commit', '-m initial commit']) + + if (defaultBranchName === 'UNSET') { + defaultBranchName = await execGit(['rev-parse', '--abbrev-ref', 'HEAD']) + } }) afterEach(async () => { @@ -461,7 +468,7 @@ describe('lint-staged', () => { await gitCommit(fixJsConfig, ['-m commit a']) expect(await readFile('test.js')).toEqual(fileInBranchA) - await execGit(['checkout', 'master']) + await execGit(['checkout', defaultBranchName]) // Create another branch await execGit(['checkout', '-b', 'branch-b']) @@ -471,7 +478,7 @@ describe('lint-staged', () => { expect(await readFile('test.js')).toEqual(fileInBranchBFixed) // Merge first branch - await execGit(['checkout', 'master']) + await execGit(['checkout', defaultBranchName]) await execGit(['merge', 'branch-a']) expect(await readFile('test.js')).toEqual(fileInBranchA) expect(await execGit(['log', '-1', '--pretty=%B'])).toMatch('commit a') @@ -522,7 +529,7 @@ describe('lint-staged', () => { await gitCommit(fixJsConfig, ['-m commit a']) expect(await readFile('test.js')).toEqual(fileInBranchA) - await execGit(['checkout', 'master']) + await execGit(['checkout', defaultBranchName]) // Create another branch await execGit(['checkout', '-b', 'branch-b']) @@ -532,7 +539,7 @@ describe('lint-staged', () => { expect(await readFile('test.js')).toEqual(fileInBranchBFixed) // Merge first branch - await execGit(['checkout', 'master']) + await execGit(['checkout', defaultBranchName]) await execGit(['merge', 'branch-a']) expect(await readFile('test.js')).toEqual(fileInBranchA) expect(await execGit(['log', '-1', '--pretty=%B'])).toMatch('commit a') @@ -1083,7 +1090,7 @@ describe('lintStaged', () => { await execGit(['add', 'test.js'], { cwd }) await expect(execGit(['log', '-1'], { cwd })).rejects.toThrowErrorMatchingInlineSnapshot( - `"fatal: your current branch 'master' does not have any commits yet"` + `"fatal: your current branch '${defaultBranchName}' does not have any commits yet"` ) await gitCommit({ From 1321674f6f4e17afcdd96d83a1853c2d1f790782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iiro=20J=C3=A4ppinen?= Date: Fri, 7 Jan 2022 17:58:27 +0200 Subject: [PATCH 3/3] fix: use explicit file extension in import path --- lib/loadConfig.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/loadConfig.js b/lib/loadConfig.js index 626a6da02..8c9b8c55e 100644 --- a/lib/loadConfig.js +++ b/lib/loadConfig.js @@ -6,7 +6,7 @@ import debug from 'debug' import { lilconfig } from 'lilconfig' import YAML from 'yaml' -import { resolveConfig } from './resolveConfig' +import { resolveConfig } from './resolveConfig.js' const debugLog = debug('lint-staged:loadConfig')