diff --git a/src/build-rule-tree.test.ts b/src/build-rule-tree.test.ts index bb31bb1..20f2082 100644 --- a/src/build-rule-tree.test.ts +++ b/src/build-rule-tree.test.ts @@ -2,6 +2,7 @@ import * as dependencyGraphModule from 'dependency-graph'; import { buildRuleTree } from './build-rule-tree'; import type { Rule } from './execute-rules'; +import { RuleExecutionStatus } from './execute-rules'; jest.mock('dependency-graph', () => { return { @@ -19,7 +20,7 @@ describe('buildRuleTree', () => { dependencies: ['rule-2'], execute: async () => { return { - passed: true, + status: RuleExecutionStatus.Passed, }; }, }; @@ -29,7 +30,7 @@ describe('buildRuleTree', () => { dependencies: ['rule-3'], execute: async () => { return { - passed: true, + status: RuleExecutionStatus.Passed, }; }, }; @@ -39,7 +40,7 @@ describe('buildRuleTree', () => { dependencies: [], execute: async () => { return { - passed: true, + status: RuleExecutionStatus.Passed, }; }, }; @@ -74,7 +75,7 @@ describe('buildRuleTree', () => { dependencies: ['rule-2'], execute: async () => { return { - passed: false, + status: RuleExecutionStatus.Failed, failures: [{ message: 'Oops' }], }; }, @@ -85,7 +86,7 @@ describe('buildRuleTree', () => { dependencies: ['rule-3'], execute: async () => { return { - passed: true, + status: RuleExecutionStatus.Passed, }; }, }; @@ -95,7 +96,7 @@ describe('buildRuleTree', () => { dependencies: ['rule-1'], execute: async () => { return { - passed: true, + status: RuleExecutionStatus.Passed, }; }, }; diff --git a/src/cli.ts b/src/cli.ts index 33d18e5..f038910 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -14,7 +14,13 @@ main({ cachedRepositoriesDirectoryPath: DEFAULT_CACHED_REPOSITORIES_DIRECTORY_PATH, defaultProjectNames: DEFAULT_PROJECT_NAMES, }, -}).catch((error) => { - console.error(error); - process.exitCode = 1; -}); +}) + .then((isSuccessful) => { + if (!isSuccessful) { + process.exitCode = 1; + } + }) + .catch((error) => { + console.error(error); + process.exitCode = 1; + }); diff --git a/src/execute-rules.test.ts b/src/execute-rules.test.ts index 1d35480..3e5b2bb 100644 --- a/src/execute-rules.test.ts +++ b/src/execute-rules.test.ts @@ -48,14 +48,14 @@ describe('executeRules', () => { result: { ruleName: 'rule-2', ruleDescription: 'Description for rule 2', - passed: true, + status: 'passed', }, children: [ expect.objectContaining({ result: { ruleName: 'rule-1', ruleDescription: 'Description for rule 1', - passed: false, + status: 'failed', failures: [{ message: 'Oops' }], }, children: [], @@ -100,7 +100,7 @@ describe('executeRules', () => { result: { ruleName: 'rule-2', ruleDescription: 'Description for rule 2', - passed: false, + status: 'failed', failures: [{ message: 'Oops' }], }, children: [], @@ -109,6 +109,73 @@ describe('executeRules', () => { }); }); + it('does not prevent other rules from running if a rule throws', async () => { + const rules: Rule[] = [ + { + name: 'rule-1', + description: 'Description for rule 1', + dependencies: [], + execute: async ({ pass: locallyPass }) => { + return locallyPass(); + }, + }, + { + name: 'rule-2', + description: 'Description for rule 2', + dependencies: [], + execute: async () => { + throw new Error('oops'); + }, + }, + { + name: 'rule-3', + description: 'Description for rule 3', + dependencies: [], + execute: async ({ pass: locallyPass }) => { + return locallyPass(); + }, + }, + ]; + const project = mockDeep(); + const template = mockDeep(); + + const ruleExecutionResultTree = await executeRules({ + rules, + project, + template, + }); + + expect(ruleExecutionResultTree).toMatchObject({ + children: [ + expect.objectContaining({ + result: { + ruleName: 'rule-1', + ruleDescription: 'Description for rule 1', + status: 'passed', + }, + children: [], + }), + expect.objectContaining({ + result: { + ruleName: 'rule-2', + ruleDescription: 'Description for rule 2', + status: 'errored', + error: new Error('oops'), + }, + children: [], + }), + expect.objectContaining({ + result: { + ruleName: 'rule-3', + ruleDescription: 'Description for rule 3', + status: 'passed', + }, + children: [], + }), + ], + }); + }); + it('records the time to run each rule, exclusive and inclusive of its children', async () => { jest.setSystemTime(new Date('2023-01-01T00:00:00Z')); diff --git a/src/execute-rules.ts b/src/execute-rules.ts index 513c777..b12f94c 100644 --- a/src/execute-rules.ts +++ b/src/execute-rules.ts @@ -8,12 +8,22 @@ import { fail, pass } from './rule-helpers'; const log = createModuleLogger(projectLogger, 'establish-metamask-repository'); +/** + * The status of a rule's execution. Used to determine how to present that rule + * in the ending report. + */ +export enum RuleExecutionStatus { + Passed = 'passed', + Failed = 'failed', + Errored = 'errored', +} + /** * Represents a successfully executed rule. ("Partial" because a full result * include the name and description of the rule.) */ export type SuccessfulPartialRuleExecutionResult = { - passed: true; + status: RuleExecutionStatus.Passed; }; /** @@ -24,12 +34,21 @@ export type RuleExecutionFailure = { }; /** - * Represents an unsuccessfully executed rule. ("Partial" because a full result + * Represents a rule that returned a failure. ("Partial" because a full result * include the name and description of the rule.) */ export type FailedPartialRuleExecutionResult = { - passed: false; failures: RuleExecutionFailure[]; + status: RuleExecutionStatus.Failed; +}; + +/** + * Represents a rule that threw an error while executing. ("Partial" because a + * full result include the name and description of the rule.) + */ +export type ErroredPartialRuleExecutionResult = { + error: unknown; + status: RuleExecutionStatus.Errored; }; /** @@ -37,8 +56,9 @@ export type FailedPartialRuleExecutionResult = { * include the name and description of the rule.) */ export type PartialRuleExecutionResult = - | SuccessfulPartialRuleExecutionResult - | FailedPartialRuleExecutionResult; + | ErroredPartialRuleExecutionResult + | FailedPartialRuleExecutionResult + | SuccessfulPartialRuleExecutionResult; /** * All of the information that designates the result of a rule execution. @@ -194,13 +214,22 @@ async function executeRule({ }): Promise { log('Running rule', ruleNode.rule.name); const startDate = new Date(); + let partialRuleExecutionResult: PartialRuleExecutionResult; + + try { + partialRuleExecutionResult = await ruleNode.rule.execute({ + project, + template, + pass, + fail, + }); + } catch (error) { + partialRuleExecutionResult = { + status: RuleExecutionStatus.Errored, + error, + }; + } - const partialRuleExecutionResult = await ruleNode.rule.execute({ - project, - template, - pass, - fail, - }); const ruleExecutionResult: RuleExecutionResult = { ruleName: ruleNode.rule.name, ruleDescription: ruleNode.rule.description, @@ -214,7 +243,8 @@ async function executeRule({ const endDateBeforeChildren = new Date(); const children: RuleExecutionResultNode[] = - ruleExecutionResult.passed && ruleNode.children.length > 0 + ruleExecutionResult.status === RuleExecutionStatus.Passed && + ruleNode.children.length > 0 ? await executeRuleNodes({ ruleNodes: ruleNode.children, project, diff --git a/src/lint-project.test.ts b/src/lint-project.test.ts index 33c3e61..04de904 100644 --- a/src/lint-project.test.ts +++ b/src/lint-project.test.ts @@ -3,6 +3,7 @@ import { mockDeep } from 'jest-mock-extended'; import type { MetaMaskRepository } from './establish-metamask-repository'; import type { Rule } from './execute-rules'; +import { RuleExecutionStatus } from './execute-rules'; import { lintProject } from './lint-project'; import { FakeOutputLogger } from '../tests/fake-output-logger'; import { fakeDateOnly, withinSandbox } from '../tests/helpers'; @@ -45,7 +46,7 @@ describe('lintProject', () => { execute: async () => { jest.setSystemTime(new Date('2023-01-01T00:00:02Z')); return { - passed: false, + status: RuleExecutionStatus.Failed, failures: [{ message: 'Oops' }], }; }, @@ -57,7 +58,7 @@ describe('lintProject', () => { execute: async () => { jest.setSystemTime(new Date('2023-01-01T00:00:01Z')); return { - passed: true, + status: RuleExecutionStatus.Passed, }; }, }, @@ -83,14 +84,14 @@ describe('lintProject', () => { result: { ruleName: 'rule-2', ruleDescription: 'Description for rule 2', - passed: true, + status: 'passed', }, children: [ expect.objectContaining({ result: { ruleName: 'rule-1', ruleDescription: 'Description for rule 1', - passed: false, + status: 'failed', failures: [{ message: 'Oops' }], }, children: [], diff --git a/src/main.test.ts b/src/main.test.ts index d1fe2d7..f27d8ae 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -43,7 +43,7 @@ describe('main', () => { }); describe('given a list of project references', () => { - it('produces a fully passing report if all rules executed against the given projects pass', async () => { + it('produces a fully passing report, returning true, if all rules executed against the given projects pass', async () => { await withinSandbox(async ({ directoryPath: sandboxDirectoryPath }) => { const projectNames = ['repo-1', 'repo-2']; const { cachedRepositoriesDirectoryPath, repositories } = @@ -182,7 +182,7 @@ describe('main', () => { } const outputLogger = new FakeOutputLogger(); - await main({ + const isSuccessful = await main({ argv: ['node', 'module-lint', ...projectNames], stdout: outputLogger.stdout, stderr: outputLogger.stderr, @@ -198,104 +198,105 @@ describe('main', () => { repo-1 ------ -- Is the classic Yarn config file (\`.yarnrc\`) absent? ✅ -- Does the package have a well-formed manifest (\`package.json\`)? ✅ -- Does the \`packageManager\` field in \`package.json\` conform? ✅ -- Does the \`engines.node\` field in \`package.json\` conform? ✅ -- Do the lint-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the jest-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the test-related \`scripts\` in \`package.json\` conform? ✅ -- Do the typescript-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the typescript-related \`scripts\` in \`package.json\` conform? ✅ -- Does the \`exports\` field in \`package.json\` conform? ✅ -- Does the \`main\` field in \`package.json\` conform? ✅ -- Does the \`module\` field in \`package.json\` conform? ✅ -- Does the \`types\` field in \`package.json\` conform? ✅ -- Does the \`files\` field in \`package.json\` conform? ✅ -- Does LavaMoat allow scripts for \`tsup>esbuild\`? ✅ -- Do the typedoc-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the typedoc-related \`scripts\` in \`package.json\` conform? ✅ -- Do the changelog-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the changelog-related \`scripts\` in \`package.json\` conform? ✅ -- Do the lavamoat-related \`devDependencies\` in \`package.json\` conform? ✅ -- Are postinstall scripts disabled for \`@lavamoat/preinstall-always-fail\`? ✅ -- Is \`README.md\` present? ✅ -- Does the README conform by recommending the correct Yarn version to install? ✅ -- Does the README conform by recommending node install from nodejs.org? ✅ -- Are all of the files for Yarn Modern present, and do they conform? ✅ -- Does the README conform by recommending the correct Yarn version to install? ✅ -- Does allow scripts conforms to yarn? ✅ -- Is the allow-scripts Yarn plugin installed? ✅ -- Does the \`src/\` directory exist? ✅ -- Is \`.nvmrc\` present, and does it conform? ✅ -- Is \`jest.config.js\` present, and does it conform? ✅ -- Is \`tsconfig.json\` present, and does it conform? ✅ -- Is \`tsconfig.build.json\` present, and does it conform? ✅ -- Is \`tsup.config.ts\` present, and does it conform? ✅ -- Is \`typedoc.json\` present, and does it conform? ✅ -- Is \`CHANGELOG.md\` present? ✅ -- Is \`CHANGELOG.md\` well-formatted? ✅ -- Is \`.editorconfig\` present, and does it conform? ✅ -- Is \`.gitattributes\` present, and does it conform? ✅ -- Is \`.gitignore\` present, and does it conform? ✅ - -Results: 40 passed, 0 failed, 40 total + ✔︎ Is the classic Yarn config file (\`.yarnrc\`) absent? + ✔︎ Does the package have a well-formed manifest (\`package.json\`)? + ✔︎ Does the \`packageManager\` field in \`package.json\` conform? + ✔︎ Does the \`engines.node\` field in \`package.json\` conform? + ✔︎ Do the lint-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the jest-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the test-related \`scripts\` in \`package.json\` conform? + ✔︎ Do the typescript-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the typescript-related \`scripts\` in \`package.json\` conform? + ✔︎ Does the \`exports\` field in \`package.json\` conform? + ✔︎ Does the \`main\` field in \`package.json\` conform? + ✔︎ Does the \`module\` field in \`package.json\` conform? + ✔︎ Does the \`types\` field in \`package.json\` conform? + ✔︎ Does the \`files\` field in \`package.json\` conform? + ✔︎ Does LavaMoat allow scripts for \`tsup>esbuild\`? + ✔︎ Do the typedoc-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the typedoc-related \`scripts\` in \`package.json\` conform? + ✔︎ Do the changelog-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the changelog-related \`scripts\` in \`package.json\` conform? + ✔︎ Do the lavamoat-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Are postinstall scripts disabled for \`@lavamoat/preinstall-always-fail\`? + ✔︎ Is \`README.md\` present? + ✔︎ Does the README conform by recommending the correct Yarn version to install? + ✔︎ Does the README conform by recommending node install from nodejs.org? + ✔︎ Are all of the files for Yarn Modern present, and do they conform? + ✔︎ Does the README conform by recommending the correct Yarn version to install? + ✔︎ Does allow scripts conforms to yarn? + ✔︎ Is the allow-scripts Yarn plugin installed? + ✔︎ Does the \`src/\` directory exist? + ✔︎ Is \`.nvmrc\` present, and does it conform? + ✔︎ Is \`jest.config.js\` present, and does it conform? + ✔︎ Is \`tsconfig.json\` present, and does it conform? + ✔︎ Is \`tsconfig.build.json\` present, and does it conform? + ✔︎ Is \`tsup.config.ts\` present, and does it conform? + ✔︎ Is \`typedoc.json\` present, and does it conform? + ✔︎ Is \`CHANGELOG.md\` present? + ✔︎ Is \`CHANGELOG.md\` well-formatted? + ✔︎ Is \`.editorconfig\` present, and does it conform? + ✔︎ Is \`.gitattributes\` present, and does it conform? + ✔︎ Is \`.gitignore\` present, and does it conform? + +Results: 40 passed, 0 failed, 0 errored, 40 total Elapsed time: 0 ms repo-2 ------ -- Is the classic Yarn config file (\`.yarnrc\`) absent? ✅ -- Does the package have a well-formed manifest (\`package.json\`)? ✅ -- Does the \`packageManager\` field in \`package.json\` conform? ✅ -- Does the \`engines.node\` field in \`package.json\` conform? ✅ -- Do the lint-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the jest-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the test-related \`scripts\` in \`package.json\` conform? ✅ -- Do the typescript-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the typescript-related \`scripts\` in \`package.json\` conform? ✅ -- Does the \`exports\` field in \`package.json\` conform? ✅ -- Does the \`main\` field in \`package.json\` conform? ✅ -- Does the \`module\` field in \`package.json\` conform? ✅ -- Does the \`types\` field in \`package.json\` conform? ✅ -- Does the \`files\` field in \`package.json\` conform? ✅ -- Does LavaMoat allow scripts for \`tsup>esbuild\`? ✅ -- Do the typedoc-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the typedoc-related \`scripts\` in \`package.json\` conform? ✅ -- Do the changelog-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the changelog-related \`scripts\` in \`package.json\` conform? ✅ -- Do the lavamoat-related \`devDependencies\` in \`package.json\` conform? ✅ -- Are postinstall scripts disabled for \`@lavamoat/preinstall-always-fail\`? ✅ -- Is \`README.md\` present? ✅ -- Does the README conform by recommending the correct Yarn version to install? ✅ -- Does the README conform by recommending node install from nodejs.org? ✅ -- Are all of the files for Yarn Modern present, and do they conform? ✅ -- Does the README conform by recommending the correct Yarn version to install? ✅ -- Does allow scripts conforms to yarn? ✅ -- Is the allow-scripts Yarn plugin installed? ✅ -- Does the \`src/\` directory exist? ✅ -- Is \`.nvmrc\` present, and does it conform? ✅ -- Is \`jest.config.js\` present, and does it conform? ✅ -- Is \`tsconfig.json\` present, and does it conform? ✅ -- Is \`tsconfig.build.json\` present, and does it conform? ✅ -- Is \`tsup.config.ts\` present, and does it conform? ✅ -- Is \`typedoc.json\` present, and does it conform? ✅ -- Is \`CHANGELOG.md\` present? ✅ -- Is \`CHANGELOG.md\` well-formatted? ✅ -- Is \`.editorconfig\` present, and does it conform? ✅ -- Is \`.gitattributes\` present, and does it conform? ✅ -- Is \`.gitignore\` present, and does it conform? ✅ - -Results: 40 passed, 0 failed, 40 total + ✔︎ Is the classic Yarn config file (\`.yarnrc\`) absent? + ✔︎ Does the package have a well-formed manifest (\`package.json\`)? + ✔︎ Does the \`packageManager\` field in \`package.json\` conform? + ✔︎ Does the \`engines.node\` field in \`package.json\` conform? + ✔︎ Do the lint-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the jest-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the test-related \`scripts\` in \`package.json\` conform? + ✔︎ Do the typescript-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the typescript-related \`scripts\` in \`package.json\` conform? + ✔︎ Does the \`exports\` field in \`package.json\` conform? + ✔︎ Does the \`main\` field in \`package.json\` conform? + ✔︎ Does the \`module\` field in \`package.json\` conform? + ✔︎ Does the \`types\` field in \`package.json\` conform? + ✔︎ Does the \`files\` field in \`package.json\` conform? + ✔︎ Does LavaMoat allow scripts for \`tsup>esbuild\`? + ✔︎ Do the typedoc-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the typedoc-related \`scripts\` in \`package.json\` conform? + ✔︎ Do the changelog-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the changelog-related \`scripts\` in \`package.json\` conform? + ✔︎ Do the lavamoat-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Are postinstall scripts disabled for \`@lavamoat/preinstall-always-fail\`? + ✔︎ Is \`README.md\` present? + ✔︎ Does the README conform by recommending the correct Yarn version to install? + ✔︎ Does the README conform by recommending node install from nodejs.org? + ✔︎ Are all of the files for Yarn Modern present, and do they conform? + ✔︎ Does the README conform by recommending the correct Yarn version to install? + ✔︎ Does allow scripts conforms to yarn? + ✔︎ Is the allow-scripts Yarn plugin installed? + ✔︎ Does the \`src/\` directory exist? + ✔︎ Is \`.nvmrc\` present, and does it conform? + ✔︎ Is \`jest.config.js\` present, and does it conform? + ✔︎ Is \`tsconfig.json\` present, and does it conform? + ✔︎ Is \`tsconfig.build.json\` present, and does it conform? + ✔︎ Is \`tsup.config.ts\` present, and does it conform? + ✔︎ Is \`typedoc.json\` present, and does it conform? + ✔︎ Is \`CHANGELOG.md\` present? + ✔︎ Is \`CHANGELOG.md\` well-formatted? + ✔︎ Is \`.editorconfig\` present, and does it conform? + ✔︎ Is \`.gitattributes\` present, and does it conform? + ✔︎ Is \`.gitignore\` present, and does it conform? + +Results: 40 passed, 0 failed, 0 errored, 40 total Elapsed time: 0 ms `, ); + expect(isSuccessful).toBe(true); }); }); - it('produces a fully failing report if all rules executed against the given projects fail, listing reasons for failure', async () => { + it('produces a fully failing report, listing reasons for failure and returning false, if all rules executed against the given projects fail', async () => { await withinSandbox(async ({ directoryPath: sandboxDirectoryPath }) => { const projectNames = ['repo-1', 'repo-2']; const { cachedRepositoriesDirectoryPath, repositories } = @@ -316,7 +317,7 @@ Elapsed time: 0 ms } const outputLogger = new FakeOutputLogger(); - await main({ + const isSuccessful = await main({ argv: ['node', 'module-lint', ...projectNames], stdout: outputLogger.stdout, stderr: outputLogger.stderr, @@ -332,88 +333,211 @@ Elapsed time: 0 ms repo-1 ------ -- Is the classic Yarn config file (\`.yarnrc\`) absent? ❌ - - The config file for Yarn Classic, \`.yarnrc\`, is present. Please upgrade this project to Yarn Modern. -- Does the package have a well-formed manifest (\`package.json\`)? ❌ - - \`package.json\` does not exist in this project. -- Is \`README.md\` present? ❌ - - \`README.md\` does not exist in this project. -- Are all of the files for Yarn Modern present, and do they conform? ❌ - - \`.yarnrc.yml\` does not exist in this project. - - \`.yarn/releases/\` does not exist in this project. - - \`.yarn/plugins/\` does not exist in this project. -- Does the \`src/\` directory exist? ❌ - - \`src/\` does not exist in this project. -- Is \`.nvmrc\` present, and does it conform? ❌ - - \`.nvmrc\` does not exist in this project. -- Is \`jest.config.js\` present, and does it conform? ❌ - - \`jest.config.js\` does not exist in this project. -- Is \`tsconfig.json\` present, and does it conform? ❌ - - \`tsconfig.json\` does not exist in this project. -- Is \`tsconfig.build.json\` present, and does it conform? ❌ - - \`tsconfig.build.json\` does not exist in this project. -- Is \`tsup.config.ts\` present, and does it conform? ❌ - - \`tsup.config.ts\` does not exist in this project. -- Is \`typedoc.json\` present, and does it conform? ❌ - - \`typedoc.json\` does not exist in this project. -- Is \`CHANGELOG.md\` present? ❌ - - \`CHANGELOG.md\` does not exist in this project. -- Is \`.editorconfig\` present, and does it conform? ❌ - - \`.editorconfig\` does not exist in this project. -- Is \`.gitattributes\` present, and does it conform? ❌ - - \`.gitattributes\` does not exist in this project. -- Is \`.gitignore\` present, and does it conform? ❌ - - \`.gitignore\` does not exist in this project. - -Results: 0 passed, 15 failed, 15 total + ✘ Is the classic Yarn config file (\`.yarnrc\`) absent? + - The config file for Yarn Classic, \`.yarnrc\`, is present. Please upgrade this project to Yarn Modern. + ✘ Does the package have a well-formed manifest (\`package.json\`)? + - \`package.json\` does not exist in this project. + ✘ Is \`README.md\` present? + - \`README.md\` does not exist in this project. + ✘ Are all of the files for Yarn Modern present, and do they conform? + - \`.yarnrc.yml\` does not exist in this project. + - \`.yarn/releases/\` does not exist in this project. + - \`.yarn/plugins/\` does not exist in this project. + ✘ Does the \`src/\` directory exist? + - \`src/\` does not exist in this project. + ✘ Is \`.nvmrc\` present, and does it conform? + - \`.nvmrc\` does not exist in this project. + ✘ Is \`jest.config.js\` present, and does it conform? + - \`jest.config.js\` does not exist in this project. + ✘ Is \`tsconfig.json\` present, and does it conform? + - \`tsconfig.json\` does not exist in this project. + ✘ Is \`tsconfig.build.json\` present, and does it conform? + - \`tsconfig.build.json\` does not exist in this project. + ✘ Is \`tsup.config.ts\` present, and does it conform? + - \`tsup.config.ts\` does not exist in this project. + ✘ Is \`typedoc.json\` present, and does it conform? + - \`typedoc.json\` does not exist in this project. + ✘ Is \`CHANGELOG.md\` present? + - \`CHANGELOG.md\` does not exist in this project. + ✘ Is \`.editorconfig\` present, and does it conform? + - \`.editorconfig\` does not exist in this project. + ✘ Is \`.gitattributes\` present, and does it conform? + - \`.gitattributes\` does not exist in this project. + ✘ Is \`.gitignore\` present, and does it conform? + - \`.gitignore\` does not exist in this project. + +Results: 0 passed, 15 failed, 0 errored, 15 total Elapsed time: 0 ms repo-2 ------ -- Is the classic Yarn config file (\`.yarnrc\`) absent? ❌ - - The config file for Yarn Classic, \`.yarnrc\`, is present. Please upgrade this project to Yarn Modern. -- Does the package have a well-formed manifest (\`package.json\`)? ❌ - - \`package.json\` does not exist in this project. -- Is \`README.md\` present? ❌ - - \`README.md\` does not exist in this project. -- Are all of the files for Yarn Modern present, and do they conform? ❌ - - \`.yarnrc.yml\` does not exist in this project. - - \`.yarn/releases/\` does not exist in this project. - - \`.yarn/plugins/\` does not exist in this project. -- Does the \`src/\` directory exist? ❌ - - \`src/\` does not exist in this project. -- Is \`.nvmrc\` present, and does it conform? ❌ - - \`.nvmrc\` does not exist in this project. -- Is \`jest.config.js\` present, and does it conform? ❌ - - \`jest.config.js\` does not exist in this project. -- Is \`tsconfig.json\` present, and does it conform? ❌ - - \`tsconfig.json\` does not exist in this project. -- Is \`tsconfig.build.json\` present, and does it conform? ❌ - - \`tsconfig.build.json\` does not exist in this project. -- Is \`tsup.config.ts\` present, and does it conform? ❌ - - \`tsup.config.ts\` does not exist in this project. -- Is \`typedoc.json\` present, and does it conform? ❌ - - \`typedoc.json\` does not exist in this project. -- Is \`CHANGELOG.md\` present? ❌ - - \`CHANGELOG.md\` does not exist in this project. -- Is \`.editorconfig\` present, and does it conform? ❌ - - \`.editorconfig\` does not exist in this project. -- Is \`.gitattributes\` present, and does it conform? ❌ - - \`.gitattributes\` does not exist in this project. -- Is \`.gitignore\` present, and does it conform? ❌ - - \`.gitignore\` does not exist in this project. - -Results: 0 passed, 15 failed, 15 total + ✘ Is the classic Yarn config file (\`.yarnrc\`) absent? + - The config file for Yarn Classic, \`.yarnrc\`, is present. Please upgrade this project to Yarn Modern. + ✘ Does the package have a well-formed manifest (\`package.json\`)? + - \`package.json\` does not exist in this project. + ✘ Is \`README.md\` present? + - \`README.md\` does not exist in this project. + ✘ Are all of the files for Yarn Modern present, and do they conform? + - \`.yarnrc.yml\` does not exist in this project. + - \`.yarn/releases/\` does not exist in this project. + - \`.yarn/plugins/\` does not exist in this project. + ✘ Does the \`src/\` directory exist? + - \`src/\` does not exist in this project. + ✘ Is \`.nvmrc\` present, and does it conform? + - \`.nvmrc\` does not exist in this project. + ✘ Is \`jest.config.js\` present, and does it conform? + - \`jest.config.js\` does not exist in this project. + ✘ Is \`tsconfig.json\` present, and does it conform? + - \`tsconfig.json\` does not exist in this project. + ✘ Is \`tsconfig.build.json\` present, and does it conform? + - \`tsconfig.build.json\` does not exist in this project. + ✘ Is \`tsup.config.ts\` present, and does it conform? + - \`tsup.config.ts\` does not exist in this project. + ✘ Is \`typedoc.json\` present, and does it conform? + - \`typedoc.json\` does not exist in this project. + ✘ Is \`CHANGELOG.md\` present? + - \`CHANGELOG.md\` does not exist in this project. + ✘ Is \`.editorconfig\` present, and does it conform? + - \`.editorconfig\` does not exist in this project. + ✘ Is \`.gitattributes\` present, and does it conform? + - \`.gitattributes\` does not exist in this project. + ✘ Is \`.gitignore\` present, and does it conform? + - \`.gitignore\` does not exist in this project. + +Results: 0 passed, 15 failed, 0 errored, 15 total Elapsed time: 0 ms `, ); + expect(isSuccessful).toBe(false); }); }); - it('does not exit immediately if a project errors during linting, but shows the error and continues', async () => { + it('does not abort linting of a project if a lint rule throws, but shows the error and continues to the next line rule, returning false', async () => { + await withinSandbox(async ({ directoryPath: sandboxDirectoryPath }) => { + const projectNames = ['repo-1', 'repo-2']; + const { cachedRepositoriesDirectoryPath, repositories } = + await setupToolWithMockRepositories({ + execaMock, + sandboxDirectoryPath, + repositories: [ + { name: 'metamask-module-template', create: true }, + ...projectNames.map((projectName) => ({ + name: projectName, + create: true, + })), + ], + }); + // Skip first repo since it's the module template + for (const repository of repositories.slice(1)) { + await writeFile( + path.join(repository.directoryPath, 'CHANGELOG.md'), + '', + ); + } + const outputLogger = new FakeOutputLogger(); + + const isSuccessful = await main({ + argv: ['node', 'module-lint', ...projectNames], + stdout: outputLogger.stdout, + stderr: outputLogger.stderr, + config: { + cachedRepositoriesDirectoryPath, + defaultProjectNames: [], + }, + }); + + expect(outputLogger.getStderr()).toBe(''); + expect(outputLogger.getStdout()).toBe( + ` +repo-1 +------ + + ✔︎ Is the classic Yarn config file (\`.yarnrc\`) absent? + ✘ Does the package have a well-formed manifest (\`package.json\`)? + - \`package.json\` does not exist in this project. + ✘ Is \`README.md\` present? + - \`README.md\` does not exist in this project. + ✘ Are all of the files for Yarn Modern present, and do they conform? + - \`.yarnrc.yml\` does not exist in this project. + - \`.yarn/releases/\` does not exist in this project. + - \`.yarn/plugins/\` does not exist in this project. + ✘ Does the \`src/\` directory exist? + - \`src/\` does not exist in this project. + ✘ Is \`.nvmrc\` present, and does it conform? + - \`.nvmrc\` does not exist in this project. + ✘ Is \`jest.config.js\` present, and does it conform? + - \`jest.config.js\` does not exist in this project. + ✘ Is \`tsconfig.json\` present, and does it conform? + - \`tsconfig.json\` does not exist in this project. + ✘ Is \`tsconfig.build.json\` present, and does it conform? + - \`tsconfig.build.json\` does not exist in this project. + ✘ Is \`tsup.config.ts\` present, and does it conform? + - \`tsup.config.ts\` does not exist in this project. + ✘ Is \`typedoc.json\` present, and does it conform? + - \`typedoc.json\` does not exist in this project. + ✔︎ Is \`CHANGELOG.md\` present? + ? Is \`CHANGELOG.md\` well-formatted? + - ERROR: Encountered an error validating the changelog: Could not read JSON file '${sandboxDirectoryPath}/repositories/repo-1/package.json'. + ✘ Is \`.editorconfig\` present, and does it conform? + - \`.editorconfig\` does not exist in this project. + ✘ Is \`.gitattributes\` present, and does it conform? + - \`.gitattributes\` does not exist in this project. + ✘ Is \`.gitignore\` present, and does it conform? + - \`.gitignore\` does not exist in this project. + +Results: 2 passed, 13 failed, 1 errored, 16 total +Elapsed time: 0 ms + + +repo-2 +------ + + ✔︎ Is the classic Yarn config file (\`.yarnrc\`) absent? + ✘ Does the package have a well-formed manifest (\`package.json\`)? + - \`package.json\` does not exist in this project. + ✘ Is \`README.md\` present? + - \`README.md\` does not exist in this project. + ✘ Are all of the files for Yarn Modern present, and do they conform? + - \`.yarnrc.yml\` does not exist in this project. + - \`.yarn/releases/\` does not exist in this project. + - \`.yarn/plugins/\` does not exist in this project. + ✘ Does the \`src/\` directory exist? + - \`src/\` does not exist in this project. + ✘ Is \`.nvmrc\` present, and does it conform? + - \`.nvmrc\` does not exist in this project. + ✘ Is \`jest.config.js\` present, and does it conform? + - \`jest.config.js\` does not exist in this project. + ✘ Is \`tsconfig.json\` present, and does it conform? + - \`tsconfig.json\` does not exist in this project. + ✘ Is \`tsconfig.build.json\` present, and does it conform? + - \`tsconfig.build.json\` does not exist in this project. + ✘ Is \`tsup.config.ts\` present, and does it conform? + - \`tsup.config.ts\` does not exist in this project. + ✘ Is \`typedoc.json\` present, and does it conform? + - \`typedoc.json\` does not exist in this project. + ✔︎ Is \`CHANGELOG.md\` present? + ? Is \`CHANGELOG.md\` well-formatted? + - ERROR: Encountered an error validating the changelog: Could not read JSON file '${sandboxDirectoryPath}/repositories/repo-2/package.json'. + ✘ Is \`.editorconfig\` present, and does it conform? + - \`.editorconfig\` does not exist in this project. + ✘ Is \`.gitattributes\` present, and does it conform? + - \`.gitattributes\` does not exist in this project. + ✘ Is \`.gitignore\` present, and does it conform? + - \`.gitignore\` does not exist in this project. + +Results: 2 passed, 13 failed, 1 errored, 16 total +Elapsed time: 0 ms + +`, + ); + expect(isSuccessful).toBe(false); + }); + }); + + it('does not exit immediately if an unknown error is thrown while linting a project, but shows the error and continues, returning false', async () => { await withinSandbox(async ({ directoryPath: sandboxDirectoryPath }) => { const projectNames = ['repo-1', 'repo-2']; const { cachedRepositoriesDirectoryPath } = @@ -437,7 +561,7 @@ Elapsed time: 0 ms }); const outputLogger = new FakeOutputLogger(); - await main({ + const isSuccessful = await main({ argv: ['node', 'module-lint', ...projectNames], stdout: outputLogger.stdout, stderr: outputLogger.stderr, @@ -457,49 +581,50 @@ Cloning repository MetaMask/repo-2, please wait... repo-2 ------ -- Is the classic Yarn config file (\`.yarnrc\`) absent? ✅ -- Does the package have a well-formed manifest (\`package.json\`)? ❌ - - \`package.json\` does not exist in this project. -- Is \`README.md\` present? ❌ - - \`README.md\` does not exist in this project. -- Are all of the files for Yarn Modern present, and do they conform? ❌ - - \`.yarnrc.yml\` does not exist in this project. - - \`.yarn/releases/\` does not exist in this project. - - \`.yarn/plugins/\` does not exist in this project. -- Does the \`src/\` directory exist? ❌ - - \`src/\` does not exist in this project. -- Is \`.nvmrc\` present, and does it conform? ❌ - - \`.nvmrc\` does not exist in this project. -- Is \`jest.config.js\` present, and does it conform? ❌ - - \`jest.config.js\` does not exist in this project. -- Is \`tsconfig.json\` present, and does it conform? ❌ - - \`tsconfig.json\` does not exist in this project. -- Is \`tsconfig.build.json\` present, and does it conform? ❌ - - \`tsconfig.build.json\` does not exist in this project. -- Is \`tsup.config.ts\` present, and does it conform? ❌ - - \`tsup.config.ts\` does not exist in this project. -- Is \`typedoc.json\` present, and does it conform? ❌ - - \`typedoc.json\` does not exist in this project. -- Is \`CHANGELOG.md\` present? ❌ - - \`CHANGELOG.md\` does not exist in this project. -- Is \`.editorconfig\` present, and does it conform? ❌ - - \`.editorconfig\` does not exist in this project. -- Is \`.gitattributes\` present, and does it conform? ❌ - - \`.gitattributes\` does not exist in this project. -- Is \`.gitignore\` present, and does it conform? ❌ - - \`.gitignore\` does not exist in this project. - -Results: 1 passed, 14 failed, 15 total + ✔︎ Is the classic Yarn config file (\`.yarnrc\`) absent? + ✘ Does the package have a well-formed manifest (\`package.json\`)? + - \`package.json\` does not exist in this project. + ✘ Is \`README.md\` present? + - \`README.md\` does not exist in this project. + ✘ Are all of the files for Yarn Modern present, and do they conform? + - \`.yarnrc.yml\` does not exist in this project. + - \`.yarn/releases/\` does not exist in this project. + - \`.yarn/plugins/\` does not exist in this project. + ✘ Does the \`src/\` directory exist? + - \`src/\` does not exist in this project. + ✘ Is \`.nvmrc\` present, and does it conform? + - \`.nvmrc\` does not exist in this project. + ✘ Is \`jest.config.js\` present, and does it conform? + - \`jest.config.js\` does not exist in this project. + ✘ Is \`tsconfig.json\` present, and does it conform? + - \`tsconfig.json\` does not exist in this project. + ✘ Is \`tsconfig.build.json\` present, and does it conform? + - \`tsconfig.build.json\` does not exist in this project. + ✘ Is \`tsup.config.ts\` present, and does it conform? + - \`tsup.config.ts\` does not exist in this project. + ✘ Is \`typedoc.json\` present, and does it conform? + - \`typedoc.json\` does not exist in this project. + ✘ Is \`CHANGELOG.md\` present? + - \`CHANGELOG.md\` does not exist in this project. + ✘ Is \`.editorconfig\` present, and does it conform? + - \`.editorconfig\` does not exist in this project. + ✘ Is \`.gitattributes\` present, and does it conform? + - \`.gitattributes\` does not exist in this project. + ✘ Is \`.gitignore\` present, and does it conform? + - \`.gitignore\` does not exist in this project. + +Results: 1 passed, 14 failed, 0 errored, 15 total Elapsed time: 0 ms `.trimStart(), ); + expect(isSuccessful).toBe(false); }); }); }); describe('given no project references', () => { - it('produces a fully passing report if all rules executed against the default projects pass', async () => { + it('produces a fully passing report, returning true, if all rules executed against the default projects pass', async () => { await withinSandbox(async ({ directoryPath: sandboxDirectoryPath }) => { const projectNames = ['repo-1', 'repo-2']; const { cachedRepositoriesDirectoryPath, repositories } = @@ -639,7 +764,7 @@ Elapsed time: 0 ms } const outputLogger = new FakeOutputLogger(); - await main({ + const isSuccessful = await main({ argv: ['node', 'module-lint'], stdout: outputLogger.stdout, stderr: outputLogger.stderr, @@ -655,104 +780,105 @@ Elapsed time: 0 ms repo-1 ------ -- Is the classic Yarn config file (\`.yarnrc\`) absent? ✅ -- Does the package have a well-formed manifest (\`package.json\`)? ✅ -- Does the \`packageManager\` field in \`package.json\` conform? ✅ -- Does the \`engines.node\` field in \`package.json\` conform? ✅ -- Do the lint-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the jest-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the test-related \`scripts\` in \`package.json\` conform? ✅ -- Do the typescript-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the typescript-related \`scripts\` in \`package.json\` conform? ✅ -- Does the \`exports\` field in \`package.json\` conform? ✅ -- Does the \`main\` field in \`package.json\` conform? ✅ -- Does the \`module\` field in \`package.json\` conform? ✅ -- Does the \`types\` field in \`package.json\` conform? ✅ -- Does the \`files\` field in \`package.json\` conform? ✅ -- Does LavaMoat allow scripts for \`tsup>esbuild\`? ✅ -- Do the typedoc-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the typedoc-related \`scripts\` in \`package.json\` conform? ✅ -- Do the changelog-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the changelog-related \`scripts\` in \`package.json\` conform? ✅ -- Do the lavamoat-related \`devDependencies\` in \`package.json\` conform? ✅ -- Are postinstall scripts disabled for \`@lavamoat/preinstall-always-fail\`? ✅ -- Is \`README.md\` present? ✅ -- Does the README conform by recommending the correct Yarn version to install? ✅ -- Does the README conform by recommending node install from nodejs.org? ✅ -- Are all of the files for Yarn Modern present, and do they conform? ✅ -- Does the README conform by recommending the correct Yarn version to install? ✅ -- Does allow scripts conforms to yarn? ✅ -- Is the allow-scripts Yarn plugin installed? ✅ -- Does the \`src/\` directory exist? ✅ -- Is \`.nvmrc\` present, and does it conform? ✅ -- Is \`jest.config.js\` present, and does it conform? ✅ -- Is \`tsconfig.json\` present, and does it conform? ✅ -- Is \`tsconfig.build.json\` present, and does it conform? ✅ -- Is \`tsup.config.ts\` present, and does it conform? ✅ -- Is \`typedoc.json\` present, and does it conform? ✅ -- Is \`CHANGELOG.md\` present? ✅ -- Is \`CHANGELOG.md\` well-formatted? ✅ -- Is \`.editorconfig\` present, and does it conform? ✅ -- Is \`.gitattributes\` present, and does it conform? ✅ -- Is \`.gitignore\` present, and does it conform? ✅ - -Results: 40 passed, 0 failed, 40 total + ✔︎ Is the classic Yarn config file (\`.yarnrc\`) absent? + ✔︎ Does the package have a well-formed manifest (\`package.json\`)? + ✔︎ Does the \`packageManager\` field in \`package.json\` conform? + ✔︎ Does the \`engines.node\` field in \`package.json\` conform? + ✔︎ Do the lint-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the jest-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the test-related \`scripts\` in \`package.json\` conform? + ✔︎ Do the typescript-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the typescript-related \`scripts\` in \`package.json\` conform? + ✔︎ Does the \`exports\` field in \`package.json\` conform? + ✔︎ Does the \`main\` field in \`package.json\` conform? + ✔︎ Does the \`module\` field in \`package.json\` conform? + ✔︎ Does the \`types\` field in \`package.json\` conform? + ✔︎ Does the \`files\` field in \`package.json\` conform? + ✔︎ Does LavaMoat allow scripts for \`tsup>esbuild\`? + ✔︎ Do the typedoc-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the typedoc-related \`scripts\` in \`package.json\` conform? + ✔︎ Do the changelog-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the changelog-related \`scripts\` in \`package.json\` conform? + ✔︎ Do the lavamoat-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Are postinstall scripts disabled for \`@lavamoat/preinstall-always-fail\`? + ✔︎ Is \`README.md\` present? + ✔︎ Does the README conform by recommending the correct Yarn version to install? + ✔︎ Does the README conform by recommending node install from nodejs.org? + ✔︎ Are all of the files for Yarn Modern present, and do they conform? + ✔︎ Does the README conform by recommending the correct Yarn version to install? + ✔︎ Does allow scripts conforms to yarn? + ✔︎ Is the allow-scripts Yarn plugin installed? + ✔︎ Does the \`src/\` directory exist? + ✔︎ Is \`.nvmrc\` present, and does it conform? + ✔︎ Is \`jest.config.js\` present, and does it conform? + ✔︎ Is \`tsconfig.json\` present, and does it conform? + ✔︎ Is \`tsconfig.build.json\` present, and does it conform? + ✔︎ Is \`tsup.config.ts\` present, and does it conform? + ✔︎ Is \`typedoc.json\` present, and does it conform? + ✔︎ Is \`CHANGELOG.md\` present? + ✔︎ Is \`CHANGELOG.md\` well-formatted? + ✔︎ Is \`.editorconfig\` present, and does it conform? + ✔︎ Is \`.gitattributes\` present, and does it conform? + ✔︎ Is \`.gitignore\` present, and does it conform? + +Results: 40 passed, 0 failed, 0 errored, 40 total Elapsed time: 0 ms repo-2 ------ -- Is the classic Yarn config file (\`.yarnrc\`) absent? ✅ -- Does the package have a well-formed manifest (\`package.json\`)? ✅ -- Does the \`packageManager\` field in \`package.json\` conform? ✅ -- Does the \`engines.node\` field in \`package.json\` conform? ✅ -- Do the lint-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the jest-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the test-related \`scripts\` in \`package.json\` conform? ✅ -- Do the typescript-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the typescript-related \`scripts\` in \`package.json\` conform? ✅ -- Does the \`exports\` field in \`package.json\` conform? ✅ -- Does the \`main\` field in \`package.json\` conform? ✅ -- Does the \`module\` field in \`package.json\` conform? ✅ -- Does the \`types\` field in \`package.json\` conform? ✅ -- Does the \`files\` field in \`package.json\` conform? ✅ -- Does LavaMoat allow scripts for \`tsup>esbuild\`? ✅ -- Do the typedoc-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the typedoc-related \`scripts\` in \`package.json\` conform? ✅ -- Do the changelog-related \`devDependencies\` in \`package.json\` conform? ✅ -- Do the changelog-related \`scripts\` in \`package.json\` conform? ✅ -- Do the lavamoat-related \`devDependencies\` in \`package.json\` conform? ✅ -- Are postinstall scripts disabled for \`@lavamoat/preinstall-always-fail\`? ✅ -- Is \`README.md\` present? ✅ -- Does the README conform by recommending the correct Yarn version to install? ✅ -- Does the README conform by recommending node install from nodejs.org? ✅ -- Are all of the files for Yarn Modern present, and do they conform? ✅ -- Does the README conform by recommending the correct Yarn version to install? ✅ -- Does allow scripts conforms to yarn? ✅ -- Is the allow-scripts Yarn plugin installed? ✅ -- Does the \`src/\` directory exist? ✅ -- Is \`.nvmrc\` present, and does it conform? ✅ -- Is \`jest.config.js\` present, and does it conform? ✅ -- Is \`tsconfig.json\` present, and does it conform? ✅ -- Is \`tsconfig.build.json\` present, and does it conform? ✅ -- Is \`tsup.config.ts\` present, and does it conform? ✅ -- Is \`typedoc.json\` present, and does it conform? ✅ -- Is \`CHANGELOG.md\` present? ✅ -- Is \`CHANGELOG.md\` well-formatted? ✅ -- Is \`.editorconfig\` present, and does it conform? ✅ -- Is \`.gitattributes\` present, and does it conform? ✅ -- Is \`.gitignore\` present, and does it conform? ✅ - -Results: 40 passed, 0 failed, 40 total + ✔︎ Is the classic Yarn config file (\`.yarnrc\`) absent? + ✔︎ Does the package have a well-formed manifest (\`package.json\`)? + ✔︎ Does the \`packageManager\` field in \`package.json\` conform? + ✔︎ Does the \`engines.node\` field in \`package.json\` conform? + ✔︎ Do the lint-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the jest-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the test-related \`scripts\` in \`package.json\` conform? + ✔︎ Do the typescript-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the typescript-related \`scripts\` in \`package.json\` conform? + ✔︎ Does the \`exports\` field in \`package.json\` conform? + ✔︎ Does the \`main\` field in \`package.json\` conform? + ✔︎ Does the \`module\` field in \`package.json\` conform? + ✔︎ Does the \`types\` field in \`package.json\` conform? + ✔︎ Does the \`files\` field in \`package.json\` conform? + ✔︎ Does LavaMoat allow scripts for \`tsup>esbuild\`? + ✔︎ Do the typedoc-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the typedoc-related \`scripts\` in \`package.json\` conform? + ✔︎ Do the changelog-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Do the changelog-related \`scripts\` in \`package.json\` conform? + ✔︎ Do the lavamoat-related \`devDependencies\` in \`package.json\` conform? + ✔︎ Are postinstall scripts disabled for \`@lavamoat/preinstall-always-fail\`? + ✔︎ Is \`README.md\` present? + ✔︎ Does the README conform by recommending the correct Yarn version to install? + ✔︎ Does the README conform by recommending node install from nodejs.org? + ✔︎ Are all of the files for Yarn Modern present, and do they conform? + ✔︎ Does the README conform by recommending the correct Yarn version to install? + ✔︎ Does allow scripts conforms to yarn? + ✔︎ Is the allow-scripts Yarn plugin installed? + ✔︎ Does the \`src/\` directory exist? + ✔︎ Is \`.nvmrc\` present, and does it conform? + ✔︎ Is \`jest.config.js\` present, and does it conform? + ✔︎ Is \`tsconfig.json\` present, and does it conform? + ✔︎ Is \`tsconfig.build.json\` present, and does it conform? + ✔︎ Is \`tsup.config.ts\` present, and does it conform? + ✔︎ Is \`typedoc.json\` present, and does it conform? + ✔︎ Is \`CHANGELOG.md\` present? + ✔︎ Is \`CHANGELOG.md\` well-formatted? + ✔︎ Is \`.editorconfig\` present, and does it conform? + ✔︎ Is \`.gitattributes\` present, and does it conform? + ✔︎ Is \`.gitignore\` present, and does it conform? + +Results: 40 passed, 0 failed, 0 errored, 40 total Elapsed time: 0 ms `, ); + expect(isSuccessful).toBe(true); }); }); - it('produces a fully failing report if all rules executed against the default projects fail, listing reasons for failure', async () => { + it('produces a fully failing report, listing reasons for failure and returning false, if all rules executed against the default projects fail', async () => { await withinSandbox(async ({ directoryPath: sandboxDirectoryPath }) => { const projectNames = ['repo-1', 'repo-2']; const { cachedRepositoriesDirectoryPath, repositories } = @@ -773,7 +899,129 @@ Elapsed time: 0 ms } const outputLogger = new FakeOutputLogger(); - await main({ + const isSuccessful = await main({ + argv: ['node', 'module-lint'], + stdout: outputLogger.stdout, + stderr: outputLogger.stderr, + config: { + cachedRepositoriesDirectoryPath, + defaultProjectNames: projectNames, + }, + }); + + expect(outputLogger.getStderr()).toBe(''); + expect(outputLogger.getStdout()).toBe( + ` +repo-1 +------ + + ✘ Is the classic Yarn config file (\`.yarnrc\`) absent? + - The config file for Yarn Classic, \`.yarnrc\`, is present. Please upgrade this project to Yarn Modern. + ✘ Does the package have a well-formed manifest (\`package.json\`)? + - \`package.json\` does not exist in this project. + ✘ Is \`README.md\` present? + - \`README.md\` does not exist in this project. + ✘ Are all of the files for Yarn Modern present, and do they conform? + - \`.yarnrc.yml\` does not exist in this project. + - \`.yarn/releases/\` does not exist in this project. + - \`.yarn/plugins/\` does not exist in this project. + ✘ Does the \`src/\` directory exist? + - \`src/\` does not exist in this project. + ✘ Is \`.nvmrc\` present, and does it conform? + - \`.nvmrc\` does not exist in this project. + ✘ Is \`jest.config.js\` present, and does it conform? + - \`jest.config.js\` does not exist in this project. + ✘ Is \`tsconfig.json\` present, and does it conform? + - \`tsconfig.json\` does not exist in this project. + ✘ Is \`tsconfig.build.json\` present, and does it conform? + - \`tsconfig.build.json\` does not exist in this project. + ✘ Is \`tsup.config.ts\` present, and does it conform? + - \`tsup.config.ts\` does not exist in this project. + ✘ Is \`typedoc.json\` present, and does it conform? + - \`typedoc.json\` does not exist in this project. + ✘ Is \`CHANGELOG.md\` present? + - \`CHANGELOG.md\` does not exist in this project. + ✘ Is \`.editorconfig\` present, and does it conform? + - \`.editorconfig\` does not exist in this project. + ✘ Is \`.gitattributes\` present, and does it conform? + - \`.gitattributes\` does not exist in this project. + ✘ Is \`.gitignore\` present, and does it conform? + - \`.gitignore\` does not exist in this project. + +Results: 0 passed, 15 failed, 0 errored, 15 total +Elapsed time: 0 ms + + +repo-2 +------ + + ✘ Is the classic Yarn config file (\`.yarnrc\`) absent? + - The config file for Yarn Classic, \`.yarnrc\`, is present. Please upgrade this project to Yarn Modern. + ✘ Does the package have a well-formed manifest (\`package.json\`)? + - \`package.json\` does not exist in this project. + ✘ Is \`README.md\` present? + - \`README.md\` does not exist in this project. + ✘ Are all of the files for Yarn Modern present, and do they conform? + - \`.yarnrc.yml\` does not exist in this project. + - \`.yarn/releases/\` does not exist in this project. + - \`.yarn/plugins/\` does not exist in this project. + ✘ Does the \`src/\` directory exist? + - \`src/\` does not exist in this project. + ✘ Is \`.nvmrc\` present, and does it conform? + - \`.nvmrc\` does not exist in this project. + ✘ Is \`jest.config.js\` present, and does it conform? + - \`jest.config.js\` does not exist in this project. + ✘ Is \`tsconfig.json\` present, and does it conform? + - \`tsconfig.json\` does not exist in this project. + ✘ Is \`tsconfig.build.json\` present, and does it conform? + - \`tsconfig.build.json\` does not exist in this project. + ✘ Is \`tsup.config.ts\` present, and does it conform? + - \`tsup.config.ts\` does not exist in this project. + ✘ Is \`typedoc.json\` present, and does it conform? + - \`typedoc.json\` does not exist in this project. + ✘ Is \`CHANGELOG.md\` present? + - \`CHANGELOG.md\` does not exist in this project. + ✘ Is \`.editorconfig\` present, and does it conform? + - \`.editorconfig\` does not exist in this project. + ✘ Is \`.gitattributes\` present, and does it conform? + - \`.gitattributes\` does not exist in this project. + ✘ Is \`.gitignore\` present, and does it conform? + - \`.gitignore\` does not exist in this project. + +Results: 0 passed, 15 failed, 0 errored, 15 total +Elapsed time: 0 ms + +`, + ); + expect(isSuccessful).toBe(false); + }); + }); + + it('does not abort linting of a project if a lint rule throws, but shows the error and continues to the next line rule, returning false', async () => { + await withinSandbox(async ({ directoryPath: sandboxDirectoryPath }) => { + const projectNames = ['repo-1', 'repo-2']; + const { cachedRepositoriesDirectoryPath, repositories } = + await setupToolWithMockRepositories({ + execaMock, + sandboxDirectoryPath, + repositories: [ + { name: 'metamask-module-template', create: true }, + ...projectNames.map((projectName) => ({ + name: projectName, + create: true, + })), + ], + }); + // Skip first repo since it's the module template + for (const repository of repositories.slice(1)) { + await writeFile( + path.join(repository.directoryPath, 'CHANGELOG.md'), + '', + ); + } + const outputLogger = new FakeOutputLogger(); + + const isSuccessful = await main({ argv: ['node', 'module-lint'], stdout: outputLogger.stdout, stderr: outputLogger.stderr, @@ -789,88 +1037,89 @@ Elapsed time: 0 ms repo-1 ------ -- Is the classic Yarn config file (\`.yarnrc\`) absent? ❌ - - The config file for Yarn Classic, \`.yarnrc\`, is present. Please upgrade this project to Yarn Modern. -- Does the package have a well-formed manifest (\`package.json\`)? ❌ - - \`package.json\` does not exist in this project. -- Is \`README.md\` present? ❌ - - \`README.md\` does not exist in this project. -- Are all of the files for Yarn Modern present, and do they conform? ❌ - - \`.yarnrc.yml\` does not exist in this project. - - \`.yarn/releases/\` does not exist in this project. - - \`.yarn/plugins/\` does not exist in this project. -- Does the \`src/\` directory exist? ❌ - - \`src/\` does not exist in this project. -- Is \`.nvmrc\` present, and does it conform? ❌ - - \`.nvmrc\` does not exist in this project. -- Is \`jest.config.js\` present, and does it conform? ❌ - - \`jest.config.js\` does not exist in this project. -- Is \`tsconfig.json\` present, and does it conform? ❌ - - \`tsconfig.json\` does not exist in this project. -- Is \`tsconfig.build.json\` present, and does it conform? ❌ - - \`tsconfig.build.json\` does not exist in this project. -- Is \`tsup.config.ts\` present, and does it conform? ❌ - - \`tsup.config.ts\` does not exist in this project. -- Is \`typedoc.json\` present, and does it conform? ❌ - - \`typedoc.json\` does not exist in this project. -- Is \`CHANGELOG.md\` present? ❌ - - \`CHANGELOG.md\` does not exist in this project. -- Is \`.editorconfig\` present, and does it conform? ❌ - - \`.editorconfig\` does not exist in this project. -- Is \`.gitattributes\` present, and does it conform? ❌ - - \`.gitattributes\` does not exist in this project. -- Is \`.gitignore\` present, and does it conform? ❌ - - \`.gitignore\` does not exist in this project. - -Results: 0 passed, 15 failed, 15 total + ✔︎ Is the classic Yarn config file (\`.yarnrc\`) absent? + ✘ Does the package have a well-formed manifest (\`package.json\`)? + - \`package.json\` does not exist in this project. + ✘ Is \`README.md\` present? + - \`README.md\` does not exist in this project. + ✘ Are all of the files for Yarn Modern present, and do they conform? + - \`.yarnrc.yml\` does not exist in this project. + - \`.yarn/releases/\` does not exist in this project. + - \`.yarn/plugins/\` does not exist in this project. + ✘ Does the \`src/\` directory exist? + - \`src/\` does not exist in this project. + ✘ Is \`.nvmrc\` present, and does it conform? + - \`.nvmrc\` does not exist in this project. + ✘ Is \`jest.config.js\` present, and does it conform? + - \`jest.config.js\` does not exist in this project. + ✘ Is \`tsconfig.json\` present, and does it conform? + - \`tsconfig.json\` does not exist in this project. + ✘ Is \`tsconfig.build.json\` present, and does it conform? + - \`tsconfig.build.json\` does not exist in this project. + ✘ Is \`tsup.config.ts\` present, and does it conform? + - \`tsup.config.ts\` does not exist in this project. + ✘ Is \`typedoc.json\` present, and does it conform? + - \`typedoc.json\` does not exist in this project. + ✔︎ Is \`CHANGELOG.md\` present? + ? Is \`CHANGELOG.md\` well-formatted? + - ERROR: Encountered an error validating the changelog: Could not read JSON file '${sandboxDirectoryPath}/repositories/repo-1/package.json'. + ✘ Is \`.editorconfig\` present, and does it conform? + - \`.editorconfig\` does not exist in this project. + ✘ Is \`.gitattributes\` present, and does it conform? + - \`.gitattributes\` does not exist in this project. + ✘ Is \`.gitignore\` present, and does it conform? + - \`.gitignore\` does not exist in this project. + +Results: 2 passed, 13 failed, 1 errored, 16 total Elapsed time: 0 ms repo-2 ------ -- Is the classic Yarn config file (\`.yarnrc\`) absent? ❌ - - The config file for Yarn Classic, \`.yarnrc\`, is present. Please upgrade this project to Yarn Modern. -- Does the package have a well-formed manifest (\`package.json\`)? ❌ - - \`package.json\` does not exist in this project. -- Is \`README.md\` present? ❌ - - \`README.md\` does not exist in this project. -- Are all of the files for Yarn Modern present, and do they conform? ❌ - - \`.yarnrc.yml\` does not exist in this project. - - \`.yarn/releases/\` does not exist in this project. - - \`.yarn/plugins/\` does not exist in this project. -- Does the \`src/\` directory exist? ❌ - - \`src/\` does not exist in this project. -- Is \`.nvmrc\` present, and does it conform? ❌ - - \`.nvmrc\` does not exist in this project. -- Is \`jest.config.js\` present, and does it conform? ❌ - - \`jest.config.js\` does not exist in this project. -- Is \`tsconfig.json\` present, and does it conform? ❌ - - \`tsconfig.json\` does not exist in this project. -- Is \`tsconfig.build.json\` present, and does it conform? ❌ - - \`tsconfig.build.json\` does not exist in this project. -- Is \`tsup.config.ts\` present, and does it conform? ❌ - - \`tsup.config.ts\` does not exist in this project. -- Is \`typedoc.json\` present, and does it conform? ❌ - - \`typedoc.json\` does not exist in this project. -- Is \`CHANGELOG.md\` present? ❌ - - \`CHANGELOG.md\` does not exist in this project. -- Is \`.editorconfig\` present, and does it conform? ❌ - - \`.editorconfig\` does not exist in this project. -- Is \`.gitattributes\` present, and does it conform? ❌ - - \`.gitattributes\` does not exist in this project. -- Is \`.gitignore\` present, and does it conform? ❌ - - \`.gitignore\` does not exist in this project. - -Results: 0 passed, 15 failed, 15 total + ✔︎ Is the classic Yarn config file (\`.yarnrc\`) absent? + ✘ Does the package have a well-formed manifest (\`package.json\`)? + - \`package.json\` does not exist in this project. + ✘ Is \`README.md\` present? + - \`README.md\` does not exist in this project. + ✘ Are all of the files for Yarn Modern present, and do they conform? + - \`.yarnrc.yml\` does not exist in this project. + - \`.yarn/releases/\` does not exist in this project. + - \`.yarn/plugins/\` does not exist in this project. + ✘ Does the \`src/\` directory exist? + - \`src/\` does not exist in this project. + ✘ Is \`.nvmrc\` present, and does it conform? + - \`.nvmrc\` does not exist in this project. + ✘ Is \`jest.config.js\` present, and does it conform? + - \`jest.config.js\` does not exist in this project. + ✘ Is \`tsconfig.json\` present, and does it conform? + - \`tsconfig.json\` does not exist in this project. + ✘ Is \`tsconfig.build.json\` present, and does it conform? + - \`tsconfig.build.json\` does not exist in this project. + ✘ Is \`tsup.config.ts\` present, and does it conform? + - \`tsup.config.ts\` does not exist in this project. + ✘ Is \`typedoc.json\` present, and does it conform? + - \`typedoc.json\` does not exist in this project. + ✔︎ Is \`CHANGELOG.md\` present? + ? Is \`CHANGELOG.md\` well-formatted? + - ERROR: Encountered an error validating the changelog: Could not read JSON file '${sandboxDirectoryPath}/repositories/repo-2/package.json'. + ✘ Is \`.editorconfig\` present, and does it conform? + - \`.editorconfig\` does not exist in this project. + ✘ Is \`.gitattributes\` present, and does it conform? + - \`.gitattributes\` does not exist in this project. + ✘ Is \`.gitignore\` present, and does it conform? + - \`.gitignore\` does not exist in this project. + +Results: 2 passed, 13 failed, 1 errored, 16 total Elapsed time: 0 ms `, ); + expect(isSuccessful).toBe(false); }); }); - it('does not exit immediately if a project errors during linting, but shows the error and continues', async () => { + it('does not exit immediately if an unknown error is thrown while linting a project, but shows the error and continues, returning false', async () => { await withinSandbox(async ({ directoryPath: sandboxDirectoryPath }) => { const projectNames = ['repo-1', 'repo-2']; const { cachedRepositoriesDirectoryPath } = @@ -894,7 +1143,7 @@ Elapsed time: 0 ms }); const outputLogger = new FakeOutputLogger(); - await main({ + const isSuccessful = await main({ argv: ['node', 'module-lint'], stdout: outputLogger.stdout, stderr: outputLogger.stderr, @@ -913,43 +1162,44 @@ Elapsed time: 0 ms repo-2 ------ -- Is the classic Yarn config file (\`.yarnrc\`) absent? ✅ -- Does the package have a well-formed manifest (\`package.json\`)? ❌ - - \`package.json\` does not exist in this project. -- Is \`README.md\` present? ❌ - - \`README.md\` does not exist in this project. -- Are all of the files for Yarn Modern present, and do they conform? ❌ - - \`.yarnrc.yml\` does not exist in this project. - - \`.yarn/releases/\` does not exist in this project. - - \`.yarn/plugins/\` does not exist in this project. -- Does the \`src/\` directory exist? ❌ - - \`src/\` does not exist in this project. -- Is \`.nvmrc\` present, and does it conform? ❌ - - \`.nvmrc\` does not exist in this project. -- Is \`jest.config.js\` present, and does it conform? ❌ - - \`jest.config.js\` does not exist in this project. -- Is \`tsconfig.json\` present, and does it conform? ❌ - - \`tsconfig.json\` does not exist in this project. -- Is \`tsconfig.build.json\` present, and does it conform? ❌ - - \`tsconfig.build.json\` does not exist in this project. -- Is \`tsup.config.ts\` present, and does it conform? ❌ - - \`tsup.config.ts\` does not exist in this project. -- Is \`typedoc.json\` present, and does it conform? ❌ - - \`typedoc.json\` does not exist in this project. -- Is \`CHANGELOG.md\` present? ❌ - - \`CHANGELOG.md\` does not exist in this project. -- Is \`.editorconfig\` present, and does it conform? ❌ - - \`.editorconfig\` does not exist in this project. -- Is \`.gitattributes\` present, and does it conform? ❌ - - \`.gitattributes\` does not exist in this project. -- Is \`.gitignore\` present, and does it conform? ❌ - - \`.gitignore\` does not exist in this project. - -Results: 1 passed, 14 failed, 15 total + ✔︎ Is the classic Yarn config file (\`.yarnrc\`) absent? + ✘ Does the package have a well-formed manifest (\`package.json\`)? + - \`package.json\` does not exist in this project. + ✘ Is \`README.md\` present? + - \`README.md\` does not exist in this project. + ✘ Are all of the files for Yarn Modern present, and do they conform? + - \`.yarnrc.yml\` does not exist in this project. + - \`.yarn/releases/\` does not exist in this project. + - \`.yarn/plugins/\` does not exist in this project. + ✘ Does the \`src/\` directory exist? + - \`src/\` does not exist in this project. + ✘ Is \`.nvmrc\` present, and does it conform? + - \`.nvmrc\` does not exist in this project. + ✘ Is \`jest.config.js\` present, and does it conform? + - \`jest.config.js\` does not exist in this project. + ✘ Is \`tsconfig.json\` present, and does it conform? + - \`tsconfig.json\` does not exist in this project. + ✘ Is \`tsconfig.build.json\` present, and does it conform? + - \`tsconfig.build.json\` does not exist in this project. + ✘ Is \`tsup.config.ts\` present, and does it conform? + - \`tsup.config.ts\` does not exist in this project. + ✘ Is \`typedoc.json\` present, and does it conform? + - \`typedoc.json\` does not exist in this project. + ✘ Is \`CHANGELOG.md\` present? + - \`CHANGELOG.md\` does not exist in this project. + ✘ Is \`.editorconfig\` present, and does it conform? + - \`.editorconfig\` does not exist in this project. + ✘ Is \`.gitattributes\` present, and does it conform? + - \`.gitattributes\` does not exist in this project. + ✘ Is \`.gitignore\` present, and does it conform? + - \`.gitignore\` does not exist in this project. + +Results: 1 passed, 14 failed, 0 errored, 15 total Elapsed time: 0 ms `, ); + expect(isSuccessful).toBe(false); }); }); }); diff --git a/src/main.ts b/src/main.ts index d6b4781..fd53171 100644 --- a/src/main.ts +++ b/src/main.ts @@ -51,16 +51,13 @@ export async function main({ cachedRepositoriesDirectoryPath: string; defaultProjectNames: string[]; }; -}) { +}): Promise { const outputLogger = new OutputLogger({ stdout, stderr }); const workingDirectoryPath = process.cwd(); const inputs = await parseInputs({ argv, outputLogger, defaultProjectNames }); if (!inputs) { - // Even if `process` changes, it's okay. - // eslint-disable-next-line require-atomic-updates - process.exitCode = 1; - return; + return false; } const { templateRepositoryName, projectReferences } = inputs; @@ -71,7 +68,7 @@ export async function main({ outputLogger, }); - const isAllPassed = await lintProjects({ + const allLintingSuccessful = await lintProjects({ projectReferences, template, workingDirectoryPath, @@ -79,10 +76,7 @@ export async function main({ outputLogger, }); - if (!isAllPassed) { - // eslint-disable-next-line require-atomic-updates - process.exitCode = 1; - } + return allLintingSuccessful; } /** @@ -231,23 +225,25 @@ async function lintProjects({ projectLintResultPromiseOutcomes.filter(isPromiseRejectedResult); outputLogger.logToStdout(''); - let isAllPassed = true; + + let allPassed = true; fulfilledProjectLintResultPromiseOutcomes .sort((a, b) => { return a.value.projectName.localeCompare(b.value.projectName); }) .forEach((fulfilledProjectLintResultPromiseOutcome, index) => { - const { numberOfFailing } = reportProjectLintResult({ + const { totalFailed, totalErrored } = reportProjectLintResult({ projectLintResult: fulfilledProjectLintResultPromiseOutcome.value, outputLogger, }); if (index < fulfilledProjectLintResultPromiseOutcomes.length - 1) { outputLogger.logToStdout('\n'); } - if (numberOfFailing > 0) { - isAllPassed = false; + if (totalFailed > 0 || totalErrored > 0) { + allPassed = false; } }); + outputLogger.logToStdout(''); rejectedProjectLintResultPromiseOutcomes.forEach( @@ -256,5 +252,5 @@ async function lintProjects({ }, ); - return isAllPassed && rejectedProjectLintResultPromiseOutcomes.length === 0; + return allPassed && rejectedProjectLintResultPromiseOutcomes.length === 0; } diff --git a/src/report-project-lint-result.test.ts b/src/report-project-lint-result.test.ts index ff1d748..36fce23 100644 --- a/src/report-project-lint-result.test.ts +++ b/src/report-project-lint-result.test.ts @@ -1,10 +1,10 @@ -import type { ProjectLintResult } from './lint-project'; +import { RuleExecutionStatus } from './execute-rules'; import { reportProjectLintResult } from './report-project-lint-result'; import { FakeOutputLogger } from '../tests/fake-output-logger'; describe('reportProjectLintResult', () => { - it('outputs the rules executed against a project and whether they passed or failed, along with a summary', () => { - const projectLintResult: ProjectLintResult = { + it('outputs the rules executed against a project and whether they passed, failed, or errored, along with a summary', () => { + const projectLintResult = { projectName: 'some-project', elapsedTimeIncludingLinting: 30, elapsedTimeExcludingLinting: 0, @@ -14,7 +14,7 @@ describe('reportProjectLintResult', () => { result: { ruleName: 'rule-1', ruleDescription: 'Description for rule 1', - passed: true, + status: RuleExecutionStatus.Passed as const, }, elapsedTimeExcludingChildren: 0, elapsedTimeIncludingChildren: 0, @@ -23,7 +23,7 @@ describe('reportProjectLintResult', () => { result: { ruleName: 'rule-2', ruleDescription: 'Description for rule 2', - passed: false, + status: RuleExecutionStatus.Failed as const, failures: [ { message: 'Failure 1' }, { message: 'Failure 2' }, @@ -39,52 +39,18 @@ describe('reportProjectLintResult', () => { result: { ruleName: 'rule-3', ruleDescription: 'Description for rule 3', - passed: true, + status: RuleExecutionStatus.Passed as const, }, elapsedTimeExcludingChildren: 0, elapsedTimeIncludingChildren: 0, children: [], }, - ], - }, - }; - const outputLogger = new FakeOutputLogger(); - - reportProjectLintResult({ - projectLintResult, - outputLogger, - }); - - expect(outputLogger.getStdout()).toBe( - ` -some-project ------------- - -- Description for rule 1 ✅ -- Description for rule 2 ❌ - - Failure 1 - - Failure 2 -- Description for rule 3 ✅ - -Results: 2 passed, 1 failed, 3 total -Elapsed time: 30 ms -`.trimStart(), - ); - }); - - it('prints "0 passed" if no rules passed', () => { - const projectLintResult: ProjectLintResult = { - projectName: 'some-project', - elapsedTimeIncludingLinting: 30, - elapsedTimeExcludingLinting: 0, - ruleExecutionResultTree: { - children: [ { result: { - ruleName: 'some-rule', - ruleDescription: 'Description for rule', - passed: false, - failures: [{ message: 'Some failure' }], + ruleName: 'rule-4', + ruleDescription: 'Description for rule 4', + status: RuleExecutionStatus.Errored as const, + error: new Error('oops'), }, elapsedTimeExcludingChildren: 0, elapsedTimeIncludingChildren: 0, @@ -105,33 +71,27 @@ Elapsed time: 30 ms some-project ------------ -- Description for rule ❌ - - Some failure + ✔︎ Description for rule 1 + ✘ Description for rule 2 + - Failure 1 + - Failure 2 + ✔︎ Description for rule 3 + ? Description for rule 4 + - ERROR: oops -Results: 0 passed, 1 failed, 1 total +Results: 2 passed, 1 failed, 1 errored, 4 total Elapsed time: 30 ms `.trimStart(), ); }); - it('prints "0 failed" if no rules failed', () => { - const projectLintResult: ProjectLintResult = { + it('outputs an empty report if no rules were executed', () => { + const projectLintResult = { projectName: 'some-project', elapsedTimeIncludingLinting: 30, elapsedTimeExcludingLinting: 0, ruleExecutionResultTree: { - children: [ - { - result: { - ruleName: 'some-rule', - ruleDescription: 'Description for rule', - passed: true, - }, - elapsedTimeExcludingChildren: 0, - elapsedTimeIncludingChildren: 0, - children: [], - }, - ], + children: [], }, }; const outputLogger = new FakeOutputLogger(); @@ -146,9 +106,7 @@ Elapsed time: 30 ms some-project ------------ -- Description for rule ✅ - -Results: 1 passed, 0 failed, 1 total +Results: 0 passed, 0 failed, 0 errored, 0 total Elapsed time: 30 ms `.trimStart(), ); diff --git a/src/report-project-lint-result.ts b/src/report-project-lint-result.ts index 39a169d..c4ba80e 100644 --- a/src/report-project-lint-result.ts +++ b/src/report-project-lint-result.ts @@ -1,6 +1,8 @@ +import { getErrorMessage } from '@metamask/utils'; import chalk from 'chalk'; import type { RuleExecutionResultNode } from './execute-rules'; +import { RuleExecutionStatus } from './execute-rules'; import type { ProjectLintResult } from './lint-project'; import { createModuleLogger, projectLogger } from './logging-utils'; import { repeat, indent } from './misc-utils'; @@ -8,6 +10,16 @@ import type { AbstractOutputLogger } from './output-logger'; const log = createModuleLogger(projectLogger, 'fetch-or-populate-file-cache'); +/** + * The number of lint rules that were run and that passed, failed, or errored. + */ +export type ProjectLintStats = { + totalErrored: number; + totalFailed: number; + totalPassed: number; + totalRun: number; +}; + /** * Prints a report following linting of a project, including all of the rules * that were executed and whether they passed or failed. @@ -23,7 +35,7 @@ export function reportProjectLintResult({ }: { projectLintResult: ProjectLintResult; outputLogger: AbstractOutputLogger; -}) { +}): ProjectLintStats { log( 'elapsedTimeIncludingLinting', projectLintResult.elapsedTimeIncludingLinting, @@ -31,31 +43,33 @@ export function reportProjectLintResult({ projectLintResult.elapsedTimeExcludingLinting, ); - outputLogger.logToStdout(chalk.magenta(projectLintResult.projectName)); + outputLogger.logToStdout(chalk.blue(projectLintResult.projectName)); outputLogger.logToStdout( - `${chalk.magenta(repeat('-', projectLintResult.projectName.length))}\n`, + `${chalk.blue(repeat('-', projectLintResult.projectName.length))}\n`, ); - const { numberOfPassing, numberOfFailing } = reportRuleExecutionResultNodes({ - ruleExecutionResultNodes: - projectLintResult.ruleExecutionResultTree.children, - outputLogger, - }); + const ruleExecutionResultNodes = + projectLintResult.ruleExecutionResultTree.children; + const { totalErrored, totalFailed, totalPassed, totalRun } = + reportRuleExecutionResultNodes({ + ruleExecutionResultNodes, + outputLogger, + }); - outputLogger.logToStdout(''); + if (ruleExecutionResultNodes.length > 0) { + outputLogger.logToStdout(''); + } - const numberOfPassingPhrase = `${numberOfPassing} passed`; - const numberOfFailingPhrase = `${numberOfFailing} failed`; + const totalPassedPhrase = `${totalPassed} passed`; + const totalFailedPhrase = `${totalFailed} failed`; + const totalErroredPhrase = `${totalErrored} errored`; outputLogger.logToStdout( - '%s %s, %s, %s', + '%s %s, %s, %s, %s', chalk.bold('Results:'), - numberOfPassing > 0 - ? chalk.green(numberOfPassingPhrase) - : numberOfPassingPhrase, - numberOfFailing > 0 - ? chalk.red(numberOfFailingPhrase) - : numberOfFailingPhrase, - `${numberOfPassing + numberOfFailing} total`, + totalPassed > 0 ? chalk.green(totalPassedPhrase) : totalPassedPhrase, + totalFailed > 0 ? chalk.red(totalFailedPhrase) : totalFailedPhrase, + totalErrored > 0 ? chalk.yellow(totalErroredPhrase) : totalErroredPhrase, + `${totalRun} total`, ); outputLogger.logToStdout( @@ -64,7 +78,23 @@ export function reportProjectLintResult({ projectLintResult.elapsedTimeIncludingLinting, ); - return { numberOfPassing, numberOfFailing }; + return { totalErrored, totalFailed, totalPassed, totalRun }; +} + +/** + * Determines an appropriate icon for a rule execution result. + * + * @param ruleExecutionStatus - The status of executing a rule. + * @returns The icon as a string. + */ +function determineIconFor(ruleExecutionStatus: RuleExecutionStatus) { + if (ruleExecutionStatus === RuleExecutionStatus.Failed) { + return chalk.white.bgRed(' ✘ '); + } + if (ruleExecutionStatus === RuleExecutionStatus.Errored) { + return chalk.black.bgYellow(' ? '); + } + return chalk.black.bgGreen(' ✔︎ '); } /** @@ -82,39 +112,57 @@ function reportRuleExecutionResultNodes({ }: { ruleExecutionResultNodes: RuleExecutionResultNode[]; outputLogger: AbstractOutputLogger; -}) { - let numberOfPassing = 0; - let numberOfFailing = 0; +}): ProjectLintStats { + let totalPassed = 0; + let totalFailed = 0; + let totalErrored = 0; for (const ruleExecutionResultNode of ruleExecutionResultNodes) { outputLogger.logToStdout( - `- ${ruleExecutionResultNode.result.ruleDescription} ${ - ruleExecutionResultNode.result.passed ? '✅' : '❌' + `${determineIconFor(ruleExecutionResultNode.result.status)} ${ + ruleExecutionResultNode.result.ruleDescription }`, ); - if (ruleExecutionResultNode.result.passed) { - numberOfPassing += 1; - } else { - numberOfFailing += 1; + if (ruleExecutionResultNode.result.status === RuleExecutionStatus.Passed) { + totalPassed += 1; + } else if ( + ruleExecutionResultNode.result.status === RuleExecutionStatus.Failed + ) { + totalFailed += 1; for (const failure of ruleExecutionResultNode.result.failures) { - outputLogger.logToStdout( - indent(`- ${chalk.yellow(failure.message)}`, 1), - ); + outputLogger.logToStdout(indent(`- ${chalk.red(failure.message)}`, 2)); } + } else if ( + ruleExecutionResultNode.result.status === RuleExecutionStatus.Errored + ) { + totalErrored += 1; + + outputLogger.logToStdout( + indent( + `- ${chalk.yellow( + `ERROR: ${getErrorMessage(ruleExecutionResultNode.result.error)}`, + )}`, + 2, + ), + ); } const { - numberOfPassing: numberOfChildrenPassing, - numberOfFailing: numberOfChildrenFailing, + totalPassed: totalPassedChildren, + totalFailed: totalFailedChildren, + totalErrored: totalErroredChildren, } = reportRuleExecutionResultNodes({ ruleExecutionResultNodes: ruleExecutionResultNode.children, outputLogger, }); - numberOfPassing += numberOfChildrenPassing; - numberOfFailing += numberOfChildrenFailing; + totalPassed += totalPassedChildren; + totalFailed += totalFailedChildren; + totalErrored += totalErroredChildren; } - return { numberOfPassing, numberOfFailing }; + const totalRun = totalPassed + totalFailed + totalErrored; + + return { totalErrored, totalFailed, totalPassed, totalRun }; } diff --git a/src/rule-helpers.test.ts b/src/rule-helpers.test.ts index a1757c1..72952b1 100644 --- a/src/rule-helpers.test.ts +++ b/src/rule-helpers.test.ts @@ -4,11 +4,13 @@ import { } from '@metamask/utils/node'; import path from 'path'; +import { RuleExecutionStatus } from './execute-rules'; import { combineRuleExecutionResults, dataConform, directoryAndContentsConform, directoryExists, + error, fail, fileConforms, fileExists, @@ -22,54 +24,88 @@ import { } from '../tests/helpers'; describe('pass', () => { - it('returns a result that represents a passing rule', () => { - expect(pass()).toStrictEqual({ passed: true }); + it('returns a result that represents a rule that has passed', () => { + expect(pass()).toStrictEqual({ status: 'passed' }); }); }); describe('fail', () => { - it('returns a result that represents a failing rule, with the given failures', () => { + it('returns a result that represents a rule that has failed, with the given failures', () => { expect(fail([{ message: 'oops' }])).toStrictEqual({ - passed: false, + status: 'failed', failures: [{ message: 'oops' }], }); }); }); +describe('error', () => { + it('returns a result that represents a rule that has errored, with the given error', () => { + const capturedError = new Error('oops'); + expect(error(capturedError)).toStrictEqual({ + status: 'errored', + error: capturedError, + }); + }); +}); + describe('combineRuleExecutionResults', () => { - it('returns a single passing result if all of the given results are passing', () => { + it('returns a single result with a status of "passed" if all of the given results have this status', () => { + const result = combineRuleExecutionResults([ + { + status: RuleExecutionStatus.Passed, + }, + { + status: RuleExecutionStatus.Passed, + }, + ]); + + expect(result).toStrictEqual({ status: 'passed' }); + }); + + it('returns a single result with a status of "errored", using the first error, if any of the given results have this status', () => { const result = combineRuleExecutionResults([ { - passed: true, + status: RuleExecutionStatus.Passed, + }, + { + status: RuleExecutionStatus.Errored, + error: new Error('error 1'), }, { - passed: true, + status: RuleExecutionStatus.Errored, + error: new Error('error 2'), + }, + { + status: RuleExecutionStatus.Passed, }, ]); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ + status: 'errored', + error: new Error('error 1'), + }); }); - it('returns a single failed result, consolidating all failures, if any of the given results are failing', () => { + it('returns a single result with a status of "failed", consolidating all failures, if any of the given results have this status', () => { const result = combineRuleExecutionResults([ { - passed: true, + status: RuleExecutionStatus.Passed, }, { - passed: false, + status: RuleExecutionStatus.Failed, failures: [{ message: 'message 1' }], }, { - passed: true, + status: RuleExecutionStatus.Passed, }, { - passed: false, + status: RuleExecutionStatus.Failed, failures: [{ message: 'message 2' }, { message: 'message 3' }], }, ]); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: 'message 1' }, { message: 'message 2' }, @@ -81,7 +117,7 @@ describe('combineRuleExecutionResults', () => { it('returns a passing result if given nothing to combine', () => { const result = combineRuleExecutionResults([]); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); }); @@ -103,7 +139,7 @@ describe('fileExists', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -124,7 +160,7 @@ describe('fileExists', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: `\`${filePath}\` does not exist in this project.`, @@ -151,7 +187,7 @@ describe('fileExists', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: `\`${filePath}\` is not a file when it should be.` }, ], @@ -178,7 +214,7 @@ describe('directoryExists', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -199,7 +235,7 @@ describe('directoryExists', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: `\`${directoryPath}/\` does not exist in this project.`, @@ -226,7 +262,7 @@ describe('directoryExists', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: `\`${directoryPath}/\` is not a directory when it should be.`, @@ -264,7 +300,7 @@ describe('fileConforms', () => { fail, }); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); }); @@ -295,7 +331,7 @@ describe('fileConforms', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -329,7 +365,7 @@ describe('fileConforms', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`some.file` does not exist in this project.', @@ -397,7 +433,7 @@ describe('directoryAndContentsConform', () => { fail, }); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); }); @@ -458,7 +494,7 @@ describe('directoryAndContentsConform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -516,7 +552,7 @@ describe('directoryAndContentsConform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -565,7 +601,7 @@ describe('directoryAndContentsConform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`some-directory/` does not exist in this project.', @@ -605,7 +641,7 @@ describe('packageManifestPropertiesConform', () => { }, ); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); }); @@ -641,7 +677,7 @@ describe('packageManifestPropertiesConform', () => { }, ); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); }); @@ -678,7 +714,7 @@ describe('packageManifestPropertiesConform', () => { ); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -725,7 +761,7 @@ describe('packageManifestPropertiesConform', () => { ); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -784,8 +820,9 @@ describe('dataConform', () => { 'test.json', ); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); + it('passes if the reference and target have the same property at a deeper level and its value matches', () => { const referenceObject = { firstLevel: 'test', @@ -806,8 +843,9 @@ describe('dataConform', () => { 'test.json', ); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); + it('passes if the target has same properties as reference with additional properties', () => { const referenceObject = { firstLevel: 'test', @@ -829,8 +867,9 @@ describe('dataConform', () => { 'test.json', ); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); + it('fails if the reference and target does not match at the first level', () => { const referenceObject = { firstLevel: 'first level', @@ -853,7 +892,7 @@ describe('dataConform', () => { ); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: "`firstLevel` is 'test', when it should be 'first level'.", @@ -884,7 +923,7 @@ describe('dataConform', () => { ); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -893,6 +932,7 @@ describe('dataConform', () => { ], }); }); + it('fails if the target is null', () => { const referenceObject = { firstLevel: 'first level', @@ -909,7 +949,7 @@ describe('dataConform', () => { ); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -940,7 +980,7 @@ describe('dataConform', () => { ); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -949,6 +989,7 @@ describe('dataConform', () => { ], }); }); + it('throws error if a propertyPath does not exist in the reference object', () => { const referenceObject = { deeperLevel: { diff --git a/src/rule-helpers.ts b/src/rule-helpers.ts index 3e80552..5e808d3 100644 --- a/src/rule-helpers.ts +++ b/src/rule-helpers.ts @@ -7,25 +7,25 @@ import type { PartialRuleExecutionResult, RuleExecutionArguments, RuleExecutionFailure, + ErroredPartialRuleExecutionResult, } from './execute-rules'; +import { RuleExecutionStatus } from './execute-rules'; import { PackageManifestSchema } from './rules/types'; /** - * A utility for a rule which is intended to end its execution by marking it as - * passing. + * A utility for a rule which ends its execution by marking it as passing. * * @returns Part of a successful rule execution result (the rest will be filled * in automatically). */ export function pass(): SuccessfulPartialRuleExecutionResult { return { - passed: true, + status: RuleExecutionStatus.Passed, }; } /** - * A utility for a rule which is intended to end its execution by marking it as - * failing. + * A utility for a rule which ends its execution by marking it as failing. * * @param failures - The list of associated failures. * @returns Part of a failed rule execution result (the rest will be filled @@ -34,14 +34,35 @@ export function pass(): SuccessfulPartialRuleExecutionResult { export function fail( failures: FailedPartialRuleExecutionResult['failures'], ): FailedPartialRuleExecutionResult { - return { passed: false, failures }; + return { + status: RuleExecutionStatus.Failed, + failures, + }; +} + +/** + * A utility for a rule which ends its execution by marking it as having + * errored. + * + * @param capturedError - The error to include in the execution result object. + * @returns Part of an errored rule execution result (the rest will be filled + * in automatically). + */ +export function error( + capturedError: unknown, +): ErroredPartialRuleExecutionResult { + return { + status: RuleExecutionStatus.Errored, + error: capturedError, + }; } /** - * A utility which encapsulates multiple rule execution results into one. If all - * of the results are passing, then the combined result will be passing; - * otherwise, the combined result will be failing, and messages from failing - * results will be consolidated into a single array. + * A utility which encapsulates multiple rule execution results into one. If any + * of the results have errored, then the combined result will have errored, and + * the first error wins; if any of the results have failed, the combined result + * will have failed, and failures will be consolidated; otherwise the combined + * result will have passed. * * @param results - The rule execution results. * @returns The combined rule execution result. @@ -49,15 +70,25 @@ export function fail( export function combineRuleExecutionResults( results: PartialRuleExecutionResult[], ): PartialRuleExecutionResult { + let caughtError: unknown; const failures: FailedPartialRuleExecutionResult['failures'] = []; for (const result of results) { - if (!result.passed) { + if (result.status === RuleExecutionStatus.Errored) { + if (caughtError === undefined) { + caughtError = result.error; + } + } else if (result.status === RuleExecutionStatus.Failed) { failures.push(...result.failures); } } - return failures.length > 0 ? fail(failures) : pass(); + if (caughtError) { + return error(caughtError); + } else if (failures.length > 0) { + return fail(failures); + } + return pass(); } /** @@ -142,7 +173,7 @@ export async function fileConforms( ): Promise { const { template, project } = ruleExecutionArguments; const fileExistsResult = await fileExists(filePath, ruleExecutionArguments); - if (!fileExistsResult.passed) { + if (fileExistsResult.status !== RuleExecutionStatus.Passed) { return fileExistsResult; } @@ -181,7 +212,7 @@ export async function directoryAndContentsConform( directoryPath, ruleExecutionArguments, ); - if (!directoryExistsResult.passed) { + if (directoryExistsResult.status !== RuleExecutionStatus.Passed) { return directoryExistsResult; } diff --git a/src/rules/all-yarn-modern-files-conform.test.ts b/src/rules/all-yarn-modern-files-conform.test.ts index 6e6cf01..69244bb 100644 --- a/src/rules/all-yarn-modern-files-conform.test.ts +++ b/src/rules/all-yarn-modern-files-conform.test.ts @@ -49,7 +49,7 @@ describe('Rule: all-yarn-modern-files-conform', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -93,7 +93,7 @@ describe('Rule: all-yarn-modern-files-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`.yarnrc.yml` does not exist in this project.', @@ -142,7 +142,7 @@ describe('Rule: all-yarn-modern-files-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`.yarn/releases/` does not exist in this project.', @@ -195,7 +195,7 @@ describe('Rule: all-yarn-modern-files-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -245,7 +245,7 @@ describe('Rule: all-yarn-modern-files-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`.yarn/plugins/` does not exist in this project.', @@ -298,7 +298,7 @@ describe('Rule: all-yarn-modern-files-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/classic-yarn-config-file-absent.test.ts b/src/rules/classic-yarn-config-file-absent.test.ts index ede3afa..1638643 100644 --- a/src/rules/classic-yarn-config-file-absent.test.ts +++ b/src/rules/classic-yarn-config-file-absent.test.ts @@ -21,7 +21,7 @@ describe('Rule: classic-yarn-config-file-absent', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -45,7 +45,7 @@ describe('Rule: classic-yarn-config-file-absent', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/package-allow-scripts-yarn-conform.test.ts b/src/rules/package-allow-scripts-yarn-conform.test.ts index 18290aa..e118f2c 100644 --- a/src/rules/package-allow-scripts-yarn-conform.test.ts +++ b/src/rules/package-allow-scripts-yarn-conform.test.ts @@ -30,7 +30,7 @@ describe('Rule: package-allow-scripts-yarn-conform', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -58,7 +58,7 @@ describe('Rule: package-allow-scripts-yarn-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/package-allow-scripts-yarn-plugins-conform.test.ts b/src/rules/package-allow-scripts-yarn-plugins-conform.test.ts index fbf5ead..0cd519f 100644 --- a/src/rules/package-allow-scripts-yarn-plugins-conform.test.ts +++ b/src/rules/package-allow-scripts-yarn-plugins-conform.test.ts @@ -52,7 +52,7 @@ describe('Rule: package-allow-scripts-yarn-plugins-conform', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -97,7 +97,7 @@ describe('Rule: package-allow-scripts-yarn-plugins-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -152,7 +152,7 @@ describe('Rule: package-allow-scripts-yarn-plugins-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/package-changelog-dev-dependencies-conform.test.ts b/src/rules/package-changelog-dev-dependencies-conform.test.ts index 6d968d2..82e8ea9 100644 --- a/src/rules/package-changelog-dev-dependencies-conform.test.ts +++ b/src/rules/package-changelog-dev-dependencies-conform.test.ts @@ -43,7 +43,7 @@ describe('Rule: package-changelog-dev-dependencies-conform', () => { fail, }); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); }); @@ -81,7 +81,7 @@ describe('Rule: package-changelog-dev-dependencies-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -126,7 +126,7 @@ describe('Rule: package-changelog-dev-dependencies-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/package-changelog-scripts-conform.test.ts b/src/rules/package-changelog-scripts-conform.test.ts index 3c64cab..f4c7ee5 100644 --- a/src/rules/package-changelog-scripts-conform.test.ts +++ b/src/rules/package-changelog-scripts-conform.test.ts @@ -45,7 +45,7 @@ describe('Rule: package-changelog-scripts-conform', () => { fail, }); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); }); @@ -85,7 +85,7 @@ describe('Rule: package-changelog-scripts-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -131,7 +131,7 @@ describe('Rule: package-changelog-scripts-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -216,7 +216,7 @@ describe('Rule: package-changelog-scripts-conform', () => { fail, }); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); }); @@ -256,7 +256,7 @@ describe('Rule: package-changelog-scripts-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/package-engines-node-field-conforms.test.ts b/src/rules/package-engines-node-field-conforms.test.ts index fe9e2f8..53e1480 100644 --- a/src/rules/package-engines-node-field-conforms.test.ts +++ b/src/rules/package-engines-node-field-conforms.test.ts @@ -37,7 +37,7 @@ describe('Rule: package-engines-node-field-conforms', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -69,7 +69,7 @@ describe('Rule: package-engines-node-field-conforms', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/package-exports-field-conforms.test.ts b/src/rules/package-exports-field-conforms.test.ts index b8a6b7b..0c377c1 100644 --- a/src/rules/package-exports-field-conforms.test.ts +++ b/src/rules/package-exports-field-conforms.test.ts @@ -52,7 +52,7 @@ describe('Rule: package-exports-field-conforms', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -98,7 +98,7 @@ describe('Rule: package-exports-field-conforms', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/package-files-field-conforms.test.ts b/src/rules/package-files-field-conforms.test.ts index 8259bcb..7b9cff5 100644 --- a/src/rules/package-files-field-conforms.test.ts +++ b/src/rules/package-files-field-conforms.test.ts @@ -37,7 +37,7 @@ describe('Rule: package-files-field-conforms', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -69,7 +69,7 @@ describe('Rule: package-files-field-conforms', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/package-jest-dependencies-conform.test.ts b/src/rules/package-jest-dependencies-conform.test.ts index cc03f82..9a66757 100644 --- a/src/rules/package-jest-dependencies-conform.test.ts +++ b/src/rules/package-jest-dependencies-conform.test.ts @@ -41,7 +41,7 @@ describe('Rule: package-jest-dependencies-conform', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -77,7 +77,7 @@ describe('Rule: package-jest-dependencies-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`jest` is "0.0.1", when it should be "1.0.0".' }, ], @@ -116,7 +116,7 @@ describe('Rule: package-jest-dependencies-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/package-lavamoat-allow-scripts-conforms.test.ts b/src/rules/package-lavamoat-allow-scripts-conforms.test.ts index 9fc2bd3..342220e 100644 --- a/src/rules/package-lavamoat-allow-scripts-conforms.test.ts +++ b/src/rules/package-lavamoat-allow-scripts-conforms.test.ts @@ -37,7 +37,7 @@ describe('Rule: package-lavamoat-allow-scripts-conforms', () => { fail, }); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); }); @@ -69,7 +69,7 @@ describe('Rule: package-lavamoat-allow-scripts-conforms', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/package-lavamoat-dev-dependencies-conform.test.ts b/src/rules/package-lavamoat-dev-dependencies-conform.test.ts index 1083d06..3253d33 100644 --- a/src/rules/package-lavamoat-dev-dependencies-conform.test.ts +++ b/src/rules/package-lavamoat-dev-dependencies-conform.test.ts @@ -45,7 +45,7 @@ describe('Rule: package-lavamoat-dev-dependencies-conform', () => { fail, }); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); }); @@ -85,7 +85,7 @@ describe('Rule: package-lavamoat-dev-dependencies-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -131,7 +131,7 @@ describe('Rule: package-lavamoat-dev-dependencies-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/package-lavamoat-tsup-conforms.test.ts b/src/rules/package-lavamoat-tsup-conforms.test.ts index 65a2dd2..13ca547 100644 --- a/src/rules/package-lavamoat-tsup-conforms.test.ts +++ b/src/rules/package-lavamoat-tsup-conforms.test.ts @@ -48,7 +48,7 @@ describe('Rule: package-lavamoat-tsup-conforms', () => { fail, }); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); }); @@ -91,7 +91,7 @@ describe('Rule: package-lavamoat-tsup-conforms', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`tsup>esbuild` is false, when it should be true.', @@ -139,7 +139,7 @@ describe('Rule: package-lavamoat-tsup-conforms', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -180,7 +180,7 @@ describe('Rule: package-lavamoat-tsup-conforms', () => { pass, fail, }); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); }); }); diff --git a/src/rules/package-lint-dependencies-conform.test.ts b/src/rules/package-lint-dependencies-conform.test.ts index bcf7f48..5bd7524 100644 --- a/src/rules/package-lint-dependencies-conform.test.ts +++ b/src/rules/package-lint-dependencies-conform.test.ts @@ -59,7 +59,7 @@ describe('Rule: package-lint-dependencies-conform', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -113,7 +113,7 @@ describe('Rule: package-lint-dependencies-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`eslint` is "0.0.1", when it should be "1.0.0".' }, ], @@ -169,7 +169,7 @@ describe('Rule: package-lint-dependencies-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -218,7 +218,7 @@ describe('Rule: package-lint-dependencies-conform', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); diff --git a/src/rules/package-main-field-conforms.test.ts b/src/rules/package-main-field-conforms.test.ts index 822d929..83ef596 100644 --- a/src/rules/package-main-field-conforms.test.ts +++ b/src/rules/package-main-field-conforms.test.ts @@ -41,7 +41,7 @@ describe('Rule: package-main-field-conforms', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -77,7 +77,7 @@ describe('Rule: package-main-field-conforms', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: "`main` is 'test', when it should be 'test-main'.", diff --git a/src/rules/package-module-field-conforms.test.ts b/src/rules/package-module-field-conforms.test.ts index 11f6e4f..7c20238 100644 --- a/src/rules/package-module-field-conforms.test.ts +++ b/src/rules/package-module-field-conforms.test.ts @@ -41,7 +41,7 @@ describe('Rule: package-module-field-conforms', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -77,7 +77,7 @@ describe('Rule: package-module-field-conforms', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: "`module` is 'test', when it should be 'test-module'.", diff --git a/src/rules/package-package-manager-field-conforms.test.ts b/src/rules/package-package-manager-field-conforms.test.ts index 6eef8c6..1fcfe86 100644 --- a/src/rules/package-package-manager-field-conforms.test.ts +++ b/src/rules/package-package-manager-field-conforms.test.ts @@ -41,7 +41,7 @@ describe('Rule: package-manager-field-conforms', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -77,7 +77,7 @@ describe('Rule: package-manager-field-conforms', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`packageManager` is "test", when it should be "yarn".' }, ], diff --git a/src/rules/package-test-scripts-conform.test.ts b/src/rules/package-test-scripts-conform.test.ts index a0dd33a..f85922f 100644 --- a/src/rules/package-test-scripts-conform.test.ts +++ b/src/rules/package-test-scripts-conform.test.ts @@ -41,7 +41,7 @@ describe('Rule: package-test-scripts-conform', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -77,7 +77,7 @@ describe('Rule: package-test-scripts-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -119,7 +119,7 @@ describe('Rule: package-test-scripts-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/package-typedoc-dev-dependencies-conform.test.ts b/src/rules/package-typedoc-dev-dependencies-conform.test.ts index 8452635..94d45f6 100644 --- a/src/rules/package-typedoc-dev-dependencies-conform.test.ts +++ b/src/rules/package-typedoc-dev-dependencies-conform.test.ts @@ -43,7 +43,7 @@ describe('Rule: package-typedoc-dev-dependencies-conform', () => { fail, }); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); }); @@ -81,7 +81,7 @@ describe('Rule: package-typedoc-dev-dependencies-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -126,7 +126,7 @@ describe('Rule: package-typedoc-dev-dependencies-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/package-typedoc-scripts-conform.test.ts b/src/rules/package-typedoc-scripts-conform.test.ts index 1deeebc..94cbe9c 100644 --- a/src/rules/package-typedoc-scripts-conform.test.ts +++ b/src/rules/package-typedoc-scripts-conform.test.ts @@ -39,7 +39,7 @@ describe('Rule: package-typedoc-scripts-conform', () => { fail, }); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); }); @@ -73,7 +73,7 @@ describe('Rule: package-typedoc-scripts-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -114,7 +114,7 @@ describe('Rule: package-typedoc-scripts-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/package-types-field-conforms.test.ts b/src/rules/package-types-field-conforms.test.ts index d4345f9..6ba793b 100644 --- a/src/rules/package-types-field-conforms.test.ts +++ b/src/rules/package-types-field-conforms.test.ts @@ -37,7 +37,7 @@ describe('Rule: package-types-field-conforms', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -69,7 +69,7 @@ describe('Rule: package-types-field-conforms', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: "`types` is 'test', when it should be 'test-types'.", diff --git a/src/rules/package-typescript-dev-dependencies-conform.test.ts b/src/rules/package-typescript-dev-dependencies-conform.test.ts index 675c0d0..e57bfde 100644 --- a/src/rules/package-typescript-dev-dependencies-conform.test.ts +++ b/src/rules/package-typescript-dev-dependencies-conform.test.ts @@ -49,7 +49,7 @@ describe('Rule: package-typescript-dev-dependencies-conform', () => { fail, }); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); }); @@ -93,7 +93,7 @@ describe('Rule: package-typescript-dev-dependencies-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -143,7 +143,7 @@ describe('Rule: package-typescript-dev-dependencies-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/package-typescript-scripts-conform.test.ts b/src/rules/package-typescript-scripts-conform.test.ts index 6ac5896..1e5d962 100644 --- a/src/rules/package-typescript-scripts-conform.test.ts +++ b/src/rules/package-typescript-scripts-conform.test.ts @@ -45,7 +45,7 @@ describe('Rule: package-typescript-scripts-conform', () => { fail, }); - expect(result).toStrictEqual({ passed: true }); + expect(result).toStrictEqual({ status: 'passed' }); }); }); @@ -85,7 +85,7 @@ describe('Rule: package-typescript-scripts-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: @@ -131,7 +131,7 @@ describe('Rule: package-typescript-scripts-conform', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/readme-lists-correct-yarn-version.test.ts b/src/rules/readme-lists-correct-yarn-version.test.ts index 63c2a44..efb5b43 100644 --- a/src/rules/readme-lists-correct-yarn-version.test.ts +++ b/src/rules/readme-lists-correct-yarn-version.test.ts @@ -33,7 +33,7 @@ describe('Rule: readme-lists-correct-yarn-version', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -65,7 +65,7 @@ describe('Rule: readme-lists-correct-yarn-version', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/readme-recommends-node-install.test.ts b/src/rules/readme-recommends-node-install.test.ts index 6564473..5e02323 100644 --- a/src/rules/readme-recommends-node-install.test.ts +++ b/src/rules/readme-recommends-node-install.test.ts @@ -33,7 +33,7 @@ describe('Rule: readme-recommends-node-install', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -65,7 +65,7 @@ describe('Rule: readme-recommends-node-install', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/require-changelog.test.ts b/src/rules/require-changelog.test.ts index 96c36bb..6d8c7c7 100644 --- a/src/rules/require-changelog.test.ts +++ b/src/rules/require-changelog.test.ts @@ -25,7 +25,7 @@ describe('Rule: require-changelog', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -45,7 +45,7 @@ describe('Rule: require-changelog', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`CHANGELOG.md` does not exist in this project.', diff --git a/src/rules/require-editorconfig.test.ts b/src/rules/require-editorconfig.test.ts index ac749e4..7489e8a 100644 --- a/src/rules/require-editorconfig.test.ts +++ b/src/rules/require-editorconfig.test.ts @@ -33,7 +33,7 @@ describe('Rule: require-editorconfig', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -61,7 +61,7 @@ describe('Rule: require-editorconfig', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`.editorconfig` does not exist in this project.', diff --git a/src/rules/require-gitattributes.test.ts b/src/rules/require-gitattributes.test.ts index 0a82fb7..1449d8c 100644 --- a/src/rules/require-gitattributes.test.ts +++ b/src/rules/require-gitattributes.test.ts @@ -33,7 +33,7 @@ describe('Rule: require-gitattributes', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -61,7 +61,7 @@ describe('Rule: require-gitattributes', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`.gitattributes` does not exist in this project.', diff --git a/src/rules/require-gitignore.test.ts b/src/rules/require-gitignore.test.ts index edd48a5..85877e6 100644 --- a/src/rules/require-gitignore.test.ts +++ b/src/rules/require-gitignore.test.ts @@ -33,7 +33,7 @@ describe('Rule: require-gitignore', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -61,7 +61,7 @@ describe('Rule: require-gitignore', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`.gitignore` does not exist in this project.', diff --git a/src/rules/require-nvmrc.test.ts b/src/rules/require-nvmrc.test.ts index bde1e2a..dc0763d 100644 --- a/src/rules/require-nvmrc.test.ts +++ b/src/rules/require-nvmrc.test.ts @@ -33,7 +33,7 @@ describe('Rule: require-nvmrc', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -61,7 +61,7 @@ describe('Rule: require-nvmrc', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`.nvmrc` does not exist in this project.', diff --git a/src/rules/require-readme.test.ts b/src/rules/require-readme.test.ts index c0ca319..fc8ea58 100644 --- a/src/rules/require-readme.test.ts +++ b/src/rules/require-readme.test.ts @@ -25,7 +25,7 @@ describe('Rule: require-readme', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -45,7 +45,7 @@ describe('Rule: require-readme', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`README.md` does not exist in this project.', diff --git a/src/rules/require-source-directory.test.ts b/src/rules/require-source-directory.test.ts index b7a8f2f..47fe187 100644 --- a/src/rules/require-source-directory.test.ts +++ b/src/rules/require-source-directory.test.ts @@ -27,7 +27,7 @@ describe('Rule: require-source-directory', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -47,7 +47,7 @@ describe('Rule: require-source-directory', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`src/` does not exist in this project.', @@ -73,7 +73,7 @@ describe('Rule: require-source-directory', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`src/` is not a directory when it should be.', diff --git a/src/rules/require-tsconfig-build.test.ts b/src/rules/require-tsconfig-build.test.ts index cb527e7..9354cdd 100644 --- a/src/rules/require-tsconfig-build.test.ts +++ b/src/rules/require-tsconfig-build.test.ts @@ -33,7 +33,7 @@ describe('Rule: require-tsconfig-build', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -61,7 +61,7 @@ describe('Rule: require-tsconfig-build', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`tsconfig.build.json` does not exist in this project.', diff --git a/src/rules/require-tsconfig.test.ts b/src/rules/require-tsconfig.test.ts index 8ab7546..2670ddd 100644 --- a/src/rules/require-tsconfig.test.ts +++ b/src/rules/require-tsconfig.test.ts @@ -33,7 +33,7 @@ describe('Rule: require-tsconfig', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -61,7 +61,7 @@ describe('Rule: require-tsconfig', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`tsconfig.json` does not exist in this project.', diff --git a/src/rules/require-tsup-config.test.ts b/src/rules/require-tsup-config.test.ts index c04d4d8..1192f09 100644 --- a/src/rules/require-tsup-config.test.ts +++ b/src/rules/require-tsup-config.test.ts @@ -33,7 +33,7 @@ describe('Rule: require-tsup-config', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -61,7 +61,7 @@ describe('Rule: require-tsup-config', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`tsup.config.ts` does not exist in this project.', diff --git a/src/rules/require-typedoc.test.ts b/src/rules/require-typedoc.test.ts index cb2d3d1..e64a69b 100644 --- a/src/rules/require-typedoc.test.ts +++ b/src/rules/require-typedoc.test.ts @@ -33,7 +33,7 @@ describe('Rule: require-typedoc', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -61,7 +61,7 @@ describe('Rule: require-typedoc', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`typedoc.json` does not exist in this project.', diff --git a/src/rules/require-valid-changelog.test.ts b/src/rules/require-valid-changelog.test.ts index 7905b63..7a03a5d 100644 --- a/src/rules/require-valid-changelog.test.ts +++ b/src/rules/require-valid-changelog.test.ts @@ -61,7 +61,7 @@ describe('Rule: require-valid-changelog', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -96,7 +96,7 @@ describe('Rule: require-valid-changelog', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: 'Changelog is not well-formatted.', diff --git a/src/rules/require-valid-package-manifest.test.ts b/src/rules/require-valid-package-manifest.test.ts index 1fdd940..89489f9 100644 --- a/src/rules/require-valid-package-manifest.test.ts +++ b/src/rules/require-valid-package-manifest.test.ts @@ -29,7 +29,7 @@ describe('Rule: require-package-manifest', () => { }); expect(result).toStrictEqual({ - passed: true, + status: 'passed', }); }); }); @@ -49,7 +49,7 @@ describe('Rule: require-package-manifest', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: '`package.json` does not exist in this project.', @@ -78,7 +78,7 @@ describe('Rule: require-package-manifest', () => { }); expect(result).toStrictEqual({ - passed: false, + status: 'failed', failures: [ { message: diff --git a/src/rules/require-valid-package-manifest.ts b/src/rules/require-valid-package-manifest.ts index 7630f18..d1703a6 100644 --- a/src/rules/require-valid-package-manifest.ts +++ b/src/rules/require-valid-package-manifest.ts @@ -2,6 +2,7 @@ import { isErrorWithCode, isErrorWithMessage } from '@metamask/utils/node'; import { buildRule } from './build-rule'; import { PackageManifestSchema, RuleName } from './types'; +import { RuleExecutionStatus } from '../execute-rules'; import { fileExists } from '../rule-helpers'; export default buildRule({ @@ -16,7 +17,7 @@ export default buildRule({ entryPath, ruleExecutionArguments, ); - if (!fileExistsResult.passed) { + if (fileExistsResult.status !== RuleExecutionStatus.Passed) { return fileExistsResult; }