diff --git a/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts index 8917723e38b0..7fea0fa55d2c 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts @@ -22,6 +22,8 @@ import { isPrimaryKeyNonExist, selectPrimaryKeyField, checkPreFilledPrimaryKeyField, + checkStreamFields, + expandStreamDetails } from "pages/replicationPage"; import { openSourceDestinationFromGrid, goToSourcePage } from "pages/sourcePage"; import { goToSettingsPage } from "pages/settingsConnectionPage"; @@ -36,7 +38,7 @@ import { } from "../pages/modals/catalogDiffModal"; import { updateSchemaModalConfirmBtnClick } from "../pages/modals/updateSchemaModal"; -describe("Connection main actions", () => { +describe("Connection - main actions", () => { beforeEach(() => { initialSetupCompleted(); }); @@ -83,140 +85,6 @@ describe("Connection main actions", () => { deleteDestination(destName); }); - it("Connection sync mode Incremental Append", () => { - const sourceName = appendRandomString("Test connection Postgres source cypress"); - const destName = appendRandomString("Test connection Postgres destination cypress"); - - cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection"); - - populateDBSource(); - - createTestConnection(sourceName, destName); - - goToSourcePage(); - openSourceDestinationFromGrid(sourceName); - openSourceDestinationFromGrid(destName); - - goToReplicationTab(); - - searchStream("users"); - selectSyncMode("Incremental", "Append"); - selectCursorField("col1"); - - submitButtonClick(); - confirmStreamConfigurationChangedPopup(); - - cy.wait("@updateConnection", { timeout: 5000 }).then((interception) => { - assert.isNotNull(interception.response?.statusCode, "200"); - }); - - checkSuccessResult(); - - goToSourcePage(); - openSourceDestinationFromGrid(sourceName); - openSourceDestinationFromGrid(destName); - - goToReplicationTab(); - - searchStream("users"); - checkCursorField("col1"); - - deleteSource(sourceName); - deleteDestination(destName); - cleanDBSource(); - }); - - it("Connection sync mode Incremental Deduped History - PK is defined", () => { - const sourceName = appendRandomString("Test connection Postgres source cypress"); - const destName = appendRandomString("Test connection Postgres destination cypress"); - - cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection"); - - populateDBSource(); - createTestConnection(sourceName, destName); - - goToSourcePage(); - openSourceDestinationFromGrid(sourceName); - openSourceDestinationFromGrid(destName); - - goToReplicationTab(); - - searchStream("users"); - selectSyncMode("Incremental", "Deduped + history"); - selectCursorField("col1"); - checkPreFilledPrimaryKeyField("id"); - - submitButtonClick(); - confirmStreamConfigurationChangedPopup(); - - cy.wait("@updateConnection", { timeout: 5000 }).then((interception) => { - assert.isNotNull(interception.response?.statusCode, "200"); - }); - - checkSuccessResult(); - - goToSourcePage(); - openSourceDestinationFromGrid(sourceName); - openSourceDestinationFromGrid(destName); - - goToReplicationTab(); - - searchStream("users"); - - checkCursorField("col1"); - checkPreFilledPrimaryKeyField("id"); - - deleteSource(sourceName); - deleteDestination(destName); - cleanDBSource(); - }); - - it("Connection sync mode Incremental Deduped History - PK is not defined", () => { - const sourceName = appendRandomString("Test connection Postgres source cypress"); - const destName = appendRandomString("Test connection Postgres destination cypress"); - - cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection"); - - populateDBSource(); - createTestConnection(sourceName, destName); - - goToSourcePage(); - openSourceDestinationFromGrid(sourceName); - openSourceDestinationFromGrid(destName); - - goToReplicationTab(); - - searchStream("cities"); - selectSyncMode("Incremental", "Deduped + history"); - selectCursorField("city"); - isPrimaryKeyNonExist(); - selectPrimaryKeyField("city_code"); - - submitButtonClick(); - confirmStreamConfigurationChangedPopup(); - - cy.wait("@updateConnection", { timeout: 5000 }).then((interception) => { - assert.isNotNull(interception.response?.statusCode, "200"); - }); - - checkSuccessResult(); - - goToSourcePage(); - openSourceDestinationFromGrid(sourceName); - openSourceDestinationFromGrid(destName); - - goToReplicationTab(); - - searchStream("cities"); - - checkCursorField("city"); - checkPrimaryKey("city_code"); - - deleteSource(sourceName); - deleteDestination(destName); - cleanDBSource(); - }); - it("Update connection (pokeAPI)", () => { cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection"); @@ -359,54 +227,6 @@ describe("Connection main actions", () => { deleteDestination(destName); }); - it("Create a connection, update data in source, show diff modal, reset streams", () => { - cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection"); - - populateDBSource(); - const sourceName = appendRandomString( - "Test refresh source schema with changed data - connection Postgres source cypress" - ); - const destName = appendRandomString( - "Test refresh source schema with changed data - connection Local JSON destination cypress" - ); - - createTestConnection(sourceName, destName); - cy.get("div").contains(sourceName).should("exist"); - cy.get("div").contains(destName).should("exist"); - - makeChangesInDBSource(); - openSourceDestinationFromGrid(sourceName); - goToReplicationTab(); - refreshSourceSchemaBtnClick(); - - cy.get(catalogDiffModal).should("exist"); - - cy.get(removedStreamsTable).should("contain", "users"); - - cy.get(newStreamsTable).should("contain", "cars"); - - toggleStreamWithChangesAccordion("cities"); - cy.get(removedFieldsTable).should("contain", "city_code"); - cy.get(newFieldsTable).children().should("contain", "country").and("contain", "state"); - - updateSchemaModalConfirmBtnClick(); - - toggleStreamEnabledState("cars"); - - submitButtonClick(); - resetModalSaveBtnClick(); - - cy.wait("@updateConnection").then((interception) => { - assert.isNotNull(interception.response?.statusCode, "200"); - }); - - checkSuccessResult(); - - deleteSource(sourceName); - deleteDestination(destName); - cleanDBSource(); - }); - it("Delete connection", () => { const sourceName = "Test delete connection source cypress"; const destName = "Test delete connection destination cypress"; @@ -540,3 +360,232 @@ describe("Connection main actions", () => { deleteDestination(destName); }); }); + +describe("Connection - stream view", () => { + beforeEach(() => { + initialSetupCompleted(); + populateDBSource(); + }); + + afterEach(() => { + cleanDBSource(); + }); + + it("Stream view", () => { + const sourceName = appendRandomString("Test connection Postgres source cypress"); + const destName = appendRandomString("Test connection Postgres destination cypress"); + + const collectionNames = ["Field name", "col1", "id"]; + const collectionTypes = ["Data type", "String", "Integer"]; + + createTestConnection(sourceName, destName); + + goToSourcePage(); + openSourceDestinationFromGrid(sourceName); + openSourceDestinationFromGrid(destName); + + goToReplicationTab(); + + searchStream("users"); + expandStreamDetails(); + checkStreamFields(collectionNames, collectionTypes); + + deleteSource(sourceName); + deleteDestination(destName); + }); +}); + +describe("Connection sync modes", () => { + beforeEach(() => { + initialSetupCompleted(); + populateDBSource(); + }); + + afterEach(() => { + cleanDBSource(); + }); + + it("Connection sync mode Incremental Append", () => { + const sourceName = appendRandomString("Test connection Postgres source cypress"); + const destName = appendRandomString("Test connection Postgres destination cypress"); + + cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection"); + + createTestConnection(sourceName, destName); + + goToSourcePage(); + openSourceDestinationFromGrid(sourceName); + openSourceDestinationFromGrid(destName); + + goToReplicationTab(); + + searchStream("users"); + selectSyncMode("Incremental", "Append"); + selectCursorField("col1"); + + submitButtonClick(); + confirmStreamConfigurationChangedPopup(); + + cy.wait("@updateConnection", { timeout: 5000 }).then((interception) => { + assert.isNotNull(interception.response?.statusCode, "200"); + }); + + checkSuccessResult(); + + goToSourcePage(); + openSourceDestinationFromGrid(sourceName); + openSourceDestinationFromGrid(destName); + + goToReplicationTab(); + + searchStream("users"); + checkCursorField("col1"); + + deleteSource(sourceName); + deleteDestination(destName); + }); + + it("Connection sync mode Incremental Deduped History - PK is defined", () => { + const sourceName = appendRandomString("Test connection Postgres source cypress"); + const destName = appendRandomString("Test connection Postgres destination cypress"); + + cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection"); + + createTestConnection(sourceName, destName); + + goToSourcePage(); + openSourceDestinationFromGrid(sourceName); + openSourceDestinationFromGrid(destName); + + goToReplicationTab(); + + searchStream("users"); + selectSyncMode("Incremental", "Deduped + history"); + selectCursorField("col1"); + checkPreFilledPrimaryKeyField("id"); + + submitButtonClick(); + confirmStreamConfigurationChangedPopup(); + + cy.wait("@updateConnection", { timeout: 5000 }).then((interception) => { + assert.isNotNull(interception.response?.statusCode, "200"); + }); + + checkSuccessResult(); + + goToSourcePage(); + openSourceDestinationFromGrid(sourceName); + openSourceDestinationFromGrid(destName); + + goToReplicationTab(); + + searchStream("users"); + + checkCursorField("col1"); + checkPreFilledPrimaryKeyField("id"); + + deleteSource(sourceName); + deleteDestination(destName); + }); + + it("Connection sync mode Incremental Deduped History - PK is not defined", () => { + const sourceName = appendRandomString("Test connection Postgres source cypress"); + const destName = appendRandomString("Test connection Postgres destination cypress"); + + cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection"); + + createTestConnection(sourceName, destName); + + goToSourcePage(); + openSourceDestinationFromGrid(sourceName); + openSourceDestinationFromGrid(destName); + + goToReplicationTab(); + + searchStream("cities"); + selectSyncMode("Incremental", "Deduped + history"); + selectCursorField("city"); + isPrimaryKeyNonExist(); + selectPrimaryKeyField("city_code"); + + submitButtonClick(); + confirmStreamConfigurationChangedPopup(); + + cy.wait("@updateConnection", { timeout: 5000 }).then((interception) => { + assert.isNotNull(interception.response?.statusCode, "200"); + }); + + checkSuccessResult(); + + goToSourcePage(); + openSourceDestinationFromGrid(sourceName); + openSourceDestinationFromGrid(destName); + + goToReplicationTab(); + + searchStream("cities"); + + checkCursorField("city"); + checkPrimaryKey("city_code"); + + deleteSource(sourceName); + deleteDestination(destName); + }); +}); + +describe("Connection - detect changes in source", () => { + beforeEach(() => { + initialSetupCompleted(); + populateDBSource(); + }); + + afterEach(() => { + cleanDBSource(); + }); + + it("Create a connection, update data in source, show diff modal, reset streams", () => { + cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection"); + + const sourceName = appendRandomString( + "Test refresh source schema with changed data - connection Postgres source cypress" + ); + const destName = appendRandomString( + "Test refresh source schema with changed data - connection Local JSON destination cypress" + ); + + createTestConnection(sourceName, destName); + cy.get("div").contains(sourceName).should("exist"); + cy.get("div").contains(destName).should("exist"); + + makeChangesInDBSource(); + openSourceDestinationFromGrid(sourceName); + goToReplicationTab(); + refreshSourceSchemaBtnClick(); + + cy.get(catalogDiffModal).should("exist"); + + cy.get(removedStreamsTable).should("contain", "users"); + + cy.get(newStreamsTable).should("contain", "cars"); + + toggleStreamWithChangesAccordion("cities"); + cy.get(removedFieldsTable).should("contain", "city_code"); + cy.get(newFieldsTable).children().should("contain", "country").and("contain", "state"); + + updateSchemaModalConfirmBtnClick(); + + toggleStreamEnabledState("cars"); + + submitButtonClick(); + resetModalSaveBtnClick(); + + cy.wait("@updateConnection").then((interception) => { + assert.isNotNull(interception.response?.statusCode, "200"); + }); + + checkSuccessResult(); + + deleteSource(sourceName); + deleteDestination(destName); + }); +}); diff --git a/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts index ed90e798019e..cd7bcab3e15e 100644 --- a/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts +++ b/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts @@ -9,6 +9,9 @@ const destinationNamespaceSource = "div[data-testid='namespaceDefinition-source' const destinationNamespaceCustomInput = "input[data-testid='input']"; const syncModeDropdown = "div[data-testid='syncSettingsDropdown'] input"; const cursorFieldDropdown = "button[class^='PathPopoutButton_button']"; +const streamFieldNames = "[class^='TreeRowWrapper_rowWrapper'] span"; +const streamDataTypes = "[class^='TreeRowWrapper_rowWrapper'] div:nth-child(2)"; +const ExpandStreamDetailsTableBtn = "[class^='Arrow_container__']"; const cursorFieldText = "[class^='PathPopoutButton_button__']"; const primaryKeyText = "[class^='PathPopoutButton_button__']"; const preFilledPrimaryKeyText = "div[class^='PathPopout_text']"; @@ -28,6 +31,10 @@ export const enterConnectionName = (name: string) => { cy.get(connectionNameInput).type(name); }; +export const expandStreamDetails = () => { + cy.get(ExpandStreamDetailsTableBtn).click(); +}; + export const selectSchedule = (value: string) => { cy.get(scheduleDropdown).click(); cy.get(scheduleValue(value)).click(); @@ -73,6 +80,18 @@ export const selectCursorField = (value: string) => { cy.get(`.react-select__option`).contains(value).click(); }; +export const checkStreamFields = (listNames: Array, listTypes: Array,) => { + cy.get(streamFieldNames) + .each(($span, i) => { + expect($span.text()).to.equal(listNames[i]); + }); + + cy.get(streamDataTypes) + .each(($span, i) => { + expect($span.text()).to.equal(listTypes[i]); + }); +}; + export const checkCursorField = (expectedValue: string) => { cy.get(cursorFieldText).first().contains(expectedValue); };