From 5ff8d49f93e68e327eb42fd1406de8b872f998dc Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Tue, 13 Dec 2022 17:07:01 -0500 Subject: [PATCH 01/24] Add support to get workspaceId, create/delete source/destination from cypress --- .../cypress/commands/request.ts | 60 +++++++++++++++++++ .../integration/autoDetectSchema.spec.ts | 27 +++++++++ 2 files changed, 87 insertions(+) create mode 100644 airbyte-webapp-e2e-tests/cypress/commands/request.ts create mode 100644 airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts diff --git a/airbyte-webapp-e2e-tests/cypress/commands/request.ts b/airbyte-webapp-e2e-tests/cypress/commands/request.ts new file mode 100644 index 000000000000..864457752dda --- /dev/null +++ b/airbyte-webapp-e2e-tests/cypress/commands/request.ts @@ -0,0 +1,60 @@ +let _workspaceId: string; + +const getApiUrl = (path: string): string => `http://localhost:8001/api/v1${path}`; + +export const getPostgresCreateSourceBody = (name: string) => ({ + name, + sourceDefinitionId: "decd338e-5647-4c0b-adf4-da0e75f5a750", + workspaceId: _workspaceId, + connectionConfiguration: { + ssl_mode: { mode: "disable" }, + tunnel_method: { tunnel_method: "NO_TUNNEL" }, + replication_method: { method: "Standard" }, + ssl: false, + port: 5433, + schemas: ["public"], + host: "localhost", + database: "airbyte_ci_source", + username: "postgres", + password: "secret_password", + }, +}); + +export const requestWorkspaceId = () => { + if (!_workspaceId) { + cy.request("POST", getApiUrl("/workspaces/list")).then((response) => { + expect(response.status).to.eq(200); + ({ + workspaces: [{ workspaceId: _workspaceId }], + } = response.body); + }); + } +}; + +export const requestCreateSource = (name: string, payload: Record) => { + return cy.request("POST", getApiUrl("/sources/create"), payload).then((response) => { + expect(response.status).to.eq(200); + + return response.body as { sourceId: string }; + }); +}; + +export const requestDeleteSource = (sourceId: string) => { + return cy.request("POST", getApiUrl("/sources/delete"), { sourceId }).then((response) => { + expect(response.status).to.eq(204); + }); +}; + +export const requestCreateDestination = (name: string, payload: Record) => { + return cy.request("POST", getApiUrl("/destinations/create"), payload).then((response) => { + expect(response.status).to.eq(200); + + return response.body as { destinationId: string }; + }); +}; + +export const requestDeleteDestination = (destinationId: string) => { + return cy.request("POST", getApiUrl("/destinations/delete"), { destinationId }).then((response) => { + expect(response.status).to.eq(204); + }); +}; diff --git a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts new file mode 100644 index 000000000000..accf3c2cf2b1 --- /dev/null +++ b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts @@ -0,0 +1,27 @@ +import { + getPostgresCreateSourceBody, + requestCreateSource, + requestDeleteSource, + requestWorkspaceId, +} from "commands/request"; +import { initialSetupCompleted } from "commands/workspaces"; + +describe("Auto-detect schema changes", () => { + beforeEach(() => { + initialSetupCompleted(); + requestWorkspaceId(); + }); + + it("creates a source", () => { + const payload = getPostgresCreateSourceBody("Test source"); + let sourceId: string; + console.log("payload", payload); + + requestCreateSource("Test source", payload).then((response) => { + sourceId = response.sourceId; + expect(sourceId).to.be.a("string"); + + requestDeleteSource(sourceId); + }); + }); +}); From e751d9d8a97266aa48c7a5ea8881eaec4cf7d12c Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Wed, 14 Dec 2022 12:47:40 -0500 Subject: [PATCH 02/24] Test delete source --- .../cypress/integration/autoDetectSchema.spec.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts index accf3c2cf2b1..e683dba98a33 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts @@ -17,11 +17,13 @@ describe("Auto-detect schema changes", () => { let sourceId: string; console.log("payload", payload); - requestCreateSource("Test source", payload).then((response) => { - sourceId = response.sourceId; - expect(sourceId).to.be.a("string"); + requestCreateSource("Test source", payload) + .then((response) => { + sourceId = response.sourceId; - requestDeleteSource(sourceId); - }); + expect(sourceId).to.be.a("string"); + requestDeleteSource(sourceId); + }) + .as("@test"); }); }); From 7f771e956efb1d42e95eba2a773c855eb9d0816f Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Wed, 14 Dec 2022 13:05:06 -0500 Subject: [PATCH 03/24] commands/request -> commands/api --- .../cypress/commands/{request.ts => api.ts} | 0 .../cypress/integration/autoDetectSchema.spec.ts | 14 ++++++-------- 2 files changed, 6 insertions(+), 8 deletions(-) rename airbyte-webapp-e2e-tests/cypress/commands/{request.ts => api.ts} (100%) diff --git a/airbyte-webapp-e2e-tests/cypress/commands/request.ts b/airbyte-webapp-e2e-tests/cypress/commands/api.ts similarity index 100% rename from airbyte-webapp-e2e-tests/cypress/commands/request.ts rename to airbyte-webapp-e2e-tests/cypress/commands/api.ts diff --git a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts index e683dba98a33..e593e7125834 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts @@ -3,7 +3,7 @@ import { requestCreateSource, requestDeleteSource, requestWorkspaceId, -} from "commands/request"; +} from "commands/api"; import { initialSetupCompleted } from "commands/workspaces"; describe("Auto-detect schema changes", () => { @@ -17,13 +17,11 @@ describe("Auto-detect schema changes", () => { let sourceId: string; console.log("payload", payload); - requestCreateSource("Test source", payload) - .then((response) => { - sourceId = response.sourceId; + requestCreateSource("Test source", payload).then((response) => { + sourceId = response.sourceId; - expect(sourceId).to.be.a("string"); - requestDeleteSource(sourceId); - }) - .as("@test"); + expect(sourceId).to.be.a("string"); + requestDeleteSource(sourceId); + }); }); }); From b14f7eb2e781140b7ee8d96db010d7837f312cfa Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Wed, 14 Dec 2022 14:21:15 -0500 Subject: [PATCH 04/24] Add util to convert chains to promises, cleanup api, use async/await on test --- .../cypress/commands/api.ts | 52 +++++++++---------- .../cypress/commands/utils/promise.ts | 18 +++++++ .../integration/autoDetectSchema.spec.ts | 12 ++--- 3 files changed, 47 insertions(+), 35 deletions(-) create mode 100644 airbyte-webapp-e2e-tests/cypress/commands/utils/promise.ts diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api.ts b/airbyte-webapp-e2e-tests/cypress/commands/api.ts index 864457752dda..961bff7d8821 100644 --- a/airbyte-webapp-e2e-tests/cypress/commands/api.ts +++ b/airbyte-webapp-e2e-tests/cypress/commands/api.ts @@ -1,3 +1,5 @@ +import { toPromise } from "./utils/promise"; + let _workspaceId: string; const getApiUrl = (path: string): string => `http://localhost:8001/api/v1${path}`; @@ -31,30 +33,26 @@ export const requestWorkspaceId = () => { } }; -export const requestCreateSource = (name: string, payload: Record) => { - return cy.request("POST", getApiUrl("/sources/create"), payload).then((response) => { - expect(response.status).to.eq(200); - - return response.body as { sourceId: string }; - }); -}; - -export const requestDeleteSource = (sourceId: string) => { - return cy.request("POST", getApiUrl("/sources/delete"), { sourceId }).then((response) => { - expect(response.status).to.eq(204); - }); -}; - -export const requestCreateDestination = (name: string, payload: Record) => { - return cy.request("POST", getApiUrl("/destinations/create"), payload).then((response) => { - expect(response.status).to.eq(200); - - return response.body as { destinationId: string }; - }); -}; - -export const requestDeleteDestination = (destinationId: string) => { - return cy.request("POST", getApiUrl("/destinations/delete"), { destinationId }).then((response) => { - expect(response.status).to.eq(204); - }); -}; +const apiRequest = ( + method: Cypress.HttpMethod, + path: string, + payload: Record | undefined, + expectedStatus: number +): Promise => + toPromise( + cy.request(method, getApiUrl(path), payload).then((response) => { + expect(response.status).to.eq(expectedStatus, "response status"); + return response.body; + }) + ); + +export const requestCreateSource = (name: string, payload: Record) => + apiRequest<{ sourceId: string }>("POST", "/sources/create", payload, 200); + +export const requestDeleteSource = (sourceId: string) => apiRequest("POST", "/sources/delete", { sourceId }, 204); + +export const requestCreateDestination = (name: string, payload: Record) => + apiRequest<{ destinationId: string }>("POST", "/destinations/create", payload, 200); + +export const requestDeleteDestination = (destinationId: string) => + apiRequest("POST", "/destinations/delete", { destinationId }, 204); diff --git a/airbyte-webapp-e2e-tests/cypress/commands/utils/promise.ts b/airbyte-webapp-e2e-tests/cypress/commands/utils/promise.ts new file mode 100644 index 000000000000..27d07454e160 --- /dev/null +++ b/airbyte-webapp-e2e-tests/cypress/commands/utils/promise.ts @@ -0,0 +1,18 @@ +/** + * Converts Cypress chain to regular Promise. + */ +export const toPromise = (chain: Cypress.Chainable): Promise => { + return new Cypress.Promise((resolve, reject) => { + const onFail = (error: Error) => { + Cypress.off("fail", onFail); + reject(error); + }; + + Cypress.on("fail", onFail); + + chain.then((value) => { + Cypress.off("fail", onFail); + resolve(value); + }); + }); +}; diff --git a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts index e593e7125834..a45bebeca24a 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts @@ -12,16 +12,12 @@ describe("Auto-detect schema changes", () => { requestWorkspaceId(); }); - it("creates a source", () => { + it("creates a source", async () => { const payload = getPostgresCreateSourceBody("Test source"); - let sourceId: string; - console.log("payload", payload); - requestCreateSource("Test source", payload).then((response) => { - sourceId = response.sourceId; + const { sourceId } = await requestCreateSource("Test source", payload); - expect(sourceId).to.be.a("string"); - requestDeleteSource(sourceId); - }); + expect(sourceId).to.be.a("string"); + requestDeleteSource(sourceId); }); }); From 4758486458bafb3bf27178c16a55ee0a9d00aa96 Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Wed, 14 Dec 2022 17:15:35 -0500 Subject: [PATCH 05/24] Add the ability to create and delete a connection --- .../cypress/commands/api.ts | 58 -------------- .../cypress/commands/api/api.ts | 76 +++++++++++++++++++ .../cypress/commands/api/index.ts | 2 + .../cypress/commands/api/payloads.ts | 66 ++++++++++++++++ .../cypress/commands/api/types.ts | 70 +++++++++++++++++ .../cypress/commands/api/workspace.ts | 9 +++ .../integration/autoDetectSchema.spec.ts | 52 +++++++++++-- 7 files changed, 267 insertions(+), 66 deletions(-) delete mode 100644 airbyte-webapp-e2e-tests/cypress/commands/api.ts create mode 100644 airbyte-webapp-e2e-tests/cypress/commands/api/api.ts create mode 100644 airbyte-webapp-e2e-tests/cypress/commands/api/index.ts create mode 100644 airbyte-webapp-e2e-tests/cypress/commands/api/payloads.ts create mode 100644 airbyte-webapp-e2e-tests/cypress/commands/api/types.ts create mode 100644 airbyte-webapp-e2e-tests/cypress/commands/api/workspace.ts diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api.ts b/airbyte-webapp-e2e-tests/cypress/commands/api.ts deleted file mode 100644 index 961bff7d8821..000000000000 --- a/airbyte-webapp-e2e-tests/cypress/commands/api.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { toPromise } from "./utils/promise"; - -let _workspaceId: string; - -const getApiUrl = (path: string): string => `http://localhost:8001/api/v1${path}`; - -export const getPostgresCreateSourceBody = (name: string) => ({ - name, - sourceDefinitionId: "decd338e-5647-4c0b-adf4-da0e75f5a750", - workspaceId: _workspaceId, - connectionConfiguration: { - ssl_mode: { mode: "disable" }, - tunnel_method: { tunnel_method: "NO_TUNNEL" }, - replication_method: { method: "Standard" }, - ssl: false, - port: 5433, - schemas: ["public"], - host: "localhost", - database: "airbyte_ci_source", - username: "postgres", - password: "secret_password", - }, -}); - -export const requestWorkspaceId = () => { - if (!_workspaceId) { - cy.request("POST", getApiUrl("/workspaces/list")).then((response) => { - expect(response.status).to.eq(200); - ({ - workspaces: [{ workspaceId: _workspaceId }], - } = response.body); - }); - } -}; - -const apiRequest = ( - method: Cypress.HttpMethod, - path: string, - payload: Record | undefined, - expectedStatus: number -): Promise => - toPromise( - cy.request(method, getApiUrl(path), payload).then((response) => { - expect(response.status).to.eq(expectedStatus, "response status"); - return response.body; - }) - ); - -export const requestCreateSource = (name: string, payload: Record) => - apiRequest<{ sourceId: string }>("POST", "/sources/create", payload, 200); - -export const requestDeleteSource = (sourceId: string) => apiRequest("POST", "/sources/delete", { sourceId }, 204); - -export const requestCreateDestination = (name: string, payload: Record) => - apiRequest<{ destinationId: string }>("POST", "/destinations/create", payload, 200); - -export const requestDeleteDestination = (destinationId: string) => - apiRequest("POST", "/destinations/delete", { destinationId }, 204); diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts b/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts new file mode 100644 index 000000000000..2ebe02f04cb1 --- /dev/null +++ b/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts @@ -0,0 +1,76 @@ +import { toPromise } from "../utils/promise"; +import { + Connection, + ConnectionCreateRequestBody, + ConnectionsList, + Destination, + DestinationsList, + Source, + SourceDiscoverSchema, + SourcesList, +} from "./types"; +import { getWorkspaceId, setWorkspaceId } from "./workspace"; + +const getApiUrl = (path: string): string => `http://localhost:8001/api/v1${path}`; + +export const requestWorkspaceId = () => { + if (!getWorkspaceId()) { + return toPromise( + cy.request("POST", getApiUrl("/workspaces/list")).then((response) => { + expect(response.status).to.eq(200); + const { + workspaces: [{ workspaceId }], + } = response.body; + + setWorkspaceId(workspaceId as string); + }) + ); + } + + return Promise.resolve(); +}; + +const apiRequest = ( + method: Cypress.HttpMethod, + path: string, + payload?: Cypress.RequestBody, + expectedStatus = 200 +): Promise => + toPromise( + cy.request(method, getApiUrl(path), payload).then((response) => { + expect(response.status).to.eq(expectedStatus, "response status"); + return response.body; + }) + ); + +export const requestConnectionsList = () => + apiRequest("POST", "/connections/list", { workspaceId: getWorkspaceId() }); + +export const requestCreateConnection = (body: ConnectionCreateRequestBody) => + apiRequest("POST", "/web_backend/connections/create", body); + +export const requestUpdateConnection = (body: Record) => + apiRequest("POST", "/web_backend/connections/update", body); + +export const requestDeleteConnection = (connectionId: string) => + apiRequest("POST", "/connections/delete", { connectionId }, 204); + +export const requestSourcesList = () => + apiRequest("POST", "/sources/list", { workspaceId: getWorkspaceId() }); + +export const requestSourceDiscoverSchema = (sourceId: string) => + apiRequest("POST", "/sources/discover_schema", { sourceId, disable_cache: true }); + +export const requestCreateSource = (body: Record) => + apiRequest("POST", "/sources/create", body); + +export const requestDeleteSource = (sourceId: string) => apiRequest("POST", "/sources/delete", { sourceId }, 204); + +export const requestDestinationsList = () => + apiRequest("POST", "/destinations/list", { workspaceId: getWorkspaceId() }); + +export const requestCreateDestination = (body: Record) => + apiRequest("POST", "/destinations/create", body); + +export const requestDeleteDestination = (destinationId: string) => + apiRequest("POST", "/destinations/delete", { destinationId }, 204); diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api/index.ts b/airbyte-webapp-e2e-tests/cypress/commands/api/index.ts new file mode 100644 index 000000000000..f5d0fb3b55c2 --- /dev/null +++ b/airbyte-webapp-e2e-tests/cypress/commands/api/index.ts @@ -0,0 +1,2 @@ +export * from "./api"; +export * from "./payloads"; diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api/payloads.ts b/airbyte-webapp-e2e-tests/cypress/commands/api/payloads.ts new file mode 100644 index 000000000000..44db5c99d501 --- /dev/null +++ b/airbyte-webapp-e2e-tests/cypress/commands/api/payloads.ts @@ -0,0 +1,66 @@ +import { ConnectionCreateRequestBody } from "./types"; +import { getWorkspaceId } from "./workspace"; + +type RequiredConnectionCreateRequestProps = "name" | "sourceId" | "destinationId" | "syncCatalog" | "sourceCatalogId"; +type CreationConnectRequestParams = Pick & + Partial>; + +export const getConnectionCreateRequest = (params: CreationConnectRequestParams): ConnectionCreateRequestBody => ({ + geography: "auto", + namespaceDefinition: "source", + namespaceFormat: "${SOURCE_NAMESPACE}", + nonBreakingChangesPreference: "ignore", + operations: [], + prefix: "", + scheduleType: "manual", + status: "active", + ...params, +}); + +export const getPostgresCreateSourceBody = (name: string) => ({ + name, + sourceDefinitionId: "decd338e-5647-4c0b-adf4-da0e75f5a750", + workspaceId: getWorkspaceId(), + connectionConfiguration: { + ssl_mode: { mode: "disable" }, + tunnel_method: { tunnel_method: "NO_TUNNEL" }, + replication_method: { method: "Standard" }, + ssl: false, + port: 5433, + schemas: ["public"], + host: "localhost", + database: "airbyte_ci_source", + username: "postgres", + password: "secret_password", + }, +}); + +export const getE2ETestingCreateDestinationBody = (name: string) => ({ + name, + workspaceId: getWorkspaceId(), + destinationDefinitionId: "2eb65e87-983a-4fd7-b3e3-9d9dc6eb8537", + connectionConfiguration: { + type: "LOGGING", + logging_config: { + logging_type: "FirstN", + max_entry_count: 100, + }, + }, +}); + +export const getPostgresCreateDestinationBody = (name: string) => ({ + name, + workspaceId: getWorkspaceId(), + destinationDefinitionId: "25c5221d-dce2-4163-ade9-739ef790f503", + connectionConfiguration: { + ssl_mode: { mode: "disable" }, + tunnel_method: { tunnel_method: "NO_TUNNEL" }, + ssl: false, + port: 5434, + schema: "public", + host: "localhost", + database: "airbyte_ci_destination", + username: "postgres", + password: "secret_password", + }, +}); diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api/types.ts b/airbyte-webapp-e2e-tests/cypress/commands/api/types.ts new file mode 100644 index 000000000000..0c849c04b005 --- /dev/null +++ b/airbyte-webapp-e2e-tests/cypress/commands/api/types.ts @@ -0,0 +1,70 @@ +export interface Connection { + connectionId: string; + destination: Destination; + destinationId: string; + isSyncing: boolean; + name: string; + scheduleType: string; + schemaChange: string; + source: Source; + sourceId: string; + status: "active" | "inactive" | "deprecated"; + nonBreakingChangesPreference: "ignore" | "disable"; + syncCatalog: SyncCatalog; +} + +export interface ConnectionCreateRequestBody { + destinationId: string; + geography: string; + name: string; + namespaceDefinition: string; + namespaceFormat: string; + nonBreakingChangesPreference: "ignore" | "disable"; + operations: unknown[]; + prefix: string; + scheduleType: string; + sourceCatalogId: string; + sourceId: string; + status: "active"; + syncCatalog: SyncCatalog; +} + +export interface ConnectionsList { + connections: Connection[]; +} + +export interface Destination { + destinationDefinitionId: string; + destinationName: string; + destinationId: string; + connectionConfiguration: Record; +} + +export interface DestinationsList { + destinations: Destination[]; +} + +export interface Source { + sourceDefinitionId: string; + sourceName: string; + sourceId: string; + connectionConfiguration: Record; +} + +export interface SourceDiscoverSchema { + catalog: SyncCatalog; + catalogId: string; +} + +export interface SourcesList { + sources: Source[]; +} + +export interface SyncCatalog { + streams: SyncCatalogStream[]; +} + +export interface SyncCatalogStream { + config: Record; + stream: Record; +} diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api/workspace.ts b/airbyte-webapp-e2e-tests/cypress/commands/api/workspace.ts new file mode 100644 index 000000000000..9e1bcf6c1d25 --- /dev/null +++ b/airbyte-webapp-e2e-tests/cypress/commands/api/workspace.ts @@ -0,0 +1,9 @@ +let _workspaceId: string; + +export const setWorkspaceId = (workspaceId: string) => { + _workspaceId = workspaceId; +}; + +export const getWorkspaceId = () => { + return _workspaceId; +}; diff --git a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts index a45bebeca24a..9bc55ae95945 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts @@ -1,23 +1,59 @@ import { + getConnectionCreateRequest, + getPostgresCreateDestinationBody, getPostgresCreateSourceBody, + requestCreateConnection, + requestCreateDestination, requestCreateSource, + requestDeleteConnection, + requestDeleteDestination, requestDeleteSource, + requestSourceDiscoverSchema, requestWorkspaceId, } from "commands/api"; +import { Connection, Destination, Source } from "commands/api/types"; import { initialSetupCompleted } from "commands/workspaces"; describe("Auto-detect schema changes", () => { - beforeEach(() => { + let source: Source; + let destination: Destination; + let connection: Connection; + + beforeEach(async () => { initialSetupCompleted(); - requestWorkspaceId(); - }); + await requestWorkspaceId(); - it("creates a source", async () => { - const payload = getPostgresCreateSourceBody("Test source"); + const sourceRequestBody = getPostgresCreateSourceBody("Auto-detect schema Source"); + const destinationRequestBody = getPostgresCreateDestinationBody("Auto-detect schema Destination"); - const { sourceId } = await requestCreateSource("Test source", payload); + source = await requestCreateSource(sourceRequestBody); + destination = await requestCreateDestination(destinationRequestBody); + const { catalog, catalogId } = await requestSourceDiscoverSchema(source.sourceId); - expect(sourceId).to.be.a("string"); - requestDeleteSource(sourceId); + const connectionRequestBody = await getConnectionCreateRequest({ + name: "Auto-detect schema test connection", + sourceId: source.sourceId, + destinationId: destination.destinationId, + syncCatalog: catalog, + sourceCatalogId: catalogId, + }); + + connection = await requestCreateConnection(connectionRequestBody); + }); + + afterEach(async () => { + if (connection) { + await requestDeleteConnection(connection.connectionId); + } + if (source) { + await requestDeleteSource(source.sourceId); + } + if (destination) { + await requestDeleteDestination(destination.destinationId); + } + }); + + it("creates a source", async () => { + expect(connection.connectionId).to.be.a("string"); }); }); From 679a608ae4dcf0da68286cabe85e4fe669c9336c Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Mon, 19 Dec 2022 16:21:05 -0500 Subject: [PATCH 06/24] Add E2E test for non-breaking schema changes * Update db queries with generator functions * Update users table to include better columns and cursor * Add name to ResetWarningModalSwitch * Add test ID to review button in SchemaChangesDetected modal --- .../cypress/commands/api/api.ts | 5 ++ .../cypress/commands/api/types.ts | 5 ++ .../cypress/commands/db/queries.ts | 89 +++++++++++++------ .../integration/autoDetectSchema.spec.ts | 31 ++++++- .../cypress/integration/connection.spec.ts | 17 ++-- .../cypress/pages/connectionPage.ts | 8 ++ .../cypress/pages/modals/catalogDiffModal.ts | 9 ++ .../cypress/pages/modals/updateSchemaModal.ts | 3 - .../cypress/pages/replicationPage.ts | 37 +++++++- .../SchemaChangesDetected.tsx | 7 +- .../ResetWarningModal.tsx | 1 + 11 files changed, 169 insertions(+), 43 deletions(-) create mode 100644 airbyte-webapp-e2e-tests/cypress/pages/connectionPage.ts delete mode 100644 airbyte-webapp-e2e-tests/cypress/pages/modals/updateSchemaModal.ts diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts b/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts index 2ebe02f04cb1..7883caebee95 100644 --- a/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts +++ b/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts @@ -1,5 +1,6 @@ import { toPromise } from "../utils/promise"; import { + ConectionGetBody, Connection, ConnectionCreateRequestBody, ConnectionsList, @@ -52,6 +53,10 @@ export const requestCreateConnection = (body: ConnectionCreateRequestBody) => export const requestUpdateConnection = (body: Record) => apiRequest("POST", "/web_backend/connections/update", body); + +export const requestGetConnection = (body: ConectionGetBody) => + apiRequest("POST", "/web_backend/connections/get", body); + export const requestDeleteConnection = (connectionId: string) => apiRequest("POST", "/connections/delete", { connectionId }, 204); diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api/types.ts b/airbyte-webapp-e2e-tests/cypress/commands/api/types.ts index 0c849c04b005..b7f9a2a31248 100644 --- a/airbyte-webapp-e2e-tests/cypress/commands/api/types.ts +++ b/airbyte-webapp-e2e-tests/cypress/commands/api/types.ts @@ -29,6 +29,11 @@ export interface ConnectionCreateRequestBody { syncCatalog: SyncCatalog; } +export interface ConectionGetBody { + connectionId: string; + withRefreshedCatalog?: boolean +} + export interface ConnectionsList { connections: Connection[]; } diff --git a/airbyte-webapp-e2e-tests/cypress/commands/db/queries.ts b/airbyte-webapp-e2e-tests/cypress/commands/db/queries.ts index 2ffc964c3b97..089656f3a2e6 100644 --- a/airbyte-webapp-e2e-tests/cypress/commands/db/queries.ts +++ b/airbyte-webapp-e2e-tests/cypress/commands/db/queries.ts @@ -1,33 +1,68 @@ +export const createTable = (tableName: string, columns: string[]): string => + `CREATE TABLE ${tableName}(${columns.join(", ")});`; + +export const dropTable = (tableName: string) => `DROP TABLE IF EXISTS ${tableName}`; + +export const alterTable = (tableName: string, params: { add?: string[]; drop?: string[] }): string => { + const adds = params.add ? params.add.map((add) => `ADD COLUMN ${add}`) : []; + const drops = params.drop ? params.drop.map((columnName) => `DROP COLUMN ${columnName}`) : []; + const alterations = [...adds, ...drops]; + + return `ALTER TABLE ${tableName} ${alterations.join(", ")};`; +}; + +export const insertIntoTable = (tableName: string, valuesByColumn: Record): string => { + const keys = Object.keys(valuesByColumn); + const values = keys + .map((key) => valuesByColumn[key]) + .map((value) => (typeof value === "string" ? `'${value}'` : value)); + + return `INSERT INTO ${tableName}(${keys.join(", ")}) VALUES(${values.join(", ")});`; +}; + +export const insertMultipleIntoTable = (tableName: string, valuesByColumns: Array>): string => + valuesByColumns.map((valuesByColumn) => insertIntoTable(tableName, valuesByColumn)).join("\n"); + // Users table -export const createUsersTableQuery = ` - CREATE TABLE users(id SERIAL PRIMARY KEY, col1 VARCHAR(200));`; -export const insertUsersTableQuery = ` - INSERT INTO public.users(col1) VALUES('record1'); - INSERT INTO public.users(col1) VALUES('record2'); - INSERT INTO public.users(col1) VALUES('record3');`; +export const createUsersTableQuery = createTable("public.users", [ + "id SERIAL", + "name VARCHAR(200) NULL", + "email VARCHAR(200) NULL", + "updated_at TIMESTAMP", + "CONSTRAINT users_pkey PRIMARY KEY (id)", +]); +export const insertUsersTableQuery = insertMultipleIntoTable("public.users", [ + { name: "Abigail", updated_at: "2022-12-19 00:00:00" }, + { name: "Andrew", updated_at: "2022-12-19 00:00:00" }, + { name: "Kat", updated_at: "2022-12-19 00:00:00" }, +]); -export const dropUsersTableQuery = ` - DROP TABLE IF EXISTS users;`; +export const dropUsersTableQuery = dropTable("public.users"); // Cities table -export const createCitiesTableQuery = ` - CREATE TABLE cities(city_code VARCHAR(8), city VARCHAR(200));`; - -export const insertCitiesTableQuery = ` - INSERT INTO public.cities(city_code, city) VALUES('BCN', 'Barcelona'); - INSERT INTO public.cities(city_code, city) VALUES('MAD', 'Madrid'); - INSERT INTO public.cities(city_code, city) VALUES('VAL', 'Valencia')`; - -export const alterCitiesTableQuery = ` - ALTER TABLE public.cities - DROP COLUMN "city_code", - ADD COLUMN "state" text, - ADD COLUMN "country" text;`; -export const dropCitiesTableQuery = ` - DROP TABLE IF EXISTS cities;`; +export const createCitiesTableQuery = createTable("public.cities", ["city_code VARCHAR(8)", "city VARCHAR(200)"]); + +export const insertCitiesTableQuery = insertMultipleIntoTable("public.cities", [ + { + city_code: "BCN", + city: "Barcelona", + }, + { city_code: "MAD", city: "Madrid" }, + { city_code: "VAL", city: "Valencia" }, +]); + +export const alterCitiesTableQuery = alterTable("public.cities", { + add: ["state TEXT", "country TEXT"], + drop: ["city_code"], +}); +export const dropCitiesTableQuery = dropTable("public.cities"); // Cars table -export const createCarsTableQuery = ` - CREATE TABLE cars(id SERIAL PRIMARY KEY, mark VARCHAR(200), model VARCHAR(200), color VARCHAR(200));`; -export const dropCarsTableQuery = ` - DROP TABLE IF EXISTS cars;`; +export const createCarsTableQuery = createTable("public.cars", [ + "id SERIAL PRIMARY KEY", + "mark VARCHAR(200)", + "model VARCHAR(200)", + "color VARCHAR(200)", +]); + +export const dropCarsTableQuery = dropTable("public.cars"); diff --git a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts index 9bc55ae95945..f475b6b6ae30 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts @@ -8,11 +8,18 @@ import { requestDeleteConnection, requestDeleteDestination, requestDeleteSource, + requestGetConnection, requestSourceDiscoverSchema, requestWorkspaceId, } from "commands/api"; import { Connection, Destination, Source } from "commands/api/types"; +import { submitButtonClick } from "commands/common"; +import { runDbQuery } from "commands/db/db"; +import { alterTable, createUsersTableQuery, dropUsersTableQuery } from "commands/db/queries"; import { initialSetupCompleted } from "commands/workspaces"; +import { visitConnectionPage } from "pages/connectionPage"; +import { checkCatalogDiffModal, clickCatalogDiffCloseButton } from "pages/modals/catalogDiffModal"; +import { checkSchemaChangesDetected, checkSchemaChangesDetectedCleared, checkSuccessResult, clickSaveReplication, clickSchemaChangesReviewButton } from "pages/replicationPage"; describe("Auto-detect schema changes", () => { let source: Source; @@ -28,6 +35,10 @@ describe("Auto-detect schema changes", () => { source = await requestCreateSource(sourceRequestBody); destination = await requestCreateDestination(destinationRequestBody); + + runDbQuery(dropUsersTableQuery); + runDbQuery(createUsersTableQuery); + const { catalog, catalogId } = await requestSourceDiscoverSchema(source.sourceId); const connectionRequestBody = await getConnectionCreateRequest({ @@ -51,9 +62,25 @@ describe("Auto-detect schema changes", () => { if (destination) { await requestDeleteDestination(destination.destinationId); } + + runDbQuery(dropUsersTableQuery); }); - it("creates a source", async () => { - expect(connection.connectionId).to.be.a("string"); + it("has working non-breaking changes flow", () => { + runDbQuery(alterTable("public.users", { drop: ['updated_at'] })) + requestGetConnection({ connectionId: connection.connectionId, withRefreshedCatalog: true }) + + // Need to continue running but async breaks everything + visitConnectionPage(connection, 'replication'); + + checkSchemaChangesDetected(); + clickSchemaChangesReviewButton(); + + checkCatalogDiffModal(); + clickCatalogDiffCloseButton(); + + checkSchemaChangesDetectedCleared(); + + clickSaveReplication(); }); }); diff --git a/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts index 160af7c0d751..4e3d0f73ce90 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts @@ -29,14 +29,14 @@ import { goToSourcePage, openSourceOverview } from "pages/sourcePage"; import { goToSettingsPage, openConnectionOverviewByDestinationName } from "pages/settingsConnectionPage"; import { cleanDBSource, makeChangesInDBSource, populateDBSource } from "commands/db"; import { - catalogDiffModal, + checkCatalogDiffModal, + clickCatalogDiffCloseButton, newFieldsTable, newStreamsTable, removedFieldsTable, removedStreamsTable, toggleStreamWithChangesAccordion, } from "pages/modals/catalogDiffModal"; -import { updateSchemaModalConfirmBtnClick } from "pages/modals/updateSchemaModal"; import { interceptGetConnectionRequest, interceptUpdateConnectionRequest, @@ -414,7 +414,7 @@ describe("Connection sync modes", () => { searchStream(streamName); selectSyncMode("Incremental", "Append"); - selectCursorField(streamName, "col1"); + selectCursorField(streamName, "updated_at"); submitButtonClick(); confirmStreamConfigurationChangedPopup(); @@ -432,8 +432,7 @@ describe("Connection sync modes", () => { goToReplicationTab(); searchStream("users"); - //FIXME: rename "check" to "verify" or similar - checkCursorField(streamName, "col1"); + checkCursorField(streamName, "updated_at"); deleteSource(sourceName); deleteDestination(destName); @@ -454,7 +453,7 @@ describe("Connection sync modes", () => { searchStream(streamName); selectSyncMode("Incremental", "Deduped + history"); - selectCursorField(streamName, "col1"); + selectCursorField(streamName, "updated_at"); checkPreFilledPrimaryKeyField(streamName, "id"); submitButtonClick(); @@ -474,7 +473,7 @@ describe("Connection sync modes", () => { searchStream(streamName); - checkCursorField(streamName, "col1"); + checkCursorField(streamName, "updated_at"); checkPreFilledPrimaryKeyField(streamName, "id"); deleteSource(sourceName); @@ -553,7 +552,7 @@ describe("Connection - detect source schema changes in source", () => { goToReplicationTab(); refreshSourceSchemaBtnClick(); - cy.get(catalogDiffModal).should("exist"); + checkCatalogDiffModal(); cy.get(removedStreamsTable).should("contain", "users"); @@ -563,7 +562,7 @@ describe("Connection - detect source schema changes in source", () => { cy.get(removedFieldsTable).should("contain", "city_code"); cy.get(newFieldsTable).children().should("contain", "country").and("contain", "state"); - updateSchemaModalConfirmBtnClick(); + clickCatalogDiffCloseButton(); toggleStreamEnabledState("cars"); diff --git a/airbyte-webapp-e2e-tests/cypress/pages/connectionPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/connectionPage.ts new file mode 100644 index 000000000000..0a0ee0ca07ff --- /dev/null +++ b/airbyte-webapp-e2e-tests/cypress/pages/connectionPage.ts @@ -0,0 +1,8 @@ +import { Connection } from "commands/api/types"; +import { getWorkspaceId } from "commands/api/workspace"; + +export const visitConnectionPage = (connection: Connection, tab = "") => { + cy.intercept("**/web_backend/connections/get").as("getConnection"); + cy.visit(`/workspaces/${getWorkspaceId()}/connections/${connection.connectionId}/${tab}`); + cy.wait("@getConnection"); +}; diff --git a/airbyte-webapp-e2e-tests/cypress/pages/modals/catalogDiffModal.ts b/airbyte-webapp-e2e-tests/cypress/pages/modals/catalogDiffModal.ts index e625f0ee3c51..4abcf8891b3d 100644 --- a/airbyte-webapp-e2e-tests/cypress/pages/modals/catalogDiffModal.ts +++ b/airbyte-webapp-e2e-tests/cypress/pages/modals/catalogDiffModal.ts @@ -5,7 +5,16 @@ const streamWithChangesToggleBtn = (streamName: string) => `button[data-testid='toggle-accordion-${streamName}-stream']`; export const removedFieldsTable = "table[aria-label='removed fields']"; export const newFieldsTable = "table[aria-label='new fields']"; +export const closeButton = "[data-testid='update-schema-confirm-btn']"; + +export const checkCatalogDiffModal = () => { + cy.get(catalogDiffModal).should("exist"); +}; export const toggleStreamWithChangesAccordion = (streamName: string) => { cy.get(streamWithChangesToggleBtn(streamName)).click(); }; + +export const clickCatalogDiffCloseButton = () => { + cy.get(closeButton).click(); +}; diff --git a/airbyte-webapp-e2e-tests/cypress/pages/modals/updateSchemaModal.ts b/airbyte-webapp-e2e-tests/cypress/pages/modals/updateSchemaModal.ts deleted file mode 100644 index d75314333b3e..000000000000 --- a/airbyte-webapp-e2e-tests/cypress/pages/modals/updateSchemaModal.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const updateSchemaModalConfirmBtnClick = () => { - cy.get("[data-testid='update-schema-confirm-btn']").click(); -}; diff --git a/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts index e833fc14be34..5d8a72f9fad4 100644 --- a/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts +++ b/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts @@ -1,3 +1,5 @@ +import { submitButtonClick } from "commands/common"; + const scheduleDropdown = "div[data-testid='scheduleData']"; const scheduleValue = (value: string) => `div[data-testid='${value}']`; const destinationPrefix = "input[data-testid='prefixInput']"; @@ -18,12 +20,16 @@ const streamDataTypeCell = "[data-testid='dataTypeCell']"; const getExpandStreamArrowBtn = (streamName: string) => `[data-testid='${streamName}_expandStreamDetails']`; const getPreFilledPrimaryKeyText = (streamName: string) => `[data-testid='${streamName}_primaryKey_pathPopout_text']`; const successResult = "div[data-id='success-result']"; +const resetModalResetCheckbox = "[data-testid='resetModal-reset-checkbox']"; const saveStreamChangesButton = "button[data-testid='resetModal-save']"; const connectionNameInput = "input[data-testid='connectionName']"; const refreshSourceSchemaButton = "button[data-testid='refresh-source-schema-btn']"; const streamSyncEnabledSwitch = (streamName: string) => `[data-testid='${streamName}-stream-sync-switch']`; const streamNameInput = "input[data-testid='input']"; const resetModalSaveButton = "[data-testid='resetModal-save']"; +const schemaChangesDetectedBanner = "[data-testid='schemaChangesDetected']"; +const schemaChangesReviewButton = "[data-testid='schemaChangesReviewButton']"; +const schemaChangesBackdrop = "[data-testid='schemaChangesBackdrop']"; export const goToReplicationTab = () => { cy.get(replicationTab).click(); @@ -117,7 +123,7 @@ export const selectCursorField = (streamName: string, cursorValue: string) => export const selectPrimaryKeyField = (streamName: string, primaryKeyValues: string[]) => selectFieldDropdownOption(streamName, "primaryKey", primaryKeyValues); -export const checkStreamFields = (listNames: Array, listTypes: Array) => { +export const checkStreamFields = (listNames: string[], listTypes: string[]) => { cy.get(streamNameCell).each(($span, i) => { expect($span.text()).to.equal(listNames[i]); }); @@ -170,14 +176,43 @@ export const searchStream = (value: string) => { cy.get(streamNameInput).type(value); }; +export const clickSaveReplication = () => { + cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection"); + + submitButtonClick(); + + confirmStreamConfigurationChangedPopup(); + + cy.wait("@updateConnection").then((interception) => { + assert.isNotNull(interception.response?.statusCode, "200"); + }); + + checkSuccessResult(); +}; + export const checkSuccessResult = () => { cy.get(successResult).should("exist"); }; export const confirmStreamConfigurationChangedPopup = () => { + cy.get(resetModalResetCheckbox).click({ force: true }); cy.get(saveStreamChangesButton).click(); }; export const toggleStreamEnabledState = (streamName: string) => { cy.get(streamSyncEnabledSwitch(streamName)).check({ force: true }); }; + +export const checkSchemaChangesDetected = () => { + cy.get(schemaChangesDetectedBanner).should("exist"); + cy.get(schemaChangesBackdrop).should("exist"); +}; + +export const checkSchemaChangesDetectedCleared = () => { + cy.get(schemaChangesDetectedBanner).should("not.exist"); + cy.get(schemaChangesBackdrop).should("not.exist"); +}; + +export const clickSchemaChangesReviewButton = () => { + cy.get(schemaChangesReviewButton).click(); +}; diff --git a/airbyte-webapp/src/components/connection/ConnectionInfoCard/SchemaChangesDetected.tsx b/airbyte-webapp/src/components/connection/ConnectionInfoCard/SchemaChangesDetected.tsx index a1ab52a9a1a6..9a713130d617 100644 --- a/airbyte-webapp/src/components/connection/ConnectionInfoCard/SchemaChangesDetected.tsx +++ b/airbyte-webapp/src/components/connection/ConnectionInfoCard/SchemaChangesDetected.tsx @@ -48,7 +48,12 @@ export const SchemaChangesDetected: React.FC = () => { - diff --git a/airbyte-webapp/src/pages/connections/ConnectionReplicationPage/ResetWarningModal.tsx b/airbyte-webapp/src/pages/connections/ConnectionReplicationPage/ResetWarningModal.tsx index 7d3fac8cab85..a61f2efb431f 100644 --- a/airbyte-webapp/src/pages/connections/ConnectionReplicationPage/ResetWarningModal.tsx +++ b/airbyte-webapp/src/pages/connections/ConnectionReplicationPage/ResetWarningModal.tsx @@ -35,6 +35,7 @@ export const ResetWarningModal: React.FC = ({ onCancel,

setWithReset(ev.target.checked)} label={formatMessage({ From ca7369a7dd1b8de6c8b88e4b79c3291e1a6da662 Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Tue, 20 Dec 2022 15:06:29 -0500 Subject: [PATCH 07/24] Add test for breaking change auto-detect flow --- .../integration/autoDetectSchema.spec.ts | 58 ++++++++++++++++--- .../cypress/pages/connectionPage.ts | 4 ++ .../cypress/pages/replicationPage.ts | 15 +++-- 3 files changed, 64 insertions(+), 13 deletions(-) diff --git a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts index f475b6b6ae30..af23ae24ab1b 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts @@ -13,13 +13,20 @@ import { requestWorkspaceId, } from "commands/api"; import { Connection, Destination, Source } from "commands/api/types"; -import { submitButtonClick } from "commands/common"; import { runDbQuery } from "commands/db/db"; import { alterTable, createUsersTableQuery, dropUsersTableQuery } from "commands/db/queries"; import { initialSetupCompleted } from "commands/workspaces"; -import { visitConnectionPage } from "pages/connectionPage"; +import { getSyncEnabledSwitch, visitConnectionPage } from "pages/connectionPage"; import { checkCatalogDiffModal, clickCatalogDiffCloseButton } from "pages/modals/catalogDiffModal"; -import { checkSchemaChangesDetected, checkSchemaChangesDetectedCleared, checkSuccessResult, clickSaveReplication, clickSchemaChangesReviewButton } from "pages/replicationPage"; +import { + checkSchemaChangesDetected, + checkSchemaChangesDetectedCleared, + clickSaveReplication, + clickSchemaChangesReviewButton, + searchStream, + selectCursorField, + selectSyncMode, +} from "pages/replicationPage"; describe("Auto-detect schema changes", () => { let source: Source; @@ -66,15 +73,16 @@ describe("Auto-detect schema changes", () => { runDbQuery(dropUsersTableQuery); }); - it("has working non-breaking changes flow", () => { - runDbQuery(alterTable("public.users", { drop: ['updated_at'] })) - requestGetConnection({ connectionId: connection.connectionId, withRefreshedCatalog: true }) + it("shows non-breaking change that can be saved after refresh", () => { + runDbQuery(alterTable("public.users", { drop: ["updated_at"] })); + requestGetConnection({ connectionId: connection.connectionId, withRefreshedCatalog: true }); // Need to continue running but async breaks everything - visitConnectionPage(connection, 'replication'); + visitConnectionPage(connection, "replication"); - checkSchemaChangesDetected(); + checkSchemaChangesDetected({ breaking: false }); clickSchemaChangesReviewButton(); + getSyncEnabledSwitch().should("be.enabled"); checkCatalogDiffModal(); clickCatalogDiffCloseButton(); @@ -82,5 +90,39 @@ describe("Auto-detect schema changes", () => { checkSchemaChangesDetectedCleared(); clickSaveReplication(); + getSyncEnabledSwitch().should("be.enabled"); + }); + + it("shows breaking change that can be saved after refresh and fix", () => { + visitConnectionPage(connection, "replication"); + + // Change users sync mode + searchStream("users"); + selectSyncMode("Incremental", "Deduped + history"); + selectCursorField("updated_at"); + clickSaveReplication(); + + // Remove cursor from db and refreshs schema to force breaking change detection + runDbQuery(alterTable("public.users", { drop: ["updated_at"] })); + requestGetConnection({ connectionId: connection.connectionId, withRefreshedCatalog: true }).then(console.log); + + // Reload the page to pick up the changes + cy.reload(); + + // Confirm that breaking changes are there + checkSchemaChangesDetected({ breaking: true }); + clickSchemaChangesReviewButton(); + getSyncEnabledSwitch().should("be.disabled"); + + checkCatalogDiffModal(); + clickCatalogDiffCloseButton(); + checkSchemaChangesDetectedCleared(); + + // Fix the conflict + searchStream("Users"); + selectSyncMode("Full refresh", "Append"); + + clickSaveReplication(); + getSyncEnabledSwitch().should("be.enabled"); }); }); diff --git a/airbyte-webapp-e2e-tests/cypress/pages/connectionPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/connectionPage.ts index 0a0ee0ca07ff..4c7b92ec5fec 100644 --- a/airbyte-webapp-e2e-tests/cypress/pages/connectionPage.ts +++ b/airbyte-webapp-e2e-tests/cypress/pages/connectionPage.ts @@ -1,8 +1,12 @@ import { Connection } from "commands/api/types"; import { getWorkspaceId } from "commands/api/workspace"; +const syncEnabledSwitch = "[data-testid='enabledControl-switch']"; + export const visitConnectionPage = (connection: Connection, tab = "") => { cy.intercept("**/web_backend/connections/get").as("getConnection"); cy.visit(`/workspaces/${getWorkspaceId()}/connections/${connection.connectionId}/${tab}`); cy.wait("@getConnection"); }; + +export const getSyncEnabledSwitch = () => cy.get(syncEnabledSwitch); diff --git a/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts index 5d8a72f9fad4..4b1724d0ae02 100644 --- a/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts +++ b/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts @@ -176,12 +176,12 @@ export const searchStream = (value: string) => { cy.get(streamNameInput).type(value); }; -export const clickSaveReplication = () => { +export const clickSaveReplication = ({ reset = false } = {}) => { cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection"); submitButtonClick(); - confirmStreamConfigurationChangedPopup(); + confirmStreamConfigurationChangedPopup({ reset }); cy.wait("@updateConnection").then((interception) => { assert.isNotNull(interception.response?.statusCode, "200"); @@ -194,8 +194,10 @@ export const checkSuccessResult = () => { cy.get(successResult).should("exist"); }; -export const confirmStreamConfigurationChangedPopup = () => { - cy.get(resetModalResetCheckbox).click({ force: true }); +export const confirmStreamConfigurationChangedPopup = ({ reset = false } = {}) => { + if (!reset) { + cy.get(resetModalResetCheckbox).click({ force: true }); + } cy.get(saveStreamChangesButton).click(); }; @@ -203,8 +205,11 @@ export const toggleStreamEnabledState = (streamName: string) => { cy.get(streamSyncEnabledSwitch(streamName)).check({ force: true }); }; -export const checkSchemaChangesDetected = () => { +export const checkSchemaChangesDetected = ({ breaking }: { breaking: boolean }) => { cy.get(schemaChangesDetectedBanner).should("exist"); + cy.get(schemaChangesDetectedBanner) + .invoke("attr", "class") + .should("match", breaking ? /\_breaking/ : /nonBreaking/); cy.get(schemaChangesBackdrop).should("exist"); }; From ed7a9c8f19bedfb71b231b1f5c74e32e9e9aa193 Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Tue, 20 Dec 2022 15:06:55 -0500 Subject: [PATCH 08/24] Fix linting issues --- airbyte-webapp-e2e-tests/cypress/commands/api/api.ts | 1 - airbyte-webapp-e2e-tests/cypress/commands/api/types.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts b/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts index 7883caebee95..796a962cb2b6 100644 --- a/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts +++ b/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts @@ -53,7 +53,6 @@ export const requestCreateConnection = (body: ConnectionCreateRequestBody) => export const requestUpdateConnection = (body: Record) => apiRequest("POST", "/web_backend/connections/update", body); - export const requestGetConnection = (body: ConectionGetBody) => apiRequest("POST", "/web_backend/connections/get", body); diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api/types.ts b/airbyte-webapp-e2e-tests/cypress/commands/api/types.ts index b7f9a2a31248..070c3c3f3ceb 100644 --- a/airbyte-webapp-e2e-tests/cypress/commands/api/types.ts +++ b/airbyte-webapp-e2e-tests/cypress/commands/api/types.ts @@ -31,7 +31,7 @@ export interface ConnectionCreateRequestBody { export interface ConectionGetBody { connectionId: string; - withRefreshedCatalog?: boolean + withRefreshedCatalog?: boolean; } export interface ConnectionsList { From 32f40a0c3152d43fe8a197ac1fda11fc4ca188e2 Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Tue, 20 Dec 2022 15:27:32 -0500 Subject: [PATCH 09/24] Clean up afterEach for autoDetectSchema --- .../cypress/integration/autoDetectSchema.spec.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts index af23ae24ab1b..108a31cbdcf4 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts @@ -59,15 +59,15 @@ describe("Auto-detect schema changes", () => { connection = await requestCreateConnection(connectionRequestBody); }); - afterEach(async () => { + afterEach(() => { if (connection) { - await requestDeleteConnection(connection.connectionId); + requestDeleteConnection(connection.connectionId); } if (source) { - await requestDeleteSource(source.sourceId); + requestDeleteSource(source.sourceId); } if (destination) { - await requestDeleteDestination(destination.destinationId); + requestDeleteDestination(destination.destinationId); } runDbQuery(dropUsersTableQuery); From ed9e38fc3f6dfdf0a26214568faada4c581234c3 Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Tue, 20 Dec 2022 15:27:49 -0500 Subject: [PATCH 10/24] schemaChangesButton should be disabled after clicking --- airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts index 4b1724d0ae02..6babd515fb6f 100644 --- a/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts +++ b/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts @@ -220,4 +220,5 @@ export const checkSchemaChangesDetectedCleared = () => { export const clickSchemaChangesReviewButton = () => { cy.get(schemaChangesReviewButton).click(); + cy.get(schemaChangesReviewButton).should("be.disabled"); }; From 1f9fefa8f0dc58bde18dbb3b85e9eb82981cd1cd Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Tue, 20 Dec 2022 16:25:10 -0500 Subject: [PATCH 11/24] Append random strings to source, dest, and connection created by auto-detect e2e test --- .../cypress/integration/autoDetectSchema.spec.ts | 7 ++++--- airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts index 108a31cbdcf4..25bd6b8393cf 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts @@ -13,6 +13,7 @@ import { requestWorkspaceId, } from "commands/api"; import { Connection, Destination, Source } from "commands/api/types"; +import { appendRandomString } from "commands/common"; import { runDbQuery } from "commands/db/db"; import { alterTable, createUsersTableQuery, dropUsersTableQuery } from "commands/db/queries"; import { initialSetupCompleted } from "commands/workspaces"; @@ -37,8 +38,8 @@ describe("Auto-detect schema changes", () => { initialSetupCompleted(); await requestWorkspaceId(); - const sourceRequestBody = getPostgresCreateSourceBody("Auto-detect schema Source"); - const destinationRequestBody = getPostgresCreateDestinationBody("Auto-detect schema Destination"); + const sourceRequestBody = getPostgresCreateSourceBody(appendRandomString("Auto-detect schema Source")); + const destinationRequestBody = getPostgresCreateDestinationBody(appendRandomString("Auto-detect schema Destination")); source = await requestCreateSource(sourceRequestBody); destination = await requestCreateDestination(destinationRequestBody); @@ -49,7 +50,7 @@ describe("Auto-detect schema changes", () => { const { catalog, catalogId } = await requestSourceDiscoverSchema(source.sourceId); const connectionRequestBody = await getConnectionCreateRequest({ - name: "Auto-detect schema test connection", + name: appendRandomString("Auto-detect schema test connection"), sourceId: source.sourceId, destinationId: destination.destinationId, syncCatalog: catalog, diff --git a/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts index 6babd515fb6f..a7f3058d6dac 100644 --- a/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts +++ b/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts @@ -220,5 +220,5 @@ export const checkSchemaChangesDetectedCleared = () => { export const clickSchemaChangesReviewButton = () => { cy.get(schemaChangesReviewButton).click(); - cy.get(schemaChangesReviewButton).should("be.disabled"); + // cy.get(schemaChangesReviewButton).should("be.disabled"); }; From aae4d3d53fbb953f2c167f28387d6c30328bf213 Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Wed, 21 Dec 2022 15:17:03 -0500 Subject: [PATCH 12/24] Add E2E tests to verify status icon in list pages --- .../integration/autoDetectSchema.spec.ts | 97 +++++++++++-------- .../cypress/pages/connnectionsListPage.ts | 11 +++ .../components/ChangesStatusIcon.tsx | 9 +- .../EntityTable/components/StatusCell.tsx | 2 +- 4 files changed, 79 insertions(+), 40 deletions(-) create mode 100644 airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts diff --git a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts index 25bd6b8393cf..cb5c384c36e1 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts @@ -18,6 +18,7 @@ import { runDbQuery } from "commands/db/db"; import { alterTable, createUsersTableQuery, dropUsersTableQuery } from "commands/db/queries"; import { initialSetupCompleted } from "commands/workspaces"; import { getSyncEnabledSwitch, visitConnectionPage } from "pages/connectionPage"; +import { getNonBreakingChangeIcon, getSchemaChangeIcon, visitConnectionsListPage } from "pages/connnectionsListPage"; import { checkCatalogDiffModal, clickCatalogDiffCloseButton } from "pages/modals/catalogDiffModal"; import { checkSchemaChangesDetected, @@ -39,7 +40,9 @@ describe("Auto-detect schema changes", () => { await requestWorkspaceId(); const sourceRequestBody = getPostgresCreateSourceBody(appendRandomString("Auto-detect schema Source")); - const destinationRequestBody = getPostgresCreateDestinationBody(appendRandomString("Auto-detect schema Destination")); + const destinationRequestBody = getPostgresCreateDestinationBody( + appendRandomString("Auto-detect schema Destination") + ); source = await requestCreateSource(sourceRequestBody); destination = await requestCreateDestination(destinationRequestBody); @@ -74,56 +77,74 @@ describe("Auto-detect schema changes", () => { runDbQuery(dropUsersTableQuery); }); - it("shows non-breaking change that can be saved after refresh", () => { - runDbQuery(alterTable("public.users", { drop: ["updated_at"] })); - requestGetConnection({ connectionId: connection.connectionId, withRefreshedCatalog: true }); + describe("non-breaking changes", () => { + beforeEach(() => { + runDbQuery(alterTable("public.users", { drop: ["updated_at"] })); + requestGetConnection({ connectionId: connection.connectionId, withRefreshedCatalog: true }); + }); + + it("shows breaking change on list page", () => { + visitConnectionsListPage(); + getSchemaChangeIcon(connection, "non_breaking").should("exist"); + }); - // Need to continue running but async breaks everything - visitConnectionPage(connection, "replication"); + it("shows non-breaking change that can be saved after refresh", () => { + // Need to continue running but async breaks everything + visitConnectionPage(connection, "replication"); - checkSchemaChangesDetected({ breaking: false }); - clickSchemaChangesReviewButton(); - getSyncEnabledSwitch().should("be.enabled"); + checkSchemaChangesDetected({ breaking: false }); + clickSchemaChangesReviewButton(); + getSyncEnabledSwitch().should("be.enabled"); - checkCatalogDiffModal(); - clickCatalogDiffCloseButton(); + checkCatalogDiffModal(); + clickCatalogDiffCloseButton(); - checkSchemaChangesDetectedCleared(); + checkSchemaChangesDetectedCleared(); - clickSaveReplication(); - getSyncEnabledSwitch().should("be.enabled"); + clickSaveReplication(); + getSyncEnabledSwitch().should("be.enabled"); + }); }); - it("shows breaking change that can be saved after refresh and fix", () => { - visitConnectionPage(connection, "replication"); + describe("breaking changes", () => { + beforeEach(() => { + visitConnectionPage(connection, "replication"); - // Change users sync mode - searchStream("users"); - selectSyncMode("Incremental", "Deduped + history"); - selectCursorField("updated_at"); - clickSaveReplication(); + // Change users sync mode + searchStream("users"); + selectSyncMode("Incremental", "Deduped + history"); + selectCursorField("updated_at"); + clickSaveReplication(); - // Remove cursor from db and refreshs schema to force breaking change detection - runDbQuery(alterTable("public.users", { drop: ["updated_at"] })); - requestGetConnection({ connectionId: connection.connectionId, withRefreshedCatalog: true }).then(console.log); + // Remove cursor from db and refreshs schema to force breaking change detection + runDbQuery(alterTable("public.users", { drop: ["updated_at"] })); + requestGetConnection({ connectionId: connection.connectionId, withRefreshedCatalog: true }); + cy.reload(); + }); + + it("shows breaking change on list page", () => { + visitConnectionsListPage(); + getSchemaChangeIcon(connection, "breaking").should("exist"); + }); - // Reload the page to pick up the changes - cy.reload(); + it("shows breaking change that can be saved after refresh and fix", () => { + visitConnectionPage(connection, "replication"); - // Confirm that breaking changes are there - checkSchemaChangesDetected({ breaking: true }); - clickSchemaChangesReviewButton(); - getSyncEnabledSwitch().should("be.disabled"); + // Confirm that breaking changes are there + checkSchemaChangesDetected({ breaking: true }); + clickSchemaChangesReviewButton(); + getSyncEnabledSwitch().should("be.disabled"); - checkCatalogDiffModal(); - clickCatalogDiffCloseButton(); - checkSchemaChangesDetectedCleared(); + checkCatalogDiffModal(); + clickCatalogDiffCloseButton(); + checkSchemaChangesDetectedCleared(); - // Fix the conflict - searchStream("Users"); - selectSyncMode("Full refresh", "Append"); + // Fix the conflict + searchStream("Users"); + selectSyncMode("Full refresh", "Append"); - clickSaveReplication(); - getSyncEnabledSwitch().should("be.enabled"); + clickSaveReplication(); + getSyncEnabledSwitch().should("be.enabled"); + }); }); }); diff --git a/airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts new file mode 100644 index 000000000000..c42fa0c6f332 --- /dev/null +++ b/airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts @@ -0,0 +1,11 @@ +import { Connection } from "commands/api/types"; +import { getWorkspaceId } from "commands/api/workspace"; + +export const visitConnectionsListPage = () => { + cy.intercept("**/web_backend/connections/list").as("listConnections"); + cy.visit(`/workspaces/${getWorkspaceId()}/connections`); + cy.wait("@listConnections"); +}; + +export const getSchemaChangeIcon = (connection: Connection, type: "breaking" | "non_breaking") => + cy.get(`[data-testId='statusCell-${connection.connectionId}'] [data-testId='changesStatusIcon-${type}']`); diff --git a/airbyte-webapp/src/components/EntityTable/components/ChangesStatusIcon.tsx b/airbyte-webapp/src/components/EntityTable/components/ChangesStatusIcon.tsx index 12898895d14c..53c3278c1370 100644 --- a/airbyte-webapp/src/components/EntityTable/components/ChangesStatusIcon.tsx +++ b/airbyte-webapp/src/components/EntityTable/components/ChangesStatusIcon.tsx @@ -27,7 +27,14 @@ export const ChangesStatusIcon: React.FC = ({ schemaChan } + control={ + + } > diff --git a/airbyte-webapp/src/components/EntityTable/components/StatusCell.tsx b/airbyte-webapp/src/components/EntityTable/components/StatusCell.tsx index 790c45e41fca..948dac83a3fe 100644 --- a/airbyte-webapp/src/components/EntityTable/components/StatusCell.tsx +++ b/airbyte-webapp/src/components/EntityTable/components/StatusCell.tsx @@ -31,7 +31,7 @@ export const StatusCell: React.FC = ({ const allowAutoDetectSchema = useFeature(FeatureItem.AllowAutoDetectSchema); return ( -

+
Date: Wed, 21 Dec 2022 15:22:53 -0500 Subject: [PATCH 13/24] Ensure that the manual sync button is enabled or disabled depending on the schema change type --- .../cypress/integration/autoDetectSchema.spec.ts | 9 ++++++++- .../cypress/pages/connnectionsListPage.ts | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts index cb5c384c36e1..3492b5204f76 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts @@ -18,7 +18,12 @@ import { runDbQuery } from "commands/db/db"; import { alterTable, createUsersTableQuery, dropUsersTableQuery } from "commands/db/queries"; import { initialSetupCompleted } from "commands/workspaces"; import { getSyncEnabledSwitch, visitConnectionPage } from "pages/connectionPage"; -import { getNonBreakingChangeIcon, getSchemaChangeIcon, visitConnectionsListPage } from "pages/connnectionsListPage"; +import { + getManualSyncButton, + getNonBreakingChangeIcon, + getSchemaChangeIcon, + visitConnectionsListPage, +} from "pages/connnectionsListPage"; import { checkCatalogDiffModal, clickCatalogDiffCloseButton } from "pages/modals/catalogDiffModal"; import { checkSchemaChangesDetected, @@ -86,6 +91,7 @@ describe("Auto-detect schema changes", () => { it("shows breaking change on list page", () => { visitConnectionsListPage(); getSchemaChangeIcon(connection, "non_breaking").should("exist"); + getManualSyncButton(connection).should("be.enabled"); }); it("shows non-breaking change that can be saved after refresh", () => { @@ -125,6 +131,7 @@ describe("Auto-detect schema changes", () => { it("shows breaking change on list page", () => { visitConnectionsListPage(); getSchemaChangeIcon(connection, "breaking").should("exist"); + getManualSyncButton(connection).should("be.disabled"); }); it("shows breaking change that can be saved after refresh and fix", () => { diff --git a/airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts index c42fa0c6f332..00a940d84665 100644 --- a/airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts +++ b/airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts @@ -9,3 +9,6 @@ export const visitConnectionsListPage = () => { export const getSchemaChangeIcon = (connection: Connection, type: "breaking" | "non_breaking") => cy.get(`[data-testId='statusCell-${connection.connectionId}'] [data-testId='changesStatusIcon-${type}']`); + +export const getManualSyncButton = (connection: Connection) => + cy.get(`[data-testId='statusCell-${connection.connectionId}'] button[data-testId='manual-sync-button']`); From c9336bb784e57259eb8f69c6138e67d2f61f593c Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Wed, 21 Dec 2022 16:09:23 -0500 Subject: [PATCH 14/24] Add test to verify non-breaking prefrence update --- .../integration/autoDetectSchema.spec.ts | 25 +++++++++++++------ .../cypress/pages/connnectionsListPage.ts | 8 ++++-- .../cypress/pages/replicationPage.ts | 13 ++++++++-- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts index 3492b5204f76..50db383734a0 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts @@ -18,12 +18,7 @@ import { runDbQuery } from "commands/db/db"; import { alterTable, createUsersTableQuery, dropUsersTableQuery } from "commands/db/queries"; import { initialSetupCompleted } from "commands/workspaces"; import { getSyncEnabledSwitch, visitConnectionPage } from "pages/connectionPage"; -import { - getManualSyncButton, - getNonBreakingChangeIcon, - getSchemaChangeIcon, - visitConnectionsListPage, -} from "pages/connnectionsListPage"; +import { getManualSyncButton, getSchemaChangeIcon, visitConnectionsListPage } from "pages/connnectionsListPage"; import { checkCatalogDiffModal, clickCatalogDiffCloseButton } from "pages/modals/catalogDiffModal"; import { checkSchemaChangesDetected, @@ -32,10 +27,11 @@ import { clickSchemaChangesReviewButton, searchStream, selectCursorField, + selectNonBreakingChangesPreference, selectSyncMode, } from "pages/replicationPage"; -describe("Auto-detect schema changes", () => { +describe("Connection - Auto-detect schema changes", () => { let source: Source; let destination: Destination; let connection: Connection; @@ -154,4 +150,19 @@ describe("Auto-detect schema changes", () => { getSyncEnabledSwitch().should("be.enabled"); }); }); + + describe("non-breaking schema update preference", () => { + it("saves non-breaking schema update preference change", () => { + visitConnectionPage(connection, "replication"); + selectNonBreakingChangesPreference("disable"); + + cy.intercept("/api/v1/web_backend/connections/update").as("updatesNonBreakingPreference"); + + clickSaveReplication({ confirm: false }); + + cy.wait("@updatesNonBreakingPreference").then((interception) => { + assert.equal((interception.response?.body as Connection).nonBreakingChangesPreference, "disable"); + }); + }); + }); }); diff --git a/airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts index 00a940d84665..1afce8345071 100644 --- a/airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts +++ b/airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts @@ -1,6 +1,10 @@ import { Connection } from "commands/api/types"; import { getWorkspaceId } from "commands/api/workspace"; +const statusCell = (connectionId: string) => `[data-testId='statusCell-${connectionId}']`; +const changesStatusIcon = (type: string) => `[data-testId='changesStatusIcon-${type}']`; +const manualSyncButton = "button[data-testId='manual-sync-button']"; + export const visitConnectionsListPage = () => { cy.intercept("**/web_backend/connections/list").as("listConnections"); cy.visit(`/workspaces/${getWorkspaceId()}/connections`); @@ -8,7 +12,7 @@ export const visitConnectionsListPage = () => { }; export const getSchemaChangeIcon = (connection: Connection, type: "breaking" | "non_breaking") => - cy.get(`[data-testId='statusCell-${connection.connectionId}'] [data-testId='changesStatusIcon-${type}']`); + cy.get(`${statusCell(connection.connectionId)} ${changesStatusIcon(type)}`); export const getManualSyncButton = (connection: Connection) => - cy.get(`[data-testId='statusCell-${connection.connectionId}'] button[data-testId='manual-sync-button']`); + cy.get(`${statusCell(connection.connectionId)} ${manualSyncButton}`); diff --git a/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts index a7f3058d6dac..a02f63e3e04c 100644 --- a/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts +++ b/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts @@ -30,6 +30,8 @@ const resetModalSaveButton = "[data-testid='resetModal-save']"; const schemaChangesDetectedBanner = "[data-testid='schemaChangesDetected']"; const schemaChangesReviewButton = "[data-testid='schemaChangesReviewButton']"; const schemaChangesBackdrop = "[data-testid='schemaChangesBackdrop']"; +const nonBreakingChangesPreference = "[data-testid='nonBreakingChangesPreference']"; +const nonBreakingChangesPreferenceValue = (value: string) => `div[data-testid='nonBreakingChangesPreference-${value}']`; export const goToReplicationTab = () => { cy.get(replicationTab).click(); @@ -176,12 +178,14 @@ export const searchStream = (value: string) => { cy.get(streamNameInput).type(value); }; -export const clickSaveReplication = ({ reset = false } = {}) => { +export const clickSaveReplication = ({ reset = false, confirm = true } = {}) => { cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection"); submitButtonClick(); - confirmStreamConfigurationChangedPopup({ reset }); + if (confirm) { + confirmStreamConfigurationChangedPopup({ reset }); + } cy.wait("@updateConnection").then((interception) => { assert.isNotNull(interception.response?.statusCode, "200"); @@ -222,3 +226,8 @@ export const clickSchemaChangesReviewButton = () => { cy.get(schemaChangesReviewButton).click(); // cy.get(schemaChangesReviewButton).should("be.disabled"); }; + +export const selectNonBreakingChangesPreference = (preference: "ignore" | "disable") => { + cy.get(nonBreakingChangesPreference).click(); + cy.get(nonBreakingChangesPreferenceValue(preference)).click(); +}; From ca31816a1e14d62a6ac880195d346f9d277f275a Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Wed, 18 Jan 2023 13:43:54 -0500 Subject: [PATCH 15/24] Fix testid prop case in StatusCell --- .../src/components/EntityTable/components/StatusCell.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airbyte-webapp/src/components/EntityTable/components/StatusCell.tsx b/airbyte-webapp/src/components/EntityTable/components/StatusCell.tsx index 948dac83a3fe..5baf909c2cf5 100644 --- a/airbyte-webapp/src/components/EntityTable/components/StatusCell.tsx +++ b/airbyte-webapp/src/components/EntityTable/components/StatusCell.tsx @@ -31,7 +31,7 @@ export const StatusCell: React.FC = ({ const allowAutoDetectSchema = useFeature(FeatureItem.AllowAutoDetectSchema); return ( -
+
Date: Fri, 27 Jan 2023 16:33:33 -0500 Subject: [PATCH 16/24] Fix small issues in auto-detect schema tests --- .../cypress/commands/utils/promise.ts | 2 +- .../cypress/integration/autoDetectSchema.spec.ts | 11 ++++++----- .../cypress/pages/replicationPage.ts | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/airbyte-webapp-e2e-tests/cypress/commands/utils/promise.ts b/airbyte-webapp-e2e-tests/cypress/commands/utils/promise.ts index 27d07454e160..248a9fd39fbf 100644 --- a/airbyte-webapp-e2e-tests/cypress/commands/utils/promise.ts +++ b/airbyte-webapp-e2e-tests/cypress/commands/utils/promise.ts @@ -2,7 +2,7 @@ * Converts Cypress chain to regular Promise. */ export const toPromise = (chain: Cypress.Chainable): Promise => { - return new Cypress.Promise((resolve, reject) => { + return new Cypress.Promise((resolve, reject) => { const onFail = (error: Error) => { Cypress.off("fail", onFail); reject(error); diff --git a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts index 50db383734a0..9ce866faab26 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts @@ -84,7 +84,7 @@ describe("Connection - Auto-detect schema changes", () => { requestGetConnection({ connectionId: connection.connectionId, withRefreshedCatalog: true }); }); - it("shows breaking change on list page", () => { + it("shows non-breaking change on list page", () => { visitConnectionsListPage(); getSchemaChangeIcon(connection, "non_breaking").should("exist"); getManualSyncButton(connection).should("be.enabled"); @@ -110,12 +110,13 @@ describe("Connection - Auto-detect schema changes", () => { describe("breaking changes", () => { beforeEach(() => { + const streamName = "users"; visitConnectionPage(connection, "replication"); // Change users sync mode - searchStream("users"); + searchStream(streamName); selectSyncMode("Incremental", "Deduped + history"); - selectCursorField("updated_at"); + selectCursorField(streamName, "updated_at"); clickSaveReplication(); // Remove cursor from db and refreshs schema to force breaking change detection @@ -130,7 +131,7 @@ describe("Connection - Auto-detect schema changes", () => { getManualSyncButton(connection).should("be.disabled"); }); - it("shows breaking change that can be saved after refresh and fix", () => { + it.only("shows breaking change that can be saved after refresh and fix", () => { visitConnectionPage(connection, "replication"); // Confirm that breaking changes are there @@ -143,7 +144,7 @@ describe("Connection - Auto-detect schema changes", () => { checkSchemaChangesDetectedCleared(); // Fix the conflict - searchStream("Users"); + searchStream("users"); selectSyncMode("Full refresh", "Append"); clickSaveReplication(); diff --git a/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts index a02f63e3e04c..2417f2e7b6e4 100644 --- a/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts +++ b/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts @@ -224,7 +224,7 @@ export const checkSchemaChangesDetectedCleared = () => { export const clickSchemaChangesReviewButton = () => { cy.get(schemaChangesReviewButton).click(); - // cy.get(schemaChangesReviewButton).should("be.disabled"); + cy.get(schemaChangesReviewButton).should("be.disabled"); }; export const selectNonBreakingChangesPreference = (preference: "ignore" | "disable") => { From 00309efb278efae02ee1eebd7c9a50b5c3a6c5b8 Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Mon, 30 Jan 2023 09:52:51 -0500 Subject: [PATCH 17/24] Remove it.only from autoDetectSchema.spec --- .../cypress/integration/autoDetectSchema.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts index 9ce866faab26..a8eed835f423 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts @@ -131,7 +131,7 @@ describe("Connection - Auto-detect schema changes", () => { getManualSyncButton(connection).should("be.disabled"); }); - it.only("shows breaking change that can be saved after refresh and fix", () => { + it("shows breaking change that can be saved after refresh and fix", () => { visitConnectionPage(connection, "replication"); // Confirm that breaking changes are there From 6b99bab9aa897ab1971b143c16620d56302997ac Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Mon, 30 Jan 2023 13:33:37 -0500 Subject: [PATCH 18/24] Remove promisification of api requests in e2e --- .../cypress/commands/api/api.ts | 36 +++++--------- .../integration/autoDetectSchema.spec.ts | 47 ++++++++++--------- .../cypress/pages/connectionPage.ts | 2 +- .../cypress/pages/connnectionsListPage.ts | 2 +- 4 files changed, 41 insertions(+), 46 deletions(-) diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts b/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts index 796a962cb2b6..e1be7a90694f 100644 --- a/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts +++ b/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts @@ -1,4 +1,3 @@ -import { toPromise } from "../utils/promise"; import { ConectionGetBody, Connection, @@ -14,35 +13,26 @@ import { getWorkspaceId, setWorkspaceId } from "./workspace"; const getApiUrl = (path: string): string => `http://localhost:8001/api/v1${path}`; -export const requestWorkspaceId = () => { - if (!getWorkspaceId()) { - return toPromise( - cy.request("POST", getApiUrl("/workspaces/list")).then((response) => { - expect(response.status).to.eq(200); - const { - workspaces: [{ workspaceId }], - } = response.body; +export const requestWorkspaceId = () => + cy.request("POST", getApiUrl("/workspaces/list")).then((response) => { + expect(response.status).to.eq(200); + const { + workspaces: [{ workspaceId }], + } = response.body; - setWorkspaceId(workspaceId as string); - }) - ); - } - - return Promise.resolve(); -}; + setWorkspaceId(workspaceId as string); + }); const apiRequest = ( method: Cypress.HttpMethod, path: string, payload?: Cypress.RequestBody, expectedStatus = 200 -): Promise => - toPromise( - cy.request(method, getApiUrl(path), payload).then((response) => { - expect(response.status).to.eq(expectedStatus, "response status"); - return response.body; - }) - ); +) => + cy.request(method, getApiUrl(path), payload).then((response) => { + expect(response.status).to.eq(expectedStatus, "response status"); + return response.body; + }); export const requestConnectionsList = () => apiRequest("POST", "/connections/list", { workspaceId: getWorkspaceId() }); diff --git a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts index a8eed835f423..ae9278e80167 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts @@ -36,32 +36,37 @@ describe("Connection - Auto-detect schema changes", () => { let destination: Destination; let connection: Connection; - beforeEach(async () => { + beforeEach(() => { initialSetupCompleted(); - await requestWorkspaceId(); - - const sourceRequestBody = getPostgresCreateSourceBody(appendRandomString("Auto-detect schema Source")); - const destinationRequestBody = getPostgresCreateDestinationBody( - appendRandomString("Auto-detect schema Destination") - ); - - source = await requestCreateSource(sourceRequestBody); - destination = await requestCreateDestination(destinationRequestBody); - runDbQuery(dropUsersTableQuery); runDbQuery(createUsersTableQuery); - const { catalog, catalogId } = await requestSourceDiscoverSchema(source.sourceId); - - const connectionRequestBody = await getConnectionCreateRequest({ - name: appendRandomString("Auto-detect schema test connection"), - sourceId: source.sourceId, - destinationId: destination.destinationId, - syncCatalog: catalog, - sourceCatalogId: catalogId, + requestWorkspaceId()?.then(() => { + const sourceRequestBody = getPostgresCreateSourceBody(appendRandomString("Auto-detect schema Source")); + const destinationRequestBody = getPostgresCreateDestinationBody( + appendRandomString("Auto-detect schema Destination") + ); + + requestCreateSource(sourceRequestBody).then((sourceResponse) => { + source = sourceResponse; + requestCreateDestination(destinationRequestBody).then((destinationResponse) => { + destination = destinationResponse; + }); + + requestSourceDiscoverSchema(source.sourceId).then(({ catalog, catalogId }) => { + const connectionRequestBody = getConnectionCreateRequest({ + name: appendRandomString("Auto-detect schema test connection"), + sourceId: source.sourceId, + destinationId: destination.destinationId, + syncCatalog: catalog, + sourceCatalogId: catalogId, + }); + requestCreateConnection(connectionRequestBody).then((connectionResponse) => { + connection = connectionResponse; + }); + }); + }); }); - - connection = await requestCreateConnection(connectionRequestBody); }); afterEach(() => { diff --git a/airbyte-webapp-e2e-tests/cypress/pages/connectionPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/connectionPage.ts index 4c7b92ec5fec..f901c448d8da 100644 --- a/airbyte-webapp-e2e-tests/cypress/pages/connectionPage.ts +++ b/airbyte-webapp-e2e-tests/cypress/pages/connectionPage.ts @@ -6,7 +6,7 @@ const syncEnabledSwitch = "[data-testid='enabledControl-switch']"; export const visitConnectionPage = (connection: Connection, tab = "") => { cy.intercept("**/web_backend/connections/get").as("getConnection"); cy.visit(`/workspaces/${getWorkspaceId()}/connections/${connection.connectionId}/${tab}`); - cy.wait("@getConnection"); + cy.wait("@getConnection", { timeout: 20000 }); }; export const getSyncEnabledSwitch = () => cy.get(syncEnabledSwitch); diff --git a/airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts index 1afce8345071..e1c7876d252a 100644 --- a/airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts +++ b/airbyte-webapp-e2e-tests/cypress/pages/connnectionsListPage.ts @@ -8,7 +8,7 @@ const manualSyncButton = "button[data-testId='manual-sync-button']"; export const visitConnectionsListPage = () => { cy.intercept("**/web_backend/connections/list").as("listConnections"); cy.visit(`/workspaces/${getWorkspaceId()}/connections`); - cy.wait("@listConnections"); + cy.wait("@listConnections", { timeout: 20000 }); }; export const getSchemaChangeIcon = (connection: Connection, type: "breaking" | "non_breaking") => From 96a712d4a155b4cd11e76d4e82c33c5c3c408f97 Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Mon, 30 Jan 2023 13:42:18 -0500 Subject: [PATCH 19/24] Fix typing in apiRequest --- airbyte-webapp-e2e-tests/cypress/commands/api/api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts b/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts index e1be7a90694f..2812fb4a74b8 100644 --- a/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts +++ b/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts @@ -28,7 +28,7 @@ const apiRequest = ( path: string, payload?: Cypress.RequestBody, expectedStatus = 200 -) => +): Cypress.Chainable => cy.request(method, getApiUrl(path), payload).then((response) => { expect(response.status).to.eq(expectedStatus, "response status"); return response.body; From fd30bddb2ab473b7ae7823df88fea0d2f6e6ddd9 Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Mon, 30 Jan 2023 13:49:58 -0500 Subject: [PATCH 20/24] Cleanup requestWorkspaceId --- .../cypress/commands/api/api.ts | 21 ++++++++----------- .../cypress/commands/api/types.ts | 2 +- .../integration/autoDetectSchema.spec.ts | 2 +- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts b/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts index 2812fb4a74b8..a7e4ea35d218 100644 --- a/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts +++ b/airbyte-webapp-e2e-tests/cypress/commands/api/api.ts @@ -1,5 +1,5 @@ import { - ConectionGetBody, + ConnectionGetBody, Connection, ConnectionCreateRequestBody, ConnectionsList, @@ -13,16 +13,6 @@ import { getWorkspaceId, setWorkspaceId } from "./workspace"; const getApiUrl = (path: string): string => `http://localhost:8001/api/v1${path}`; -export const requestWorkspaceId = () => - cy.request("POST", getApiUrl("/workspaces/list")).then((response) => { - expect(response.status).to.eq(200); - const { - workspaces: [{ workspaceId }], - } = response.body; - - setWorkspaceId(workspaceId as string); - }); - const apiRequest = ( method: Cypress.HttpMethod, path: string, @@ -34,6 +24,13 @@ const apiRequest = ( return response.body; }); +export const requestWorkspaceId = () => + apiRequest<{ workspaces: Array<{ workspaceId: string }> }>("POST", "/workspaces/list").then( + ({ workspaces: [{ workspaceId }] }) => { + setWorkspaceId(workspaceId); + } + ); + export const requestConnectionsList = () => apiRequest("POST", "/connections/list", { workspaceId: getWorkspaceId() }); @@ -43,7 +40,7 @@ export const requestCreateConnection = (body: ConnectionCreateRequestBody) => export const requestUpdateConnection = (body: Record) => apiRequest("POST", "/web_backend/connections/update", body); -export const requestGetConnection = (body: ConectionGetBody) => +export const requestGetConnection = (body: ConnectionGetBody) => apiRequest("POST", "/web_backend/connections/get", body); export const requestDeleteConnection = (connectionId: string) => diff --git a/airbyte-webapp-e2e-tests/cypress/commands/api/types.ts b/airbyte-webapp-e2e-tests/cypress/commands/api/types.ts index 070c3c3f3ceb..ff07d04bf326 100644 --- a/airbyte-webapp-e2e-tests/cypress/commands/api/types.ts +++ b/airbyte-webapp-e2e-tests/cypress/commands/api/types.ts @@ -29,7 +29,7 @@ export interface ConnectionCreateRequestBody { syncCatalog: SyncCatalog; } -export interface ConectionGetBody { +export interface ConnectionGetBody { connectionId: string; withRefreshedCatalog?: boolean; } diff --git a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts index ae9278e80167..32724670b8e0 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/autoDetectSchema.spec.ts @@ -41,7 +41,7 @@ describe("Connection - Auto-detect schema changes", () => { runDbQuery(dropUsersTableQuery); runDbQuery(createUsersTableQuery); - requestWorkspaceId()?.then(() => { + requestWorkspaceId().then(() => { const sourceRequestBody = getPostgresCreateSourceBody(appendRandomString("Auto-detect schema Source")); const destinationRequestBody = getPostgresCreateDestinationBody( appendRandomString("Auto-detect schema Destination") From e06f4f53ab522bcf8dffd03a02ed418e9fb89876 Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Mon, 30 Jan 2023 14:57:34 -0500 Subject: [PATCH 21/24] Update auto-detect e2e test to check where backdrop should not exist for non-breaking changes --- airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts b/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts index 2417f2e7b6e4..fd4ac27f47de 100644 --- a/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts +++ b/airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts @@ -214,7 +214,7 @@ export const checkSchemaChangesDetected = ({ breaking }: { breaking: boolean }) cy.get(schemaChangesDetectedBanner) .invoke("attr", "class") .should("match", breaking ? /\_breaking/ : /nonBreaking/); - cy.get(schemaChangesBackdrop).should("exist"); + cy.get(schemaChangesBackdrop).should(breaking ? "exist" : "not.exist"); }; export const checkSchemaChangesDetectedCleared = () => { From 096f5f3f281c3c34ccaade425370f8191deba725 Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Mon, 30 Jan 2023 15:06:59 -0500 Subject: [PATCH 22/24] Remove promise util for cypress --- .../cypress/commands/utils/promise.ts | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 airbyte-webapp-e2e-tests/cypress/commands/utils/promise.ts diff --git a/airbyte-webapp-e2e-tests/cypress/commands/utils/promise.ts b/airbyte-webapp-e2e-tests/cypress/commands/utils/promise.ts deleted file mode 100644 index 248a9fd39fbf..000000000000 --- a/airbyte-webapp-e2e-tests/cypress/commands/utils/promise.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Converts Cypress chain to regular Promise. - */ -export const toPromise = (chain: Cypress.Chainable): Promise => { - return new Cypress.Promise((resolve, reject) => { - const onFail = (error: Error) => { - Cypress.off("fail", onFail); - reject(error); - }; - - Cypress.on("fail", onFail); - - chain.then((value) => { - Cypress.off("fail", onFail); - resolve(value); - }); - }); -}; From 874f0e9bf1d50a4514c9bf52ba10bc1ebe418d4e Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Mon, 30 Jan 2023 15:50:41 -0500 Subject: [PATCH 23/24] Fix column name in connection e2e spec --- airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts index 4e3d0f73ce90..03a6f38e0efa 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts @@ -367,7 +367,7 @@ describe("Connection - stream details", () => { const destName = appendRandomString("Test connection Postgres destination cypress"); const streamName = "users"; - const collectionNames = ["col1", "id"]; + const collectionNames = ["email", "id"]; const collectionTypes = ["String", "Integer"]; createTestConnection(sourceName, destName); From 14a29c5bd20143f0166650c289f69b1dc13c3217 Mon Sep 17 00:00:00 2001 From: Edmundo Ruiz Ghanem Date: Tue, 31 Jan 2023 14:24:48 -0500 Subject: [PATCH 24/24] Fix fields in connection spec to match the new users table. Add email records to users table --- airbyte-webapp-e2e-tests/cypress/commands/db/queries.ts | 6 +++--- .../cypress/integration/connection.spec.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/airbyte-webapp-e2e-tests/cypress/commands/db/queries.ts b/airbyte-webapp-e2e-tests/cypress/commands/db/queries.ts index 089656f3a2e6..bf7128cf2cbf 100644 --- a/airbyte-webapp-e2e-tests/cypress/commands/db/queries.ts +++ b/airbyte-webapp-e2e-tests/cypress/commands/db/queries.ts @@ -32,9 +32,9 @@ export const createUsersTableQuery = createTable("public.users", [ "CONSTRAINT users_pkey PRIMARY KEY (id)", ]); export const insertUsersTableQuery = insertMultipleIntoTable("public.users", [ - { name: "Abigail", updated_at: "2022-12-19 00:00:00" }, - { name: "Andrew", updated_at: "2022-12-19 00:00:00" }, - { name: "Kat", updated_at: "2022-12-19 00:00:00" }, + { name: "Abigail", email: "abigail@example.com", updated_at: "2022-12-19 00:00:00" }, + { name: "Andrew", email: "andrew@example.com", updated_at: "2022-12-19 00:00:00" }, + { name: "Kat", email: "kat@example.com", updated_at: "2022-12-19 00:00:00" }, ]); export const dropUsersTableQuery = dropTable("public.users"); diff --git a/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts b/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts index 03a6f38e0efa..0f9ece580688 100644 --- a/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts +++ b/airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts @@ -367,8 +367,8 @@ describe("Connection - stream details", () => { const destName = appendRandomString("Test connection Postgres destination cypress"); const streamName = "users"; - const collectionNames = ["email", "id"]; - const collectionTypes = ["String", "Integer"]; + const collectionNames = ["email", "id", "name", "updated_at"]; + const collectionTypes = ["String", "Integer", "String", "Datetime"]; createTestConnection(sourceName, destName);