Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/kbn-docs-utils/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,11 @@ module.exports = {
preset: '@kbn/test',
rootDir: '../..',
roots: ['<rootDir>/packages/kbn-docs-utils'],
coverageDirectory: '<rootDir>/target/kibana-coverage/jest/packages/kbn-docs-utils',
coverageReporters: ['text', 'html'],
collectCoverageFrom: [
'<rootDir>/packages/kbn-docs-utils/src/**/*.{ts,tsx}',
'!<rootDir>/packages/kbn-docs-utils/src/**/*.test.ts',
'!<rootDir>/packages/kbn-docs-utils/src/**/__fixtures__/**',
],
};
6 changes: 6 additions & 0 deletions packages/kbn-docs-utils/jest.integration.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,10 @@ module.exports = {
preset: '@kbn/test/jest_integration_node',
rootDir: '../..',
roots: ['<rootDir>/packages/kbn-docs-utils'],
coverageDirectory: '<rootDir>/target/kibana-coverage/jest/packages/kbn-docs-utils',
coverageReporters: ['text', 'html'],
collectCoverageFrom: [
'<rootDir>/packages/kbn-docs-utils/src/**/*.{ts,tsx}',
'!<rootDir>/packages/kbn-docs-utils/src/**/*.test.ts',
],
};
115 changes: 115 additions & 0 deletions packages/kbn-docs-utils/scripts/update_fixture_comments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

const fs = require('node:fs');
const path = require('node:path');

const categories = [
{ key: 'missingComments', title: 'missing comments' },
{ key: 'isAnyType', title: 'any usage' },
{ key: 'noReferences', title: 'no references' },
];

/**
* Reads stats from the snapshot JSON file.
*/
const readStatsFromSnapshot = () => {
const snapshotPath = path.resolve(
__dirname,
'../src/integration_tests/snapshots/plugin_a.stats.json'
);

if (!fs.existsSync(snapshotPath)) {
console.error(`Stats snapshot file not found: ${snapshotPath}`);
console.error('Run the integration tests first to generate the snapshot.');
process.exit(1);
}

return JSON.parse(fs.readFileSync(snapshotPath, 'utf8'));
};

const normalizePath = (statPath) =>
path.resolve(__dirname, '..', statPath.replace(/^packages\/kbn-docs-utils\//, ''));

const emptyCategories = () =>
categories.reduce((acc, { key }) => {
acc[key] = [];
return acc;
}, {});

const groupByFile = (stats) => {
const byFile = new Map();
categories.forEach(({ key }) => {
const entries = stats[key] || [];
entries.forEach((entry) => {
const absPath = normalizePath(entry.path);
if (!byFile.has(absPath)) byFile.set(absPath, emptyCategories());
byFile.get(absPath)[key].push(entry);
});
});
return byFile;
};

const formatCategory = (title, entries) => {
const count = entries.length;
const lines = [`// ${title} (${count}):`];
const sorted = [...entries].sort((a, b) => {
const lineA = a.lineNumber ?? Number.MAX_SAFE_INTEGER;
const lineB = b.lineNumber ?? Number.MAX_SAFE_INTEGER;
return lineA === lineB ? a.label.localeCompare(b.label) : lineA - lineB;
});
sorted.forEach((entry) => {
const lineInfo = entry.lineNumber != null ? `line ${entry.lineNumber}` : 'unknown line';
lines.push(`// ${lineInfo} - ${entry.label}`);
});
return lines.join('\n');
};

const buildBlock = (fileStats) => {
const parts = ['// Expected issues:'];
let added = false;
categories.forEach(({ key, title }) => {
const entries = fileStats[key] || [];
if (!entries.length) return;
parts.push(formatCategory(title, entries));
added = true;
});
if (!added) {
parts.push('// none');
}
return `${parts.join('\n')}\n`;
};

const replaceBlock = (content, block) => {
const marker = '// Expected issues:';
const idx = content.lastIndexOf(marker);
if (idx === -1) {
const trimmed = content.endsWith('\n') ? content : `${content}\n`;
return `${trimmed}${block}`;
}
return `${content.slice(0, idx)}${block}`;
};

const main = () => {
const stats = readStatsFromSnapshot();
const byFile = groupByFile(stats);

byFile.forEach((fileStats, absPath) => {
if (!fs.existsSync(absPath)) return;
const original = fs.readFileSync(absPath, 'utf8');
const block = buildBlock(fileStats);
const next = replaceBlock(original, block);
if (next !== original) {
fs.writeFileSync(absPath, next, 'utf8');
console.log(`Updated: ${absPath}`);
}
});
};

main();
108 changes: 108 additions & 0 deletions packages/kbn-docs-utils/src/__test_helpers__/mocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import type {
ApiDeclaration,
ApiReference,
ApiStats,
PluginApi,
PluginMetaInfo,
PluginOrPackage,
} from '../types';
import { TypeKind } from '../types';

/**
* Creates a mock `ApiDeclaration` for testing purposes.
*/
export const createMockApiDeclaration = (
overrides: Partial<ApiDeclaration> = {}
): ApiDeclaration => ({
id: 'testApi',
label: 'testApi',
type: TypeKind.FunctionKind,
path: 'src/plugins/test/public/index.ts',
parentPluginId: 'testPlugin',
...overrides,
});

/**
* Creates a mock `ApiReference` for testing purposes.
*/
export const createMockReference = (overrides: Partial<ApiReference> = {}): ApiReference => ({
plugin: 'referencingPlugin',
path: 'src/plugins/referencing/public/file.ts',
...overrides,
});

/**
* Creates a mock `PluginOrPackage` for testing purposes.
*/
export const createMockPlugin = (overrides: Partial<PluginOrPackage> = {}): PluginOrPackage => ({
id: 'testPlugin',
manifest: {
id: 'testPlugin',
description: 'A test plugin',
owner: { name: 'Test Team', githubTeam: 'test-team' },
serviceFolders: [],
},
isPlugin: true,
directory: 'src/plugins/test',
manifestPath: 'src/plugins/test/kibana.jsonc',
...overrides,
});

/**
* Creates a mock `ApiStats` for testing purposes.
*/
export const createMockPluginStats = (overrides: Partial<ApiStats> = {}): ApiStats => ({
apiCount: 10,
missingComments: [],
isAnyType: [],
noReferences: [],
missingExports: 0,
deprecatedAPIsReferencedCount: 0,
unreferencedDeprecatedApisCount: 0,
adoptionTrackedAPIs: [],
adoptionTrackedAPIsCount: 0,
adoptionTrackedAPIsUnreferencedCount: 0,
...overrides,
});

/**
* Creates a mock `PluginApi` for testing purposes.
*/
export const createMockPluginApi = (overrides: Partial<PluginApi> = {}): PluginApi => ({
id: 'testPlugin',
client: [],
server: [],
common: [],
...overrides,
});

/**
* Creates a mock `PluginMetaInfo` for testing purposes.
*/
export const createMockPluginMetaInfo = (
overrides: Partial<PluginMetaInfo> = {}
): PluginMetaInfo => ({
apiCount: 10,
missingComments: [],
isAnyType: [],
noReferences: [],
missingExports: 0,
deprecatedAPIsReferencedCount: 0,
unreferencedDeprecatedApisCount: 0,
adoptionTrackedAPIs: [],
adoptionTrackedAPIsCount: 0,
adoptionTrackedAPIsUnreferencedCount: 0,
owner: { name: 'Test Team', githubTeam: 'test-team' },
description: 'A test plugin',
isPlugin: true,
...overrides,
});
Loading