From 468b09599bff1499eb9594bd9c1328fff11fdd72 Mon Sep 17 00:00:00 2001
From: Saravana
Date: Thu, 3 Aug 2023 23:00:24 +0200
Subject: [PATCH] Migration to typescript (#61)
* Adding package.json value
* Simply converting all JS to TS
* Main should be JS
* Fix issue in index.ts
* Print something in action()
* Trying a different import
* More logs
* More logs
* More logs
* Fixing the util.test.ts
* Migrating all tests to TS with the @ts-nocheck annotation
* Fix all issues in util.ts expect return types
* Fix all issues in util.ts
* Fix all issues in render.ts
* Fix all issues in process.ts
* Fix some issues in action.ts
* Fixing all issues in action.ts
* Fixing all prettier issues
* Fixing all errors
* Changed from 1.6.1
* Changed from 1.6.1 - Build
* Building
---
.eslintignore | 6 +-
.eslintrc.js | 24 -
.eslintrc.json | 64 +
.prettierignore | 5 +-
.prettierrc.js | 12 -
.prettierrc.json | 10 +
__tests__/{action.test.js => action.test.ts} | 27 +-
...egate.test.js => action_aggregate.test.ts} | 25 +-
...ltiple.test.js => action_multiple.test.ts} | 17 +-
...n_single.test.js => action_single.test.ts} | 68 +-
__tests__/{mocks.test.js => mocks.test.ts} | 87 +-
.../{process.test.js => process.test.ts} | 96 +-
__tests__/{render.test.js => render.test.ts} | 8 +-
__tests__/{util.test.js => util.test.ts} | 310 +-
dist/build/Release/node_expat.node | Bin 205732 -> 0 bytes
dist/index.js | 2115 ++++-----
dist/index.js.map | 1 +
dist/sourcemap-register.js | 1 +
jest.config.js | 9 +
lib/__tests__/action.test.js | 121 +
lib/__tests__/action_aggregate.test.js | 192 +
lib/__tests__/action_multiple.test.js | 195 +
lib/__tests__/action_single.test.js | 354 ++
lib/__tests__/mocks.test.js | 438 ++
lib/__tests__/process.test.js | 457 ++
lib/__tests__/render.test.js | 345 ++
lib/__tests__/util.test.js | 280 ++
lib/src/action.js | 209 +
lib/src/index.js | 4 +
lib/src/models/github.js | 2 +
lib/src/models/jacoco.js | 2 +
lib/src/models/project.js | 2 +
lib/src/process.js | 200 +
lib/src/render.js | 129 +
lib/src/util.js | 101 +
package-lock.json | 4136 +++++++++++++++--
package.json | 14 +-
src/{action.js => action.ts} | 96 +-
src/index.js | 6 -
src/index.ts | 3 +
src/models/github.ts | 5 +
src/models/jacoco.ts | 21 +
src/models/project.ts | 44 +
src/{process.js => process.ts} | 151 +-
src/{render.js => render.ts} | 132 +-
src/{util.js => util.ts} | 75 +-
tsconfig.json | 11 +
47 files changed, 8528 insertions(+), 2082 deletions(-)
delete mode 100644 .eslintrc.js
create mode 100644 .eslintrc.json
delete mode 100644 .prettierrc.js
create mode 100644 .prettierrc.json
rename __tests__/{action.test.js => action.test.ts} (79%)
rename __tests__/{action_aggregate.test.js => action_aggregate.test.ts} (89%)
rename __tests__/{action_multiple.test.js => action_multiple.test.ts} (94%)
rename __tests__/{action_single.test.js => action_single.test.ts} (86%)
rename __tests__/{mocks.test.js => mocks.test.ts} (90%)
rename __tests__/{process.test.js => process.test.ts} (81%)
rename __tests__/{render.test.js => render.test.ts} (99%)
rename __tests__/{util.test.js => util.test.ts} (50%)
delete mode 100755 dist/build/Release/node_expat.node
create mode 100644 dist/index.js.map
create mode 100644 dist/sourcemap-register.js
create mode 100644 jest.config.js
create mode 100644 lib/__tests__/action.test.js
create mode 100644 lib/__tests__/action_aggregate.test.js
create mode 100644 lib/__tests__/action_multiple.test.js
create mode 100644 lib/__tests__/action_single.test.js
create mode 100644 lib/__tests__/mocks.test.js
create mode 100644 lib/__tests__/process.test.js
create mode 100644 lib/__tests__/render.test.js
create mode 100644 lib/__tests__/util.test.js
create mode 100644 lib/src/action.js
create mode 100644 lib/src/index.js
create mode 100644 lib/src/models/github.js
create mode 100644 lib/src/models/jacoco.js
create mode 100644 lib/src/models/project.js
create mode 100644 lib/src/process.js
create mode 100644 lib/src/render.js
create mode 100644 lib/src/util.js
rename src/{action.js => action.ts} (71%)
delete mode 100644 src/index.js
create mode 100644 src/index.ts
create mode 100644 src/models/github.ts
create mode 100644 src/models/jacoco.ts
create mode 100644 src/models/project.ts
rename src/{process.js => process.ts} (58%)
rename src/{render.js => render.ts} (60%)
rename src/{util.js => util.ts} (58%)
create mode 100644 tsconfig.json
diff --git a/.eslintignore b/.eslintignore
index ea32dad..5105076 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1 +1,5 @@
-dist/index.js
\ No newline at end of file
+dist/
+node_modules/
+jest.config.js
+lib/
+coverage/
diff --git a/.eslintrc.js b/.eslintrc.js
deleted file mode 100644
index 0f2b0d2..0000000
--- a/.eslintrc.js
+++ /dev/null
@@ -1,24 +0,0 @@
-module.exports = {
- env: {
- node: true,
- es2021: true,
- jest: true,
- jasmine: true,
- },
- extends: ['standard', 'prettier'],
- overrides: [
- {
- files: ['.eslintrc.{js, cjs}'],
- },
- ],
- parserOptions: {
- ecmaVersion: 'latest',
- sourceType: 'module',
- project: true,
- },
- rules: {
- quotes: ['error', 'single', { avoidEscape: true }],
- 'no-var': ['error'],
- 'dot-notation': ['off'],
- },
-}
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..95010d1
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,64 @@
+{
+ "plugins": ["jest", "@typescript-eslint"],
+ "extends": ["plugin:github/recommended"],
+ "parser": "@typescript-eslint/parser",
+ "parserOptions": {
+ "ecmaVersion": 9,
+ "sourceType": "module",
+ "project": "./tsconfig.json"
+ },
+ "rules": {
+ "i18n-text/no-en": "off",
+ "eslint-comments/no-use": "off",
+ "import/no-namespace": "off",
+ "no-unused-vars": "off",
+ "@typescript-eslint/no-unused-vars": "error",
+ "@typescript-eslint/explicit-member-accessibility": [
+ "error",
+ {"accessibility": "no-public"}
+ ],
+ "@typescript-eslint/no-require-imports": "error",
+ "@typescript-eslint/array-type": "error",
+ "@typescript-eslint/await-thenable": "error",
+ "@typescript-eslint/ban-ts-comment": "error",
+ "camelcase": "off",
+ "@typescript-eslint/consistent-type-assertions": "error",
+ "@typescript-eslint/explicit-function-return-type": [
+ "error",
+ {"allowExpressions": true}
+ ],
+ "filenames/match-regex": "off",
+ "@typescript-eslint/func-call-spacing": ["error", "never"],
+ "@typescript-eslint/no-array-constructor": "error",
+ "@typescript-eslint/no-empty-interface": "error",
+ "@typescript-eslint/no-explicit-any": "error",
+ "@typescript-eslint/no-extraneous-class": "error",
+ "@typescript-eslint/no-for-in-array": "error",
+ "@typescript-eslint/no-inferrable-types": "error",
+ "@typescript-eslint/no-misused-new": "error",
+ "@typescript-eslint/no-namespace": "error",
+ "@typescript-eslint/no-non-null-assertion": "warn",
+ "@typescript-eslint/no-unnecessary-qualifier": "error",
+ "@typescript-eslint/no-unnecessary-type-assertion": "error",
+ "@typescript-eslint/no-useless-constructor": "error",
+ "@typescript-eslint/no-var-requires": "error",
+ "@typescript-eslint/prefer-for-of": "warn",
+ "@typescript-eslint/prefer-function-type": "warn",
+ "@typescript-eslint/prefer-includes": "error",
+ "@typescript-eslint/prefer-string-starts-ends-with": "error",
+ "@typescript-eslint/promise-function-async": "error",
+ "@typescript-eslint/require-array-sort-compare": "error",
+ "@typescript-eslint/restrict-plus-operands": "error",
+ "semi": "off",
+ "@typescript-eslint/semi": ["error", "never"],
+ "@typescript-eslint/type-annotation-spacing": "error",
+ "@typescript-eslint/unbound-method": "error"
+ },
+ "env": {
+ "node": true,
+ "es6": true,
+ "jest/globals": true,
+ "jasmine": true,
+ "jest": true
+ }
+}
diff --git a/.prettierignore b/.prettierignore
index ea32dad..af7ce60 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1 +1,4 @@
-dist/index.js
\ No newline at end of file
+dist/
+node_modules/
+lib/
+coverage/
diff --git a/.prettierrc.js b/.prettierrc.js
deleted file mode 100644
index eec4b7e..0000000
--- a/.prettierrc.js
+++ /dev/null
@@ -1,12 +0,0 @@
-// prettier.config.js, .prettierrc.js, prettier.config.mjs, or .prettierrc.mjs
-
-/** @type {import("prettier").Options} */
-const config = {
- trailingComma: 'es5',
- tabWidth: 2,
- semi: false,
- singleQuote: true,
- useTabs: false,
-}
-
-module.exports = config
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 0000000..c00d385
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1,10 @@
+{
+ "printWidth": 80,
+ "tabWidth": 2,
+ "useTabs": false,
+ "semi": false,
+ "singleQuote": true,
+ "trailingComma": "es5",
+ "bracketSpacing": false,
+ "arrowParens": "avoid"
+}
diff --git a/__tests__/action.test.js b/__tests__/action.test.ts
similarity index 79%
rename from __tests__/action.test.js
rename to __tests__/action.test.ts
index 721c72b..674629e 100644
--- a/__tests__/action.test.js
+++ b/__tests__/action.test.ts
@@ -1,12 +1,12 @@
-const action = require('../src/action')
-const core = require('@actions/core')
-const github = require('@actions/github')
+import * as action from '../src/action'
+import * as core from '@actions/core'
+import * as github from '@actions/github'
jest.mock('@actions/core')
jest.mock('@actions/github')
describe('Input validation', function () {
- function getInput(key) {
+ function getInput(key: string): string | undefined {
switch (key) {
case 'paths':
return './__tests__/__fixtures__/report.xml'
@@ -19,7 +19,10 @@ describe('Input validation', function () {
const listComments = jest.fn()
const updateComment = jest.fn()
+ /* eslint-disable @typescript-eslint/ban-ts-comment */
+ // @ts-ignore
core.getInput = jest.fn(getInput)
+ // @ts-ignore
github.getOctokit = jest.fn(() => {
return {
repos: {
@@ -50,12 +53,14 @@ describe('Input validation', function () {
},
}
})
- core.setFailed = jest.fn((c) => {
+ // @ts-ignore
+ core.setFailed = jest.fn(c => {
fail(c)
})
it('Fail if paths is not present', async () => {
- core.getInput = jest.fn((c) => {
+ // @ts-ignore
+ core.getInput = jest.fn(c => {
switch (c) {
case 'paths':
return ''
@@ -65,14 +70,16 @@ describe('Input validation', function () {
})
github.context.eventName = 'pull_request'
- core.setFailed = jest.fn((c) => {
+ // @ts-ignore
+ core.setFailed = jest.fn(c => {
expect(c).toEqual("'paths' is missing")
})
await action.action()
})
it('Fail if token is not present', async () => {
- core.getInput = jest.fn((c) => {
+ // @ts-ignore
+ core.getInput = jest.fn(c => {
switch (c) {
case 'token':
return ''
@@ -81,8 +88,8 @@ describe('Input validation', function () {
}
})
github.context.eventName = 'pull_request'
-
- core.setFailed = jest.fn((c) => {
+ // @ts-ignore
+ core.setFailed = jest.fn(c => {
expect(c).toEqual("'token' is missing")
})
await action.action()
diff --git a/__tests__/action_aggregate.test.js b/__tests__/action_aggregate.test.ts
similarity index 89%
rename from __tests__/action_aggregate.test.js
rename to __tests__/action_aggregate.test.ts
index ba3d543..e65749e 100644
--- a/__tests__/action_aggregate.test.js
+++ b/__tests__/action_aggregate.test.ts
@@ -1,8 +1,9 @@
-/* eslint-disable no-template-curly-in-string */
-const action = require('../src/action')
-const core = require('@actions/core')
-const github = require('@actions/github')
-const { PATCH } = require('./mocks.test')
+/* eslint-disable @typescript-eslint/ban-ts-comment */
+// @ts-nocheck
+import * as action from '../src/action'
+import * as core from '@actions/core'
+import * as github from '@actions/github'
+import {PATCH} from './mocks.test'
jest.mock('@actions/core')
jest.mock('@actions/github')
@@ -13,7 +14,7 @@ describe('Aggregate report', function () {
let updateComment
let output
- function getInput(key) {
+ function getInput(key: string): string {
switch (key) {
case 'paths':
return './__tests__/__fixtures__/aggregate-report.xml'
@@ -39,6 +40,7 @@ describe('Aggregate report', function () {
output = jest.fn()
core.getInput = jest.fn(getInput)
+ // @ts-ignore
github.getOctokit = jest.fn(() => {
return {
rest: {
@@ -55,7 +57,8 @@ describe('Aggregate report', function () {
},
}
})
- core.setFailed = jest.fn((c) => {
+ // @ts-ignore
+ core.setFailed = jest.fn(c => {
fail(c)
})
})
@@ -123,7 +126,7 @@ describe('Aggregate report', function () {
it('updates a previous comment', async () => {
initContext(eventName, payload)
const title = 'JaCoCo Report'
- core.getInput = jest.fn((c) => {
+ core.getInput = jest.fn(c => {
switch (c) {
case 'title':
return title
@@ -136,8 +139,8 @@ describe('Aggregate report', function () {
listComments.mockReturnValue({
data: [
- { id: 1, body: 'some comment' },
- { id: 2, body: `### ${title}\n to update` },
+ {id: 1, body: 'some comment'},
+ {id: 2, body: `### ${title}\n to update`},
],
})
@@ -169,7 +172,7 @@ describe('Aggregate report', function () {
})
})
-function initContext(eventName, payload) {
+function initContext(eventName, payload): void {
const context = github.context
context.eventName = eventName
context.payload = payload
diff --git a/__tests__/action_multiple.test.js b/__tests__/action_multiple.test.ts
similarity index 94%
rename from __tests__/action_multiple.test.js
rename to __tests__/action_multiple.test.ts
index 6060480..fabbeef 100644
--- a/__tests__/action_multiple.test.js
+++ b/__tests__/action_multiple.test.ts
@@ -1,8 +1,9 @@
-/* eslint-disable no-template-curly-in-string */
-const action = require('../src/action')
-const core = require('@actions/core')
-const github = require('@actions/github')
-const { PATCH } = require('./mocks.test')
+/* eslint-disable @typescript-eslint/ban-ts-comment */
+// @ts-nocheck
+import * as action from '../src/action'
+import * as core from '@actions/core'
+import * as github from '@actions/github'
+import {PATCH} from './mocks.test'
jest.mock('@actions/core')
jest.mock('@actions/github')
@@ -50,7 +51,7 @@ describe('Multiple reports', function () {
},
}
- core.getInput = jest.fn((c) => {
+ core.getInput = jest.fn(c => {
switch (c) {
case 'paths':
return './__tests__/__fixtures__/multi_module/appCoverage.xml,./__tests__/__fixtures__/multi_module/mathCoverage.xml,./__tests__/__fixtures__/multi_module/textCoverage.xml'
@@ -82,7 +83,7 @@ describe('Multiple reports', function () {
},
}
})
- core.setFailed = jest.fn((c) => {
+ core.setFailed = jest.fn(c => {
fail(c)
})
@@ -179,7 +180,7 @@ describe('Multiple reports', function () {
})
})
-function initContext(eventName, payload) {
+function initContext(eventName, payload): void {
const context = github.context
context.eventName = eventName
context.payload = payload
diff --git a/__tests__/action_single.test.js b/__tests__/action_single.test.ts
similarity index 86%
rename from __tests__/action_single.test.js
rename to __tests__/action_single.test.ts
index cd761f6..47cdc7e 100644
--- a/__tests__/action_single.test.js
+++ b/__tests__/action_single.test.ts
@@ -1,8 +1,9 @@
-/* eslint-disable no-template-curly-in-string */
-const action = require('../src/action')
-const core = require('@actions/core')
-const github = require('@actions/github')
-const { PATCH } = require('./mocks.test')
+/* eslint-disable @typescript-eslint/ban-ts-comment */
+// @ts-nocheck
+import * as action from '../src/action'
+import * as core from '@actions/core'
+import * as github from '@actions/github'
+import {PATCH} from './mocks.test'
jest.mock('@actions/core')
jest.mock('@actions/github')
@@ -13,7 +14,7 @@ describe('Single report', function () {
let updateComment
let output
- function getInput(key) {
+ function getInput(key): string {
switch (key) {
case 'paths':
return './__tests__/__fixtures__/report.xml'
@@ -55,7 +56,7 @@ describe('Single report', function () {
},
}
})
- core.setFailed = jest.fn((c) => {
+ core.setFailed = jest.fn(c => {
fail(c)
})
})
@@ -135,7 +136,7 @@ describe('Single report', function () {
describe('With update-comment ON', function () {
const title = 'JaCoCo Report'
- function mockInput(key) {
+ function mockInput(key): string {
switch (key) {
case 'title':
return title
@@ -148,14 +149,14 @@ describe('Single report', function () {
it('if comment exists, update it', async () => {
initContext(eventName, payload)
- core.getInput = jest.fn((key) => {
+ core.getInput = jest.fn(key => {
return mockInput(key)
})
listComments.mockReturnValue({
data: [
- { id: 1, body: 'some comment' },
- { id: 2, body: `### ${title}\n to update` },
+ {id: 1, body: 'some comment'},
+ {id: 2, body: `### ${title}\n to update`},
],
})
@@ -167,11 +168,11 @@ describe('Single report', function () {
it('if comment does not exist, create new comment', async () => {
initContext(eventName, payload)
- core.getInput = jest.fn((key) => {
+ core.getInput = jest.fn(key => {
return mockInput(key)
})
listComments.mockReturnValue({
- data: [{ id: 1, body: 'some comment' }],
+ data: [{id: 1, body: 'some comment'}],
})
await action.action()
@@ -182,7 +183,7 @@ describe('Single report', function () {
it('if title not set, warn user and create new comment', async () => {
initContext(eventName, payload)
- core.getInput = jest.fn((c) => {
+ core.getInput = jest.fn(c => {
switch (c) {
case 'title':
return ''
@@ -193,8 +194,8 @@ describe('Single report', function () {
listComments.mockReturnValue({
data: [
- { id: 1, body: 'some comment' },
- { id: 2, body: `### ${title}\n to update` },
+ {id: 1, body: 'some comment'},
+ {id: 2, body: `### ${title}\n to update`},
],
})
@@ -209,8 +210,8 @@ describe('Single report', function () {
})
describe('Skip if no changes set to true', function () {
- function mockInput() {
- core.getInput = jest.fn((c) => {
+ function mockInput(): void {
+ core.getInput = jest.fn(c => {
switch (c) {
case 'skip-if-no-changes':
return 'true'
@@ -232,24 +233,23 @@ describe('Single report', function () {
it("Don't add comment when coverage absent for changes files", async () => {
initContext(eventName, payload)
mockInput()
- const compareCommitsResponse = {
- data: {
- files: [
- {
- filename: '.github/workflows/coverage.yml',
- blob_url:
- 'https://github.com/thsaravana/jacoco-playground/blob/14a554976c0e5909d8e69bc8cce72958c49a7dc5/.github/workflows/coverage.yml',
- patch: PATCH.SINGLE_MODULE.COVERAGE,
- },
- ],
- },
- }
github.getOctokit = jest.fn(() => {
return {
rest: {
repos: {
compareCommits: jest.fn(() => {
- return compareCommitsResponse
+ return {
+ data: {
+ files: [
+ {
+ filename: '.github/workflows/coverage.yml',
+ blob_url:
+ 'https://github.com/thsaravana/jacoco-playground/blob/14a554976c0e5909d8e69bc8cce72958c49a7dc5/.github/workflows/coverage.yml',
+ patch: PATCH.SINGLE_MODULE.COVERAGE,
+ },
+ ],
+ },
+ }
}),
},
issues: {
@@ -270,7 +270,7 @@ describe('Single report', function () {
describe('With custom emoji', function () {
it('publish proper comment', async () => {
initContext(eventName, payload)
- core.getInput = jest.fn((key) => {
+ core.getInput = jest.fn(key => {
switch (key) {
case 'pass-emoji':
return ':green_circle:'
@@ -351,7 +351,7 @@ describe('Single report', function () {
describe('Other than push or pull_request or pull_request_target event', function () {
it('Fail by throwing appropriate error', async () => {
initContext('pr_review', {})
- core.setFailed = jest.fn((c) => {
+ core.setFailed = jest.fn(c => {
expect(c).toEqual(
'Only pull requests and pushes are supported, pr_review not supported.'
)
@@ -363,7 +363,7 @@ describe('Single report', function () {
})
})
-function initContext(eventName, payload) {
+function initContext(eventName, payload): void {
const context = github.context
context.eventName = eventName
context.payload = payload
diff --git a/__tests__/mocks.test.js b/__tests__/mocks.test.ts
similarity index 90%
rename from __tests__/mocks.test.js
rename to __tests__/mocks.test.ts
index dd2dcf4..c01b0ee 100644
--- a/__tests__/mocks.test.js
+++ b/__tests__/mocks.test.ts
@@ -1,5 +1,4 @@
-/* eslint-disable no-template-curly-in-string */
-const PATCH = {
+export const PATCH = {
SINGLE_MODULE: {
COVERAGE:
"@@ -10,10 +10,10 @@ jobs:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v2\n- - name: Set up JDK 1.8\n+ - name: Set up JDK 17\n uses: actions/setup-java@v1\n with:\n- java-version: 1.8\n+ java-version: 17\n \n - name: Grant execute permission for gradlew\n run: chmod +x gradlew\n@@ -29,13 +29,15 @@ jobs:\n \n - name: Jacoco Report to PR\n id: jacoco\n- uses: madrapps/jacoco-report@v1.1\n+ uses: madrapps/jacoco-report@coverage-diff\n with:\n- path: ${{ github.workspace }}/build/reports/jacoco/testCoverage/testCoverage.xml\n+ paths: ${{ github.workspace }}/build/reports/jacoco/**/testCoverage.xml\n token: ${{ secrets.GITHUB_TOKEN }}\n min-coverage-overall: 40\n min-coverage-changed-files: 60\n- debug-mode: false\n+ update-comment: true\n+ title: '`Coverage Report`'\n+ debug-mode: true\n \n - name: Get the Coverage info\n run: | ",
@@ -34,7 +33,7 @@ const PATCH = {
},
}
-const CHANGED_FILE = {
+export const CHANGED_FILE = {
MULTI_MODULE: [
{
filePath: '.github/workflows/coverage.yml',
@@ -120,7 +119,7 @@ const CHANGED_FILE = {
],
}
-const PROJECT = {
+export const PROJECT = {
SINGLE_MODULE: {
modules: [
{
@@ -137,7 +136,7 @@ const PROJECT = {
changed: {
covered: 0,
missed: 0,
- percentage: null,
+ percentage: undefined,
},
lines: [],
},
@@ -157,43 +156,43 @@ const PROJECT = {
lines: [
{
number: 6,
- instruction: { missed: 0, covered: 3 },
- branch: { missed: 1, covered: 1 },
+ instruction: {missed: 0, covered: 3},
+ branch: {missed: 1, covered: 1},
},
{
number: 13,
- instruction: { missed: 3, covered: 0 },
- branch: { missed: 2, covered: 0 },
+ instruction: {missed: 3, covered: 0},
+ branch: {missed: 2, covered: 0},
},
{
number: 14,
- instruction: { missed: 4, covered: 0 },
- branch: { missed: 0, covered: 0 },
+ instruction: {missed: 4, covered: 0},
+ branch: {missed: 0, covered: 0},
},
{
number: 16,
- instruction: { missed: 4, covered: 0 },
- branch: { missed: 0, covered: 0 },
+ instruction: {missed: 4, covered: 0},
+ branch: {missed: 0, covered: 0},
},
{
number: 26,
- instruction: { missed: 0, covered: 3 },
- branch: { missed: 1, covered: 1 },
+ instruction: {missed: 0, covered: 3},
+ branch: {missed: 1, covered: 1},
},
{
number: 27,
- instruction: { missed: 0, covered: 4 },
- branch: { missed: 0, covered: 0 },
+ instruction: {missed: 0, covered: 4},
+ branch: {missed: 0, covered: 0},
},
{
number: 29,
- instruction: { missed: 4, covered: 0 },
- branch: { missed: 0, covered: 0 },
+ instruction: {missed: 4, covered: 0},
+ branch: {missed: 0, covered: 0},
},
{
number: 43,
- instruction: { missed: 6, covered: 0 },
- branch: { missed: 0, covered: 0 },
+ instruction: {missed: 6, covered: 0},
+ branch: {missed: 0, covered: 0},
},
],
},
@@ -213,8 +212,8 @@ const PROJECT = {
lines: [
{
number: 3,
- instruction: { missed: 0, covered: 3 },
- branch: { missed: 0, covered: 0 },
+ instruction: {missed: 0, covered: 3},
+ branch: {missed: 0, covered: 0},
},
],
},
@@ -265,13 +264,13 @@ const PROJECT = {
lines: [
{
number: 6,
- instruction: { missed: 0, covered: 3 },
- branch: { missed: 0, covered: 0 },
+ instruction: {missed: 0, covered: 3},
+ branch: {missed: 0, covered: 0},
},
{
number: 20,
- instruction: { missed: 2, covered: 0 },
- branch: { missed: 0, covered: 0 },
+ instruction: {missed: 2, covered: 0},
+ branch: {missed: 0, covered: 0},
},
],
},
@@ -306,8 +305,8 @@ const PROJECT = {
lines: [
{
number: 22,
- instruction: { missed: 5, covered: 0 },
- branch: { missed: 0, covered: 0 },
+ instruction: {missed: 5, covered: 0},
+ branch: {missed: 0, covered: 0},
},
],
},
@@ -327,13 +326,13 @@ const PROJECT = {
lines: [
{
number: 5,
- instruction: { missed: 3, covered: 0 },
- branch: { missed: 0, covered: 0 },
+ instruction: {missed: 3, covered: 0},
+ branch: {missed: 0, covered: 0},
},
{
number: 8,
- instruction: { missed: 2, covered: 0 },
- branch: { missed: 0, covered: 0 },
+ instruction: {missed: 2, covered: 0},
+ branch: {missed: 0, covered: 0},
},
],
},
@@ -368,8 +367,8 @@ const PROJECT = {
lines: [
{
number: 16,
- instruction: { missed: 8, covered: 0 },
- branch: { missed: 2, covered: 0 },
+ instruction: {missed: 8, covered: 0},
+ branch: {missed: 2, covered: 0},
},
],
},
@@ -389,8 +388,8 @@ const PROJECT = {
lines: [
{
number: 20,
- instruction: { missed: 14, covered: 0 },
- branch: { missed: 0, covered: 0 },
+ instruction: {missed: 14, covered: 0},
+ branch: {missed: 0, covered: 0},
},
],
},
@@ -410,13 +409,13 @@ const PROJECT = {
lines: [
{
number: 3,
- instruction: { missed: 3, covered: 0 },
- branch: { missed: 0, covered: 0 },
+ instruction: {missed: 3, covered: 0},
+ branch: {missed: 0, covered: 0},
},
{
number: 7,
- instruction: { missed: 1, covered: 0 },
- branch: { missed: 0, covered: 0 },
+ instruction: {missed: 1, covered: 0},
+ branch: {missed: 0, covered: 0},
},
],
},
@@ -448,12 +447,6 @@ const PROJECT = {
},
}
-module.exports = {
- PATCH,
- CHANGED_FILE,
- PROJECT,
-}
-
it('Empty test', function () {
// To Suppress - Your test suite must contain at least one test.
})
diff --git a/__tests__/process.test.js b/__tests__/process.test.ts
similarity index 81%
rename from __tests__/process.test.js
rename to __tests__/process.test.ts
index 52069da..ebd1bd5 100644
--- a/__tests__/process.test.js
+++ b/__tests__/process.test.ts
@@ -1,7 +1,8 @@
-const fs = require('fs')
-const parser = require('xml2js')
-const process = require('../src/process')
-const { CHANGED_FILE, PROJECT } = require('./mocks.test')
+import fs from 'fs'
+import parser from 'xml2js'
+import * as process from '../src/process'
+import {CHANGED_FILE, PROJECT} from './mocks.test'
+import {ChangedFile} from '../src/models/github'
describe('process', function () {
describe('get file coverage', function () {
@@ -9,7 +10,7 @@ describe('process', function () {
it('no files changed', async () => {
const v = getSingleReport()
const reports = await v
- const changedFiles = []
+ const changedFiles: ChangedFile[] = []
const actual = process.getProjectCoverage(reports, changedFiles)
expect(actual).toEqual({
modules: [],
@@ -23,14 +24,14 @@ describe('process', function () {
changed: {
covered: 0,
missed: 0,
- percentage: null,
+ percentage: undefined,
},
})
})
it('one file changed', async () => {
const reports = await getSingleReport()
- const changedFiles = CHANGED_FILE.SINGLE_MODULE.filter((file) => {
+ const changedFiles = CHANGED_FILE.SINGLE_MODULE.filter(file => {
return file.filePath.endsWith('Math.kt')
})
const actual = process.getProjectCoverage(reports, changedFiles)
@@ -43,43 +44,43 @@ describe('process', function () {
{
lines: [
{
- branch: { covered: 1, missed: 1 },
- instruction: { covered: 3, missed: 0 },
+ branch: {covered: 1, missed: 1},
+ instruction: {covered: 3, missed: 0},
number: 6,
},
{
- branch: { covered: 0, missed: 2 },
- instruction: { covered: 0, missed: 3 },
+ branch: {covered: 0, missed: 2},
+ instruction: {covered: 0, missed: 3},
number: 13,
},
{
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 4 },
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 4},
number: 14,
},
{
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 4 },
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 4},
number: 16,
},
{
- branch: { covered: 1, missed: 1 },
- instruction: { covered: 3, missed: 0 },
+ branch: {covered: 1, missed: 1},
+ instruction: {covered: 3, missed: 0},
number: 26,
},
{
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 4, missed: 0 },
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 4, missed: 0},
number: 27,
},
{
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 4 },
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 4},
number: 29,
},
{
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 6 },
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 6},
number: 43,
},
],
@@ -134,7 +135,7 @@ describe('process', function () {
describe('multiple reports', function () {
it('no files changed', async () => {
const reports = await getMultipleReports()
- const changedFiles = []
+ const changedFiles: ChangedFile[] = []
const actual = process.getProjectCoverage(reports, changedFiles)
expect(actual).toEqual({
modules: [],
@@ -148,14 +149,14 @@ describe('process', function () {
changed: {
covered: 0,
missed: 0,
- percentage: null,
+ percentage: undefined,
},
})
})
it('one file changed', async () => {
const reports = await getMultipleReports()
- const changedFiles = CHANGED_FILE.MULTI_MODULE.filter((file) => {
+ const changedFiles = CHANGED_FILE.MULTI_MODULE.filter(file => {
return file.filePath.endsWith('StringOp.java')
})
const actual = process.getProjectCoverage(reports, changedFiles)
@@ -168,13 +169,13 @@ describe('process', function () {
{
lines: [
{
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 3, missed: 0 },
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 3, missed: 0},
number: 6,
},
{
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 2 },
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 2},
number: 20,
},
],
@@ -229,7 +230,7 @@ describe('process', function () {
describe('aggregate reports', function () {
it('no files changed', async () => {
const reports = await getAggregateReport()
- const changedFiles = []
+ const changedFiles: ChangedFile[] = []
const actual = process.getProjectCoverage(reports, changedFiles)
expect(actual).toEqual({
modules: [],
@@ -243,14 +244,14 @@ describe('process', function () {
changed: {
covered: 0,
missed: 0,
- percentage: null,
+ percentage: undefined,
},
})
})
it('one file changed', async () => {
const reports = await getAggregateReport()
- const changedFiles = CHANGED_FILE.MULTI_MODULE.filter((file) => {
+ const changedFiles = CHANGED_FILE.MULTI_MODULE.filter(file => {
return file.filePath.endsWith('MainViewModel.kt')
})
const actual = process.getProjectCoverage(reports, changedFiles)
@@ -269,7 +270,7 @@ describe('process', function () {
changed: {
covered: 0,
missed: 0,
- percentage: null,
+ percentage: undefined,
},
lines: [],
name: 'MainViewModel.kt',
@@ -285,7 +286,7 @@ describe('process', function () {
changed: {
covered: 0,
missed: 0,
- percentage: null,
+ percentage: undefined,
},
},
],
@@ -297,14 +298,14 @@ describe('process', function () {
changed: {
covered: 0,
missed: 0,
- percentage: null,
+ percentage: undefined,
},
})
})
it('multiple files changed', async () => {
const reports = await getAggregateReport()
- const changedFiles = CHANGED_FILE.MULTI_MODULE.filter((file) => {
+ const changedFiles = CHANGED_FILE.MULTI_MODULE.filter(file => {
return (
file.filePath.endsWith('MainViewModel.kt') ||
file.filePath.endsWith('Math.kt') ||
@@ -321,8 +322,8 @@ describe('process', function () {
{
lines: [
{
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 5 },
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 5},
number: 22,
},
],
@@ -363,7 +364,7 @@ describe('process', function () {
changed: {
covered: 0,
missed: 0,
- percentage: null,
+ percentage: undefined,
},
name: 'MainViewModel.kt',
lines: [],
@@ -379,7 +380,7 @@ describe('process', function () {
changed: {
covered: 0,
missed: 0,
- percentage: null,
+ percentage: undefined,
},
},
],
@@ -399,29 +400,30 @@ describe('process', function () {
})
})
-async function getAggregateReport() {
+/* eslint-disable @typescript-eslint/no-explicit-any */
+async function getAggregateReport(): Promise {
const reportPath = './__tests__/__fixtures__/aggregate-report.xml'
const report = await getReport(reportPath)
return [report]
}
-async function getMultipleReports() {
+async function getMultipleReports(): Promise {
const testFolder = './__tests__/__fixtures__/multi_module'
return Promise.all(
- fs.readdirSync(testFolder).map(async (file) => {
- const reportPath = testFolder + '/' + file
+ fs.readdirSync(testFolder).map(async file => {
+ const reportPath = `${testFolder}/${file}`
return await getReport(reportPath)
})
)
}
-async function getSingleReport() {
+async function getSingleReport(): Promise {
const reportPath = './__tests__/__fixtures__/report.xml'
const report = await getReport(reportPath)
return [report]
}
-async function getReport(path) {
+async function getReport(path: string): Promise {
const reportXml = await fs.promises.readFile(path, 'utf-8')
const json = await parser.parseStringPromise(reportXml)
return json['report']
diff --git a/__tests__/render.test.js b/__tests__/render.test.ts
similarity index 99%
rename from __tests__/render.test.js
rename to __tests__/render.test.ts
index d4890bc..e981417 100644
--- a/__tests__/render.test.js
+++ b/__tests__/render.test.ts
@@ -1,10 +1,10 @@
-const render = require('../src/render')
-const { PROJECT } = require('./mocks.test')
+import * as render from '../src/render'
+import {PROJECT} from './mocks.test'
describe('Render', function () {
describe('getTitle', function () {
it('title is not present', function () {
- const title = render.getTitle(null)
+ const title = render.getTitle(undefined)
expect(title).toEqual('')
})
@@ -57,7 +57,7 @@ describe('Render', function () {
changed: {
covered: 0,
missed: 0,
- percentage: null,
+ percentage: undefined,
},
}
it('coverage greater than min coverage', function () {
diff --git a/__tests__/util.test.js b/__tests__/util.test.ts
similarity index 50%
rename from __tests__/util.test.js
rename to __tests__/util.test.ts
index a718c9d..4d5164f 100644
--- a/__tests__/util.test.js
+++ b/__tests__/util.test.ts
@@ -1,6 +1,6 @@
-const util = require('../src/util')
-const fs = require('fs')
-const parser = require('xml2js')
+import * as util from '../src/util'
+import * as fs from 'fs'
+import parser from 'xml2js'
jest.mock('@actions/core')
jest.mock('@actions/github')
@@ -8,7 +8,7 @@ jest.mock('@actions/github')
describe('Util', function () {
describe('getChangedLines', function () {
it('when patch is null', async () => {
- const changedLines = util.getChangedLines(null)
+ const changedLines = util.getChangedLines(undefined)
expect(changedLines).toEqual([])
})
@@ -26,7 +26,6 @@ describe('Util', function () {
it('multiple patch of lines within same group', async () => {
const patch =
- // eslint-disable-next-line no-template-curly-in-string
"@@ -23,17 +23,19 @@ jobs:\n \n - name: Jacoco Report to PR\n id: jacoco\n- uses: madrapps/jacoco-report@v1.2\n+ uses: madrapps/jacoco-report@coverage-diff\n with:\n paths: |\n- ${{ github.workspace }}/app/build/reports/jacoco/prodNormalDebugCoverage/prodNormalDebugCoverage.xml,\n- ${{ github.workspace }}/math/build/reports/jacoco/debugCoverage/mathCoverage.xml,\n- ${{ github.workspace }}/text/build/reports/jacoco/debugCoverage/mathCoverage.xml\n+ ${{ github.workspace }}/**/build/reports/jacoco/**/prodNormalDebugCoverage.xml,\n+ ${{ github.workspace }}/**/build/reports/jacoco/**/mathCoverage.xml\n token: ${{ secrets.GITHUB_TOKEN }}\n min-coverage-overall: 40\n min-coverage-changed-files: 60\n- title: Code Coverage\n- debug-mode: false\n+ title: ':lobster: Coverage Report'\n+ update-comment: true\n+ pass-emoji: ':green_circle:'\n+ fail-emoji: ':red_circle:'\n+ debug-mode: true\n \n - name: Get the Coverage info\n run: |"
const changedLines = util.getChangedLines(patch)
expect(changedLines).toEqual([26, 29, 30, 34, 35, 36, 37, 38])
@@ -34,7 +33,6 @@ describe('Util', function () {
it('single line', async () => {
const patch =
- // eslint-disable-next-line no-template-curly-in-string
'@@ -17,7 +17,7 @@ class MainActivity : AppCompatActivity() {\n val userId = \\"admin\\"\n val model: MainViewModel by viewModels()\n Log.d(\\"App\\", \\"Validate = ${model.validate(userId)}\\")\n- Log.d(\\"App\\", \\"Verify Access = ${model.verifyAccess(userId)}\\")\n+ Log.d(\\"App\\", \\"Verify Access = ${model.verifyAccess1(userId)}\\")\n \n // Math module\n val arithmetic = Arithmetic()'
const changedLines = util.getChangedLines(patch)
expect(changedLines).toEqual([20])
@@ -42,7 +40,6 @@ describe('Util', function () {
it('full new file', async () => {
const patch =
- // eslint-disable-next-line no-template-curly-in-string
'@@ -0,0 +1,8 @@\n+package com.madrapps.playground.events\n+\n+class OnClickEvent {\n+\n+ fun onClick() {\n+ // do nothing\n+ }\n+}\n\\\\ No newline at end of file'
const changedLines = util.getChangedLines(patch)
expect(changedLines).toEqual([1, 2, 3, 4, 5, 6, 7, 8])
@@ -50,7 +47,6 @@ describe('Util', function () {
it('different groups', async () => {
const patch =
- // eslint-disable-next-line no-template-curly-in-string
'@@ -3,7 +3,7 @@\n /**\n * String related operation\n */\n-public class StringOp implements StringOperation {\n+public class StringOp implements IStringOperation {\n \n @Override\n public boolean endsWith(String source, String chars) {\n@@ -14,4 +14,9 @@ public boolean endsWith(String source, String chars) {\n public boolean startsWith(String source, String chars) {\n return source.startsWith(chars);\n }\n+\n+ @Override\n+ public boolean replace(String from, String to) {\n+ return false;\n+ }\n }'
const changedLines = util.getChangedLines(patch)
expect(changedLines).toEqual([6, 17, 18, 19, 20, 21])
@@ -64,144 +60,177 @@ describe('Util', function () {
const files = util.getFilesWithCoverage(packages)
expect(files).toEqual([
{
- class: { covered: 1, missed: 0 },
- complexity: { covered: 3, missed: 8 },
- instruction: { covered: 11, missed: 50 },
- line: { covered: 3, missed: 8 },
- lines: {
- 3: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 3, missed: 0 },
- },
- 6: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 4 },
- },
- 10: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 4, missed: 0 },
- },
- 14: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 4, missed: 0 },
- },
- 18: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 4 },
- },
- 22: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 4 },
- },
- 26: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 4 },
- },
- 30: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 6 },
- },
- 34: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 8 },
- },
- 38: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 10 },
- },
- 42: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 10 },
- },
- },
- method: { covered: 3, missed: 8 },
+ counters: [
+ {covered: 11, missed: 50, name: 'instruction'},
+ {covered: 3, missed: 8, name: 'line'},
+ {covered: 3, missed: 8, name: 'complexity'},
+ {covered: 3, missed: 8, name: 'method'},
+ {covered: 1, missed: 0, name: 'class'},
+ ],
+ lines: [
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 3, missed: 0},
+ number: 3,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 4},
+ number: 6,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 4, missed: 0},
+ number: 10,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 4, missed: 0},
+ number: 14,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 4},
+ number: 18,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 4},
+ number: 22,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 4},
+ number: 26,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 6},
+ number: 30,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 8},
+ number: 34,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 10},
+ number: 38,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 10},
+ number: 42,
+ },
+ ],
name: 'Utility.java',
packageName: 'com/madrapps/jacoco',
},
{
- branch: { covered: 2, missed: 4 },
- class: { covered: 1, missed: 0 },
- complexity: { covered: 4, missed: 7 },
- instruction: { covered: 21, missed: 29 },
- line: { covered: 6, missed: 7 },
- lines: {
- 3: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 3, missed: 0 },
- },
- 6: {
- branch: { covered: 1, missed: 1 },
- instruction: { covered: 3, missed: 0 },
- },
- 9: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 4, missed: 0 },
- },
- 13: {
- branch: { covered: 0, missed: 2 },
- instruction: { covered: 0, missed: 3 },
- },
- 14: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 4 },
- },
- 16: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 4 },
- },
- 22: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 4, missed: 0 },
- },
- 26: {
- branch: { covered: 1, missed: 1 },
- instruction: { covered: 3, missed: 0 },
- },
- 27: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 4, missed: 0 },
- },
- 29: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 4 },
- },
- 35: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 4 },
- },
- 39: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 4 },
- },
- 43: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 0, missed: 6 },
- },
- },
- method: { covered: 4, missed: 4 },
+ counters: [
+ {covered: 21, missed: 29, name: 'instruction'},
+ {covered: 2, missed: 4, name: 'branch'},
+ {covered: 6, missed: 7, name: 'line'},
+ {covered: 4, missed: 7, name: 'complexity'},
+ {covered: 4, missed: 4, name: 'method'},
+ {covered: 1, missed: 0, name: 'class'},
+ ],
+ lines: [
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 3, missed: 0},
+ number: 3,
+ },
+ {
+ branch: {covered: 1, missed: 1},
+ instruction: {covered: 3, missed: 0},
+ number: 6,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 4, missed: 0},
+ number: 9,
+ },
+ {
+ branch: {covered: 0, missed: 2},
+ instruction: {covered: 0, missed: 3},
+ number: 13,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 4},
+ number: 14,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 4},
+ number: 16,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 4, missed: 0},
+ number: 22,
+ },
+ {
+ branch: {covered: 1, missed: 1},
+ instruction: {covered: 3, missed: 0},
+ number: 26,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 4, missed: 0},
+ number: 27,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 4},
+ number: 29,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 4},
+ number: 35,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 4},
+ number: 39,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 0, missed: 6},
+ number: 43,
+ },
+ ],
name: 'Math.kt',
packageName: 'com/madrapps/jacoco',
},
{
- class: { covered: 1, missed: 0 },
- complexity: { covered: 3, missed: 0 },
- instruction: { covered: 11, missed: 0 },
- line: { covered: 3, missed: 0 },
- lines: {
- 3: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 3, missed: 0 },
- },
- 12: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 4, missed: 0 },
- },
- 17: {
- branch: { covered: 0, missed: 0 },
- instruction: { covered: 4, missed: 0 },
- },
- },
- method: { covered: 3, missed: 0 },
+ counters: [
+ {covered: 11, missed: 0, name: 'instruction'},
+ {covered: 3, missed: 0, name: 'line'},
+ {covered: 3, missed: 0, name: 'complexity'},
+ {covered: 3, missed: 0, name: 'method'},
+ {covered: 1, missed: 0, name: 'class'},
+ ],
+ lines: [
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 3, missed: 0},
+ number: 3,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 4, missed: 0},
+ number: 12,
+ },
+ {
+ branch: {covered: 0, missed: 0},
+ instruction: {covered: 4, missed: 0},
+ number: 17,
+ },
+ ],
name: 'StringOp.java',
packageName: 'com/madrapps/jacoco/operation',
},
@@ -210,13 +239,14 @@ describe('Util', function () {
})
})
-async function getSingleReport() {
+/* eslint-disable @typescript-eslint/no-explicit-any */
+async function getSingleReport(): Promise {
const reportPath = './__tests__/__fixtures__/report.xml'
const report = await getReport(reportPath)
return [report]
}
-async function getReport(path) {
+async function getReport(path: string): Promise {
const reportXml = await fs.promises.readFile(path, 'utf-8')
const json = await parser.parseStringPromise(reportXml)
return json['report']
diff --git a/dist/build/Release/node_expat.node b/dist/build/Release/node_expat.node
deleted file mode 100755
index 8c69428aea7512498cbb3d9c577f4c768f9080b1..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 205732
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