From 84db794b35c2e534dab4e973a41d0137a4dce764 Mon Sep 17 00:00:00 2001 From: suzhou Date: Fri, 23 Dec 2022 16:22:43 +0800 Subject: [PATCH 1/6] feat: update Signed-off-by: suzhou --- cypress/integration/templates.js | 91 ++ models/interfaces.ts | 92 +- .../AliasSelect/AliasSelect.test.tsx | 117 ++ .../__snapshots__/AliasSelect.test.tsx.snap | 115 ++ .../components/AliasSelect/index.tsx | 70 ++ .../components/IndexMapping/IndexMapping.scss | 19 + .../IndexMapping/IndexMapping.test.tsx | 165 +++ .../components/IndexMapping/IndexMapping.tsx | 366 ++++++ .../__snapshots__/IndexMapping.test.tsx.snap | 794 ++++++++++++ .../components/IndexMapping/index.ts | 9 + .../MappingLabel/MappingLabel.test.tsx | 39 + .../components/MappingLabel/MappingLabel.tsx | 268 +++++ .../__snapshots__/MappingLabel.test.tsx.snap | 240 ++++ .../components/MappingLabel/index.ts | 4 + .../CreateIndex/CreateIndex.test.tsx | 95 ++ .../containers/CreateIndex/CreateIndex.tsx | 61 + .../containers/CreateIndex/index.ts | 8 + .../containers/IndexForm/IndexForm.test.tsx | 289 +++++ .../containers/IndexForm/index.tsx | 417 +++++++ public/pages/CreateIndex/index.ts | 8 + .../components/TemplateType/TemplateType.tsx | 31 + .../components/TemplateType/index.ts | 4 + .../CreateIndexTemplate.test.tsx | 129 ++ .../CreateIndexTemplate.tsx | 73 ++ .../CreateIndexTemplate.test.tsx.snap | 720 +++++++++++ .../containers/CreateIndexTemplate/index.ts | 8 + .../TemplateDetail/TemplateDetail.test.tsx | 109 ++ .../TemplateDetail/TemplateDetail.tsx | 575 +++++++++ .../TemplateDetail.test.tsx.snap | 1070 +++++++++++++++++ .../containers/TemplateDetail/hooks.tsx | 55 + .../containers/TemplateDetail/index.ts | 9 + public/pages/CreateIndexTemplate/index.ts | 8 + public/pages/Main/Main.tsx | 61 +- .../IndexControls/IndexControls.test.tsx | 32 + .../IndexControls/IndexControls.tsx | 36 + .../__snapshots__/IndexControls.test.tsx.snap | 47 + .../components/IndexControls/index.ts | 9 + .../DeleteTemplateModal.test.tsx | 17 + .../DeleteTemplateModal.tsx | 52 + .../DeleteTemplateModal.test.tsx.snap | 143 +++ .../containers/DeleteTemplatesModal/index.ts | 8 + .../containers/Templates/Templates.test.tsx | 96 ++ .../containers/Templates/Templates.tsx | 335 ++++++ .../__snapshots__/Templates.test.tsx.snap | 400 ++++++ .../Templates/containers/Templates/index.ts | 3 + .../TemplatesActions.test.tsx | 142 +++ .../TemplatesActions.test.tsx.snap | 55 + .../containers/TemplatesActions/index.tsx | 77 ++ public/pages/Templates/index.ts | 8 + public/pages/Templates/interface.ts | 10 + public/pages/Templates/utils/constants.tsx | 16 + 51 files changed, 7594 insertions(+), 11 deletions(-) create mode 100644 cypress/integration/templates.js create mode 100644 public/pages/CreateIndex/components/AliasSelect/AliasSelect.test.tsx create mode 100644 public/pages/CreateIndex/components/AliasSelect/__snapshots__/AliasSelect.test.tsx.snap create mode 100644 public/pages/CreateIndex/components/AliasSelect/index.tsx create mode 100644 public/pages/CreateIndex/components/IndexMapping/IndexMapping.scss create mode 100644 public/pages/CreateIndex/components/IndexMapping/IndexMapping.test.tsx create mode 100644 public/pages/CreateIndex/components/IndexMapping/IndexMapping.tsx create mode 100644 public/pages/CreateIndex/components/IndexMapping/__snapshots__/IndexMapping.test.tsx.snap create mode 100644 public/pages/CreateIndex/components/IndexMapping/index.ts create mode 100644 public/pages/CreateIndex/components/MappingLabel/MappingLabel.test.tsx create mode 100644 public/pages/CreateIndex/components/MappingLabel/MappingLabel.tsx create mode 100644 public/pages/CreateIndex/components/MappingLabel/__snapshots__/MappingLabel.test.tsx.snap create mode 100644 public/pages/CreateIndex/components/MappingLabel/index.ts create mode 100644 public/pages/CreateIndex/containers/CreateIndex/CreateIndex.test.tsx create mode 100644 public/pages/CreateIndex/containers/CreateIndex/CreateIndex.tsx create mode 100644 public/pages/CreateIndex/containers/CreateIndex/index.ts create mode 100644 public/pages/CreateIndex/containers/IndexForm/IndexForm.test.tsx create mode 100644 public/pages/CreateIndex/containers/IndexForm/index.tsx create mode 100644 public/pages/CreateIndex/index.ts create mode 100644 public/pages/CreateIndexTemplate/components/TemplateType/TemplateType.tsx create mode 100644 public/pages/CreateIndexTemplate/components/TemplateType/index.ts create mode 100644 public/pages/CreateIndexTemplate/containers/CreateIndexTemplate/CreateIndexTemplate.test.tsx create mode 100644 public/pages/CreateIndexTemplate/containers/CreateIndexTemplate/CreateIndexTemplate.tsx create mode 100644 public/pages/CreateIndexTemplate/containers/CreateIndexTemplate/__snapshots__/CreateIndexTemplate.test.tsx.snap create mode 100644 public/pages/CreateIndexTemplate/containers/CreateIndexTemplate/index.ts create mode 100644 public/pages/CreateIndexTemplate/containers/TemplateDetail/TemplateDetail.test.tsx create mode 100644 public/pages/CreateIndexTemplate/containers/TemplateDetail/TemplateDetail.tsx create mode 100644 public/pages/CreateIndexTemplate/containers/TemplateDetail/__snapshots__/TemplateDetail.test.tsx.snap create mode 100644 public/pages/CreateIndexTemplate/containers/TemplateDetail/hooks.tsx create mode 100644 public/pages/CreateIndexTemplate/containers/TemplateDetail/index.ts create mode 100644 public/pages/CreateIndexTemplate/index.ts create mode 100644 public/pages/Templates/components/IndexControls/IndexControls.test.tsx create mode 100644 public/pages/Templates/components/IndexControls/IndexControls.tsx create mode 100644 public/pages/Templates/components/IndexControls/__snapshots__/IndexControls.test.tsx.snap create mode 100644 public/pages/Templates/components/IndexControls/index.ts create mode 100644 public/pages/Templates/containers/DeleteTemplatesModal/DeleteTemplateModal.test.tsx create mode 100644 public/pages/Templates/containers/DeleteTemplatesModal/DeleteTemplateModal.tsx create mode 100644 public/pages/Templates/containers/DeleteTemplatesModal/__snapshots__/DeleteTemplateModal.test.tsx.snap create mode 100644 public/pages/Templates/containers/DeleteTemplatesModal/index.ts create mode 100644 public/pages/Templates/containers/Templates/Templates.test.tsx create mode 100644 public/pages/Templates/containers/Templates/Templates.tsx create mode 100644 public/pages/Templates/containers/Templates/__snapshots__/Templates.test.tsx.snap create mode 100644 public/pages/Templates/containers/Templates/index.ts create mode 100644 public/pages/Templates/containers/TemplatesActions/TemplatesActions.test.tsx create mode 100644 public/pages/Templates/containers/TemplatesActions/__snapshots__/TemplatesActions.test.tsx.snap create mode 100644 public/pages/Templates/containers/TemplatesActions/index.tsx create mode 100644 public/pages/Templates/index.ts create mode 100644 public/pages/Templates/interface.ts create mode 100644 public/pages/Templates/utils/constants.tsx diff --git a/cypress/integration/templates.js b/cypress/integration/templates.js new file mode 100644 index 000000000..c0743a8cf --- /dev/null +++ b/cypress/integration/templates.js @@ -0,0 +1,91 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +import { PLUGIN_NAME } from "../support/constants"; + +const SAMPLE_TEMPLATE_PREFIX = "index-for-alias-test"; +const MAX_TEMPLATE_NUMBER = 30; + +describe("Templates", () => { + before(() => { + // Set welcome screen tracking to false + localStorage.setItem("home:welcome:show", "false"); + cy.deleteTemplate(`${SAMPLE_TEMPLATE_PREFIX}-${MAX_TEMPLATE_NUMBER}`); + for (let i = 0; i < MAX_TEMPLATE_NUMBER; i++) { + cy.deleteTemplate(`${SAMPLE_TEMPLATE_PREFIX}-${i}`); + cy.createIndexTemplate(`${SAMPLE_TEMPLATE_PREFIX}-${i}`, { + index_patterns: ["template-test-*"], + priority: i, + template: { + aliases: {}, + settings: { + number_of_shards: 2, + number_of_replicas: 1, + }, + }, + }); + } + }); + + beforeEach(() => { + // Visit ISM OSD + cy.visit(`${Cypress.env("opensearch_dashboards")}/app/${PLUGIN_NAME}#/templates`); + + // Common text to wait for to confirm page loaded, give up to 60 seconds for initial load + cy.contains("Rows per page", { timeout: 60000 }); + }); + + describe("can be searched / sorted / paginated", () => { + it("successfully", () => { + cy.get('[data-test-subj="pagination-button-1"]').should("exist"); + cy.get('[placeholder="Search..."]').type(`${SAMPLE_TEMPLATE_PREFIX}-0`); + cy.contains(`${SAMPLE_TEMPLATE_PREFIX}-0`); + cy.get(".euiTableRow").should("have.length", 1); + }); + }); + + describe("can create a template", () => { + it("successfully", () => { + cy.get('[data-test-subj="Create templateButton"]').click(); + cy.contains("Define template"); + + cy.get('[data-test-subj="form-row-name"] input').type(`${SAMPLE_TEMPLATE_PREFIX}-${MAX_TEMPLATE_NUMBER}`); + cy.get('[data-test-subj="form-row-index_patterns"] [data-test-subj="comboBoxSearchInput"]').type("test{enter}"); + cy.get('[data-test-subj="CreateIndexTemplateCreateButton"]').click(); + + cy.contains(`${SAMPLE_TEMPLATE_PREFIX}-${MAX_TEMPLATE_NUMBER} has been successfully created.`); + + cy.get('[placeholder="Search..."]').type(`${SAMPLE_TEMPLATE_PREFIX}-${MAX_TEMPLATE_NUMBER}`); + cy.contains(`${SAMPLE_TEMPLATE_PREFIX}-${MAX_TEMPLATE_NUMBER}`); + cy.get(".euiTableRow").should("have.length", 1); + }); + }); + + describe("can delete a template", () => { + it("successfully", () => { + cy.get('[placeholder="Search..."]').type(`${SAMPLE_TEMPLATE_PREFIX}-0`); + cy.contains(`${SAMPLE_TEMPLATE_PREFIX}-0`); + cy.get(`#_selection_column_${SAMPLE_TEMPLATE_PREFIX}-0-checkbox`).click(); + + cy.get('[data-test-subj="moreAction"] button').click().get('[data-test-subj="deleteAction"]').click(); + // The confirm button should be disabled + cy.get('[data-test-subj="deleteConfirmButton"]').should("be.disabled"); + // type delete + cy.wait(500).get('[data-test-subj="deleteInput"]').type("delete"); + cy.get('[data-test-subj="deleteConfirmButton"]').should("not.be.disabled"); + // click to delete + cy.get('[data-test-subj="deleteConfirmButton"]').click(); + // the alias should not exist + cy.wait(500); + cy.get(`#_selection_column_${SAMPLE_TEMPLATE_PREFIX}-0-checkbox`).should("not.exist"); + }); + }); + + after(() => { + cy.deleteTemplate(`${SAMPLE_TEMPLATE_PREFIX}-${MAX_TEMPLATE_NUMBER}`); + for (let i = 0; i < MAX_TEMPLATE_NUMBER; i++) { + cy.deleteTemplate(`${SAMPLE_TEMPLATE_PREFIX}-${i}`); + } + }); +}); diff --git a/models/interfaces.ts b/models/interfaces.ts index 136a900a2..f4909d816 100644 --- a/models/interfaces.ts +++ b/models/interfaces.ts @@ -23,12 +23,70 @@ export interface ManagedIndexMetaData { info?: object; } +export type MappingsPropertiesObject = Record< + string, + { + type: string; + properties?: MappingsPropertiesObject; + } +>; + +export type MappingsProperties = { + fieldName: string; + type: string; + path?: string; + analyzer?: string; + properties?: MappingsProperties; +}[]; + +export interface IndexItem { + index: string; + indexUuid?: string; + data_stream: string | null; + settings?: { + index?: { + number_of_shards?: number; + number_of_replicas?: number; + creation_date?: string; + [key: string]: any; + }; + "index.number_of_shards"?: number; + "index.number_of_replicas"?: number; + "index.refresh_interval"?: string; + [key: string]: any; + }; + aliases?: Record; + mappings?: { + properties?: MappingsProperties; + [key: string]: any; + }; +} + +export interface IndexItemRemote extends Omit { + mappings?: { + properties?: MappingsPropertiesObject; + }; +} + +interface ITemplateExtras { + name: string; + data_stream?: {}; + version: number; + priority: number; + index_patterns: string[]; +} + +export interface TemplateItem extends ITemplateExtras { + template: Pick; +} +export interface TemplateItemRemote extends ITemplateExtras { + template: Pick; +} + /** * ManagedIndex item shown in the Managed Indices table */ -export interface ManagedIndexItem { - index: string; - indexUuid: string; +export interface ManagedIndexItem extends IndexItem { dataStream: string | null; policyId: string; policySeqNo: number; @@ -38,10 +96,6 @@ export interface ManagedIndexItem { managedIndexMetaData: ManagedIndexMetaData | null; } -export interface IndexItem { - index: string; -} - /** * Interface what the Policy Opensearch Document */ @@ -168,7 +222,7 @@ export interface SMDeleteCondition { export interface ErrorNotification { destination?: Destination; channel?: Channel; - message_template: MessageTemplate; + message_template?: MessageTemplate; } export interface Notification { @@ -564,3 +618,25 @@ export enum TRANSFORM_AGG_TYPE { histogram = "histogram", date_histogram = "date_histogram", } +export interface IAPICaller { + endpoint: string; + method?: string; + data?: any; +} + +export interface IRecoveryItem { + index: string; + stage: "done" | "translog"; +} + +export interface ITaskItem { + action: string; + description: string; +} + +export interface IReindexItem extends ITaskItem { + fromIndex: string; + toIndex: string; +} + +export type IAliasAction = Record; diff --git a/public/pages/CreateIndex/components/AliasSelect/AliasSelect.test.tsx b/public/pages/CreateIndex/components/AliasSelect/AliasSelect.test.tsx new file mode 100644 index 000000000..b78e65f70 --- /dev/null +++ b/public/pages/CreateIndex/components/AliasSelect/AliasSelect.test.tsx @@ -0,0 +1,117 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import React, { useState } from "react"; +import { render, waitFor } from "@testing-library/react"; +import AliasSelect, { AliasSelectProps } from "./index"; +import userEvent from "@testing-library/user-event"; + +const onChangeMock = jest.fn(); + +const AliasSelectWithOnchange = (props: AliasSelectProps) => { + const [tempValue, setTempValue] = useState(props.value); + return ( + { + onChangeMock(val); + setTempValue(val); + }} + /> + ); +}; + +describe(" spec", () => { + it("renders the component and remove duplicate aliases", async () => { + const onOptionsChange = jest.fn(); + const { container } = render( + + Promise.resolve({ + ok: true, + response: [ + { + alias: "a", + index: "a", + }, + { + alias: "a", + index: "b", + }, + ], + }) + } + onChange={() => {}} + onOptionsChange={onOptionsChange} + /> + ); + await waitFor( + () => { + expect(onOptionsChange).toBeCalledWith([ + { + label: "a", + }, + ]); + expect(container.firstChild).toMatchSnapshot(); + }, + { + timeout: 3000, + } + ); + }); + + it("renders with error", async () => { + const onOptionsChange = jest.fn(); + const { container } = render( + + Promise.resolve({ + ok: false, + error: "Some error", + }) + } + onChange={() => {}} + onOptionsChange={onOptionsChange} + /> + ); + await waitFor(() => {}); + expect(container).toMatchSnapshot(); + }); + + it("it should choose options or create one", async () => { + const { getByTestId } = render( + Promise.resolve({ ok: true, response: [{ alias: "test", index: "123", query: "test" }] })} + /> + ); + await waitFor(() => { + expect(getByTestId("comboBoxInput")).toBeInTheDocument(); + }); + await userEvent.click(getByTestId("comboBoxInput")); + await waitFor(() => { + expect(document.querySelector('button[title="test"]')).toBeInTheDocument(); + }); + await userEvent.click(document.querySelector('button[title="test"]') as Element); + await waitFor(() => { + expect(onChangeMock).toBeCalledTimes(1); + expect(onChangeMock).toBeCalledWith({ + test: {}, + }); + }); + await userEvent.type(getByTestId("comboBoxInput"), "test2{enter}"); + await waitFor(() => { + expect(onChangeMock).toBeCalledTimes(2); + expect(onChangeMock).toBeCalledWith({ + test: {}, + test2: {}, + }); + }); + await userEvent.type(getByTestId("comboBoxInput"), " {enter}"); + await waitFor(() => { + expect(onChangeMock).toBeCalledTimes(2); + }); + }); +}); diff --git a/public/pages/CreateIndex/components/AliasSelect/__snapshots__/AliasSelect.test.tsx.snap b/public/pages/CreateIndex/components/AliasSelect/__snapshots__/AliasSelect.test.tsx.snap new file mode 100644 index 000000000..fe44d3c78 --- /dev/null +++ b/public/pages/CreateIndex/components/AliasSelect/__snapshots__/AliasSelect.test.tsx.snap @@ -0,0 +1,115 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` spec renders the component and remove duplicate aliases 1`] = ` +