[Application Usage] Functional test to validate the full list of appIds in the schema (#88080)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Alejandro Fernández Haro 2021-01-19 14:44:08 +00:00 committed by GitHub
parent 659c157cba
commit 7c9b11476d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 453 additions and 5 deletions

View file

@ -48,8 +48,7 @@ const commonSchema: MakeSchemaFrom<ApplicationUsageTelemetryReport[string]> = {
},
};
// These keys obtained by searching for `/application\w*\.register\(/` and checking the value of the attr `id`.
// TODO: Find a way to update these keys automatically.
// There is a test in x-pack/test/usage_collection that validates that the keys in here match all the registered apps
export const applicationUsageSchema = {
// OSS
dashboards: commonSchema,
@ -61,10 +60,12 @@ export const applicationUsageSchema = {
short_url_redirect: commonSchema, // It's a forward app so we'll likely never report it
timelion: commonSchema,
visualize: commonSchema,
error: commonSchema,
status: commonSchema,
kibanaOverview: commonSchema,
// X-Pack
apm: commonSchema,
csm: commonSchema,
canvas: commonSchema,
dashboard_mode: commonSchema, // It's a forward app so we'll likely never report it
enterpriseSearch: commonSchema,
@ -75,6 +76,7 @@ export const applicationUsageSchema = {
metrics: commonSchema,
infra: commonSchema, // It's a forward app so we'll likely never report it
fleet: commonSchema,
ingestManager: commonSchema,
lens: commonSchema,
maps: commonSchema,
ml: commonSchema,
@ -98,4 +100,5 @@ export const applicationUsageSchema = {
siem: commonSchema,
space_selector: commonSchema,
uptime: commonSchema,
ux: commonSchema,
};

View file

@ -719,7 +719,7 @@
}
}
},
"apm": {
"error": {
"properties": {
"appId": {
"type": "keyword"
@ -790,7 +790,149 @@
}
}
},
"csm": {
"status": {
"properties": {
"appId": {
"type": "keyword"
},
"viewId": {
"type": "keyword"
},
"clicks_total": {
"type": "long"
},
"clicks_7_days": {
"type": "long"
},
"clicks_30_days": {
"type": "long"
},
"clicks_90_days": {
"type": "long"
},
"minutes_on_screen_total": {
"type": "float"
},
"minutes_on_screen_7_days": {
"type": "float"
},
"minutes_on_screen_30_days": {
"type": "float"
},
"minutes_on_screen_90_days": {
"type": "float"
},
"views": {
"type": "array",
"items": {
"properties": {
"appId": {
"type": "keyword"
},
"viewId": {
"type": "keyword"
},
"clicks_total": {
"type": "long"
},
"clicks_7_days": {
"type": "long"
},
"clicks_30_days": {
"type": "long"
},
"clicks_90_days": {
"type": "long"
},
"minutes_on_screen_total": {
"type": "float"
},
"minutes_on_screen_7_days": {
"type": "float"
},
"minutes_on_screen_30_days": {
"type": "float"
},
"minutes_on_screen_90_days": {
"type": "float"
}
}
}
}
}
},
"kibanaOverview": {
"properties": {
"appId": {
"type": "keyword"
},
"viewId": {
"type": "keyword"
},
"clicks_total": {
"type": "long"
},
"clicks_7_days": {
"type": "long"
},
"clicks_30_days": {
"type": "long"
},
"clicks_90_days": {
"type": "long"
},
"minutes_on_screen_total": {
"type": "float"
},
"minutes_on_screen_7_days": {
"type": "float"
},
"minutes_on_screen_30_days": {
"type": "float"
},
"minutes_on_screen_90_days": {
"type": "float"
},
"views": {
"type": "array",
"items": {
"properties": {
"appId": {
"type": "keyword"
},
"viewId": {
"type": "keyword"
},
"clicks_total": {
"type": "long"
},
"clicks_7_days": {
"type": "long"
},
"clicks_30_days": {
"type": "long"
},
"clicks_90_days": {
"type": "long"
},
"minutes_on_screen_total": {
"type": "float"
},
"minutes_on_screen_7_days": {
"type": "float"
},
"minutes_on_screen_30_days": {
"type": "float"
},
"minutes_on_screen_90_days": {
"type": "float"
}
}
}
}
}
},
"apm": {
"properties": {
"appId": {
"type": "keyword"
@ -1571,6 +1713,77 @@
}
}
},
"ingestManager": {
"properties": {
"appId": {
"type": "keyword"
},
"viewId": {
"type": "keyword"
},
"clicks_total": {
"type": "long"
},
"clicks_7_days": {
"type": "long"
},
"clicks_30_days": {
"type": "long"
},
"clicks_90_days": {
"type": "long"
},
"minutes_on_screen_total": {
"type": "float"
},
"minutes_on_screen_7_days": {
"type": "float"
},
"minutes_on_screen_30_days": {
"type": "float"
},
"minutes_on_screen_90_days": {
"type": "float"
},
"views": {
"type": "array",
"items": {
"properties": {
"appId": {
"type": "keyword"
},
"viewId": {
"type": "keyword"
},
"clicks_total": {
"type": "long"
},
"clicks_7_days": {
"type": "long"
},
"clicks_30_days": {
"type": "long"
},
"clicks_90_days": {
"type": "long"
},
"minutes_on_screen_total": {
"type": "float"
},
"minutes_on_screen_7_days": {
"type": "float"
},
"minutes_on_screen_30_days": {
"type": "float"
},
"minutes_on_screen_90_days": {
"type": "float"
}
}
}
}
}
},
"lens": {
"properties": {
"appId": {
@ -3203,6 +3416,77 @@
}
}
}
},
"ux": {
"properties": {
"appId": {
"type": "keyword"
},
"viewId": {
"type": "keyword"
},
"clicks_total": {
"type": "long"
},
"clicks_7_days": {
"type": "long"
},
"clicks_30_days": {
"type": "long"
},
"clicks_90_days": {
"type": "long"
},
"minutes_on_screen_total": {
"type": "float"
},
"minutes_on_screen_7_days": {
"type": "float"
},
"minutes_on_screen_30_days": {
"type": "float"
},
"minutes_on_screen_90_days": {
"type": "float"
},
"views": {
"type": "array",
"items": {
"properties": {
"appId": {
"type": "keyword"
},
"viewId": {
"type": "keyword"
},
"clicks_total": {
"type": "long"
},
"clicks_7_days": {
"type": "long"
},
"clicks_30_days": {
"type": "long"
},
"clicks_90_days": {
"type": "long"
},
"minutes_on_screen_total": {
"type": "float"
},
"minutes_on_screen_7_days": {
"type": "float"
},
"minutes_on_screen_30_days": {
"type": "float"
},
"minutes_on_screen_90_days": {
"type": "float"
}
}
}
}
}
}
}
},

