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

[Canvas] Adds functional test for Canvas custom elements #52920

Merged
merged 3 commits into from
Jan 14, 2020
Merged
Show file tree
Hide file tree
Changes from all 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

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ export class CustomElementModal extends PureComponent<Props, State> {
this._handleChange('name', e.target.value)
}
required
data-test-subj="canvasCustomElementForm-name"
/>
</EuiFormRow>
<EuiFormRow
Expand All @@ -156,6 +157,7 @@ export class CustomElementModal extends PureComponent<Props, State> {
e.target.value.length <= MAX_DESCRIPTION_LENGTH &&
this._handleChange('description', e.target.value)
}
data-test-subj="canvasCustomElementForm-description"
/>
</EuiFormRow>
<EuiFormRow
Expand Down Expand Up @@ -197,6 +199,7 @@ export class CustomElementModal extends PureComponent<Props, State> {
onClick={() => {
onSave(name, description, image);
}}
data-test-subj="canvasCustomElementForm-submit"
>
{strings.getSaveButtonLabel()}
</EuiButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ export const basicHandlerCreators = {
.create(customElement)
.then(() =>
notify.success(
`Custom element '${customElement.displayName || customElement.id}' was saved`
`Custom element '${customElement.displayName || customElement.id}' was saved`,
{
'data-test-subj': 'canvasCustomElementCreate-success',
}
)
)
.catch((result: Http2ServerResponse) =>
Expand Down
164 changes: 164 additions & 0 deletions x-pack/test/functional/apps/canvas/custom_elements.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/*
* 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';

export default function canvasCustomElementTest({
getService,
getPageObjects,
}: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const testSubjects = getService('testSubjects');
const browser = getService('browser');
const retry = getService('retry');
const PageObjects = getPageObjects(['canvas', 'common']);
const find = getService('find');

describe('custom elements', function() {
this.tags('skipFirefox');

before(async () => {
// init data
await esArchiver.loadIfNeeded('logstash_functional');
await esArchiver.load('canvas/default');

// open canvas home
await PageObjects.common.navigateToApp('canvas');

// load test workpad
await PageObjects.common.navigateToApp('canvas', {
hash: '/workpad/workpad-1705f884-6224-47de-ba49-ca224fe6ec31/page/1',
});
});

it('creates a custom element from an element when prompted', async () => {
// find the first workpad element (a markdown element) and click it to select it
await testSubjects.click('canvasWorkpadPage > canvasWorkpadPageElementContent', 20000);

// click the "Save as new element" button
await find.clickByCssSelector('[aria-label="Save as new element"]', 20000);

// fill out the custom element form and submit it
await PageObjects.canvas.fillOutCustomElementForm(
'My New Element',
'An excellent new element'
);

// wait for the custom element success toast notif
await testSubjects.exists('canvasCustomElementCreate-success', {
timeout: 30000,
});
});

it('adds the custom element to the workpad when prompted', async () => {
await PageObjects.canvas.openAddElementModal();

// open the custom elements tab
await find.clickByCssSelector('#customElements', 20000);

// ensure the custom element is the one expected and click it to add to the workpad
const customElement = await find.byCssSelector(
'[aria-labelledby="customElements"] .canvasElementCard__wrapper'
);
const elementName = await customElement.findByCssSelector('.euiCard__title');
expect(await elementName.getVisibleText()).to.contain('My New Element');
customElement.click();

await retry.try(async () => {
// ensure the new element is on the workpad
const elements = await testSubjects.findAll(
'canvasWorkpadPage > canvasWorkpadPageElementContent'
);
expect(elements).to.have.length(5);

// ensure the new element has the expected content
const newElem = elements[4];
const md = await newElem.findByCssSelector('.canvasMarkdown');
expect(await md.getVisibleText()).to.contain('Welcome to Canvas');

// delete the element off the workpad
await newElem.click();
await browser.pressKeys(browser.keys.DELETE);

// ensure the new element has been removed
const elementsAgain = await testSubjects.findAll(
'canvasWorkpadPage > canvasWorkpadPageElementContent'
);
expect(elementsAgain).to.have.length(4);
});
});

it('saves custom element modifications', async () => {
await PageObjects.canvas.openAddElementModal();

// open the custom elements tab
await find.clickByCssSelector('#customElements', 20000);

// ensure the correct amount of custom elements exist
const container = await find.byCssSelector('[aria-labelledby="customElements"]');
const customElements = await container.findAllByCssSelector('.canvasElementCard__wrapper');
expect(customElements).to.have.length(1);

// hover over the custom element to bring up the edit and delete icons
const customElement = customElements[0];
await customElement.moveMouseTo();

// click the edit element button
const editBtn = await customElement.findByCssSelector('[aria-label="Edit element"]');
await editBtn.click();

// fill out the custom element form and submit it
await PageObjects.canvas.fillOutCustomElementForm(
'My Edited New Element',
'An excellent edited element'
);

// ensure the custom element in the modal shows the updated text
await retry.try(async () => {
const elementName = await find.byCssSelector(
'[aria-labelledby="customElements"] .canvasElementCard__wrapper .euiCard__title'
);

expect(await elementName.getVisibleText()).to.contain('My Edited New Element');
});
});

it('deletes custom element when prompted', async () => {
// open the custom elements tab
await find.clickByCssSelector('#customElements', 20000);

// ensure the correct amount of custom elements exist
const customElements = await find.allByCssSelector(
'[aria-labelledby="customElements"] .canvasElementCard__wrapper'
);
expect(customElements).to.have.length(1);

// hover over the custom element to bring up the edit and delete icons
const customElement = customElements[0];
await customElement.moveMouseTo();

// click the delete element button
const editBtn = await customElement.findByCssSelector('[aria-label="Delete element"]');
await editBtn.click();

await testSubjects.click('confirmModalConfirmButton');

// ensure the custom element was deleted
await retry.try(async () => {
const containerAgain = await find.byCssSelector('[aria-labelledby="customElements"]');
const customElementsAgain = await containerAgain.findAllByCssSelector(
'.canvasElementCard__wrapper'
);
expect(customElementsAgain).to.have.length(0);
});

// Close the modal
await browser.pressKeys(browser.keys.ESCAPE);
});
Copy link
Member

Choose a reason for hiding this comment

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

It is not critical, but nice to wrap element search and interactions into "user-readable" functions. In this case, test scenario is easy to understand and support in the future.

it('deletes custom element when prompted', async () => {
  await PageObjects.canvas.openCustomElementsTab();
  await PageObjects.canvas.checkCustomElementsCount(1);
  await PageObjects.canvas.deleteElementByIndex(0);
  await PageObjects.canvas.checkCustomElementsCount(0);
}

});
}
1 change: 1 addition & 0 deletions x-pack/test/functional/apps/canvas/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default function canvasApp({ loadTestFile }) {
this.tags('ciGroup2'); // CI requires tags ヽ(゜Q。)ノ?
loadTestFile(require.resolve('./smoke_test'));
loadTestFile(require.resolve('./expression'));
loadTestFile(require.resolve('./custom_elements'));
loadTestFile(require.resolve('./feature_controls/canvas_security'));
loadTestFile(require.resolve('./feature_controls/canvas_spaces'));
});
Expand Down
12 changes: 12 additions & 0 deletions x-pack/test/functional/page_objects/canvas_page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ export function CanvasPageProvider({ getService }: FtrProviderContext) {
await testSubjects.findAll('canvasWorkpadPage > canvasWorkpadPageElementContent');
},

async fillOutCustomElementForm(name: string, description: string) {
// Fill out the custom element form and submit it
await testSubjects.setValue('canvasCustomElementForm-name', name);
await testSubjects.setValue('canvasCustomElementForm-description', description);

await testSubjects.click('canvasCustomElementForm-submit');
},

async expectCreateWorkpadButtonEnabled() {
const button = await testSubjects.find('create-workpad-button', 20000);
const disabledAttr = await button.getAttribute('disabled');
Expand All @@ -43,6 +51,10 @@ export function CanvasPageProvider({ getService }: FtrProviderContext) {
expect(disabledAttr).to.be('true');
},

async openAddElementModal() {
await testSubjects.click('add-element-button');
},

async expectAddElementButton() {
await testSubjects.existOrFail('add-element-button');
},
Expand Down