Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Graph] Fix functional tests #47053

Merged
merged 17 commits into from
Oct 9, 2019
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ export function FieldPicker({ fieldMap, selectField, deselectField }: FieldPicke
panelPaddingSize="none"
button={
<EuiBadge
data-test-subj="graph-add-field-button"
className={classNames('gphFieldPicker__button', {
'gphFieldPicker__button--disabled': !hasFields,
})}
Expand Down Expand Up @@ -81,6 +82,7 @@ export function FieldPicker({ fieldMap, selectField, deselectField }: FieldPicke
defaultMessage: 'Filter fields',
}),
compressed: true,
'data-test-subj': 'graph-field-search',
}}
listProps={{
className: 'gphFieldPicker__selectableList',
Expand Down
7 changes: 6 additions & 1 deletion x-pack/legacy/plugins/graph/public/components/search_bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,12 @@ export function SearchBar(props: SearchBarProps) {
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton fill type="submit" disabled={isLoading || !currentIndexPattern}>
<EuiButton
data-test-subj="graph-explore-button"
fill
type="submit"
disabled={isLoading || !currentIndexPattern}
>
{i18n.translate('xpack.graph.bar.exploreLabel', { defaultMessage: 'Explore' })}
</EuiButton>
</EuiFlexItem>
Expand Down
71 changes: 32 additions & 39 deletions x-pack/test/functional/apps/graph/graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -47,67 +46,57 @@ export default function({ getService, getPageObjects }: FtrProviderContext) {
'/blog/wp-admin/',
];

const expectedConnectionWidth: Record<string, Record<string, number>> = {
'/blog/wp-admin/': { wp: 2, blog: 5.51581 },
const expectedConnections: Record<string, Record<string, boolean>> = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After syncing with @markharwood it doesn't make sense to validate specific line lengths because the exact numbers can change because of a lot of things.

'/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 PageObjects.common.sleep(1000);
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();
expect(edges.length).to.be(expectedConnectionCount);
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);
});
});

Expand All @@ -122,11 +111,15 @@ 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 => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't validate the order of nodes because it doesn't matter

expect(expectedNodes.includes(circleText)).to.be(true);
});
});

it('should create new Graph workspace', async function() {
await PageObjects.graph.newGraph();
await PageObjects.graph.selectIndexPattern('secrepo*');
await PageObjects.common.sleep(1000);
const { nodes, edges } = await PageObjects.graph.getGraphObjects();
expect(nodes).to.be.empty();
expect(edges).to.be.empty();
Expand Down
51 changes: 28 additions & 23 deletions x-pack/test/functional/page_objects/graph_page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,35 +28,31 @@ 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(`savedObjectTitle${pattern.split(' ').join('-')}`);
}

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');
}

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) {
Expand Down Expand Up @@ -125,7 +121,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<string, number> = {};
Expand Down Expand Up @@ -154,7 +150,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,
Expand All @@ -180,13 +176,20 @@ 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();
// wait for route change to complete
await PageObjects.common.sleep(3000);
dmlemeshko marked this conversation as resolved.
Show resolved Hide resolved
}

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');

Expand All @@ -213,7 +216,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) {
Expand All @@ -224,7 +230,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();
Expand Down