-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(plugin-doc-coverage): add doc-coverage-plugin to analyze documentation in ts/js projects #896
base: main
Are you sure you want to change the base?
Changes from all commits
bf1775d
b07eb8a
0de6d3f
164a86a
3fe6e3b
40c8daa
47486c8
f21fbe2
4fb478e
feefa0a
1a5a614
8909855
b8cdf77
24ab2e0
6c83208
8c2d274
a70c03b
6be3803
2f29728
adec386
47cff4b
c644029
09d9eb0
3901955
11ad4bb
19d43a5
49e5b56
54d1621
b3105ae
89893a0
97d32bf
79b6a02
fd3bd5e
0ecc193
7e0acbd
24468cc
ef77df0
b09aa57
b9f5333
6f0f19c
6634f3c
5fc371c
b609608
2dbdb7d
da133e9
7a80f85
12e3f4e
c9443a0
ac83605
1107ae4
7fc7c2e
b7a42c7
206340e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -5,6 +5,14 @@ import type { | |||||||||||||||||||||||||||||||||
import coveragePlugin, { | ||||||||||||||||||||||||||||||||||
getNxCoveragePaths, | ||||||||||||||||||||||||||||||||||
} from './packages/plugin-coverage/src/index.js'; | ||||||||||||||||||||||||||||||||||
import docCoveragePlugin, { | ||||||||||||||||||||||||||||||||||
DocCoveragePluginConfig, | ||||||||||||||||||||||||||||||||||
} from './packages/plugin-doc-coverage/src/index.js'; | ||||||||||||||||||||||||||||||||||
import { | ||||||||||||||||||||||||||||||||||
PLUGIN_SLUG, | ||||||||||||||||||||||||||||||||||
groups, | ||||||||||||||||||||||||||||||||||
} from './packages/plugin-doc-coverage/src/lib/constants.js'; | ||||||||||||||||||||||||||||||||||
import { filterGroupsByOnlyAudits } from './packages/plugin-doc-coverage/src/lib/utils.js'; | ||||||||||||||||||||||||||||||||||
import eslintPlugin, { | ||||||||||||||||||||||||||||||||||
eslintConfigFromAllNxProjects, | ||||||||||||||||||||||||||||||||||
eslintConfigFromNxProject, | ||||||||||||||||||||||||||||||||||
|
@@ -82,6 +90,24 @@ export const eslintCategories: CategoryConfig[] = [ | |||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||
]; | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
export function getDocCoverageCategories( | ||||||||||||||||||||||||||||||||||
config: DocCoveragePluginConfig, | ||||||||||||||||||||||||||||||||||
): CategoryConfig[] { | ||||||||||||||||||||||||||||||||||
return [ | ||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||
slug: 'doc-coverage-cat', | ||||||||||||||||||||||||||||||||||
title: 'Documentation coverage', | ||||||||||||||||||||||||||||||||||
Comment on lines
+98
to
+99
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't use a Also, it's best for category names to be as short as possible, since they are very high-level. How about just
Suggested change
|
||||||||||||||||||||||||||||||||||
description: 'Measures how much of your code is **documented**.', | ||||||||||||||||||||||||||||||||||
refs: filterGroupsByOnlyAudits(groups, config).map(group => ({ | ||||||||||||||||||||||||||||||||||
weight: 1, | ||||||||||||||||||||||||||||||||||
type: 'group', | ||||||||||||||||||||||||||||||||||
plugin: PLUGIN_SLUG, | ||||||||||||||||||||||||||||||||||
slug: group.slug, | ||||||||||||||||||||||||||||||||||
})), | ||||||||||||||||||||||||||||||||||
}, | ||||||||||||||||||||||||||||||||||
]; | ||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
export const coverageCategories: CategoryConfig[] = [ | ||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||
slug: 'code-coverage', | ||||||||||||||||||||||||||||||||||
|
@@ -114,6 +140,15 @@ export const lighthouseCoreConfig = async ( | |||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
export const docCoverageCoreConfig = async ( | ||||||||||||||||||||||||||||||||||
config: DocCoveragePluginConfig, | ||||||||||||||||||||||||||||||||||
): Promise<CoreConfig> => { | ||||||||||||||||||||||||||||||||||
return { | ||||||||||||||||||||||||||||||||||
plugins: [docCoveragePlugin(config)], | ||||||||||||||||||||||||||||||||||
categories: getDocCoverageCategories(config), | ||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||
Comment on lines
+143
to
+150
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't need to be
Suggested change
|
||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||
export const eslintCoreConfigNx = async ( | ||||||||||||||||||||||||||||||||||
projectName?: string, | ||||||||||||||||||||||||||||||||||
): Promise<CoreConfig> => { | ||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import tseslint from 'typescript-eslint'; | ||
import baseConfig from '../../eslint.config.js'; | ||
|
||
export default tseslint.config(...baseConfig, { | ||
files: ['**/*.ts'], | ||
languageOptions: { | ||
parserOptions: { | ||
projectService: true, | ||
tsconfigRootDir: import.meta.dirname, | ||
}, | ||
}, | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import docCoveragePlugin from '@code-pushup/doc-coverage-plugin'; | ||
|
||
export default { | ||
plugins: [await docCoveragePlugin({ sourceGlob: ['**/*.ts'] })], | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
h1 { | ||
color: #336699; | ||
text-align: center; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
<h1>{{ title }}</h1> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
function notRealisticFunction() { | ||
return 'notRealisticFunction'; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/** | ||
* Basic Angular component that displays a welcome message | ||
*/ | ||
export class AppComponent { | ||
protected readonly title = 'My Angular App'; | ||
|
||
/** | ||
* Dummy method that returns a welcome message | ||
* @returns {string} - The welcome message | ||
*/ | ||
getWelcomeMessage() { | ||
return 'Welcome to My Angular App!'; | ||
} | ||
|
||
sendEvent() { | ||
return 'Event sent'; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
export const someVariable = 'Hello World 1'; | ||
|
||
export function mapEventToCustomEvent(event: string) { | ||
return event; | ||
} | ||
|
||
/** Commented */ | ||
export function mapCustomEventToEvent(event: string) { | ||
return event; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import docCoveragePlugin from '@code-pushup/doc-coverage-plugin'; | ||
|
||
export default { | ||
plugins: [await docCoveragePlugin({ sourceGlob: ['**/*.ts'] })], | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
function MyComponent() { | ||
return ( | ||
<div> | ||
<h1>Hello World</h1> | ||
<p>This is a basic React component</p> | ||
</div> | ||
); | ||
} | ||
|
||
export default MyComponent; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"name": "plugin-doc-coverage-e2e", | ||
"$schema": "../../node_modules/nx/schemas/project-schema.json", | ||
"sourceRoot": "e2e/plugin-doc-coverage-e2e/src", | ||
"projectType": "application", | ||
"targets": { | ||
"lint": { | ||
"executor": "@nx/linter:eslint", | ||
"outputs": ["{options.outputFile}"], | ||
"options": { | ||
"lintFilePatterns": ["e2e/plugin-doc-coverage-e2e/**/*.ts"] | ||
} | ||
}, | ||
"e2e": { | ||
"executor": "@nx/vite:test", | ||
"options": { | ||
"configFile": "e2e/plugin-doc-coverage-e2e/vite.config.e2e.ts" | ||
} | ||
} | ||
}, | ||
"implicitDependencies": ["cli", "plugin-doc-coverage"], | ||
"tags": ["scope:plugin", "type:e2e"] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import { cp } from 'node:fs/promises'; | ||
import path from 'node:path'; | ||
import { afterAll, afterEach, beforeAll, describe, expect, it } from 'vitest'; | ||
import { type Report, reportSchema } from '@code-pushup/models'; | ||
import { nxTargetProject } from '@code-pushup/test-nx-utils'; | ||
import { teardownTestFolder } from '@code-pushup/test-setup'; | ||
import { | ||
E2E_ENVIRONMENTS_DIR, | ||
TEST_OUTPUT_DIR, | ||
omitVariableReportData, | ||
removeColorCodes, | ||
} from '@code-pushup/test-utils'; | ||
import { executeProcess, readJsonFile } from '@code-pushup/utils'; | ||
|
||
describe('PLUGIN collect report with doc-coverage-plugin NPM package', () => { | ||
const fixturesDir = path.join( | ||
'e2e', | ||
'plugin-doc-coverage-e2e', | ||
'mocks', | ||
'fixtures', | ||
); | ||
const fixturesAngularDir = path.join(fixturesDir, 'angular'); | ||
const fixturesReactDir = path.join(fixturesDir, 'react'); | ||
|
||
const envRoot = path.join( | ||
E2E_ENVIRONMENTS_DIR, | ||
nxTargetProject(), | ||
TEST_OUTPUT_DIR, | ||
); | ||
const angularDir = path.join(envRoot, 'angular'); | ||
const reactDir = path.join(envRoot, 'react'); | ||
const angularOutputDir = path.join(angularDir, '.code-pushup'); | ||
const reactOutputDir = path.join(reactDir, '.code-pushup'); | ||
|
||
beforeAll(async () => { | ||
await cp(fixturesAngularDir, angularDir, { recursive: true }); | ||
await cp(fixturesReactDir, reactDir, { recursive: true }); | ||
}); | ||
|
||
afterAll(async () => { | ||
await teardownTestFolder(angularDir); | ||
await teardownTestFolder(reactDir); | ||
}); | ||
|
||
afterEach(async () => { | ||
await teardownTestFolder(angularOutputDir); | ||
await teardownTestFolder(reactOutputDir); | ||
}); | ||
|
||
it('should run Doc Coverage plugin for Angular example dir and create report.json', async () => { | ||
const { code, stdout } = await executeProcess({ | ||
command: 'npx', | ||
args: ['@code-pushup/cli', 'collect', '--no-progress'], | ||
cwd: angularDir, | ||
}); | ||
|
||
expect(code).toBe(0); | ||
|
||
expect(removeColorCodes(stdout)).toMatchFileSnapshot( | ||
'__snapshots__/report.txt', | ||
); | ||
|
||
const report = await readJsonFile( | ||
path.join(angularOutputDir, 'report.json'), | ||
); | ||
|
||
expect(() => reportSchema.parse(report)).not.toThrow(); | ||
expect( | ||
JSON.stringify(omitVariableReportData(report as Report), null, 2), | ||
).toMatchFileSnapshot('__snapshots__/report.json'); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"extends": "../../tsconfig.base.json", | ||
"compilerOptions": { | ||
"module": "ESNext", | ||
"forceConsistentCasingInFileNames": true, | ||
"strict": true, | ||
"noImplicitOverride": true, | ||
"noPropertyAccessFromIndexSignature": true, | ||
"noImplicitReturns": true, | ||
"noFallthroughCasesInSwitch": true, | ||
"types": ["vitest"] | ||
}, | ||
"files": [], | ||
"include": [], | ||
"references": [ | ||
{ | ||
"path": "./tsconfig.test.json" | ||
} | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"extends": "./tsconfig.json", | ||
"compilerOptions": { | ||
"outDir": "../../dist/out-tsc", | ||
"types": ["vitest/globals", "vitest/importMeta", "vite/client", "node"], | ||
"target": "ES2020" | ||
}, | ||
"exclude": ["__test-env__/**"], | ||
"include": [ | ||
"vite.config.e2e.ts", | ||
"tests/**/*.e2e.test.ts", | ||
"tests/**/*.d.ts", | ||
"mocks/**/*.ts" | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/// <reference types="vitest" /> | ||
import { defineConfig } from 'vite'; | ||
import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js'; | ||
|
||
export default defineConfig({ | ||
cacheDir: '../../node_modules/.vite/plugin-doc-coverage-e2e', | ||
test: { | ||
reporters: ['basic'], | ||
testTimeout: 120_000, | ||
globals: true, | ||
alias: tsconfigPathAliases(), | ||
pool: 'threads', | ||
poolOptions: { threads: { singleThread: true } }, | ||
cache: { | ||
dir: '../../node_modules/.vitest', | ||
}, | ||
environment: 'node', | ||
include: ['tests/**/*.e2e.test.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], | ||
setupFiles: ['../../testing/test-setup/src/lib/reset.mocks.ts'], | ||
}, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ESLint plugin has a similar parameter called
patterns
, would be nice to have consistent naming.Since I'm guessing only these globs are needed for most usages, the plugin parameter could also enable a shorthand (again, similar to ESLint plugin):