View file

@ -12,5 +12,6 @@ node scripts/build_kibana_platform_plugins \
--scan-dir "$XPACK_DIR/test/plugin_api_integration/plugins" \
--scan-dir "$XPACK_DIR/test/plugin_api_perf/plugins" \
--scan-dir "$XPACK_DIR/test/licensing_plugin/plugins" \
--scan-dir "$XPACK_DIR/test/usage_collection/plugins" \
--workers 12 \
--verbose

View file

@ -73,6 +73,7 @@ const onlyNotInCoverageTests = [
require.resolve('../test/saved_object_tagging/functional/config.ts'),
require.resolve('../test/saved_object_tagging/api_integration/security_and_spaces/config.ts'),
require.resolve('../test/saved_object_tagging/api_integration/tagging_api/config.ts'),
require.resolve('../test/usage_collection/config.ts'),
];
require('../../src/setup_node_env');

View file

@ -0,0 +1,44 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { resolve } from 'path';
import fs from 'fs';
import { FtrConfigProviderContext } from '@kbn/test/types/ftr';
import { services } from './services';
import { pageObjects } from './page_objects';
// the default export of config files must be a config provider
// that returns an object with the projects config values
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
const xpackFunctionalConfig = await readConfigFile(require.resolve('../functional/config.js'));
// Find all folders in ./plugins since we treat all them as plugin folder
const allFiles = fs.readdirSync(resolve(__dirname, 'plugins'));
const plugins = allFiles.filter((file) =>
fs.statSync(resolve(__dirname, 'plugins', file)).isDirectory()
);
return {
...xpackFunctionalConfig.getAll(),
// list paths to the files that contain your plugins tests
testFiles: [resolve(__dirname, './test_suites/application_usage')],
services,
pageObjects,
kbnTestServer: {
...xpackFunctionalConfig.get('kbnTestServer'),
serverArgs: [
...xpackFunctionalConfig.get('kbnTestServer.serverArgs'),
...plugins.map((pluginDir) => `--plugin-path=${resolve(__dirname, 'plugins', pluginDir)}`),
],
},
junit: {
reportName: 'X-Pack Usage Collection Functional Tests',
},
};
}

View file

@ -0,0 +1,11 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { GenericFtrProviderContext } from '@kbn/test/types/ftr';
import { services } from './services';
import { pageObjects } from './page_objects';
export type FtrProviderContext = GenericFtrProviderContext<typeof services, typeof pageObjects>;

View file

@ -0,0 +1,6 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export { pageObjects } from '../functional/page_objects';

View file

@ -0,0 +1,9 @@
{
"id": "applicationUsageTest",
"version": "1.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack", "applicationUsageTest"],
"requiredPlugins": [],
"server": false,
"ui": true
}

View file

@ -0,0 +1,11 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { ApplicationUsageTest } from './plugin';
export function plugin() {
return new ApplicationUsageTest();
}

View file

@ -0,0 +1,18 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { Plugin, CoreSetup, CoreStart } from 'kibana/public';
import { first } from 'rxjs/operators';
import './types';
export class ApplicationUsageTest implements Plugin {
public setup(core: CoreSetup) {}
public async start(core: CoreStart) {
const applications = await core.application.applications$.pipe(first()).toPromise();
window.__applicationIds__ = [...applications.keys()];
}
}

View file

@ -0,0 +1,13 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export {}; // Hack to declare this file as a module so TS allows us to extend the Global Window interface
declare global {
interface Window {
__applicationIds__: string[];
}
}

View file

@ -0,0 +1,12 @@
{
"extends": "../../../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "./target",
"skipLibCheck": true
},
"include": [
"public/**/*.ts",
"public/**/*.tsx",
],
"exclude": []
}

View file

@ -0,0 +1,7 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export { services } from '../functional/services';

View file

@ -0,0 +1,28 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../ftr_provider_context';
import { applicationUsageSchema } from '../../../../../src/plugins/kibana_usage_collection/server/collectors/application_usage/schema';
export default function ({ getService, getPageObjects }: FtrProviderContext) {
describe('Application Usage', function () {
this.tags('ciGroup1');
const { common } = getPageObjects(['common']);
const browser = getService('browser');
it('keys in the schema match the registered application IDs', async () => {
await common.navigateToApp('home'); // Navigate to Home to make sure all the appIds are loaded
const appIds = await browser.execute(() => window.__applicationIds__);
try {
expect(Object.keys(applicationUsageSchema).sort()).to.eql(appIds.sort());
} catch (err) {
err.message = `Application Usage's schema is not up-to-date with the actual registered apps. Please update it at src/plugins/kibana_usage_collection/server/collectors/application_usage/schema.ts.\n${err.message}`;
throw err;
}
});
});
}