-
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add function rule plugin sources and tests
- Loading branch information
Showing
10 changed files
with
254 additions
and
4 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import { Commit, RuleConfigCondition, RuleOutcome } from '@commitlint/types'; | ||
import { beforeEach, describe, expect, it, jest } from '@jest/globals'; | ||
import functionRule, { FunctionRule } from './function-rule'; | ||
|
||
describe('functionRule', (): void => { | ||
const commit: Commit = { | ||
type: 'chore', | ||
scope: 'scope', | ||
subject: 'test', | ||
merge: null, | ||
header: 'chore(scope): test', | ||
body: null, | ||
footer: null, | ||
notes: [], | ||
references: [], | ||
mentions: [], | ||
revert: null, | ||
raw: 'chore(scope): test\n', | ||
}; | ||
const when: RuleConfigCondition = 'always'; | ||
/** | ||
* To pass this to an function, that is obviously not expecting a mock, a type | ||
* assertion is needed. For this, the as-syntax is needed when a mock is | ||
* passed as function argument. | ||
*/ | ||
const ruleImplementation = jest.fn(); | ||
|
||
beforeEach(() => { | ||
ruleImplementation.mockReset(); | ||
}); | ||
|
||
it('calls implementation function', () => { | ||
functionRule(commit, when, ruleImplementation as FunctionRule); | ||
|
||
expect(ruleImplementation).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('passes arguments to implementation function', () => { | ||
functionRule(commit, when, ruleImplementation as FunctionRule); | ||
|
||
expect(ruleImplementation).toHaveBeenCalledWith(commit, when); | ||
}); | ||
|
||
it("defaults 'when' argument to 'always'", () => { | ||
functionRule(commit, undefined, ruleImplementation as FunctionRule); | ||
|
||
expect(ruleImplementation).toHaveBeenCalledWith(commit, 'always'); | ||
}); | ||
|
||
it('returns value from sync implementation function', () => { | ||
const returnValue: RuleOutcome = [ | ||
true, | ||
'Message from sync implementation function.', | ||
]; | ||
ruleImplementation.mockImplementation(() => returnValue); | ||
const value = functionRule( | ||
commit, | ||
when, | ||
ruleImplementation as FunctionRule, | ||
); | ||
|
||
expect(ruleImplementation).toHaveBeenCalledTimes(1); | ||
expect(value).toEqual(returnValue); | ||
}); | ||
|
||
it('returns value from async implementation function', async () => { | ||
const returnValue: RuleOutcome = [ | ||
true, | ||
'Message from async implementation function.', | ||
]; | ||
ruleImplementation.mockImplementation(() => Promise.resolve(returnValue)); | ||
const value = await functionRule( | ||
commit, | ||
when, | ||
ruleImplementation as FunctionRule, | ||
); | ||
|
||
expect(ruleImplementation).toHaveBeenCalledTimes(1); | ||
expect(value).toEqual(returnValue); | ||
}); | ||
|
||
it("throws an error when 'value' is 'undefined'", () => { | ||
expect(() => { | ||
functionRule(commit, when, undefined); | ||
}).toThrow(); | ||
}); | ||
|
||
it("throws an error when 'value' is 'not an function'", () => { | ||
expect(() => { | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-expect-error: TS2345: Argument of type ... is not assignable to parameter of type ... | ||
functionRule(commit, when, 'not a function!'); | ||
}).toThrow(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { | ||
Commit, | ||
Rule, | ||
RuleConfigCondition, | ||
RuleOutcome, | ||
} from '@commitlint/types'; | ||
|
||
type FunctionRule = ( | ||
parsed: Commit, | ||
when: RuleConfigCondition, | ||
) => RuleOutcome | Promise<RuleOutcome>; | ||
|
||
const functionRule: Rule<FunctionRule> = ( | ||
parsed: Commit, | ||
when: RuleConfigCondition = 'always', | ||
value: FunctionRule | undefined, | ||
) => { | ||
if (typeof value === 'function') { | ||
return value(parsed, when); | ||
} | ||
|
||
throw new Error('Not a valid function!'); | ||
}; | ||
|
||
export default functionRule; | ||
export { FunctionRule }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import * as plugin from './index'; | ||
import { describe, expect, it } from '@jest/globals'; | ||
import rules from './rules'; | ||
|
||
describe('index', () => { | ||
it(`exports a CommonJS module with 'rules' object`, () => { | ||
expect(Object.keys(plugin)).toEqual(['rules']); | ||
expect(typeof plugin.rules).toEqual('object'); | ||
}); | ||
|
||
it('exports rules', () => { | ||
expect(plugin).toMatchObject({ rules }); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import Plugin from './plugin'; | ||
import rules from './rules'; | ||
|
||
const plugin: Plugin = { | ||
rules, | ||
}; | ||
|
||
/** | ||
* Export single object, according to the CommonJS model. The CommonJS module is | ||
* explicitly used here as that's the kind of module commitlint requires for | ||
* plugins. | ||
*/ | ||
export = plugin; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { describe, expect, it } from '@jest/globals'; | ||
import Plugin from './plugin'; | ||
|
||
describe('Plugin', (): void => { | ||
it("defines 'rules' as an object", () => { | ||
const plugin: Plugin = { | ||
rules: {}, | ||
}; | ||
|
||
expect(Object.keys(plugin)).toEqual(['rules']); | ||
expect(typeof plugin.rules).toEqual('object'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { Rules } from './rules'; | ||
|
||
interface Plugin { | ||
rules: Rules; | ||
} | ||
|
||
export default Plugin; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { describe, expect, it } from '@jest/globals'; | ||
import commitlintRules from '@commitlint/rules'; | ||
import functionRule from './function-rule'; | ||
import rules from './rules'; | ||
|
||
describe('rules', (): void => { | ||
const prefix = 'function-rules/'; | ||
const names = Object.keys(rules); | ||
const commitlintRuleNames = Object.keys(commitlintRules).sort(); | ||
|
||
it('exports the same rules as commitlint', () => { | ||
const strippedNames = names.map((e) => { | ||
return e.replace(new RegExp(`^${prefix}`), ''); | ||
}); | ||
|
||
expect(strippedNames).toEqual(commitlintRuleNames); | ||
}); | ||
|
||
it(`are exported with with '${prefix}' as prefix`, () => { | ||
const everyNameHasPrefix = names.every((e) => e.startsWith(prefix)); | ||
|
||
expect(everyNameHasPrefix).toBe(true); | ||
}); | ||
|
||
it(`have 'functionRule' as value`, () => { | ||
const values = Object.values(rules); | ||
const everyValueIsFunctionRule = values.every((e) => e === functionRule); | ||
|
||
expect(everyValueIsFunctionRule).toBe(true); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import functionRule, { FunctionRule } from './function-rule'; | ||
import { Rule } from '@commitlint/types'; | ||
|
||
type Rules = Record<string, Rule<FunctionRule>>; | ||
|
||
const rules: Rules = { | ||
'function-rules/body-case': functionRule, | ||
'function-rules/body-empty': functionRule, | ||
'function-rules/body-leading-blank': functionRule, | ||
'function-rules/body-max-length': functionRule, | ||
'function-rules/body-max-line-length': functionRule, | ||
'function-rules/body-min-length': functionRule, | ||
'function-rules/footer-empty': functionRule, | ||
'function-rules/footer-leading-blank': functionRule, | ||
'function-rules/footer-max-length': functionRule, | ||
'function-rules/footer-max-line-length': functionRule, | ||
'function-rules/footer-min-length': functionRule, | ||
'function-rules/header-case': functionRule, | ||
'function-rules/header-full-stop': functionRule, | ||
'function-rules/header-max-length': functionRule, | ||
'function-rules/header-min-length': functionRule, | ||
'function-rules/references-empty': functionRule, | ||
'function-rules/scope-case': functionRule, | ||
'function-rules/scope-empty': functionRule, | ||
'function-rules/scope-enum': functionRule, | ||
'function-rules/scope-max-length': functionRule, | ||
'function-rules/scope-min-length': functionRule, | ||
'function-rules/signed-off-by': functionRule, | ||
'function-rules/subject-case': functionRule, | ||
'function-rules/subject-empty': functionRule, | ||
'function-rules/subject-full-stop': functionRule, | ||
'function-rules/subject-max-length': functionRule, | ||
'function-rules/subject-min-length': functionRule, | ||
'function-rules/type-case': functionRule, | ||
'function-rules/type-empty': functionRule, | ||
'function-rules/type-enum': functionRule, | ||
'function-rules/type-max-length': functionRule, | ||
'function-rules/type-min-length': functionRule, | ||
}; | ||
|
||
export default rules; | ||
export { Rules }; |