diff --git a/@commitlint/parse/jest.config.js b/@commitlint/parse/jest.config.js new file mode 100644 index 0000000000..20d2ea60f5 --- /dev/null +++ b/@commitlint/parse/jest.config.js @@ -0,0 +1,4 @@ +module.exports = { + preset: 'ts-jest', + testEnvironment: 'node' +}; diff --git a/@commitlint/parse/package.json b/@commitlint/parse/package.json index 5af437cce1..52b4905c6f 100644 --- a/@commitlint/parse/package.json +++ b/@commitlint/parse/package.json @@ -3,35 +3,13 @@ "version": "8.1.0", "description": "Lint your commit messages", "main": "lib/index.js", + "types": "lib/index.d.ts", "files": [ "lib/" ], "scripts": { - "build": "cross-env NODE_ENV=production babel src --out-dir lib --source-maps", "deps": "dep-check", - "pkg": "pkg-check", - "start": "concurrently \"ava -c 4 --verbose --watch\" \"yarn run watch\"", - "test": "ava -c 4 --verbose", - "watch": "babel src --out-dir lib --watch --source-maps" - }, - "ava": { - "files": [ - "src/**/*.test.js", - "!lib/**/*" - ], - "source": [ - "src/**/*.js", - "!lib/**/*" - ], - "babel": "inherit", - "require": [ - "babel-register" - ] - }, - "babel": { - "presets": [ - "babel-preset-commitlint" - ] + "pkg": "pkg-check" }, "engines": { "node": ">=4" @@ -58,13 +36,14 @@ "devDependencies": { "@commitlint/test": "8.0.0", "@commitlint/utils": "^8.1.0", - "ava": "0.22.0", + "@types/lodash": "^4.14.136", "babel-cli": "6.26.0", "babel-preset-commitlint": "^8.0.0", "babel-register": "6.26.0", "concurrently": "3.6.1", "cross-env": "5.1.1", - "import-from": "3.0.0" + "import-from": "3.0.0", + "typescript": "^3.5.3" }, "dependencies": { "conventional-changelog-angular": "^1.3.3", diff --git a/@commitlint/parse/src/index.test.js b/@commitlint/parse/src/index.test.ts similarity index 61% rename from @commitlint/parse/src/index.test.js rename to @commitlint/parse/src/index.test.ts index f44a1182bb..58e9a8853f 100644 --- a/@commitlint/parse/src/index.test.js +++ b/@commitlint/parse/src/index.test.ts @@ -1,40 +1,40 @@ import importFrom from 'import-from'; -import test from 'ava'; import parse from '.'; -test('throws when called without params', async t => { - const error = await t.throws(parse()); - t.is(error.message, 'Expected a raw commit'); +test('throws when called without params', () => { + expect(parse()).rejects.toThrowError('Expected a raw commit'); }); -test('throws when called with empty message', async t => { - const error = await t.throws(parse()); - t.is(error.message, 'Expected a raw commit'); +test('throws when called with empty message', () => { + expect(parse()).rejects.toThrowError('Expected a raw commit'); }); -test('returns object with raw message', async t => { +test('returns object with raw message', async () => { const message = 'type(scope): subject'; const actual = await parse(message); - t.is(actual.raw, message); + + expect(actual).toHaveProperty('raw', message); }); -test('calls parser with message and passed options', async t => { +test('calls parser with message and passed options', async () => { const message = 'message'; - await parse(message, m => { - t.is(message, m); + expect.assertions(1); + await parse(message, (m: string) => { + expect(m).toBe(message); return {}; }); }); -test('passes object up from parser function', async t => { +test('passes object up from parser function', async () => { const message = 'message'; const result = {}; const actual = await parse(message, () => result); - t.is(actual, result); + + expect(actual).toBe(result); }); -test('returns object with expected keys', async t => { +test('returns object with expected keys', async () => { const message = 'message'; const actual = await parse(message); const expected = { @@ -51,10 +51,11 @@ test('returns object with expected keys', async t => { subject: null, type: null }; - t.deepEqual(actual, expected); + + expect(actual).toMatchObject(expected); }); -test('uses angular grammar', async t => { +test('uses angular grammar', async () => { const message = 'type(scope): subject'; const actual = await parse(message); const expected = { @@ -71,14 +72,15 @@ test('uses angular grammar', async t => { subject: 'subject', type: 'type' }; - t.deepEqual(actual, expected); + + expect(actual).toMatchObject(expected); }); -test('uses custom opts parser', async t => { +test('uses custom opts parser', async () => { const message = 'type(scope)-subject'; - const changelogOpts = await importFrom( - process.cwd(), - './fixtures/parser-preset/conventional-changelog-custom' + const changelogOpts: any = await importFrom( + __dirname, + '../fixtures/parser-preset/conventional-changelog-custom.js' ); const actual = await parse(message, undefined, changelogOpts.parserOpts); const expected = { @@ -95,10 +97,11 @@ test('uses custom opts parser', async t => { subject: 'subject', type: 'type' }; - t.deepEqual(actual, expected); + + expect(actual).toMatchObject(expected); }); -test('does not merge array properties with custom opts', async t => { +test('does not merge array properties with custom opts', async () => { const message = 'type: subject'; const actual = await parse(message, undefined, { headerPattern: /^(.*):\s(.*)$/, @@ -117,26 +120,29 @@ test('does not merge array properties with custom opts', async t => { subject: 'subject', type: 'type' }; - t.deepEqual(actual, expected); + + expect(actual).toMatchObject(expected); }); -test('supports scopes with /', async t => { +test('supports scopes with /', async () => { const message = 'type(some/scope): subject'; const actual = await parse(message); - t.is(actual.scope, 'some/scope'); - t.is(actual.subject, 'subject'); + + expect(actual.scope).toBe('some/scope'); + expect(actual.subject).toBe('subject'); }); -test('supports scopes with / and empty parserOpts', async t => { +test('supports scopes with / and empty parserOpts', async () => { const message = 'type(some/scope): subject'; const actual = await parse(message, undefined, {}); - t.is(actual.scope, 'some/scope'); - t.is(actual.subject, 'subject'); + + expect(actual.scope).toBe('some/scope'); + expect(actual.subject).toBe('subject'); }); -test('ignores comments', async t => { +test('ignores comments', async () => { const message = 'type(some/scope): subject\n# some comment'; - const changelogOpts = await importFrom( + const changelogOpts: any = await importFrom( process.cwd(), 'conventional-changelog-angular' ); @@ -144,15 +150,16 @@ test('ignores comments', async t => { commentChar: '#' }); const actual = await parse(message, undefined, opts); - t.is(actual.body, null); - t.is(actual.footer, null); - t.is(actual.subject, 'subject'); + + expect(actual.body).toBe(null); + expect(actual.footer).toBe(null); + expect(actual.subject).toBe('subject'); }); -test('registers inline #', async t => { +test('registers inline #', async () => { const message = 'type(some/scope): subject #reference\n# some comment\nthings #reference'; - const changelogOpts = await importFrom( + const changelogOpts: any = await importFrom( process.cwd(), 'conventional-changelog-angular' ); @@ -160,11 +167,12 @@ test('registers inline #', async t => { commentChar: '#' }); const actual = await parse(message, undefined, opts); - t.is(actual.subject, 'subject #reference'); - t.is(actual.body, 'things #reference'); + + expect(actual.subject).toBe('subject #reference'); + expect(actual.body).toBe('things #reference'); }); -test('parses references leading subject', async t => { +test('parses references leading subject', async () => { const message = '#1 some subject'; const opts = await importFrom( process.cwd(), @@ -173,17 +181,18 @@ test('parses references leading subject', async t => { const { references: [actual] } = await parse(message, undefined, opts); - t.is(actual.issue, '1'); + + expect(actual.issue).toBe('1'); }); -test('parses custom references', async t => { +test('parses custom references', async () => { const message = '#1 some subject PREFIX-2'; const {references} = await parse(message, undefined, { issuePrefixes: ['PREFIX-'] }); - t.falsy(references.find(ref => ref.issue === '1')); - t.deepEqual(references.find(ref => ref.issue === '2'), { + expect(references.find((ref: any) => ref.issue === '1')).toBeFalsy(); + expect(references.find((ref: any) => ref.issue === '2')).toMatchObject({ action: null, issue: '2', owner: null, @@ -193,44 +202,44 @@ test('parses custom references', async t => { }); }); -test('uses permissive default regex without parser opts', async t => { +test('uses permissive default regex without parser opts', async () => { const message = 'chore(component,demo): bump'; const actual = await parse(message); - t.is(actual.scope, 'component,demo'); + expect(actual.scope).toBe('component,demo'); }); -test('uses permissive default regex with other parser opts', async t => { +test('uses permissive default regex with other parser opts', async () => { const message = 'chore(component,demo): bump'; const actual = await parse(message, undefined, {commentChar: '#'}); - t.is(actual.scope, 'component,demo'); + expect(actual.scope).toBe('component,demo'); }); -test('uses restrictive default regex in passed parser opts', async t => { +test('uses restrictive default regex in passed parser opts', async () => { const message = 'chore(component,demo): bump'; const actual = await parse(message, undefined, { headerPattern: /^(\w*)(?:\(([a-z]*)\))?: (.*)$/ }); - t.is(actual.subject, null); - t.is(actual.scope, null); + expect(actual.subject).toBe(null); + expect(actual.scope).toBe(null); }); -test('works with chinese scope by default', async t => { +test('works with chinese scope by default', async () => { const message = 'fix(面试评价): 测试'; const actual = await parse(message, undefined, {commentChar: '#'}); - t.not(actual.subject, null); - t.not(actual.scope, null); + expect(actual.subject).not.toBe(null); + expect(actual.scope).not.toBe(null); }); -test('does not work with chinese scopes with incompatible pattern', async t => { +test('does not work with chinese scopes with incompatible pattern', async () => { const message = 'fix(面试评价): 测试'; const actual = await parse(message, undefined, { headerPattern: /^(\w*)(?:\(([a-z]*)\))?: (.*)$/ }); - t.is(actual.subject, null); - t.is(actual.scope, null); + expect(actual.subject).toBe(null); + expect(actual.scope).toBe(null); }); diff --git a/@commitlint/parse/src/index.js b/@commitlint/parse/src/index.ts similarity index 59% rename from @commitlint/parse/src/index.js rename to @commitlint/parse/src/index.ts index ee4f7742ce..92ae71641e 100644 --- a/@commitlint/parse/src/index.js +++ b/@commitlint/parse/src/index.ts @@ -1,10 +1,15 @@ -import {sync} from 'conventional-commits-parser'; -import defaultChangelogOpts from 'conventional-changelog-angular'; import {isArray, mergeWith} from 'lodash'; +const {sync} = require('conventional-commits-parser'); +const defaultChangelogOpts = require('conventional-changelog-angular'); + export default parse; -async function parse(message, parser = sync, parserOpts = undefined) { +async function parse( + message?: any, + parser: any = sync, + parserOpts: any = undefined +) { const defaultOpts = (await defaultChangelogOpts).parserOpts; const parsed = parser( message, diff --git a/@commitlint/parse/tsconfig.json b/@commitlint/parse/tsconfig.json new file mode 100644 index 0000000000..f4a57643f0 --- /dev/null +++ b/@commitlint/parse/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.shared.json", + "compilerOptions": { + "composite": true, + "rootDir": "./src", + "outDir": "./lib" + }, + "include": [ + "./src" + ], + "exclude": [ + "./src/**/*.test.ts", + "./lib/**/*" + ] +} diff --git a/yarn.lock b/yarn.lock index 922c12fd4e..f829f9b116 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1285,7 +1285,7 @@ dependencies: "@types/jest-diff" "*" -"@types/lodash@4.14.136": +"@types/lodash@4.14.136", "@types/lodash@^4.14.136": version "4.14.136" resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.136.tgz#413e85089046b865d960c9ff1d400e04c31ab60f" integrity sha512-0GJhzBdvsW2RUccNHOBkabI8HZVdOXmXbXhuKlDEd5Vv12P7oAVGfomGp3Ne21o5D/qu1WmthlNKFaoZJJeErA== @@ -10913,7 +10913,7 @@ typedarray@^0.0.6: resolved "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@3.5.3: +typescript@3.5.3, typescript@^3.5.3: version "3.5.3" resolved "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977" integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==