diff --git a/airbyte-webapp-e2e-tests/cypress.json b/airbyte-webapp-e2e-tests/cypress.json index 33229cb04513..41fe0938fea1 100644 --- a/airbyte-webapp-e2e-tests/cypress.json +++ b/airbyte-webapp-e2e-tests/cypress.json @@ -7,5 +7,6 @@ "retries": { "runMode": 2, "openMode": 0 - } + }, + "defaultCommandTimeout": 10000 } diff --git a/airbyte-webapp-e2e-tests/cypress/commands/common.ts b/airbyte-webapp-e2e-tests/cypress/commands/common.ts index c1dcc321071e..3c3284e2fa79 100644 --- a/airbyte-webapp-e2e-tests/cypress/commands/common.ts +++ b/airbyte-webapp-e2e-tests/cypress/commands/common.ts @@ -27,3 +27,9 @@ export const clearApp = () => { export const fillEmail = (email: string) => { cy.get("input[name=email]").type(email); }; + +// useful for ensuring that a name is unique from one test run to the next +export const appendRandomString = (string: string) => { + const randomString = Math.random().toString(36).substring(2,10); + return string + " _" + randomString; +} diff --git a/airbyte-webapp-e2e-tests/cypress/commands/workspaces.ts b/airbyte-webapp-e2e-tests/cypress/commands/workspaces.ts index 5b7daca6fe1a..8474c8b96fd4 100644 --- a/airbyte-webapp-e2e-tests/cypress/commands/workspaces.ts +++ b/airbyte-webapp-e2e-tests/cypress/commands/workspaces.ts @@ -7,4 +7,8 @@ export const initialSetupCompleted = (completed = true) => { res.send(res.body); }); }); + + cy.on('uncaught:exception', (err, runnable) => { + return false; + }); }; diff --git a/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts index 20fea0be2d9b..2bcecf91b023 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts @@ -1,4 +1,4 @@ -import { deleteEntity, submitButtonClick } from "commands/common"; +import { appendRandomString, deleteEntity, submitButtonClick } from "commands/common"; import { createTestConnection } from "commands/connection"; import { deleteDestination } from "commands/destination"; import { deleteSource } from "commands/source"; @@ -15,115 +15,126 @@ import { import { openSourceDestinationFromGrid, goToSourcePage } from "pages/sourcePage"; import { goToSettingsPage } from "pages/settingsConnectionPage"; -// describe("Connection main actions", () => { -// beforeEach(() => { -// initialSetupCompleted(); -// }); +describe("Connection main actions", () => { + beforeEach(() => { + initialSetupCompleted(); + }); -// it("Create new connection", () => { -// createTestConnection("Test connection source cypress", "Test connection destination cypress"); + it("Create new connection", () => { + const sourceName = appendRandomString("Test connection source cypress"); + const destName = appendRandomString("Test connection destination cypress") -// cy.get("div").contains("Test connection source cypress").should("exist"); -// cy.get("div").contains("Test connection destination cypress").should("exist"); + createTestConnection(sourceName, destName); -// deleteSource("Test connection source cypress"); -// deleteDestination("Test connection destination cypress"); -// }); + cy.get("div").contains(sourceName).should("exist"); + cy.get("div").contains(destName).should("exist"); -// it("Update connection", () => { -// cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection"); + deleteSource(sourceName); + deleteDestination(destName); + }); -// createTestConnection("Test update connection source cypress", "Test update connection destination cypress"); + it("Update connection", () => { + cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection"); -// goToSourcePage(); -// openSourceDestinationFromGrid("Test update connection source cypress"); -// openSourceDestinationFromGrid("Test update connection destination cypress"); + const sourceName = appendRandomString("Test update connection source cypress"); + const destName = appendRandomString("Test update connection destination cypress"); -// goToReplicationTab(); + createTestConnection(sourceName, destName); -// selectSchedule("Every hour"); -// fillOutDestinationPrefix("auto_test"); + goToSourcePage(); + openSourceDestinationFromGrid(sourceName); + openSourceDestinationFromGrid(destName); -// submitButtonClick(); + goToReplicationTab(); -// cy.wait("@updateConnection").then((interception) => { -// assert.isNotNull(interception.response?.statusCode, "200"); -// }); + selectSchedule("Every hour"); + fillOutDestinationPrefix("auto_test"); -// checkSuccessResult(); + submitButtonClick(); -// deleteSource("Test update connection source cypress"); -// deleteDestination("Test update connection destination cypress"); -// }); + cy.wait("@updateConnection").then((interception) => { + assert.isNotNull(interception.response?.statusCode, "200"); + }); -// it("Update connection (pokeAPI)", () => { -// cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection"); + checkSuccessResult(); -// createTestConnection( -// "Test update connection PokeAPI source cypress", -// "Test update connection Local JSON destination cypress" -// ); + deleteSource(sourceName); + deleteDestination(destName); + }); -// goToSourcePage(); -// openSourceDestinationFromGrid("Test update connection PokeAPI source cypress"); -// openSourceDestinationFromGrid("Test update connection Local JSON destination cypress"); + it("Update connection (pokeAPI)", () => { + cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection"); -// goToReplicationTab(); + const sourceName = appendRandomString("Test update connection PokeAPI source cypress"); + const destName = appendRandomString("Test update connection Local JSON destination cypress") -// selectSchedule("Every hour"); -// fillOutDestinationPrefix("auto_test"); -// setupDestinationNamespaceCustomFormat("_test"); -// selectFullAppendSyncMode(); + createTestConnection( + sourceName, + destName + ); -// submitButtonClick(); -// confirmStreamConfigurationChangedPopup(); + goToSourcePage(); + openSourceDestinationFromGrid(sourceName); + openSourceDestinationFromGrid("Test update connection Local JSON destination cypress"); -// cy.wait("@updateConnection").then((interception) => { -// assert.isNotNull(interception.response?.statusCode, "200"); -// expect(interception.request.method).to.eq("POST"); -// expect(interception.request).property("body").to.contain({ -// name: "Test update connection PokeAPI source cypress <> Test update connection Local JSON destination cypressConnection name", -// prefix: "auto_test", -// namespaceDefinition: "customformat", -// namespaceFormat: "${SOURCE_NAMESPACE}_test", -// status: "active", -// }); -// expect(interception.request.body.scheduleData.basicSchedule).to.contain({ -// units: 1, -// timeUnit: "hours", -// }); + goToReplicationTab(); -// const streamToUpdate = interception.request.body.syncCatalog.streams[0]; + selectSchedule("Every hour"); + fillOutDestinationPrefix("auto_test"); + setupDestinationNamespaceCustomFormat("_test"); + selectFullAppendSyncMode(); -// expect(streamToUpdate.config).to.contain({ -// aliasName: "pokemon", -// destinationSyncMode: "append", -// selected: true, -// }); + submitButtonClick(); + confirmStreamConfigurationChangedPopup(); -// expect(streamToUpdate.stream).to.contain({ -// name: "pokemon", -// }); -// expect(streamToUpdate.stream.supportedSyncModes).to.contain("full_refresh"); -// }); -// checkSuccessResult(); + cy.wait("@updateConnection").then((interception) => { + assert.isNotNull(interception.response?.statusCode, "200"); + expect(interception.request.method).to.eq("POST"); + expect(interception.request).property("body").to.contain({ + name: sourceName + " <> " + destName + "Connection name", + prefix: "auto_test", + namespaceDefinition: "customformat", + namespaceFormat: "${SOURCE_NAMESPACE}_test", + status: "active", + }); + expect(interception.request.body.scheduleData.basicSchedule).to.contain({ + units: 1, + timeUnit: "hours", + }); -// deleteSource("Test update connection PokeAPI source cypress"); -// deleteDestination("Test update connection Local JSON destination cypress"); -// }); + const streamToUpdate = interception.request.body.syncCatalog.streams[0]; -// it("Delete connection", () => { -// createTestConnection("Test delete connection source cypress", "Test delete connection destination cypress"); + expect(streamToUpdate.config).to.contain({ + aliasName: "pokemon", + destinationSyncMode: "append", + selected: true, + }); -// goToSourcePage(); -// openSourceDestinationFromGrid("Test delete connection source cypress"); -// openSourceDestinationFromGrid("Test delete connection destination cypress"); + expect(streamToUpdate.stream).to.contain({ + name: "pokemon", + }); + expect(streamToUpdate.stream.supportedSyncModes).to.contain("full_refresh"); + }); + checkSuccessResult(); -// goToSettingsPage(); + deleteSource(sourceName); + deleteDestination(destName); + }); -// deleteEntity(); + it("Delete connection", () => { + const sourceName = "Test delete connection source cypress"; + const destName = "Test delete connection destination cypress"; + createTestConnection(sourceName, destName); -// deleteSource("Test delete connection source cypress"); -// deleteDestination("Test delete connection destination cypress"); -// }); -// }); + goToSourcePage(); + openSourceDestinationFromGrid(sourceName); + openSourceDestinationFromGrid(destName); + + goToSettingsPage(); + + deleteEntity(); + + deleteSource(sourceName); + deleteDestination(destName); + }); +}); diff --git a/airbyte-webapp-e2e-tests/cypress/integration/destination.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/destination.spec.ts index 9a6452214c64..7295dcee90f2 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/destination.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/destination.spec.ts @@ -1,3 +1,4 @@ +import { appendRandomString } from "commands/common"; import { createLocalJsonDestination, deleteDestination, updateDestination } from "commands/destination"; import { initialSetupCompleted } from "commands/workspaces"; @@ -13,9 +14,10 @@ describe("Destination main actions", () => { }); it("Update destination", () => { - createLocalJsonDestination("Test destination cypress for update", "/local"); + const destName = appendRandomString("Test destination cypress for update"); + createLocalJsonDestination(destName, "/local"); updateDestination( - "Test destination cypress for update", + destName, "connectionConfiguration.destination_path", "/local/my-json" ); @@ -25,10 +27,11 @@ describe("Destination main actions", () => { }); it("Delete destination", () => { - createLocalJsonDestination("Test destination cypress for delete", "/local"); - deleteDestination("Test destination cypress for delete"); + const destName = appendRandomString("Test destination cypress for delete"); + createLocalJsonDestination(destName, "/local"); + deleteDestination(destName); cy.visit("/destination"); - cy.get("div").contains("Test destination cypress for delete").should("not.exist"); + cy.get("div").contains(destName).should("not.exist"); }); }); diff --git a/airbyte-webapp-e2e-tests/cypress/integration/source.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/source.spec.ts index 65d35bd17178..939f03083048 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/source.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/source.spec.ts @@ -1,3 +1,4 @@ +import { appendRandomString } from "commands/common"; import { createPostgresSource, deleteSource, updateSource } from "commands/source"; import { initialSetupCompleted } from "commands/workspaces"; @@ -14,18 +15,20 @@ describe("Source main actions", () => { //TODO: add update source on some other connector or create 1 more user for pg it.skip("Update source", () => { - createPostgresSource("Test source cypress for update"); - updateSource("Test source cypress for update", "connectionConfiguration.start_date", "2020-11-11"); + const sourceName = appendRandomString("Test source cypress for update"); + createPostgresSource(sourceName); + updateSource(sourceName, "connectionConfiguration.start_date", "2020-11-11"); cy.get("div[data-id='success-result']").should("exist"); cy.get("input[value='2020-11-11']").should("exist"); }); it("Delete source", () => { - createPostgresSource("Test source cypress for delete"); - deleteSource("Test source cypress for delete"); + const sourceName = appendRandomString("Test source cypress for delete"); + createPostgresSource(sourceName); + deleteSource(sourceName); cy.visit("/"); - cy.get("div").contains("Test source cypress for delete").should("not.exist"); + cy.get("div").contains(sourceName).should("not.exist"); }); }); diff --git a/airbyte-webapp/src/components/base/Text/Text.tsx b/airbyte-webapp/src/components/base/Text/Text.tsx index 6f52e54b6db4..479a6c392615 100644 --- a/airbyte-webapp/src/components/base/Text/Text.tsx +++ b/airbyte-webapp/src/components/base/Text/Text.tsx @@ -52,16 +52,17 @@ const isHeadingType = (props: TextProps | HeadingProps): props is HeadingProps = export const Text: React.FC> = React.memo((props) => { const isHeading = isHeadingType(props); - const { as = "p", centered = false, children } = props; + const { as = "p", centered = false, children, className: classNameProp, ...remainingProps } = props; const className = classNames( isHeading ? getHeadingClassNames({ centered, size: props.size ?? "md" }) : getTextClassNames({ centered, size: props.size ?? "md", bold: props.bold ?? false }), - props.className + classNameProp ); return React.createElement(as, { + ...remainingProps, className, children, });