Skip to content

Commit

Permalink
Transforms unit and cypress tests (opensearch-project#92)
Browse files Browse the repository at this point in the history
* Transform cypress tests (opensearch-project#21)

* Added Cypress tests for Transforms UI

* License update

* Unit tests initial commit

* Added jest tests for Transforms, details, edit and create

* Sample transform fix

* Fixed cypress test transform and sample data load order

Signed-off-by: Eric Lobdell <[email protected]>

* Test fix debug

* Simplified unit test

* Updated transforms cypress test comments and success criteria

Signed-off-by: Eric Lobdell <[email protected]>

* Fixed quotation mark issue in test

Signed-off-by: Eric Lobdell <[email protected]>

* Removed debug mapping and index objects from unit test

Signed-off-by: Eric Lobdell <[email protected]>

* Cypress test improvements and completed edit transform unit test

Signed-off-by: Eric Lobdell <[email protected]>

* Integ test delete fix and EditTransforms jest test fix

Signed-off-by: Eric Lobdell <[email protected]>

* Restoring enable disable page refresh delay to fix failing integ test

Signed-off-by: Eric Lobdell <[email protected]>

* Resolve test constants conflict

Signed-off-by: Eric Lobdell <[email protected]>
  • Loading branch information
lobdelle authored Oct 22, 2021
1 parent c350f9c commit 784fc02
Show file tree
Hide file tree
Showing 16 changed files with 3,202 additions and 1 deletion.
40 changes: 40 additions & 0 deletions cypress/fixtures/sample_transform.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"transform": {
"enabled": true,
"schedule": {
"interval": {
"period": 1,
"unit": "Minutes",
"start_time": 1602100553
}
},
"description": "Test transform",
"source_index": "opensearch_dashboards_sample_data_ecommerce",
"target_index": "test_transform",
"data_selection_query": {
"match_all": {}
},
"page_size": 1000,
"groups": [
{
"terms": {
"source_field": "customer_gender",
"target_field": "gender"
}
},
{
"terms": {
"source_field": "day_of_week",
"target_field": "day"
}
}
],
"aggregations": {
"quantity": {
"sum": {
"field": "total_quantity"
}
}
}
}
}
257 changes: 257 additions & 0 deletions cypress/integration/transforms_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/

import { PLUGIN_NAME } from "../support/constants";
import sampleTransform from "../fixtures/sample_transform";

const TRANSFORM_ID = "test_transform_id";

describe("Transforms", () => {
before(() => {
// Delete all indices
cy.deleteAllIndices();

// Load ecommerce data
cy.request({
method: 'POST',
url:`${Cypress.env("opensearch_dashboards")}/api/sample_data/ecommerce`,
headers: {
'osd-xsrf': true
}
}).then((response) => {
expect(response.status).equal(200);
});
});

beforeEach(() => {
// delete test transform and index
cy.request("DELETE", `${Cypress.env("opensearch")}/test_transform*`);
cy.request({
method: 'POST',
url: `${Cypress.env("opensearch")}/_plugins/_transform/${TRANSFORM_ID}/_stop`,
failOnStatusCode: false
});
cy.request({
method: 'DELETE',
url: `${Cypress.env("opensearch")}/_plugins/_transform/${TRANSFORM_ID} `,
failOnStatusCode: false
});

// Set welcome screen tracking to test_transform_target
localStorage.setItem("home:welcome:show", true);

// Visit ISM Transforms Dashboard
cy.visit(`${Cypress.env("opensearch_dashboards")}/app/${PLUGIN_NAME}#/transforms`);

// Common text to wait for to confirm page loaded, give up to 60 seconds for initial load
cy.contains("Create transform", { timeout: 60000 });
});

describe("can be created", () => {
it("successfully", () => {
// Confirm we loaded empty state
cy.contains(
"Transform jobs help you create a materialized view on top of existing data."
);

// Route to create transform page
cy.contains("Create transform").click({ force: true });

// Type in transform ID
cy.get(`input[placeholder="my-transformjob1"]`).type(TRANSFORM_ID, { force: true });

// Get description input box
cy.get(`textarea[data-test-subj="description"]`).focus().type("some description");

// Enter source index
cy.get(`div[data-test-subj="sourceIndexCombobox"]`)
.find(`input[data-test-subj="comboBoxSearchInput"]`)
.focus()
.type("opensearch_dashboards_sample_data_ecommerce{enter}");

// Enter target index
cy.get(`div[data-test-subj="targetIndexCombobox"]`)
.find(`input[data-test-subj="comboBoxSearchInput"]`)
.focus()
.type("test_transform{enter}");

// Click the next button
cy.get("button").contains("Next").click({ force: true });

// Confirm that we got to step 2 of creation page
cy.contains("Select fields to transform");

cy.get(`button[data-test-subj="category.keywordOptionsPopover"]`)
.click({ force: true });

cy.contains("Group by terms").click({ force: true });

// Confirm group was added
cy.contains("category.keyword_terms");

// Add aggregable field
cy.contains("50 columns hidden").click({ force: true });
cy.contains("taxless_total_price").click({ force: true });
// Click out of the window
cy.contains("Select fields to transform").click({ force: true });

cy.get(`button[data-test-subj="taxless_total_priceOptionsPopover"]`)
.click({ force: true });

cy.contains("Aggregate by avg").click({ force: true });

// Confirm agg was added
cy.contains("avg_taxless_total_price");

// Click the next button
cy.get("button").contains("Next").click({ force: true });

// Confirm that we got to step 3 of creation page
cy.contains("Job enabled by default");

// Click the next button
cy.get("button").contains("Next").click({ force: true });

// Confirm that we got to step 4 of creation page
cy.contains("Review and create");

// Click the create button
cy.get("button").contains("Create").click({ force: true });

// Verify that sample data is add by checking toast notification
cy.contains(`Transform job "${TRANSFORM_ID}" successfully created.`);
cy.location('hash').should('contain', 'transforms');
cy.get(`button[data-test-subj="transformLink_${TRANSFORM_ID}"]`);
});
});

describe("can be edited", () => {
beforeEach(() => {
cy.createTransform(TRANSFORM_ID, sampleTransform);
cy.reload();
});

it("successfully", () => {
// Confirm we have our initial transform
cy.contains(TRANSFORM_ID);

// Select checkbox for our transform
cy.get(`#_selection_column_${TRANSFORM_ID}-checkbox`)
.check({ force: true });

// Click on Actions popover menu
cy.get(`[data-test-subj="actionButton"]`).click({ force: true });

// Click Edit button
cy.get(`[data-test-subj="editButton"]`).click({ force: true });

// Wait for initial transform job to load
cy.contains("Test transform");

cy.get(`textArea[data-test-subj="description"]`).focus().clear().type("A new description");

// Click Save changes button
cy.get(`[data-test-subj="editTransformSaveButton"]`).click({ force: true });

// Confirm we get toaster saying changes saved
cy.contains(`Changes to transform saved`);

// Click into transform job details page
cy.get(`[data-test-subj="transformLink_${TRANSFORM_ID}"]`).click({ force: true });

// Confirm new description shows in details page
cy.contains("A new description");
});
});

describe("can be deleted", () => {
beforeEach(() => {
cy.createTransform(TRANSFORM_ID, sampleTransform);
cy.reload();
});

it("successfully", () => {
// Confirm we have our initial transform
cy.contains(TRANSFORM_ID);

// Disable transform
cy.get(`#_selection_column_${TRANSFORM_ID}-checkbox`).check({ force: true });
cy.get(`[data-test-subj="disableButton"]`).click({ force: true });
cy.contains(`"${TRANSFORM_ID}" is disabled`);

// Select checkbox for our transform job
cy.get(`#_selection_column_${TRANSFORM_ID}-checkbox`).check({ force: true });

// Click on Actions popover menu
cy.get(`[data-test-subj="actionButton"]`).click({ force: true });

// Click Delete button
cy.get(`[data-test-subj="deleteButton"]`).click({ force: true });

// Type "delete" to confirm deletion
cy.get(`input[placeholder="delete"]`).type("delete", { force: true });

// Click the delete confirmation button in modal
cy.get(`[data-test-subj="confirmModalConfirmButton"]`).click();

// Confirm we got deleted toaster
cy.contains(`"${TRANSFORM_ID}" successfully deleted`);

// Confirm showing empty loading state
cy.contains(
"Transform jobs help you create a materialized view on top of existing data."
);
});
});

describe("can be enabled and disabled", () => {
beforeEach(() => {
cy.createTransform(TRANSFORM_ID, sampleTransform);
cy.reload();
});

it("successfully", () => {
// Confirm we have our initial transform
cy.contains(TRANSFORM_ID);

// Click into transform job details page
cy.get(`[data-test-subj="transformLink_${TRANSFORM_ID}"]`).click({ force: true });

cy.contains(`${TRANSFORM_ID}`);

/* Wait required for page data to load, otherwise "Disable" button will
* appear greyed out and unavailable. Cypress automatically retries,
* but only after menu is open, doesn't re-render.
*/
cy.wait(1000);

// Click into Actions menu
cy.get(`[data-test-subj="actionButton"]`).click({ force: true });

// Click Disable button
cy.get(`[data-test-subj="disableButton"]`).click();

// Confirm we get toaster saying transform job is disabled
cy.contains(`"${TRANSFORM_ID}" is disabled`);

cy.wait(1000);

// Click into Actions menu
cy.get(`[data-test-subj="actionButton"]`).click({ force: true });

// Click Enable button
cy.get(`[data-test-subj="enableButton"]`).click({ force: true });

// Confirm we get toaster saying transform job is enabled
cy.contains(`"${TRANSFORM_ID}" is enabled`);
});
})
});
4 changes: 4 additions & 0 deletions cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,7 @@ Cypress.Commands.add("deleteDataStreams", (names) => {
Cypress.Commands.add("rollover", (target) => {
cy.request("POST", `${Cypress.env("opensearch")}/${target}/_rollover`);
});

Cypress.Commands.add("createTransform", (transformId, transformJSON) => {
cy.request("PUT", `${Cypress.env("opensearch")}${API.TRANSFORM_JOBS_BASE}/${transformId}`, transformJSON);
});
2 changes: 2 additions & 0 deletions cypress/support/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

export const API_ROUTE_PREFIX = "/_plugins/_ism";
export const API_ROUTE_PREFIX_ROLLUP = "/_plugins/_rollup";
export const API_ROUTE_PREFIX_TRANSFORM = "/_plugins/_transform";

export const INDEX = {
OPENDISTRO_ISM_CONFIG: ".opendistro-ism-config",
Expand All @@ -41,6 +42,7 @@ export const API = {
REMOVE_POLICY_BASE: `${API_ROUTE_PREFIX}/remove`,
CHANGE_POLICY_BASE: `${API_ROUTE_PREFIX}/change_policy`,
ROLLUP_JOBS_BASE: `${API_ROUTE_PREFIX_ROLLUP}/jobs`,
TRANSFORM_JOBS_BASE: `${API_ROUTE_PREFIX_TRANSFORM}`,
};

export const PLUGIN_NAME = "opensearch_index_management_dashboards";
7 changes: 7 additions & 0 deletions cypress/support/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,12 @@ declare namespace Cypress {
* cy.rollover("some_rollover_target")
*/
rollover(target: string): Chainable<any>;

/**
* Creates a transform
* @example
* cy.createTransform("some_transform", { "transform": { ... } })
*/
createTransform(transformId: string, transformJSON: object): Chainable<any>;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ export default function DefineTransforms({

React.useEffect(() => {
fetchData();

}, []);

const onChangeItemsPerPage = useCallback(
Expand Down Expand Up @@ -145,6 +146,7 @@ export default function DefineTransforms({
);

const renderCellValue = ({ rowIndex, columnId }) => {

if (!loading && data.hasOwnProperty(rowIndex)) {
if (columns?.find((column) => column.id == columnId).schema == "keyword") {
// Remove the keyword postfix for getting correct data from array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,7 @@ export default function TransformOptions({
},
];

const button = <EuiButtonIcon iconType="plusInCircleFilled" onClick={() => setIsPopoverOpen(!isPopoverOpen)} />;
const button = <EuiButtonIcon iconType="plusInCircleFilled" onClick={() => setIsPopoverOpen(!isPopoverOpen)} data-test-subj={`${name}OptionsPopover`} />;

return (
<div>
Expand Down
Loading

0 comments on commit 784fc02

Please sign in to comment.