mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Plugin Generator] Add integration test (#43219)
Addresses https://github.com/elastic/kibana/issues/17061 ### Features Covered - generating a plugin #### Then from within the generated plugin's directory - running `yarn build` - running `yarn test:browser` - running `yarn test:server` - running `yarn start` - running `yarn preinstall` - running `yarn lint` - running `yarn kbn --help` - running `yarn es --help`
This commit is contained in:
parent
f31a53c1f4
commit
ef4a73a491
11 changed files with 223 additions and 50 deletions
|
@ -21,7 +21,7 @@ const { resolve } = require('path');
|
|||
|
||||
const { debug } = require('./debug');
|
||||
|
||||
const DEFAULT_PLUGIN_PATH = '../../kibana';
|
||||
const DEFAULT_PLUGIN_PATH = '../..';
|
||||
|
||||
/*
|
||||
* Resolves the path to Kibana, either from default setting or config
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/* eslint-disable no-restricted-syntax */
|
||||
import { spawn } from 'child_process';
|
||||
import { resolve } from 'path';
|
||||
import util from 'util';
|
||||
import { stat } from 'fs';
|
||||
import { snakeCase } from 'lodash';
|
||||
import del from 'del';
|
||||
import { withProcRunner, ToolingLog } from '@kbn/dev-utils';
|
||||
import { createEsTestCluster } from '@kbn/test';
|
||||
import execa from 'execa';
|
||||
|
||||
const statP = util.promisify(stat);
|
||||
const ROOT_DIR = resolve(__dirname, '../../../');
|
||||
const oneMinute = 60000;
|
||||
|
||||
describe(`running the plugin-generator via 'node scripts/generate_plugin.js plugin-name' with default config`, () => {
|
||||
const pluginName = 'ispec-plugin';
|
||||
const snakeCased = snakeCase(pluginName);
|
||||
const generatedPath = resolve(ROOT_DIR, `plugins/${snakeCased}`);
|
||||
const collect = xs => data => xs.push(data + ''); // Coerce from Buffer to String
|
||||
|
||||
beforeAll(() => {
|
||||
jest.setTimeout(oneMinute * 10);
|
||||
});
|
||||
|
||||
beforeAll(done => {
|
||||
const create = spawn(process.execPath, ['scripts/generate_plugin.js', pluginName], {
|
||||
cwd: ROOT_DIR,
|
||||
});
|
||||
create.stdout.on('data', function selectDefaults() {
|
||||
create.stdin.write('\n'); // Generate a plugin with default options.
|
||||
});
|
||||
create.on('close', done);
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
del.sync(generatedPath, { force: true });
|
||||
});
|
||||
|
||||
it(`should succeed on creating a plugin in a directory named 'plugins/${snakeCased}`, async () => {
|
||||
const stats = await statP(generatedPath);
|
||||
expect(stats.isDirectory()).toBe(true);
|
||||
});
|
||||
|
||||
describe(`then running`, () => {
|
||||
it(`'yarn test:browser' should exit 0`, async () => {
|
||||
await execa('yarn', ['test:browser'], { cwd: generatedPath });
|
||||
});
|
||||
|
||||
it(`'yarn test:server' should exit 0`, async () => {
|
||||
await execa('yarn', ['test:server'], { cwd: generatedPath });
|
||||
});
|
||||
|
||||
it(`'yarn build' should exit 0`, async () => {
|
||||
await execa('yarn', ['build'], { cwd: generatedPath });
|
||||
});
|
||||
|
||||
it(`'yarn start' should result in the spec plugin being initialized on kibana's stdout`, async () => {
|
||||
const log = new ToolingLog();
|
||||
const es = createEsTestCluster({ license: 'basic', log });
|
||||
await es.start();
|
||||
await withProcRunner(log, async proc => {
|
||||
await proc.run('kibana', {
|
||||
cmd: 'yarn',
|
||||
args: ['start', '--optimize.enabled=false', '--logging.json=false'],
|
||||
cwd: generatedPath,
|
||||
wait: /ispec_plugin.+Status changed from uninitialized to green - Ready/,
|
||||
});
|
||||
await proc.stop('kibana');
|
||||
});
|
||||
await es.stop();
|
||||
});
|
||||
|
||||
it(`'yarn preinstall' should exit 0`, async () => {
|
||||
await execa('yarn', ['preinstall'], { cwd: generatedPath });
|
||||
});
|
||||
|
||||
it(`'yarn lint' should exit 0`, async () => {
|
||||
await execa('yarn', ['lint'], { cwd: generatedPath });
|
||||
});
|
||||
|
||||
it(`'yarn kbn --help' should print out the kbn help msg`, done => {
|
||||
const helpMsg = `
|
||||
usage: kbn <command> [<args>]
|
||||
|
||||
By default commands are run for Kibana itself, all packages in the 'packages/'
|
||||
folder and for all plugins in './plugins' and '../kibana-extra'.
|
||||
|
||||
Available commands:
|
||||
|
||||
bootstrap - Install dependencies and crosslink projects
|
||||
clean - Remove the node_modules and target directories from all projects.
|
||||
run - Run script defined in package.json in each package that contains that script.
|
||||
watch - Runs \`kbn:watch\` script for every project.
|
||||
|
||||
Global options:
|
||||
|
||||
-e, --exclude Exclude specified project. Can be specified multiple times to exclude multiple projects, e.g. '-e kibana -e @kbn/pm'.
|
||||
-i, --include Include only specified projects. If left unspecified, it defaults to including all projects.
|
||||
--oss Do not include the x-pack when running command.
|
||||
--skip-kibana-plugins Filter all plugins in ./plugins and ../kibana-extra when running command.
|
||||
`;
|
||||
const outData = [];
|
||||
const kbnHelp = spawn('yarn', ['kbn', '--help'], { cwd: generatedPath });
|
||||
kbnHelp.stdout.on('data', collect(outData));
|
||||
kbnHelp.on('close', () => {
|
||||
expect(outData.join('\n')).toContain(helpMsg);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it(`'yarn es --help' should print out the es help msg`, done => {
|
||||
const helpMsg = `
|
||||
usage: es <command> [<args>]
|
||||
|
||||
Assists with running Elasticsearch for Kibana development
|
||||
|
||||
Available commands:
|
||||
|
||||
snapshot - Downloads and run from a nightly snapshot
|
||||
source - Build and run from source
|
||||
archive - Install and run from an Elasticsearch tar
|
||||
build_snapshots - Build and collect ES snapshots
|
||||
|
||||
Global options:
|
||||
|
||||
--help
|
||||
`;
|
||||
const outData = [];
|
||||
const kbnHelp = spawn('yarn', ['es', '--help'], { cwd: generatedPath });
|
||||
kbnHelp.stdout.on('data', collect(outData));
|
||||
kbnHelp.on('close', () => {
|
||||
expect(outData.join('\n')).toContain(helpMsg);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -80,7 +80,7 @@ module.exports = function({ name }) {
|
|||
},
|
||||
move: {
|
||||
gitignore: '.gitignore',
|
||||
eslintrc: '.eslintrc',
|
||||
'eslintrc.js': '.eslintrc.js',
|
||||
'package_template.json': 'package.json',
|
||||
},
|
||||
data: answers =>
|
||||
|
|
|
@ -198,6 +198,6 @@ describe('plugin generator sao integration', () => {
|
|||
it('includes dotfiles', async () => {
|
||||
const res = await sao.mockPrompt(template);
|
||||
expect(res.files['.gitignore']).toBeTruthy();
|
||||
expect(res.files['.eslintrc']).toBeTruthy();
|
||||
expect(res.files['.eslintrc.js']).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
---
|
||||
extends: "@elastic/kibana"
|
||||
|
||||
settings:
|
||||
import/resolver:
|
||||
'@elastic/eslint-import-resolver-kibana':
|
||||
rootPackageName: '<%= snakeCase(name) %>'
|
24
packages/kbn-plugin-generator/sao_template/template/eslintrc.js
Executable file
24
packages/kbn-plugin-generator/sao_template/template/eslintrc.js
Executable file
|
@ -0,0 +1,24 @@
|
|||
module.exports = {
|
||||
root: true,
|
||||
extends: ['@elastic/eslint-config-kibana', 'plugin:@elastic/eui/recommended'],
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
'@kbn/eslint-import-resolver-kibana': {
|
||||
rootPackageName: '<%= snakeCase(name) %>',
|
||||
},
|
||||
},
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['**/public/**/*'],
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
'@kbn/eslint-import-resolver-kibana': {
|
||||
forceNode: false,
|
||||
rootPackageName: '<%= snakeCase(name) %>',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
};
|
|
@ -43,39 +43,39 @@ export default function (kibana) {
|
|||
|
||||
init(server, options) { // eslint-disable-line no-unused-vars
|
||||
<%_ if (generateApp) { -%>
|
||||
const xpackMainPlugin = server.plugins.xpack_main;
|
||||
if (xpackMainPlugin) {
|
||||
const featureId = '<%= snakeCase(name) %>';
|
||||
const xpackMainPlugin = server.plugins.xpack_main;
|
||||
if (xpackMainPlugin) {
|
||||
const featureId = '<%= snakeCase(name) %>';
|
||||
|
||||
xpackMainPlugin.registerFeature({
|
||||
id: featureId,
|
||||
name: i18n.translate('<%= camelCase(name) %>.featureRegistry.featureName', {
|
||||
defaultMessage: '<%= name %>',
|
||||
}),
|
||||
navLinkId: featureId,
|
||||
icon: 'questionInCircle',
|
||||
app: [featureId, 'kibana'],
|
||||
catalogue: [],
|
||||
privileges: {
|
||||
all: {
|
||||
api: [],
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: ['show'],
|
||||
},
|
||||
read: {
|
||||
api: [],
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: ['show'],
|
||||
xpackMainPlugin.registerFeature({
|
||||
id: featureId,
|
||||
name: i18n.translate('<%= camelCase(name) %>.featureRegistry.featureName', {
|
||||
defaultMessage: '<%= name %>',
|
||||
}),
|
||||
navLinkId: featureId,
|
||||
icon: 'questionInCircle',
|
||||
app: [featureId, 'kibana'],
|
||||
catalogue: [],
|
||||
privileges: {
|
||||
all: {
|
||||
api: [],
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: ['show'],
|
||||
},
|
||||
});
|
||||
}
|
||||
read: {
|
||||
api: [],
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: ['show'],
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
<%_ } -%>
|
||||
|
||||
<%_ if (generateApi) { -%>
|
||||
|
|
|
@ -1 +1 @@
|
|||
export { Main } from './main';
|
||||
export { Main } from './main';
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
|
||||
var resolve = require('path').resolve;
|
||||
process.argv.push('--config', resolve(__dirname, '../src/dev/jest/config.integration.js'));
|
||||
process.argv.push('--runInBand');
|
||||
|
||||
require('../src/setup_node_env');
|
||||
require('../src/dev/jest/cli');
|
||||
|
|
|
@ -20,6 +20,6 @@
|
|||
/* eslint-env jest */
|
||||
|
||||
/**
|
||||
* Set the default timeout for the integration test suite to 30 seconds
|
||||
* Set the default timeout for the integration test suite to 10 minutes
|
||||
*/
|
||||
jest.setTimeout(30 * 1000);
|
||||
jest.setTimeout(10 * 60 * 1000);
|
||||
|
|
|
@ -52,17 +52,13 @@ export default (kibana) => {
|
|||
}
|
||||
} = kbnServer;
|
||||
|
||||
const testGlobs = [
|
||||
'src/legacy/ui/public/**/*.js',
|
||||
'!src/legacy/ui/public/flot-charts/**/*',
|
||||
];
|
||||
const testGlobs = [];
|
||||
|
||||
const testingPluginIds = config.get('tests_bundle.pluginId');
|
||||
|
||||
if (testingPluginIds) {
|
||||
testGlobs.push('!src/legacy/ui/public/**/__tests__/**/*');
|
||||
testingPluginIds.split(',').forEach((pluginId) => {
|
||||
const plugin = plugins
|
||||
.find(plugin => plugin.id === pluginId);
|
||||
const plugin = plugins.find(plugin => plugin.id === pluginId);
|
||||
|
||||
if (!plugin) {
|
||||
throw new Error('Invalid testingPluginId :: unknown plugin ' + pluginId);
|
||||
|
@ -78,6 +74,8 @@ export default (kibana) => {
|
|||
testGlobs.push(`${plugin.publicDir}/**/__tests__/**/*.js`);
|
||||
});
|
||||
} else {
|
||||
// add all since we are not just focused on specific plugins
|
||||
testGlobs.push('src/legacy/ui/public/**/*.js', '!src/legacy/ui/public/flot-charts/**/*');
|
||||
// add the modules from all of the apps
|
||||
for (const app of uiApps) {
|
||||
modules.add(app.getMainModuleId());
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue