diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 4673243..9dc3826 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -19,8 +19,11 @@ jobs: path: '**/node_modules' key: ${{ runner.os }}-modules-${{ hashFiles('**/package-lock.json') }} + - name: tests + run: npm cit + - name: build - run: npm ci && npm run build + run: npm run build - name: Bump version and push tag id: changelog diff --git a/ava.config.js b/ava.config.js new file mode 100644 index 0000000..f70ef1c --- /dev/null +++ b/ava.config.js @@ -0,0 +1,7 @@ +/* eslint-disable node/no-unsupported-features/es-syntax */ + +export default { + files: ['!templates/**/*'], + extensions: ['ts'], + require: ['ts-node/register/transpile-only'], +}; diff --git a/package-lock.json b/package-lock.json index 59fdbca..e90881b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "mawesome", - "version": "1.0.0", + "version": "1.0.25", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -751,6 +751,41 @@ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.0.0.tgz", "integrity": "sha512-FyD2meJpDPjyNQejSjvnhpgI/azsQkA4lGbuu5BQZfjvJ9cbRZXzeWL2HceCekW4lixO9JPesIIQkSoLjeJHNQ==" }, + "@sinonjs/commons": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz", + "integrity": "sha512-sruwd86RJHdsVf/AtBoijDmUqJp3B6hF/DGC23C+JaegnDHaZyewCjoVGTdg3J0uz3Zs7NnIT05OBOmML72lQw==", + "dev": true, + "requires": { + "type-detect": "4.0.8" + } + }, + "@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0" + } + }, + "@sinonjs/samsam": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", + "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "@sinonjs/text-encoding": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", + "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", + "dev": true + }, "@szmarczak/http-timer": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.5.tgz", @@ -845,6 +880,21 @@ "@types/node": "*" } }, + "@types/sinon": { + "version": "9.0.10", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-9.0.10.tgz", + "integrity": "sha512-/faDC0erR06wMdybwI/uR8wEKV/E83T0k4sepIpB7gXuy2gzx2xiOjmztq6a2Y6rIGJ04D+6UU0VBmWy+4HEMA==", + "dev": true, + "requires": { + "@types/sinonjs__fake-timers": "*" + } + }, + "@types/sinonjs__fake-timers": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz", + "integrity": "sha512-dIPoZ3g5gcx9zZEszaxLSVTvMReD3xxyyDnQUjA6IYDG9Ba2AV0otMPs+77sG9ojB4Qr2N2Vk5RnKeuA0X/0bg==", + "dev": true + }, "@types/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/strip-bom/-/strip-bom-3.0.0.tgz", @@ -3367,11 +3417,6 @@ "is-obj": "^2.0.0" } }, - "dotenv": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", - "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" - }, "dotgitignore": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz", @@ -6229,6 +6274,12 @@ "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", "dev": true }, + "just-extend": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", + "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==", + "dev": true + }, "keyv": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", @@ -6415,6 +6466,12 @@ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, "lodash.ismatch": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", @@ -6912,6 +6969,19 @@ "integrity": "sha512-y0PICjHqj7BCA04ayG0neJChSWt0oUKLtnDQZJu6ey+wtlpddQA1JwH0JtB6u+Q/Twkuz+pUIAZeZMHxUqgr4A==", "dev": true }, + "nise": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz", + "integrity": "sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, "node-fetch": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", @@ -7438,6 +7508,23 @@ "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", "dev": true }, + "path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dev": true, + "requires": { + "isarray": "0.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + } + } + }, "path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -8184,6 +8271,20 @@ "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, + "sinon": { + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.3.tgz", + "integrity": "sha512-m+DyAWvqVHZtjnjX/nuShasykFeiZ+nPuEfD4G3gpvKGkXRhkF/6NSt2qN2FjZhfrcHXFzUzI+NLnk+42fnLEw==", + "dev": true, + "requires": { + "@sinonjs/commons": "^1.8.1", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/samsam": "^5.3.0", + "diff": "^4.0.2", + "nise": "^4.0.4", + "supports-color": "^7.1.0" + } + }, "slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -9447,6 +9548,12 @@ "prelude-ls": "^1.2.1" } }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, "type-fest": { "version": "0.18.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", diff --git a/package.json b/package.json index 9aefd15..43c940c 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "author": "Simone Corsi", "license": "MIT", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", + "test": "nyc --reporter=lcov --reporter=text-summary ava -s -v", + "test:watch": "ava -w", "style:lint": "eslint src --ext .ts", "style:prettier": "prettier \"src/**/*.ts\" --list-different --write", "build": "./node_modules/.bin/ncc build src/index.ts -o ./", @@ -30,6 +31,7 @@ "@types/ejs": "^3.0.5", "@types/got": "^9.6.11", "@types/node": "^14.14.5", + "@types/sinon": "^9.0.10", "@typescript-eslint/eslint-plugin": "^4.6.0", "@typescript-eslint/parser": "^4.6.0", "@vercel/ncc": "^0.26.2", @@ -47,6 +49,7 @@ "ninos": "^3.0.0", "nyc": "^15.0.1", "prettier": "^2.0.5", + "sinon": "^9.2.3", "standard-version": "^9.0.0", "ts-node-dev": "^1.1.1", "typescript": "^4.1.3" @@ -63,4 +66,4 @@ "volta": { "node": "14.15.4" } -} \ No newline at end of file +} diff --git a/src/git.ts b/src/git.ts index d864275..eb3b5b5 100644 --- a/src/git.ts +++ b/src/git.ts @@ -6,8 +6,7 @@ import * as exec from '@actions/exec'; const { GITHUB_REPOSITORY, GITHUB_REF } = process.env; const branch = GITHUB_REF?.replace('refs/heads/', ''); - -export default new (class Git { +class Git { constructor() { const githubToken = core.getInput('github-token', { required: true }); core.setSecret(githubToken); @@ -80,4 +79,6 @@ export default new (class Git { updateOrigin = (repo: string) => this.exec(`remote set-url origin ${repo}`); createTag = (tag: string) => this.exec(`tag -a ${tag} -m "${tag}"`); -})(); +} + +export default new Git(); diff --git a/src/link.js b/src/link.js index 4cfa5a5..c25dafe 100644 --- a/src/link.js +++ b/src/link.js @@ -3,6 +3,7 @@ * https://github.com/jhermsmeier/node-http-link-header */ +/* istanbul ignore file */ 'use strict'; var COMPATIBLE_ENCODING_PATTERN = /^utf-?8|ascii|utf-?16-?le|ucs-?2|base-?64|latin-?1$/i; diff --git a/test/helpers.spec.ts b/test/helpers.spec.ts new file mode 100644 index 0000000..ffd5e7d --- /dev/null +++ b/test/helpers.spec.ts @@ -0,0 +1,106 @@ +import test from 'ava'; +import * as sinon from 'sinon'; +import fs from 'fs'; + +import * as core from '@actions/core'; +sinon.replace(core, 'getInput', sinon.fake()); + +import GithubApi from '../src/api'; +const GithubApiFake = sinon.fake((rul) => ({ + body: 'data', + headers: { + link: + '; rel="next", ; rel="last"', + }, +})); +sinon.replace(GithubApi, 'get', GithubApiFake); + +import Git from '../src/git'; +const pull = sinon.fake(); +sinon.replace(Git, 'pull', pull); +const add = sinon.fake(); +sinon.replace(Git, 'add', add); +const commit = sinon.fake(); +sinon.replace(Git, 'commit', commit); +const push = sinon.fake(); +sinon.replace(Git, 'push', push); +sinon.replace(Git, 'config', sinon.fake()); +sinon.replace(Git, 'updateOrigin', sinon.fake()); + +const fsp = fs.promises; +const writeFile = sinon.fake(); +sinon.replace(fsp, 'writeFile', writeFile); + +import { + isLastPage, + wait, + renderer, + apiGetStar, + paginate, + generateMd, + pushNewFile, +} from '../src/helpers'; + +test('wait should wait', async (t) => { + await wait(200); + t.pass(); +}); + +test('isLastPage', (t) => { + t.true( + isLastPage({ + next: 'last', + last: 'last', + }) + ); + t.false( + isLastPage({ + next: 'last', + last: undefined, + }) + ); +}); + +test('renderer should render', async (t) => { + const output = await renderer({ variable: 123 }, 'Test: <%= variable %>'); + t.is(output, 'Test: 123'); +}); + +test('apiGetStar', async (t) => { + let { data, links } = await apiGetStar('url'); + t.true(GithubApiFake.called); + t.is(data, 'data'); + t.deepEqual(links, { + last: 'https://api.github.com/user/5617452/starred?page=2', + next: 'https://api.github.com/user/5617452/starred?page=2', + }); +}); + +test('paginate', async (t) => { + await paginate(); + const res = await paginate(); + t.is(res, null); +}); + +test('generateMd should create TOC', async (t) => { + const tpl = `# title + +## Table of Contents + +## Javascript +`; + const result = await generateMd(tpl); + t.is( + result, + `# title\n\n## Table of Contents\n\n* [Javascript](#javascript)\n\n## Javascript\n` + ); +}); + +test('should push', async (t) => { + await pushNewFile('# title'); + t.true(writeFile.calledWith('README.md', '# title')); + t.true(pull.called); + t.true(add.calledWith('README.md')); + t.true(commit.calledWith('chore(README.md): updated README.md')); + t.true(push.called); +});