Skip to content
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

test: add type script plugin e2e #974

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
12 changes: 12 additions & 0 deletions e2e/plugin-typescript-e2e/eslint.config.js
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,22 @@
import type { CoreConfig } from '@code-pushup/models';
import {
getCategoryRefsFromGroups,
typescriptPlugin,
} from '@code-pushup/typescript-plugin';

export default {
plugins: [
await typescriptPlugin({
tsConfigPath: 'tsconfig.json',
}),
],
categories: [
{
slug: 'typescript-quality',
title: 'Typescript',
refs: await getCategoryRefsFromGroups({
tsConfigPath: 'tsconfig.json',
}),
},
],
} satisfies CoreConfig;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function test() {
return 'test';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
const a = { ; // Error: TS1136: Property assignment expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// 2683 - NoImplicitThis: 'this' implicitly has type 'any'.
function noImplicitThisTS2683() {
console.log(this.value); // Error 2683
}

// 2531 - StrictNullChecks: Object is possibly 'null'.
const strictNullChecksTS2531: string = null;
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Standalone {
override method() { // Error: TS4114 - 'override' modifier can only be used in a class derived from a base class.
console.log("Standalone method");
}
}
const s = Standalone;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { test } from '../exclude/utils';

// TS6059:: File 'exclude/utils.ts' is not under 'rootDir' '.../configuration-errors'. 'rootDir' is expected to contain all source files.
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"compilerOptions": {
"rootDir": "./src",
"target": "ES6",
"module": "CommonJS",
"strict": true,
"verbatimModuleSyntax": false
},
"include": ["src/**/*.ts"]
}
23 changes: 23 additions & 0 deletions e2e/plugin-typescript-e2e/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "plugin-typescript-e2e",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "e2e/plugin-typescript-e2e/src",
"projectType": "application",
"targets": {
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["e2e/plugin-typescript-e2e/**/*.ts"]
}
},
"e2e": {
"executor": "@nx/vite:test",
"options": {
"configFile": "e2e/plugin-typescript-e2e/vite.config.e2e.ts"
}
}
},
"implicitDependencies": ["cli", "plugin-typescript"],
"tags": ["scope:plugin", "type:e2e"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
{
"categories": [
{
"refs": [
{
"plugin": "typescript",
"slug": "problems",
"type": "group",
"weight": 1,
},
{
"plugin": "typescript",
"slug": "ts-configuration",
"type": "group",
"weight": 1,
},
{
"plugin": "typescript",
"slug": "miscellaneous",
"type": "group",
"weight": 1,
},
],
"slug": "typescript-quality",
"title": "Typescript",
},
],
"packageName": "@code-pushup/core",
"plugins": [
{
"audits": [
{
"description": "Errors that occur during parsing and lexing of TypeScript source code",
"slug": "syntax-errors",
"title": "Syntax errors",
},
{
"description": "Errors that occur during type checking and type inference",
"slug": "semantic-errors",
"title": "Semantic errors",
},
{
"description": "Errors that occur during TypeScript language service operations",
"slug": "declaration-and-language-service-errors",
"title": "Declaration and language service errors",
},
{
"description": "Errors that occur during TypeScript internal operations",
"slug": "internal-errors",
"title": "Internal errors",
},
{
"description": "Errors that occur when parsing TypeScript configuration files",
"slug": "configuration-errors",
"title": "Configuration errors",
},
{
"description": "Errors related to no implicit any compiler option",
"slug": "no-implicit-any-errors",
"title": "No implicit any errors",
},
{
"description": "Errors that do not match any known TypeScript error code",
"slug": "unknown-codes",
"title": "Unknown codes",
},
],
"description": "Official Code PushUp Typescript plugin.",
"docsUrl": "https://www.npmjs.com/package/@code-pushup/typescript-plugin/",
"groups": [
{
"description": "Syntax, semantic, and internal compiler errors are critical for identifying and preventing bugs.",
"refs": [
{
"slug": "syntax-errors",
"weight": 1,
},
{
"slug": "semantic-errors",
"weight": 1,
},
{
"slug": "no-implicit-any-errors",
"weight": 1,
},
],
"slug": "problems",
"title": "Problems",
},
{
"description": "TypeScript configuration and options errors ensure correct project setup, reducing risks from misconfiguration.",
"refs": [
{
"slug": "configuration-errors",
"weight": 1,
},
],
"slug": "ts-configuration",
"title": "Configuration",
},
{
"description": "Errors that do not bring any specific value to the developer, but are still useful to know.",
"refs": [
{
"slug": "unknown-codes",
"weight": 1,
},
{
"slug": "internal-errors",
"weight": 1,
},
{
"slug": "declaration-and-language-service-errors",
"weight": 1,
},
],
"slug": "miscellaneous",
"title": "Miscellaneous",
},
],
"icon": "typescript",
"packageName": "@code-pushup/typescript-plugin",
"slug": "typescript",
"title": "Typescript",
},
],
}
76 changes: 76 additions & 0 deletions e2e/plugin-typescript-e2e/tests/collect.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { cp } from 'node:fs/promises';
// eslint-disable-next-line unicorn/import-style
import path, { join } from 'node:path';
import { afterAll, beforeAll, expect } from 'vitest';
import { type Report, reportSchema } from '@code-pushup/models';
import { nxTargetProject } from '@code-pushup/test-nx-utils';
import {
E2E_ENVIRONMENTS_DIR,
TEST_OUTPUT_DIR,
omitVariableReportData,
removeColorCodes,
teardownTestFolder,
} from '@code-pushup/test-utils';
import { executeProcess, readJsonFile } from '@code-pushup/utils';

describe('PLUGIN collect report with typescript-plugin NPM package', () => {
const envRoot = join(E2E_ENVIRONMENTS_DIR, nxTargetProject());
const distRoot = join(envRoot, TEST_OUTPUT_DIR);

const fixturesDir = join(
'e2e',
nxTargetProject(),
'mocks',
'fixtures',
'default-setup',
);

beforeAll(async () => {
await cp(fixturesDir, envRoot, { recursive: true });
});

afterAll(async () => {
await teardownTestFolder(distRoot);
});

it('should run plugin over CLI and creates report.json', async () => {
const outputDir = join(
path.relative(envRoot, distRoot),
'create-report',
'.code-pushup',
);

const { code, stdout } = await executeProcess({
command: 'npx',
// verbose exposes audits with perfect scores that are hidden in the default stdout
args: [
'@code-pushup/cli',
'collect',
'--no-progress',
'--verbose',
`--persist.outputDir=${outputDir}`,
],
cwd: envRoot,
});

expect(code).toBe(0);
const cleanStdout = removeColorCodes(stdout);

expect(cleanStdout).toMatch(/● Semantic errors\s+\d+ issue/);
expect(cleanStdout).toMatch(/● Configuration errors\s+\d+ issue/);
expect(cleanStdout).toMatch(
/● Declaration and language service errors\s+\d+ issue/,
);
expect(cleanStdout).toMatch(/● Syntax errors\s+\d+ issue/);
expect(cleanStdout).toMatch(/● Internal errors\s+\d+ issue/);
expect(cleanStdout).toMatch(/● No implicit any errors\s+\d+ issue/);

const reportJson = await readJsonFile<Report>(
join(envRoot, outputDir, 'report.json'),
);
expect(() => reportSchema.parse(reportJson)).not.toThrow();
expect(
omitVariableReportData(reportJson, { omitAuditData: true }),
).toMatchFileSnapshot('__snapshots__/typescript-plugin-json-report.json');
});
});
20 changes: 20 additions & 0 deletions e2e/plugin-typescript-e2e/tsconfig.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"
}
]
}
14 changes: 14 additions & 0 deletions e2e/plugin-typescript-e2e/tsconfig.test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["vitest/globals", "vitest/importMeta", "vite/client", "node"],
"target": "ES2020"
},
"include": [
"vite.config.e2e.ts",
"tests/**/*.e2e.test.ts",
"tests/**/*.d.ts",
"mocks/**/*.ts"
]
}
33 changes: 33 additions & 0 deletions e2e/plugin-typescript-e2e/vite.config.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/// <reference types="vitest" />
import { defineConfig } from 'vite';
import { tsconfigPathAliases } from '../../tools/vitest-tsconfig-path-aliases.js';

export default defineConfig({
cacheDir: '../../node_modules/.vite/plugin-typescript-e2e',
resolve: {
alias: {
'@code-pushup/test-nx-utils': '../../test-nx-utils/index.js',
'@code-pushup/test-setup': '../../test-setup/index.js',
'@code-pushup/test-utils': '../../test-utils/index.js',
},
},
test: {
reporters: ['basic'],
testTimeout: 120_000,
globals: true,
alias: tsconfigPathAliases(),
pool: 'threads',
poolOptions: { threads: { singleThread: true } },
coverage: {
reporter: ['text', 'lcov'],
reportsDirectory: '../../coverage/plugin-typescript-e2e/e2e-tests',
exclude: ['mocks/**', '**/types.ts'],
},
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'],
},
});
2 changes: 1 addition & 1 deletion packages/plugin-typescript/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export { TYPESCRIPT_PLUGIN_SLUG } from './lib/constants.js';
export { typescriptPlugin } from './lib/typescript-plugin.js';
export { getCategories } from './lib/utils.js';
export { getCategories, getCategoryRefsFromGroups } from './lib/utils.js';
export {
type TypescriptPluginConfig,
type TypescriptPluginOptions,
Expand Down