diff --git a/cypress/fixtures/sample_rollup.json b/cypress/fixtures/sample_rollup.json new file mode 100644 index 000000000..973110d04 --- /dev/null +++ b/cypress/fixtures/sample_rollup.json @@ -0,0 +1,58 @@ +{ + "rollup": { + "enabled": true, + "schedule": { + "interval": { + "period": 1, + "unit": "Minutes", + "start_time": 1602100553 + } + }, + "last_updated_time": 1602100553, + "description": "An example rollup job that rolls up the sample ecommerce data", + "source_index": "kibana_sample_data_ecommerce", + "target_index": "test_rollup_target", + "page_size": 1000, + "delay": 0, + "continuous": false, + "dimensions": [ + { + "date_histogram": { + "source_field": "order_date", + "fixed_interval": "90m", + "timezone": "America/Los_Angeles" + } + }, + { + "terms": { + "source_field": "customer_gender" + } + }, + { + "terms": { + "source_field": "geoip.city_name" + } + }, + { + "terms": { + "source_field": "geoip.region_name" + } + }, + { + "terms": { + "source_field": "day_of_week" + } + } + ], + "metrics": [ + { + "source_field": "taxless_total_price", + "metrics": [{ "avg": {} }, { "sum": {} }, { "max": {} }, { "min": {} }, { "value_count": {} }] + }, + { + "source_field": "total_quantity", + "metrics": [{ "avg": {} }, { "max": {} }] + } + ] + } +} diff --git a/cypress/integration/rollups_spec.js b/cypress/integration/rollups_spec.js new file mode 100644 index 000000000..a97ea3105 --- /dev/null +++ b/cypress/integration/rollups_spec.js @@ -0,0 +1,245 @@ +/* + * Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * or in the "license" file accompanying this file. This file is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + * express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +import { PLUGIN_NAME } from "../support/constants"; +import sampleRollup from "../fixtures/sample_rollup"; + +const ROLLUP_ID = "test_rollup_id"; + +describe("Rollups", () => { + beforeEach(() => { + // Set welcome screen tracking to true + localStorage.setItem("home:welcome:show", "true"); + + // Go to home page + cy.visit(`${Cypress.env("kibana")}/app/home`); + + // Click to add sample data + cy.get(`button[class="euiButton euiButton--primary homWelcome__footerAction euiButton--fill"]`) + .contains("Add data") + .click({ force: true }); + + // Click on "Sample data" tab + cy.contains("Sample data").click({ force: true }); + + // Load sample eCommerce data + cy.get(`button[data-test-subj="addSampleDataSetecommerce"]`).click({ force: true }); + + // Verify that sample data is add by checking toast notification + cy.contains("Sample eCommerce orders installed"); + + // Visit ISM Kibana + cy.visit(`${Cypress.env("kibana")}/app/${PLUGIN_NAME}#/rollups`); + + // Common text to wait for to confirm page loaded, give up to 60 seconds for initial load + cy.contains("Create rollup", { timeout: 60000 }); + }); + + describe("can be created", () => { + before(() => { + cy.deleteAllIndices(); + }); + + it("successfully", () => { + // Confirm we loaded empty state + cy.contains( + "Rollup jobs help you conserve storage space for historical time series data while preserving the specific information you need" + ); + + // Route us to create rollup page + cy.contains("Create rollup").click({ force: true }); + + // Type in the rollup ID + cy.get(`input[placeholder="my-rollupjob1"]`).type(ROLLUP_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("kibana_sample_data_ecommerce{enter}"); + + // Enter target index + cy.get(`div[data-test-subj="targetIndexCombobox"]`) + .find(`input[data-test-subj="comboBoxSearchInput"]`) + .focus() + .type("target_index{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("Time aggregation"); + + // Enter timestamp field + cy.get(`input[data-test-subj="comboBoxSearchInput"]`).focus().type("order_date{enter}"); + + // Add aggregation + cy.get(`button[data-test-subj="addFieldsAggregationEmpty"]`).click({ force: true }); + + // Select a few fields + cy.get(`input[data-test-subj="checkboxSelectRow-customer_gender"]`).click({ force: true }); + cy.get(`input[data-test-subj="checkboxSelectRow-day_of_week_i"]`).click({ force: true }); + cy.get(`input[data-test-subj="checkboxSelectRow-geoip.city_name"]`).click({ force: true }); + + // Click the Add button from add fields modal + cy.get(`button[data-test-subj="addFieldsAggregationAdd"]`).click({ force: true }); + + // Confirm fields are added + cy.contains("customer_gender"); + cy.contains("day_of_week_i"); + cy.contains("geoip.city_name"); + + // Add metrics + cy.get(`button[data-test-subj="addFieldsMetricEmpty"]`).click({ force: true }); + + // Select a few fields + cy.get(`input[data-test-subj="checkboxSelectRow-products.taxless_price"]`).click({ force: true }); + cy.get(`input[data-test-subj="checkboxSelectRow-total_quantity"]`).click({ force: true }); + + // Click the Add button from add fields modal + cy.get(`button[data-test-subj="addFieldsMetricAdd"]`).click({ force: true }); + + // Confirm fields are added + cy.contains("products.taxless_price"); + cy.contains("total_quantity"); + + cy.get(`input[data-test-subj="min-total_quantity"]`).click({ force: true }); + cy.get(`input[data-test-subj="max-total_quantity"]`).click({ force: true }); + cy.get(`input[data-test-subj="sum-total_quantity"]`).click({ force: true }); + cy.get(`input[data-test-subj="all-products.taxless_price"]`).click({ force: true }); + + // Click the next button + cy.get("button").contains("Next").click({ force: true }); + + // Confirm that we got to step 3 of creation page + cy.contains("Enable job 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("Job name and indices"); + + // Click the create button + cy.get("button").contains("Create").click({ force: true }); + + // Verify that sample data is add by checking toast notification + cy.contains(`Created rollup: ${ROLLUP_ID}`); + }); + }); + + describe("can be edited", () => { + before(() => { + cy.deleteAllIndices(); + cy.createRollup(ROLLUP_ID, sampleRollup); + }); + + it("successfully", () => { + // Confirm we have our initial rollup + cy.contains(ROLLUP_ID); + + // Select checkbox for our rollup job + cy.get(`#_selection_column_${ROLLUP_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 rollup job to load + cy.contains("An example rollup job that rolls up the sample ecommerce data"); + + cy.get(`textArea[data-test-subj="description"]`).focus().clear().type("A new description"); + + // Click Save changes button + cy.get(`[data-test-subj="editRollupSaveChangesButton"]`).click({ force: true }); + + // Confirm we get toaster saying changes saved + cy.contains(`Changes to "${ROLLUP_ID}" saved!`); + + // Click into rollup job details page + cy.get(`[data-test-subj="rollupLink_${ROLLUP_ID}"]`).click({ force: true }); + + // Confirm new description shows in details page + cy.contains("A new description"); + }); + }); + + describe("can be deleted", () => { + before(() => { + cy.deleteAllIndices(); + cy.createRollup(ROLLUP_ID, sampleRollup); + }); + + it("successfully", () => { + // Confirm we have our initial rollup + cy.contains(ROLLUP_ID); + + // Select checkbox for our rollup job + cy.get(`#_selection_column_${ROLLUP_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(`"${ROLLUP_ID}" successfully deleted!`); + + // Confirm showing empty loading state + cy.contains( + "Rollup jobs help you conserve storage space for historical time series data while preserving the specific information you need" + ); + }); + }); + + describe("can be enabled and disabled", () => { + before(() => { + cy.deleteAllIndices(); + cy.createRollup(ROLLUP_ID, sampleRollup); + }); + + it("successfully", () => { + // Confirm we have our initial rollup + cy.contains(ROLLUP_ID); + + // Click into rollup job details page + cy.get(`[data-test-subj="rollupLink_${ROLLUP_ID}"]`).click({ force: true }); + + // Click Disable button + cy.get(`[data-test-subj="disableButton"]`).click({ force: true }); + + // Confirm we get toaster saying rollup job is disabled + cy.contains(`${ROLLUP_ID} is disabled`); + + // Click Disable button + cy.get(`[data-test-subj="enableButton"]`).click({ force: true }); + + // Confirm we get toaster saying rollup job is enabled + cy.contains(`${ROLLUP_ID} is enabled`); + }); + }); +}); diff --git a/cypress/support/commands.js b/cypress/support/commands.js index 4e11a4e8f..eda9fffec 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -75,3 +75,7 @@ Cypress.Commands.add("updateManagedIndexConfigStartTime", (index) => { Cypress.Commands.add("createIndex", (index, settings = {}) => { cy.request("PUT", `${Cypress.env("elasticsearch")}/${index}`, settings); }); + +Cypress.Commands.add("createRollup", (rollupId, rollupJSON) => { + cy.request("PUT", `${Cypress.env("elasticsearch")}${API.ROLLUP_JOBS_BASE}/${rollupId}`, rollupJSON); +}); diff --git a/cypress/support/constants.js b/cypress/support/constants.js index 019f8aadd..63d121336 100644 --- a/cypress/support/constants.js +++ b/cypress/support/constants.js @@ -14,6 +14,7 @@ */ export const API_ROUTE_PREFIX = "/_opendistro/_ism"; +export const API_ROUTE_PREFIX_ROLLUP = "/_opendistro/_rollup"; export const INDEX = { OPENDISTRO_ISM_CONFIG: ".opendistro-ism-config", @@ -26,6 +27,7 @@ export const API = { ADD_POLICY_BASE: `${API_ROUTE_PREFIX}/add`, REMOVE_POLICY_BASE: `${API_ROUTE_PREFIX}/remove`, CHANGE_POLICY_BASE: `${API_ROUTE_PREFIX}/change_policy`, + ROLLUP_JOBS_BASE: `${API_ROUTE_PREFIX_ROLLUP}/jobs`, }; export const PLUGIN_NAME = "opendistro_index_management_kibana"; diff --git a/cypress/support/index.d.ts b/cypress/support/index.d.ts index 2bc10f1f5..6142d6f74 100644 --- a/cypress/support/index.d.ts +++ b/cypress/support/index.d.ts @@ -48,5 +48,11 @@ declare namespace Cypress { * cy.createIndex("some_index", "some_policy") */ createIndex(index: string, settings?: object): Chainable; + /** + * Creates a rollup + * @example + * cy.createRollup("some_rollup", { "rollup": { ... } }) + */ + createRollup(policyId: string, policyJSON: object): Chainable; } } diff --git a/public/pages/CreateRollup/components/AdvancedAggregation/AdvancedAggregation.tsx b/public/pages/CreateRollup/components/AdvancedAggregation/AdvancedAggregation.tsx index 7f6bc2930..130668f3c 100644 --- a/public/pages/CreateRollup/components/AdvancedAggregation/AdvancedAggregation.tsx +++ b/public/pages/CreateRollup/components/AdvancedAggregation/AdvancedAggregation.tsx @@ -484,6 +484,7 @@ export default class AdvancedAggregation extends Component Add diff --git a/public/pages/CreateRollup/components/MetricsCalculation/MetricsCalculation.tsx b/public/pages/CreateRollup/components/MetricsCalculation/MetricsCalculation.tsx index 664359031..e480cc41b 100644 --- a/public/pages/CreateRollup/components/MetricsCalculation/MetricsCalculation.tsx +++ b/public/pages/CreateRollup/components/MetricsCalculation/MetricsCalculation.tsx @@ -647,6 +647,7 @@ export default class MetricsCalculation extends Component Add diff --git a/public/pages/Rollups/containers/Rollups/Rollups.tsx b/public/pages/Rollups/containers/Rollups/Rollups.tsx index 8b4023fb7..b6fba955e 100644 --- a/public/pages/Rollups/containers/Rollups/Rollups.tsx +++ b/public/pages/Rollups/containers/Rollups/Rollups.tsx @@ -339,7 +339,11 @@ export default class Rollups extends Component { sortable: true, textOnly: true, truncateText: true, - render: (_id) => this.props.history.push(`${ROUTES.ROLLUP_DETAILS}?id=${_id}`)}>{_id}, + render: (_id) => ( + this.props.history.push(`${ROUTES.ROLLUP_DETAILS}?id=${_id}`)} data-test-subj={`rollupLink_${_id}`}> + {_id} + + ), }, { field: "rollup.rollup.source_index",