Skip to content

🪟 🧪E2E testing: DB data manipulation + Catalog Diff modal test cases #19447

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Nov 28, 2022
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion airbyte-webapp-e2e-tests/cypress.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,12 @@
"runMode": 2,
"openMode": 0
},
"defaultCommandTimeout": 10000
"defaultCommandTimeout": 10000,
"db": {
"user": "postgres",
"host": "localhost",
"database": "airbyte_ci",
"password": "secret_password",
"port":5433
}
}
4 changes: 2 additions & 2 deletions airbyte-webapp-e2e-tests/cypress/commands/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,6 @@ export const fillEmail = (email: string) => {

// useful for ensuring that a name is unique from one test run to the next
export const appendRandomString = (string: string) => {
const randomString = Math.random().toString(36).substring(2,10);
const randomString = Math.random().toString(36).substring(2, 10);
return string + " _" + randomString;
}
};
51 changes: 51 additions & 0 deletions airbyte-webapp-e2e-tests/cypress/commands/db/db.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {
alterCitiesTableQuery,
createCarsTableQuery,
createCitiesTableQuery,
createUsersTableQuery,
dropCarsTableQuery,
dropCitiesTableQuery,
dropUsersTableQuery,
insertCitiesTableQuery,
insertUsersTableQuery,
} from "./queries";

/**
* Wrapper for DB Query Cypress task
* @param queryString
*/
export const runDbQuery = <T>(queryString: string) => cy.task<T>("dbQuery", { query: queryString });

interface TableExistsResponse {
exists: boolean;
}
/**
* Function for composing the query for checking the existence of a table
* @param tableName
* @return string
*/
const composeIsTableExistQuery = (tableName: string) =>
`SELECT EXISTS (SELECT FROM pg_tables
WHERE
schemaname = 'public' AND
tablename = '${tableName}'
)`;

export const populateDBSource = () => {
runDbQuery(createUsersTableQuery);
runDbQuery(insertUsersTableQuery);
runDbQuery(createCitiesTableQuery);
runDbQuery(insertCitiesTableQuery);
};

export const makeChangesInDBSource = () => {
runDbQuery(dropUsersTableQuery);
runDbQuery(alterCitiesTableQuery);
runDbQuery(createCarsTableQuery);
};

export const cleanDBSource = () => {
runDbQuery(dropUsersTableQuery);
runDbQuery(dropCitiesTableQuery);
runDbQuery(dropCarsTableQuery);
};
1 change: 1 addition & 0 deletions airbyte-webapp-e2e-tests/cypress/commands/db/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { populateDBSource, makeChangesInDBSource, cleanDBSource } from "./db";
33 changes: 33 additions & 0 deletions airbyte-webapp-e2e-tests/cypress/commands/db/queries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// 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 dropUsersTableQuery = `
DROP TABLE IF EXISTS 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;`;

// 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;`;
61 changes: 58 additions & 3 deletions airbyte-webapp-e2e-tests/cypress/integration/connection.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@ import {
setupDestinationNamespaceCustomFormat,
selectFullAppendSyncMode,
checkSuccessResult,
refreshSourceSchemaBtnClick,
resetModalSaveBtnClick,
updateSchemaModalConfirmBtnClick,
} from "pages/replicationPage";
import { openSourceDestinationFromGrid, goToSourcePage } from "pages/sourcePage";
import { goToSettingsPage } from "pages/settingsConnectionPage";
import { update } from "cypress/types/lodash";
import { cleanDBSource, makeChangesInDBSource, populateDBSource } from "../commands/db";

