-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into spaces/flaky-selection-test
- Loading branch information
Showing
174 changed files
with
4,448 additions
and
1,930 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,9 +41,9 @@ trap "echoKibanaLogs" EXIT | |
|
||
vagrant provision "$TEST_PACKAGE" | ||
|
||
export TEST_BROWSER_HEADLESS=1 | ||
export TEST_KIBANA_URL="http://elastic:changeme@$KIBANA_IP_ADDRESS:5601" | ||
export TEST_ES_URL=http://elastic:[email protected]:9200 | ||
# export TEST_BROWSER_HEADLESS=1 | ||
# export TEST_KIBANA_URL="http://elastic:changeme@$KIBANA_IP_ADDRESS:5601" | ||
# export TEST_ES_URL=http://elastic:[email protected]:9200 | ||
|
||
cd x-pack | ||
node scripts/functional_test_runner.js --include-tag=smoke | ||
# cd x-pack | ||
# node scripts/functional_test_runner.js --include-tag=smoke |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
/* | ||
* 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 { firstValueFrom, ReplaySubject } from 'rxjs'; | ||
import { analyticsClientMock } from './analytics_service.test.mocks'; | ||
import { trackClicks } from './track_clicks'; | ||
import { take } from 'rxjs/operators'; | ||
|
||
describe('trackClicks', () => { | ||
const addEventListenerSpy = jest.spyOn(window, 'addEventListener'); | ||
const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(); | ||
|
||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
test('registers the analytics event type and a listener to the "click" events', () => { | ||
trackClicks(analyticsClientMock, true); | ||
|
||
expect(analyticsClientMock.registerEventType).toHaveBeenCalledTimes(1); | ||
expect(analyticsClientMock.registerEventType).toHaveBeenCalledWith( | ||
expect.objectContaining({ | ||
eventType: 'click', | ||
}) | ||
); | ||
expect(addEventListenerSpy).toHaveBeenCalledTimes(1); | ||
expect(addEventListenerSpy).toHaveBeenCalledWith('click', expect.any(Function), undefined); | ||
}); | ||
|
||
test('reports an analytics event when a click event occurs', async () => { | ||
// Gather an actual "click" event | ||
const event$ = new ReplaySubject<MouseEvent>(1); | ||
const parent = document.createElement('div'); | ||
parent.setAttribute('data-test-subj', 'test-click-target-parent'); | ||
const element = document.createElement('button'); | ||
parent.appendChild(element); | ||
element.setAttribute('data-test-subj', 'test-click-target'); | ||
element.innerText = 'test'; // Only to validate that it is not included in the event. | ||
element.value = 'test'; // Only to validate that it is not included in the event. | ||
element.addEventListener('click', (e) => event$.next(e)); | ||
element.click(); | ||
// Using an observable because the event might not be immediately available | ||
const event = await firstValueFrom(event$.pipe(take(1))); | ||
event$.complete(); // No longer needed | ||
|
||
trackClicks(analyticsClientMock, true); | ||
expect(addEventListenerSpy).toHaveBeenCalledTimes(1); | ||
|
||
(addEventListenerSpy.mock.calls[0][1] as EventListener)(event); | ||
expect(analyticsClientMock.reportEvent).toHaveBeenCalledTimes(1); | ||
expect(analyticsClientMock.reportEvent).toHaveBeenCalledWith('click', { | ||
target: [ | ||
'DIV', | ||
'data-test-subj=test-click-target-parent', | ||
'BUTTON', | ||
'data-test-subj=test-click-target', | ||
], | ||
}); | ||
}); | ||
|
||
test('handles any processing errors logging them in dev mode', async () => { | ||
trackClicks(analyticsClientMock, true); | ||
expect(addEventListenerSpy).toHaveBeenCalledTimes(1); | ||
|
||
// A basic MouseEvent does not have a target and will fail the logic, making it go to the catch branch as intended. | ||
(addEventListenerSpy.mock.calls[0][1] as EventListener)(new MouseEvent('click')); | ||
expect(analyticsClientMock.reportEvent).toHaveBeenCalledTimes(0); | ||
expect(consoleErrorSpy).toHaveBeenCalledTimes(1); | ||
expect(consoleErrorSpy.mock.calls[0]).toMatchInlineSnapshot(` | ||
Array [ | ||
"Failed to report the click event", | ||
Object { | ||
"error": [TypeError: Cannot read properties of null (reading 'parentElement')], | ||
"event": MouseEvent { | ||
"isTrusted": false, | ||
}, | ||
}, | ||
] | ||
`); | ||
}); | ||
|
||
test('swallows any processing errors when not in dev mode', async () => { | ||
trackClicks(analyticsClientMock, false); | ||
expect(addEventListenerSpy).toHaveBeenCalledTimes(1); | ||
|
||
// A basic MouseEvent does not have a target and will fail the logic, making it go to the catch branch as intended. | ||
(addEventListenerSpy.mock.calls[0][1] as EventListener)(new MouseEvent('click')); | ||
expect(analyticsClientMock.reportEvent).toHaveBeenCalledTimes(0); | ||
expect(consoleErrorSpy).toHaveBeenCalledTimes(0); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/* | ||
* 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 { fromEvent } from 'rxjs'; | ||
import type { AnalyticsClient } from '@kbn/analytics-client'; | ||
|
||
/** HTML attributes that should be skipped from reporting because they might contain user data */ | ||
const POTENTIAL_PII_HTML_ATTRIBUTES = ['value']; | ||
|
||
/** | ||
* Registers the event type "click" in the analytics client. | ||
* Then it listens to all the "click" events in the UI and reports them with the `target` property being a | ||
* full list of the element's and its parents' attributes. This allows | ||
* @param analytics | ||
*/ | ||
export function trackClicks(analytics: AnalyticsClient, isDevMode: boolean) { | ||
analytics.registerEventType<{ target: string[] }>({ | ||
eventType: 'click', | ||
schema: { | ||
target: { | ||
type: 'array', | ||
items: { | ||
type: 'keyword', | ||
_meta: { | ||
description: | ||
'The attributes of the clicked element and all its parents in the form `{attr.name}={attr.value}`. It allows finding the clicked elements by looking up its attributes like "data-test-subj=my-button".', | ||
}, | ||
}, | ||
}, | ||
}, | ||
}); | ||
|
||
// window or document? | ||
// I tested it on multiple browsers and it seems to work the same. | ||
// My assumption is that window captures other documents like iframes as well? | ||
return fromEvent(window, 'click').subscribe((event) => { | ||
try { | ||
const target = event.target as HTMLElement; | ||
analytics.reportEvent('click', { target: getTargetDefinition(target) }); | ||
} catch (error) { | ||
if (isDevMode) { | ||
// Defensively log the error in dev mode to catch any potential bugs. | ||
// eslint-disable-next-line no-console | ||
console.error(`Failed to report the click event`, { event, error }); | ||
} | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* Returns a list of strings consisting on the tag name and all the attributes of the element. | ||
* Additionally, it recursively walks up the DOM tree to find all the parents' definitions and prepends them to the list. | ||
* | ||
* @example | ||
* From | ||
* ```html | ||
* <div data-test-subj="my-parent"> | ||
* <div data-test-subj="my-button" /> | ||
* </div> | ||
* ``` | ||
* it returns ['DIV', 'data-test-subj=my-parent', 'DIV', 'data-test-subj=my-button'] | ||
* @param target The child node to start from. | ||
*/ | ||
function getTargetDefinition(target: HTMLElement): string[] { | ||
return [ | ||
...(target.parentElement ? getTargetDefinition(target.parentElement) : []), | ||
target.tagName, | ||
...[...target.attributes] | ||
.filter((attr) => !POTENTIAL_PII_HTML_ATTRIBUTES.includes(attr.name)) | ||
.map((attr) => `${attr.name}=${attr.value}`), | ||
]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
..._partition_vis/common/expression_functions/__snapshots__/mosaic_vis_function.test.ts.snap
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
4 changes: 2 additions & 2 deletions
4
...ion_partition_vis/common/expression_functions/__snapshots__/pie_vis_function.test.ts.snap
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
2 changes: 1 addition & 1 deletion
2
...partition_vis/common/expression_functions/__snapshots__/treemap_vis_function.test.ts.snap
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
2 changes: 1 addition & 1 deletion
2
..._partition_vis/common/expression_functions/__snapshots__/waffle_vis_function.test.ts.snap
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.