Commit 5151b8ce by Dominik Prokop Committed by Ryan McKinley

grafana/toolkit: test improvements and show stats (#18137, #18138)

* Enable running tests in watch mode and by path or name regex

* Toolkit readme update

* Show webpack stats on successful compilation

* unzip the plugin, not the docs
parent 75fa1f02
...@@ -35,6 +35,9 @@ Runs Jest against your codebase. See [Tests](#tests) for more details. ...@@ -35,6 +35,9 @@ Runs Jest against your codebase. See [Tests](#tests) for more details.
Available options: Available options:
- `-u, --updateSnapshot` - performs snapshots update - `-u, --updateSnapshot` - performs snapshots update
- `--coverage` - reports code coverage - `--coverage` - reports code coverage
- `--watch` - runs tests in interactive watch mode
- `--testNamePattern=<regex>` - runs test with names that match provided regex (https://jestjs.io/docs/en/cli#testnamepattern-regex)
- `--testPathPattern=<regex>` - runs test with paths that match provided regex (https://jestjs.io/docs/en/cli#testpathpattern-regex)
#### `grafana-toolkit plugin:dev` #### `grafana-toolkit plugin:dev`
Compiles plugin in development mode. Compiles plugin in development mode.
......
...@@ -139,11 +139,17 @@ export const run = (includeInternalScripts = false) => { ...@@ -139,11 +139,17 @@ export const run = (includeInternalScripts = false) => {
.command('plugin:test') .command('plugin:test')
.option('-u, --updateSnapshot', 'Run snapshots update') .option('-u, --updateSnapshot', 'Run snapshots update')
.option('--coverage', 'Run code coverage') .option('--coverage', 'Run code coverage')
.option('--watch', 'Run tests in interactive watch mode')
.option('--testPathPattern <regex>', 'Run only tests with a path that matches the regex')
.option('--testNamePattern <regex>', 'Run only tests with a name that matches the regex')
.description('Executes plugin tests') .description('Executes plugin tests')
.action(async cmd => { .action(async cmd => {
await execTask(pluginTestTask)({ await execTask(pluginTestTask)({
updateSnapshot: !!cmd.updateSnapshot, updateSnapshot: !!cmd.updateSnapshot,
coverage: !!cmd.coverage, coverage: !!cmd.coverage,
watch: !!cmd.watch,
testPathPattern: cmd.testPathPattern,
testNamePattern: cmd.testNamePattern,
}); });
}); });
......
...@@ -158,9 +158,8 @@ export const pluginBuildRunner: TaskRunner<PluginBuildOptions> = async ({ covera ...@@ -158,9 +158,8 @@ export const pluginBuildRunner: TaskRunner<PluginBuildOptions> = async ({ covera
await clean(); await clean();
await prepare(); await prepare();
await prettierCheckPlugin({ fix: false }); await prettierCheckPlugin({ fix: false });
// @ts-ignore
await lintPlugin({ fix: false }); await lintPlugin({ fix: false });
await testPlugin({ updateSnapshot: false, coverage }); await testPlugin({ updateSnapshot: false, coverage, watch: false });
await bundlePlugin({ watch: false, production: true }); await bundlePlugin({ watch: false, production: true });
}; };
......
...@@ -229,8 +229,14 @@ const bundlePluginRunner: TaskRunner<PluginCIOptions> = async () => { ...@@ -229,8 +229,14 @@ const bundlePluginRunner: TaskRunner<PluginCIOptions> = async () => {
console.warn('Unable to read SHA1 Checksum'); console.warn('Unable to read SHA1 Checksum');
} }
console.log('Setup Grafan Environment');
let p = path.resolve(grafanaEnvDir, 'plugins', pluginInfo.id);
fs.mkdirSync(p, { recursive: true });
await execa('unzip', [zipFile, '-d', p]);
// If docs exist, zip them into artifacts // If docs exist, zip them into artifacts
if (fs.existsSync(docsDir)) { if (fs.existsSync(docsDir)) {
console.log('Creating documentation zip');
zipName = pluginInfo.id + '-' + pluginInfo.info.version + '-docs.zip'; zipName = pluginInfo.id + '-' + pluginInfo.info.version + '-docs.zip';
zipFile = path.resolve(artifactsDir, zipName); zipFile = path.resolve(artifactsDir, zipName);
process.chdir(docsDir); process.chdir(docsDir);
...@@ -254,18 +260,13 @@ const bundlePluginRunner: TaskRunner<PluginCIOptions> = async () => { ...@@ -254,18 +260,13 @@ const bundlePluginRunner: TaskRunner<PluginCIOptions> = async () => {
info.docs = zipInfo; info.docs = zipInfo;
} }
let p = path.resolve(artifactsDir, 'info.json'); p = path.resolve(artifactsDir, 'info.json');
fs.writeFile(p, JSON.stringify(info, null, 2), err => { fs.writeFile(p, JSON.stringify(info, null, 2), err => {
if (err) { if (err) {
throw new Error('Error writing artifact info: ' + p); throw new Error('Error writing artifact info: ' + p);
} }
}); });
console.log('Setup Grafan Environment');
p = path.resolve(grafanaEnvDir, 'plugins', pluginInfo.id);
fs.mkdirSync(p, { recursive: true });
await execa('unzip', [zipFile, '-d', p]);
// Write the custom settings // Write the custom settings
p = path.resolve(grafanaEnvDir, 'custom.ini'); p = path.resolve(grafanaEnvDir, 'custom.ini');
const customIniBody = const customIniBody =
......
...@@ -33,12 +33,14 @@ export const bundlePlugin = async ({ watch, production }: PluginBundleOptions) = ...@@ -33,12 +33,14 @@ export const bundlePlugin = async ({ watch, production }: PluginBundleOptions) =
const output = formatWebpackMessages(stats.toJson()); const output = formatWebpackMessages(stats.toJson());
if (!output.errors.length && !output.warnings.length) { if (!output.errors.length && !output.warnings.length) {
console.log('Compiled successfully!'); console.log('Compiled successfully!\n');
console.log(stats.toString({ colors: true }));
} }
if (output.errors.length) { if (output.errors.length) {
console.log('Compilation failed!'); console.log('Compilation failed!');
output.errors.forEach(e => console.log(e)); output.errors.forEach(e => console.log(e));
if (output.warnings.length) { if (output.warnings.length) {
console.log('Warnings:'); console.log('Warnings:');
output.warnings.forEach(w => console.log(w)); output.warnings.forEach(w => console.log(w));
...@@ -61,6 +63,7 @@ export const bundlePlugin = async ({ watch, production }: PluginBundleOptions) = ...@@ -61,6 +63,7 @@ export const bundlePlugin = async ({ watch, production }: PluginBundleOptions) =
reject('Build failed'); reject('Build failed');
} }
console.log('\n', stats.toString({ colors: true }), '\n');
resolve(); resolve();
}); });
} }
......
...@@ -5,22 +5,38 @@ import { jestConfig } from '../../../config/jest.plugin.config'; ...@@ -5,22 +5,38 @@ import { jestConfig } from '../../../config/jest.plugin.config';
export interface PluginTestOptions { export interface PluginTestOptions {
updateSnapshot: boolean; updateSnapshot: boolean;
coverage: boolean; coverage: boolean;
watch: boolean;
testPathPattern?: string;
testNamePattern?: string;
} }
export const testPlugin = useSpinner<PluginTestOptions>('Running tests', async ({ updateSnapshot, coverage }) => { export const testPlugin = useSpinner<PluginTestOptions>(
'Running tests',
async ({ updateSnapshot, coverage, watch, testPathPattern, testNamePattern }) => {
const testConfig = jestConfig(); const testConfig = jestConfig();
const cliConfig = { const cliConfig = {
config: JSON.stringify(testConfig), config: JSON.stringify(testConfig),
updateSnapshot, updateSnapshot,
coverage, coverage,
watch,
testPathPattern: testPathPattern ? [testPathPattern] : [],
testNamePattern: testNamePattern ? [testNamePattern] : [],
passWithNoTests: true, passWithNoTests: true,
}; };
// @ts-ignore // @ts-ignore
const results = await jestCLI.runCLI(cliConfig, [process.cwd()]); const runJest = () => jestCLI.runCLI(cliConfig, [process.cwd()]);
if (watch) {
runJest();
} else {
// @ts-ignore
const results = await runJest();
if (results.results.numFailedTests > 0 || results.results.numFailedTestSuites > 0) { if (results.results.numFailedTests > 0 || results.results.numFailedTestSuites > 0) {
throw new Error('Tests failed'); throw new Error('Tests failed');
} }
}); }
}
);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment