mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
modernize test-subj-selector (#140847)
This commit is contained in:
parent
997caf021c
commit
77964bc0f7
23 changed files with 217 additions and 104 deletions
|
@ -1105,6 +1105,7 @@
|
|||
"@types/kbn__telemetry-tools": "link:bazel-bin/packages/kbn-telemetry-tools/npm_module_types",
|
||||
"@types/kbn__test": "link:bazel-bin/packages/kbn-test/npm_module_types",
|
||||
"@types/kbn__test-jest-helpers": "link:bazel-bin/packages/kbn-test-jest-helpers/npm_module_types",
|
||||
"@types/kbn__test-subj-selector": "link:bazel-bin/packages/kbn-test-subj-selector/npm_module_types",
|
||||
"@types/kbn__tooling-log": "link:bazel-bin/packages/kbn-tooling-log/npm_module_types",
|
||||
"@types/kbn__type-summarizer": "link:bazel-bin/packages/kbn-type-summarizer/npm_module_types",
|
||||
"@types/kbn__type-summarizer-cli": "link:bazel-bin/packages/kbn-type-summarizer-cli/npm_module_types",
|
||||
|
|
|
@ -562,6 +562,7 @@ filegroup(
|
|||
"//packages/kbn-telemetry-tools:build_types",
|
||||
"//packages/kbn-test:build_types",
|
||||
"//packages/kbn-test-jest-helpers:build_types",
|
||||
"//packages/kbn-test-subj-selector:build_types",
|
||||
"//packages/kbn-tooling-log:build_types",
|
||||
"//packages/kbn-type-summarizer:build_types",
|
||||
"//packages/kbn-type-summarizer-cli:build_types",
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import { EuiCallOut } from '@elastic/eui';
|
||||
import testSubjSelector from '@kbn/test-subj-selector';
|
||||
import { subj as testSubjSelector } from '@kbn/test-subj-selector';
|
||||
import React from 'react';
|
||||
import { of, ReplaySubject } from 'rxjs';
|
||||
import { mountWithIntl, shallowWithIntl } from '@kbn/test-jest-helpers';
|
||||
|
|
|
@ -1,13 +1,28 @@
|
|||
load("@npm//@bazel/typescript:index.bzl", "ts_config")
|
||||
load("@build_bazel_rules_nodejs//:index.bzl", "js_library")
|
||||
load("//src/dev/bazel:index.bzl", "pkg_npm")
|
||||
load("//src/dev/bazel:index.bzl", "jsts_transpiler", "pkg_npm", "pkg_npm_types", "ts_project")
|
||||
|
||||
PKG_BASE_NAME = "kbn-test-subj-selector"
|
||||
PKG_DIRNAME = "kbn-test-subj-selector"
|
||||
PKG_REQUIRE_NAME = "@kbn/test-subj-selector"
|
||||
|
||||
SOURCE_FILES = glob([
|
||||
"index.d.ts",
|
||||
"index.js"
|
||||
])
|
||||
SOURCE_FILES = glob(
|
||||
[
|
||||
"**/*.ts",
|
||||
],
|
||||
exclude = [
|
||||
"**/*.config.js",
|
||||
"**/*.mock.*",
|
||||
"**/*.test.*",
|
||||
"**/*.stories.*",
|
||||
"**/__snapshots__/**",
|
||||
"**/integration_tests/**",
|
||||
"**/mocks/**",
|
||||
"**/scripts/**",
|
||||
"**/storybook/**",
|
||||
"**/test_fixtures/**",
|
||||
"**/test_helpers/**",
|
||||
],
|
||||
)
|
||||
|
||||
SRCS = SOURCE_FILES
|
||||
|
||||
|
@ -20,29 +35,90 @@ NPM_MODULE_EXTRA_FILES = [
|
|||
"package.json",
|
||||
]
|
||||
|
||||
RUNTIME_DEPS = []
|
||||
# In this array place runtime dependencies, including other packages and NPM packages
|
||||
# which must be available for this code to run.
|
||||
#
|
||||
# To reference other packages use:
|
||||
# "//repo/relative/path/to/package"
|
||||
# eg. "//packages/kbn-utils"
|
||||
#
|
||||
# To reference a NPM package use:
|
||||
# "@npm//name-of-package"
|
||||
# eg. "@npm//lodash"
|
||||
RUNTIME_DEPS = [
|
||||
]
|
||||
|
||||
# In this array place dependencies necessary to build the types, which will include the
|
||||
# :npm_module_types target of other packages and packages from NPM, including @types/*
|
||||
# packages.
|
||||
#
|
||||
# To reference the types for another package use:
|
||||
# "//repo/relative/path/to/package:npm_module_types"
|
||||
# eg. "//packages/kbn-utils:npm_module_types"
|
||||
#
|
||||
# References to NPM packages work the same as RUNTIME_DEPS
|
||||
TYPES_DEPS = [
|
||||
"@npm//@types/node",
|
||||
"@npm//@types/jest",
|
||||
]
|
||||
|
||||
jsts_transpiler(
|
||||
name = "target_node",
|
||||
srcs = SRCS,
|
||||
build_pkg_name = package_name(),
|
||||
)
|
||||
|
||||
ts_config(
|
||||
name = "tsconfig",
|
||||
src = "tsconfig.json",
|
||||
deps = [
|
||||
"//:tsconfig.base.json",
|
||||
"//:tsconfig.bazel.json",
|
||||
],
|
||||
)
|
||||
|
||||
ts_project(
|
||||
name = "tsc_types",
|
||||
args = ['--pretty'],
|
||||
srcs = SRCS,
|
||||
deps = TYPES_DEPS,
|
||||
declaration = True,
|
||||
declaration_map = True,
|
||||
emit_declaration_only = True,
|
||||
out_dir = "target_types",
|
||||
tsconfig = ":tsconfig",
|
||||
)
|
||||
|
||||
js_library(
|
||||
name = PKG_BASE_NAME,
|
||||
srcs = NPM_MODULE_EXTRA_FILES + [
|
||||
":srcs",
|
||||
],
|
||||
deps = RUNTIME_DEPS,
|
||||
name = PKG_DIRNAME,
|
||||
srcs = NPM_MODULE_EXTRA_FILES,
|
||||
deps = RUNTIME_DEPS + [":target_node"],
|
||||
package_name = PKG_REQUIRE_NAME,
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
pkg_npm(
|
||||
name = "npm_module",
|
||||
deps = [
|
||||
":%s" % PKG_BASE_NAME,
|
||||
]
|
||||
deps = [":" + PKG_DIRNAME],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "build",
|
||||
srcs = [
|
||||
":npm_module",
|
||||
],
|
||||
srcs = [":npm_module"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
pkg_npm_types(
|
||||
name = "npm_module_types",
|
||||
srcs = SRCS,
|
||||
deps = [":tsc_types"],
|
||||
package_name = PKG_REQUIRE_NAME,
|
||||
tsconfig = ":tsconfig",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "build_types",
|
||||
srcs = [":npm_module_types"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
|
|
@ -7,4 +7,20 @@ date: 2022-05-19
|
|||
tags: ['kibana', 'dev', 'contributor', 'operations', 'test', 'subj', 'selector']
|
||||
---
|
||||
|
||||
Converts a string from a test subject syntax into a css selectors composed by `data-test-subj`.
|
||||
Converts a testSubject selector into a CSS selector.
|
||||
|
||||
testSubject selector syntax rules:
|
||||
|
||||
- `data-test-subj` values can include spaces
|
||||
|
||||
- prefixing a value with `~` will allow matching a single word in a `data-test-subj` that uses several space delimited list words
|
||||
- example: `~foo`
|
||||
- css equivalent: `[data-test-subj~="foo"]`
|
||||
|
||||
- the `>` character is used between two values to indicate that the value on the right must match an element inside an element matched by the value on the left
|
||||
- example: `foo > bar`
|
||||
- css equivalent: `[data-test-subj=foo] [data-test-subj=bar]`
|
||||
|
||||
- the `&` character is used between two values to indicate that the value on both sides must both match the element
|
||||
- example: `foo & bar`
|
||||
- css equivalent: `[data-test-subj=foo][data-test-subj=bar]`
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
function selectorToTerms(selector) {
|
||||
return selector
|
||||
.replace(/\s*~\s*/g, '~') // css locator with '~' operator cannot contain spaces
|
||||
.replace(/\s*>\s*/g, '>') // remove all whitespace around joins >
|
||||
.replace(/\s*&\s*/g, '&') // remove all whitespace around joins &
|
||||
.split(/>+/);
|
||||
}
|
||||
|
||||
function termToCssSelector(term) {
|
||||
if (term) {
|
||||
return term.startsWith('~')
|
||||
? '[data-test-subj~="' + term.substring(1).replace(/\s/g, '') + '"]'
|
||||
: '[data-test-subj="' + term + '"]';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function testSubjSelector(selector) {
|
||||
const cssSelectors = [];
|
||||
const terms = selectorToTerms(selector);
|
||||
|
||||
while (terms.length) {
|
||||
const term = terms.shift();
|
||||
// split each term by joins/& and map to css selectors
|
||||
cssSelectors.push(term.split('&').map(termToCssSelector).join(''));
|
||||
}
|
||||
|
||||
return cssSelectors.join(' ');
|
||||
};
|
|
@ -1,24 +0,0 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
const testSubjSelector = require('.');
|
||||
|
||||
describe('testSubjSelector()', function () {
|
||||
it('converts subjectSelectors to cssSelectors', function () {
|
||||
expect(testSubjSelector('foo bar')).toEqual('[data-test-subj="foo bar"]');
|
||||
expect(testSubjSelector('foo > bar')).toEqual('[data-test-subj="foo"] [data-test-subj="bar"]');
|
||||
expect(testSubjSelector('foo > bar baz')).toEqual(
|
||||
'[data-test-subj="foo"] [data-test-subj="bar baz"]'
|
||||
);
|
||||
expect(testSubjSelector('foo> ~bar')).toEqual('[data-test-subj="foo"] [data-test-subj~="bar"]');
|
||||
expect(testSubjSelector('~ foo')).toEqual('[data-test-subj~="foo"]');
|
||||
expect(testSubjSelector('~foo & ~ bar')).toEqual(
|
||||
'[data-test-subj~="foo"][data-test-subj~="bar"]'
|
||||
);
|
||||
});
|
||||
});
|
|
@ -6,5 +6,4 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function kbnTestSubjSelector(selector: string): string;
|
||||
export { subj } from './test_subj_selector';
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
module.exports = {
|
||||
preset: '@kbn/test',
|
||||
preset: '@kbn/test/jest_node',
|
||||
rootDir: '../..',
|
||||
roots: ['<rootDir>/packages/kbn-test-subj-selector'],
|
||||
};
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"type": "shared-common",
|
||||
"id": "@kbn/test-subj-selector",
|
||||
"devOnly": true,
|
||||
"owner": "@elastic/kibana-operations",
|
||||
"devOnly": true,
|
||||
"runtimeDeps": [],
|
||||
"typeDeps": []
|
||||
"typeDeps": [],
|
||||
}
|
||||
|
|
11
packages/kbn-test-subj-selector/package.json
Executable file → Normal file
11
packages/kbn-test-subj-selector/package.json
Executable file → Normal file
|
@ -1,10 +1,7 @@
|
|||
{
|
||||
"name": "@kbn/test-subj-selector",
|
||||
"version": "0.2.1",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"keywords": [],
|
||||
"author": "Spencer Alger <email@spalger.com>",
|
||||
"license": "SSPL-1.0 OR Elastic License 2.0",
|
||||
"private": "true"
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"main": "./target_node/index.js",
|
||||
"license": "SSPL-1.0 OR Elastic License 2.0"
|
||||
}
|
||||
|
|
20
packages/kbn-test-subj-selector/test_subj_selector.test.ts
Normal file
20
packages/kbn-test-subj-selector/test_subj_selector.test.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { subj } from './test_subj_selector';
|
||||
|
||||
describe('testSubjSelector()', function () {
|
||||
it('converts subjectSelectors to cssSelectors', function () {
|
||||
expect(subj('foo bar')).toEqual('[data-test-subj="foo bar"]');
|
||||
expect(subj('foo > bar')).toEqual('[data-test-subj="foo"] [data-test-subj="bar"]');
|
||||
expect(subj('foo > bar baz')).toEqual('[data-test-subj="foo"] [data-test-subj="bar baz"]');
|
||||
expect(subj('foo> ~bar')).toEqual('[data-test-subj="foo"] [data-test-subj~="bar"]');
|
||||
expect(subj('~ foo')).toEqual('[data-test-subj~="foo"]');
|
||||
expect(subj('~foo & ~ bar')).toEqual('[data-test-subj~="foo"][data-test-subj~="bar"]');
|
||||
});
|
||||
});
|
53
packages/kbn-test-subj-selector/test_subj_selector.ts
Normal file
53
packages/kbn-test-subj-selector/test_subj_selector.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
function selectorToTerms(selector: string) {
|
||||
return selector
|
||||
.replace(/\s*~\s*/g, '~') // css locator with '~' operator cannot contain spaces
|
||||
.replace(/\s*>\s*/g, '>') // remove all whitespace around joins >
|
||||
.replace(/\s*&\s*/g, '&') // remove all whitespace around joins &
|
||||
.split(/>+/);
|
||||
}
|
||||
|
||||
function termToCssSelector(term: string) {
|
||||
if (term) {
|
||||
return term.startsWith('~')
|
||||
? '[data-test-subj~="' + term.substring(1).replace(/\s/g, '') + '"]'
|
||||
: '[data-test-subj="' + term + '"]';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a testSubject selector into a CSS selector.
|
||||
*
|
||||
* testSubject selector syntax rules:
|
||||
*
|
||||
* - `data-test-subj` values can include spaces
|
||||
*
|
||||
* - prefixing a value with `~` will allow matching a single word in a `data-test-subj` that uses several space delimited list words
|
||||
* - example: `~foo`
|
||||
* - css equivalent: `[data-test-subj~="foo"]`
|
||||
*
|
||||
* - the `>` character is used between two values to indicate that the value on the right must match an element inside an element matched by the value on the left
|
||||
* - example: `foo > bar`
|
||||
* - css equivalent: `[data-test-subj=foo] [data-test-subj=bar]`
|
||||
*
|
||||
* - the `&` character is used between two values to indicate that the value on both sides must both match the element
|
||||
* - example: `foo & bar`
|
||||
* - css equivalent: `[data-test-subj=foo][data-test-subj=bar]`
|
||||
*/
|
||||
export function subj(selector: string) {
|
||||
return selectorToTerms(selector)
|
||||
.map((term) =>
|
||||
// split each term by joins/& and map to css selectors
|
||||
term.split('&').map(termToCssSelector).join('')
|
||||
)
|
||||
.join(' ');
|
||||
}
|
|
@ -1,9 +1,17 @@
|
|||
{
|
||||
"extends": "../../tsconfig.bazel.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "target/types"
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"emitDeclarationOnly": true,
|
||||
"outDir": "target_types",
|
||||
"stripInternal": false,
|
||||
"types": [
|
||||
"jest",
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"index.d.ts"
|
||||
"**/*.ts",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import chalk from 'chalk';
|
||||
import testSubjectToCss from '@kbn/test-subj-selector';
|
||||
import { subj as testSubjectToCss } from '@kbn/test-subj-selector';
|
||||
import { AXE_CONFIG, AXE_OPTIONS } from '@kbn/axe-config';
|
||||
|
||||
import { FtrService } from '../../ftr_provider_context';
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import testSubjSelector from '@kbn/test-subj-selector';
|
||||
import { subj as testSubjSelector } from '@kbn/test-subj-selector';
|
||||
import { PluginFunctionalProviderContext } from '../../plugin_functional/services';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import testSubjSelector from '@kbn/test-subj-selector';
|
||||
import { subj as testSubjSelector } from '@kbn/test-subj-selector';
|
||||
import { WebElementWrapper } from '../lib/web_element_wrapper';
|
||||
import { FtrService } from '../../ftr_provider_context';
|
||||
import { TimeoutOpt } from './types';
|
||||
|
|
|
@ -10,7 +10,7 @@ import { setTimeout as setTimeoutAsync } from 'timers/promises';
|
|||
import { WebElement, WebDriver, By, Key } from 'selenium-webdriver';
|
||||
import { PNG } from 'pngjs';
|
||||
import cheerio from 'cheerio';
|
||||
import testSubjSelector from '@kbn/test-subj-selector';
|
||||
import { subj as testSubjSelector } from '@kbn/test-subj-selector';
|
||||
import { ToolingLog } from '@kbn/tooling-log';
|
||||
import { CustomCheerio, CustomCheerioStatic } from './custom_cheerio_api';
|
||||
// @ts-ignore not supported yet
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import testSubject from '@kbn/test-subj-selector';
|
||||
import { subj as testSubject } from '@kbn/test-subj-selector';
|
||||
import React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import testSubjSelector from '@kbn/test-subj-selector';
|
||||
import { subj as testSubjSelector } from '@kbn/test-subj-selector';
|
||||
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import testSubjSelector from '@kbn/test-subj-selector';
|
||||
import { subj as testSubjSelector } from '@kbn/test-subj-selector';
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
const TEST_SUBJ = Object.freeze({
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import testSubjSelector from '@kbn/test-subj-selector';
|
||||
import { subj as testSubjSelector } from '@kbn/test-subj-selector';
|
||||
import { FtrService } from '../../../functional/ftr_provider_context';
|
||||
import { DATE_RANGE_OPTION_TO_TEST_SUBJ_MAP } from '../helpers/super_date_picker';
|
||||
|
||||
|
|
|
@ -7761,6 +7761,10 @@
|
|||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@types/kbn__test-subj-selector@link:bazel-bin/packages/kbn-test-subj-selector/npm_module_types":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@types/kbn__test@link:bazel-bin/packages/kbn-test/npm_module_types":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue