diff --git a/x-pack/legacy/plugins/graph/public/app.js b/x-pack/legacy/plugins/graph/public/app.js index 2f7e7890497df..f267eb178f798 100644 --- a/x-pack/legacy/plugins/graph/public/app.js +++ b/x-pack/legacy/plugins/graph/public/app.js @@ -471,9 +471,7 @@ app.controller('graphuiPlugin', function ( }), run: function () { canWipeWorkspace(function () { - $scope.$evalAsync(() => { - kbnUrl.change('/workspace/', {}); - }); + kbnUrl.change('/workspace/', {}); }); }, testId: 'graphNewButton', }); diff --git a/x-pack/legacy/plugins/graph/public/components/field_manager/field_picker.tsx b/x-pack/legacy/plugins/graph/public/components/field_manager/field_picker.tsx index 5df94ac873bc1..9d6b27ebe05d4 100644 --- a/x-pack/legacy/plugins/graph/public/components/field_manager/field_picker.tsx +++ b/x-pack/legacy/plugins/graph/public/components/field_manager/field_picker.tsx @@ -59,6 +59,7 @@ export function FieldPicker({ panelPaddingSize="none" button={ - + diff --git a/x-pack/legacy/plugins/graph/public/components/search_bar.tsx b/x-pack/legacy/plugins/graph/public/components/search_bar.tsx index 11e5d353cadaf..80aa6c3d72144 100644 --- a/x-pack/legacy/plugins/graph/public/components/search_bar.tsx +++ b/x-pack/legacy/plugins/graph/public/components/search_bar.tsx @@ -140,7 +140,12 @@ export function SearchBarComponent(props: SearchBarProps) { /> - + {i18n.translate('xpack.graph.bar.exploreLabel', { defaultMessage: 'Explore' })} diff --git a/x-pack/test/functional/apps/graph/graph.ts b/x-pack/test/functional/apps/graph/graph.ts index 97bb7c1b9918b..cb6f0b6028a2d 100644 --- a/x-pack/test/functional/apps/graph/graph.ts +++ b/x-pack/test/functional/apps/graph/graph.ts @@ -13,8 +13,7 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const browser = getService('browser'); - // FLAKY: https://github.com/elastic/kibana/issues/45317 - describe.skip('graph', function() { + describe('graph', function() { before(async () => { await browser.setWindowSize(1600, 1000); log.debug('load graph/secrepo data'); @@ -47,55 +46,48 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { '/blog/wp-admin/', ]; - const expectedConnectionWidth: Record> = { - '/blog/wp-admin/': { wp: 2, blog: 5.51581 }, + const expectedConnections: Record> = { + '/blog/wp-admin/': { wp: true, blog: true }, wp: { - blog: 2, - '202.136.75.194': 2, - 'login.php': 2, - admin: 2, - '/test/wp-admin/': 2, - '/wp-login.php': 2, - '80.5.27.16': 2, - '/wordpress/wp-admin/': 2, - '190.154.27.54': 2, - '187.131.21.37': 2, - '181.113.155.46': 2, + blog: true, + '202.136.75.194': true, + 'login.php': true, + admin: true, + '/test/wp-admin/': true, + '/wp-login.php': true, + '80.5.27.16': true, + '/wordpress/wp-admin/': true, + '190.154.27.54': true, + '187.131.21.37': true, + '181.113.155.46': true, }, - admin: { test: 2, blog: 2, '/blog/wp-admin/': 2 }, - '/test/wp-admin/': { admin: 2 }, - test: { wp: 2, '/test/wp-admin/': 8.54514 }, - wordpress: { wp: 2, admin: 2.0311 }, - '/wordpress/wp-admin/': { wordpress: 9.70794, admin: 2.30771 }, + admin: { test: true, blog: true, '/blog/wp-admin/': true }, + '/test/wp-admin/': { admin: true }, + test: { wp: true, '/test/wp-admin/': true }, + wordpress: { wp: true, admin: true }, + '/wordpress/wp-admin/': { wordpress: true, admin: true }, }; async function buildGraph() { - log.debug('select index pattern secrepo*'); - await PageObjects.graph.selectIndexPattern('secrepo*'); - // wait for the saved object to be loaded - // TODO this race condition will be removed with eui-ification - // of graph bar - await PageObjects.common.sleep(1000); // select fields url.parts, url, params and src - await PageObjects.graph.addField('url.parts'); - await PageObjects.graph.addField('url'); - await PageObjects.graph.addField('params'); - await PageObjects.graph.addField('src'); + await PageObjects.graph.addFields(['url.parts', 'url', 'params', 'src']); await PageObjects.graph.query('admin'); await PageObjects.common.sleep(8000); } it('should show correct node labels', async function() { + await PageObjects.graph.selectIndexPattern('secrepo*'); await buildGraph(); const { nodes } = await PageObjects.graph.getGraphObjects(); const circlesText = nodes.map(({ label }) => label); expect(circlesText.length).to.equal(expectedNodes.length); - expect(circlesText).to.eql(expectedNodes); + circlesText.forEach(circleText => { + expect(expectedNodes.includes(circleText)).to.be(true); + }); }); it('should show correct connections', async function() { - const epsilon = Number.EPSILON; - const expectedConnectionCount = Object.values(expectedConnectionWidth) + const expectedConnectionCount = Object.values(expectedConnections) .map(connections => Object.values(connections).length) .reduce((acc, n) => acc + n, 0); const { edges } = await PageObjects.graph.getGraphObjects(); @@ -103,11 +95,7 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { edges.forEach(edge => { const from = edge.sourceNode.label!; const to = edge.targetNode.label!; - // fuzzy matching to take floating point rounding issues into account - expect(expectedConnectionWidth[from][to]).to.be.within( - edge.width - epsilon, - edge.width + epsilon - ); + expect(expectedConnections[from][to]).to.be(true); }); }); @@ -122,11 +110,14 @@ export default function({ getService, getPageObjects }: FtrProviderContext) { const { nodes } = await PageObjects.graph.getGraphObjects(); const circlesText = nodes.map(({ label }) => label); expect(circlesText.length).to.equal(expectedNodes.length); - expect(circlesText).to.eql(expectedNodes); + circlesText.forEach(circleText => { + expect(expectedNodes.includes(circleText)).to.be(true); + }); }); it('should create new Graph workspace', async function() { await PageObjects.graph.newGraph(); + await PageObjects.graph.selectIndexPattern('secrepo*'); const { nodes, edges } = await PageObjects.graph.getGraphObjects(); expect(nodes).to.be.empty(); expect(edges).to.be.empty(); diff --git a/x-pack/test/functional/page_objects/graph_page.ts b/x-pack/test/functional/page_objects/graph_page.ts index dd5f28e221eb1..063827980e7cc 100644 --- a/x-pack/test/functional/page_objects/graph_page.ts +++ b/x-pack/test/functional/page_objects/graph_page.ts @@ -28,35 +28,41 @@ export function GraphPageProvider({ getService, getPageObjects }: FtrProviderCon class GraphPage { async selectIndexPattern(pattern: string) { - await find.clickDisplayedByCssSelector('.gphIndexSelect'); - await find.clickByCssSelector('.gphIndexSelect > option[label="' + pattern + '"]'); + await testSubjects.click('graphDatasourceButton'); + await testSubjects.click(`savedObjectTitle${pattern.split(' ').join('-')}`); + // wait till add fields button becomes available, then the index pattern is loaded completely + await testSubjects.waitForAttributeToChange( + 'graph-add-field-button', + 'aria-disabled', + 'false' + ); } async clickAddField() { await retry.try(async () => { - await find.clickByCssSelector('#addVertexFieldButton'); - // make sure the fieldSelectionList is not hidden - await testSubjects.exists('fieldSelectionList'); + await testSubjects.click('graph-add-field-button'); + await testSubjects.existOrFail('graph-field-search', { timeout: 3000 }); }); } async selectField(field: string) { - await find.clickDisplayedByCssSelector( - 'select[id="fieldList"] > option[label="' + field + '"]' - ); - await find.clickDisplayedByCssSelector('button[ng-click="addFieldToSelection()"]'); + await testSubjects.setValue('graph-field-search', field); + await find.clickDisplayedByCssSelector(`[title="${field}"]`); } - async addField(field: string) { + async addFields(fields: string[]) { log.debug('click Add Field icon'); await this.clickAddField(); - log.debug('select field ' + field); - await this.selectField(field); + for (const field of fields) { + log.debug('select field ' + field); + await this.selectField(field); + } } async query(str: string) { - await find.setValue('input.kuiLocalSearchInput', str); - await find.clickDisplayedByCssSelector('button.kuiLocalSearchButton'); + await testSubjects.click('queryInput'); + await testSubjects.setValue('queryInput', str); + await testSubjects.click('graph-explore-button'); } private getPositionAsString(x: string, y: string) { @@ -125,7 +131,7 @@ export function GraphPageProvider({ getService, getPageObjects }: FtrProviderCon async getGraphObjects() { await this.stopLayout(); const graphElements = await find.allByCssSelector( - '#svgRootGroup line, #svgRootGroup circle, text.gphNode__label' + '#graphSvg line, #graphSvg circle, #graphSvg text.gphNode__label' ); const nodes: Node[] = []; const nodePositionMap: Record = {}; @@ -154,7 +160,7 @@ export function GraphPageProvider({ getService, getPageObjects }: FtrProviderCon const [sourcePosition, targetPosition] = await this.getLinePositions(element); const lineStyle = await element.getAttribute('style'); // grep out the width of the connection from the style attribute - const strokeWidth = Number(/stroke-width: (\d+(\.\d+)?)px/.exec(lineStyle)![1]); + const strokeWidth = Number(/stroke-width: ?(\d+(\.\d+)?)/.exec(lineStyle)![1]); edges.push({ element, width: strokeWidth, @@ -180,13 +186,19 @@ export function GraphPageProvider({ getService, getPageObjects }: FtrProviderCon async newGraph() { log.debug('Click New Workspace'); - await testSubjects.click('graphNewButton'); - await PageObjects.common.sleep(1000); + await retry.try(async () => { + await testSubjects.click('graphNewButton'); + await testSubjects.existOrFail('confirmModal', { timeout: 3000 }); + }); await PageObjects.common.clickConfirmOnModal(); + await testSubjects.existOrFail('graphGuidancePanel'); } async saveGraph(name: string) { - await testSubjects.click('graphSaveButton'); + await retry.try(async () => { + await testSubjects.click('graphSaveButton'); + await testSubjects.existOrFail('savedObjectTitle', { timeout: 3000 }); + }); await testSubjects.setValue('savedObjectTitle', name); await testSubjects.click('confirmSaveSavedObjectButton'); @@ -213,7 +225,10 @@ export function GraphPageProvider({ getService, getPageObjects }: FtrProviderCon } async goToListingPage() { - await testSubjects.click('graphHomeBreadcrumb'); + await retry.try(async () => { + await testSubjects.click('breadcrumb graphHomeBreadcrumb first'); + await testSubjects.existOrFail('workspaceLandingPage', { timeout: 3000 }); + }); } async openGraph(name: string) { @@ -224,7 +239,6 @@ export function GraphPageProvider({ getService, getPageObjects }: FtrProviderCon } async deleteGraph(name: string) { - await this.goToListingPage(); await this.searchForWorkspaceWithName(name); await testSubjects.click('checkboxSelectAll'); await this.clickDeleteSelectedWorkspaces();