describe("Connection main actions", () => {
beforeEach(() => {
Expand Down Expand Up @@ -127,7 +130,7 @@ describe("Connection main actions", () => {
deleteDestination(destName);
});

it("creates a connection, then edits the schedule type", () => {
it("Creates a connection, then edits the schedule type", () => {
const sourceName = appendRandomString("Test connection source cypress PokeAPI");
const destName = appendRandomString("Test connection destination cypress");

Expand Down Expand Up @@ -171,7 +174,11 @@ describe("Connection main actions", () => {

let loadedConnection: any = null; // Should be a WebBackendConnectionRead
cy.wait("@getConnection").then((interception) => {
const { scheduleType: readScheduleType, scheduleData: readScheduleData, ...connectionRead } = interception.response?.body;
const {
scheduleType: readScheduleType,
scheduleData: readScheduleData,
...connectionRead
} = interception.response?.body;
loadedConnection = connectionRead;

expect(loadedConnection).not.to.eq(null);
Expand Down Expand Up @@ -201,6 +208,54 @@ describe("Connection main actions", () => {
deleteDestination(destName);
});

it("Create a connection, update data in source, show diff modal, reset streams", () => {
cy.intercept("/api/v1/web_backend/connections/update").as("updateConnection");

populateDBSource();
const sourceName = appendRandomString(
"Test refresh source schema with changed data - connection Postgres source cypress"
);
const destName = appendRandomString(
"Test refresh source schema with changed data - connection Local JSON destination cypress"
);

createTestConnection(sourceName, destName);
cy.get("div").contains(sourceName).should("exist");
cy.get("div").contains(destName).should("exist");

makeChangesInDBSource();
openSourceDestinationFromGrid(sourceName);
goToReplicationTab();
refreshSourceSchemaBtnClick();

cy.get("[data-testid='catalog-diff-modal']").should("exist");

cy.get("table[aria-label='removed streams table']").should("contain", "users");

cy.get("table[aria-label='new streams table']").should("contain", "cars");

cy.get("button[aria-label='toggle accordion']").click();
cy.get("table[aria-label='removed fields']").should("contain", "city_code");
cy.get("table[aria-label='new fields']").children().should("contain", "country").and("contain", "state");

updateSchemaModalConfirmBtnClick();

cy.get("[data-testid='cars-stream-sync-checkbox']").check({ force: true });

submitButtonClick();
resetModalSaveBtnClick();

cy.wait("@updateConnection").then((interception) => {
assert.isNotNull(interception.response?.statusCode, "200");
});

checkSuccessResult();

deleteSource(sourceName);
deleteDestination(destName);
cleanDBSource();
});

it("Delete connection", () => {
const sourceName = "Test delete connection source cypress";
const destName = "Test delete connection destination cypress";
Expand Down
13 changes: 13 additions & 0 deletions airbyte-webapp-e2e-tests/cypress/pages/replicationPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const syncModeDropdown = "div[data-testid='syncSettingsDropdown'] input";
const successResult = "div[data-id='success-result']";
const saveStreamChangesButton = "button[data-testid='resetModal-save']";
const connectionNameInput = "input[data-testid='connectionName']";
const refreshSourceSchemaButton = "button[data-testid='refresh-source-schema-btn']";

export const goToReplicationTab = () => {
cy.get(replicationTab).click();
Expand Down Expand Up @@ -42,6 +43,18 @@ export const setupDestinationNamespaceSourceFormat = () => {
cy.get(destinationNamespaceSource).click();
};

export const refreshSourceSchemaBtnClick = () => {
cy.get(refreshSourceSchemaButton).click();
};

export const updateSchemaModalConfirmBtnClick = () => {
cy.get("[data-testid='update-schema-confirm-btn']").click();
};

export const resetModalSaveBtnClick = () => {
cy.get("[data-testid='resetModal-save']").click();
};

export const selectFullAppendSyncMode = () => {
cy.get(syncModeDropdown).first().click({ force: true });

Expand Down
8 changes: 7 additions & 1 deletion airbyte-webapp-e2e-tests/cypress/plugins/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,16 @@
// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)

import Cypress from "cypress"


/**
* @type {Cypress.PluginConfig}
*/
module.exports = (on, config) => {
module.exports = (on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
on("task", {
dbQuery:(query)=> require("cypress-postgres")(query.query,query.connection)
});
};
Loading