Browse Source

feat(testing): Added quicktest(not complete)

pull/3848/head
Muhammed Mustafa 2 years ago
parent
commit
f8d852f9d2
  1. 2
      packages/nc-gui/components/smartsheet/Form.vue
  2. 9
      packages/nc-gui/pages/signin.vue
  3. 18
      scripts/playwright/pages/Dashboard/Form/index.ts
  4. 32
      scripts/playwright/pages/Dashboard/common/Cell/CheckboxCell.ts
  5. 21
      scripts/playwright/pages/Dashboard/common/Cell/RatingCell.ts
  6. 12
      scripts/playwright/pages/Dashboard/common/Cell/index.ts
  7. 33
      scripts/playwright/pages/LoginPage/index.ts
  8. 44
      scripts/playwright/pages/ProjectsPage/index.ts
  9. 136
      scripts/playwright/quickTests/quickTests.spec.ts

2
packages/nc-gui/components/smartsheet/Form.vue

@ -702,7 +702,7 @@ watch(view, (nextView) => {
/> />
</a-form-item> </a-form-item>
<div class="text-gray-500 text-xs">{{ element.description }}</div> <div class="text-gray-500 text-xs" pw-data="nc-form-input-help-text-label">{{ element.description }}</div>
</div> </div>
</template> </template>

9
packages/nc-gui/pages/signin.vue

@ -88,6 +88,7 @@ function resetError() {
<a-input <a-input
v-model:value="form.email" v-model:value="form.email"
data-cy="nc-form-signin__email" data-cy="nc-form-signin__email"
pw-data="nc-form-signin__email"
size="large" size="large"
:placeholder="$t('msg.info.signUp.workEmail')" :placeholder="$t('msg.info.signUp.workEmail')"
@focus="resetError" @focus="resetError"
@ -98,6 +99,7 @@ function resetError() {
<a-input-password <a-input-password
v-model:value="form.password" v-model:value="form.password"
data-cy="nc-form-signin__password" data-cy="nc-form-signin__password"
pw-data="nc-form-signin__password"
size="large" size="large"
class="password" class="password"
:placeholder="$t('msg.info.signUp.enterPassword')" :placeholder="$t('msg.info.signUp.enterPassword')"
@ -112,7 +114,12 @@ function resetError() {
</div> </div>
<div class="self-center flex flex-col flex-wrap gap-4 items-center mt-4 justify-center"> <div class="self-center flex flex-col flex-wrap gap-4 items-center mt-4 justify-center">
<button data-cy="nc-form-signin__submit" class="scaling-btn bg-opacity-100" type="submit"> <button
data-cy="nc-form-signin__submit"
pw-data="nc-form-signin__submit"
class="scaling-btn bg-opacity-100"
type="submit"
>
<span class="flex items-center gap-2"> <span class="flex items-center gap-2">
<MdiLogin /> <MdiLogin />
{{ $t('general.signIn') }} {{ $t('general.signIn') }}

18
scripts/playwright/pages/Dashboard/Form/index.ts

@ -94,7 +94,7 @@ export class FormPage extends BasePage {
} }
getFormFields() { getFormFields() {
return this.get().locator('[data-pw="nc-form-field"]'); return this.get().locator('[data-pw="nc-form-fields"]');
} }
getDragNDropToHide() { getDragNDropToHide() {
@ -120,6 +120,22 @@ export class FormPage extends BasePage {
/////////////////////////// ///////////////////////////
// Form Actions // Form Actions
async verifyFormFieldLabel({ index, label }: { index: number; label: string }) {
await expect(await this.getFormFields().nth(index).locator('[data-pw="nc-form-input-label"]')).toContainText(label);
}
async verifyFormFieldHelpText({ index, helpText }: { index: number; helpText: string }) {
await expect(await this.getFormFields().nth(index).locator('[pw-data="nc-form-input-help-text-label"]')).toContainText(helpText);
}
async verifyFieldsIsEditable({ index }: { index: number }) {
await expect(await this.getFormFields().nth(index)).toHaveClass(/nc-editable/);
}
async verifyAfterSubmitMsg({ msg }: { msg: string }) {
await expect((await this.afterSubmitMsg.inputValue()).includes(msg)).toBeTruthy()
}
async verifyFormViewFieldsOrder({ fields }: { fields: string[] }) { async verifyFormViewFieldsOrder({ fields }: { fields: string[] }) {
let fieldLabels = await this.get().locator( let fieldLabels = await this.get().locator(
'[data-pw="nc-form-input-label"]' '[data-pw="nc-form-input-label"]'

32
scripts/playwright/pages/Dashboard/common/Cell/CheckboxCell.ts

@ -0,0 +1,32 @@
import { expect } from "@playwright/test";
import { CellPageObject } from ".";
import BasePage from "../../../Base";
export class CheckboxCellPageObject extends BasePage {
readonly cell: CellPageObject;
constructor(cell: CellPageObject) {
super(cell.rootPage);
this.cell = cell;
}
get({index, columnHeader}: {index?: number, columnHeader: string}) {
return this.cell.get({index, columnHeader});
}
async click({ index, columnHeader }: { index?: number, columnHeader: string }) {
return this.get({index, columnHeader}).locator('.nc-cell').click();
}
async isChecked({ index, columnHeader }: { index?: number, columnHeader: string }) {
return this.get({index, columnHeader}).locator('.nc-cell-hover-show').isVisible();
}
async verifyChecked({ index, columnHeader }: { index?: number, columnHeader: string }) {
expect(await this.get({index, columnHeader}).locator('.nc-cell-hover-show').isVisible()).toBe(false);
}
async verifyUnchecked({ index, columnHeader }: { index?: number, columnHeader: string }) {
expect(await this.get({index, columnHeader}).locator('.nc-cell-hover-show').isVisible()).toBe(true);
}
}

21
scripts/playwright/pages/Dashboard/common/Cell/RatingCell.ts

@ -0,0 +1,21 @@
import { expect } from "@playwright/test";
import { CellPageObject } from ".";
import BasePage from "../../../Base";
export class RatingCellPageObject extends BasePage {
readonly cell: CellPageObject;
constructor(cell: CellPageObject) {
super(cell.rootPage);
this.cell = cell;
}
get({index, columnHeader}: {index?: number, columnHeader: string}) {
return this.cell.get({index, columnHeader});
}
async verify({index, columnHeader, rating}: {index?: number, columnHeader: string, rating: number}) {
expect(await this.get({index, columnHeader}).locator(`div[role="radio"][aria-checked="true"]`).count()).toBe(rating);
}
}

12
scripts/playwright/pages/Dashboard/common/Cell/index.ts

@ -4,17 +4,22 @@ import BasePage from "../../../Base";
import { AttachmentCellPageObject } from "./AttachmentCell"; import { AttachmentCellPageObject } from "./AttachmentCell";
import { SelectOptionCellPageObject } from "./SelectOptionCell"; import { SelectOptionCellPageObject } from "./SelectOptionCell";
import { SharedFormPage } from "../../../SharedForm"; import { SharedFormPage } from "../../../SharedForm";
import { CheckboxCellPageObject } from "./CheckboxCell";
import { RatingCellPageObject } from "./RatingCell";
export class CellPageObject extends BasePage { export class CellPageObject extends BasePage {
readonly parent: GridPage | SharedFormPage; readonly parent: GridPage | SharedFormPage;
readonly selectOption: SelectOptionCellPageObject; readonly selectOption: SelectOptionCellPageObject;
readonly attachment: AttachmentCellPageObject; readonly attachment: AttachmentCellPageObject;
readonly checkbox: CheckboxCellPageObject;
readonly rating: RatingCellPageObject;
constructor(parent: GridPage | SharedFormPage) { constructor(parent: GridPage | SharedFormPage) {
super(parent.rootPage); super(parent.rootPage);
this.parent = parent; this.parent = parent;
this.selectOption = new SelectOptionCellPageObject(this); this.selectOption = new SelectOptionCellPageObject(this);
this.attachment = new AttachmentCellPageObject(this); this.attachment = new AttachmentCellPageObject(this);
this.checkbox = new CheckboxCellPageObject(this);
this.rating = new RatingCellPageObject(this);
} }
get({ get({
@ -127,6 +132,7 @@ export class CellPageObject extends BasePage {
} }
} }
// todo: Improve param names (i.e value => values)
// verifyVirtualCell // verifyVirtualCell
// : virtual relational cell- HM, BT, MM // : virtual relational cell- HM, BT, MM
// : verify link count & cell value // : verify link count & cell value
@ -139,7 +145,7 @@ export class CellPageObject extends BasePage {
}: { }: {
index: number; index: number;
columnHeader: string; columnHeader: string;
count: number; count?: number;
value: string[]; value: string[];
}) { }) {
// const count = value.length; // const count = value.length;
@ -148,7 +154,7 @@ export class CellPageObject extends BasePage {
const chipCount = await chips.count(); const chipCount = await chips.count();
// verify chip count & contents // verify chip count & contents
expect(chipCount).toEqual(count); if(count) expect(chipCount).toEqual(count);
// verify only the elements that are passed in // verify only the elements that are passed in
for (let i = 0; i < value.length; ++i) { for (let i = 0; i < value.length; ++i) {

33
scripts/playwright/pages/LoginPage/index.ts

@ -0,0 +1,33 @@
// playwright-dev-page.ts
import { expect, Page } from "@playwright/test";
import BasePage from "../Base";
export class LoginPage extends BasePage {
constructor(rootPage: Page) {
super(rootPage);
}
goto() {
return this.rootPage.goto('/#/signin');
}
get() {
return this.rootPage.locator("html");
}
async fillEmail(email: string) {
await this.get().locator(`[pw-data="nc-form-signin__email"]`).fill(email);
}
async fillPassword(password: string) {
await this.get().locator(`[pw-data="nc-form-signin__password"]`).fill(password);
}
async submit() {
await this.get().locator(`[pw-data="nc-form-signin__submit"]`).click();
await expect(this.rootPage).toHaveURL('http://localhost:3000/#/');
}
}

44
scripts/playwright/pages/ProjectsPage/index.ts

@ -0,0 +1,44 @@
// playwright-dev-page.ts
import { expect, Page } from "@playwright/test";
import BasePage from "../Base";
export class ProjectsPage extends BasePage {
constructor(rootPage: Page) {
super(rootPage);
}
get() {
return this.rootPage.locator("html");
}
async selectAndGetProject(projectName: string) {
let project: any;
await Promise.all([
this.rootPage.waitForResponse(async (res) => {
let json:any = {}
try{
json = await res.json()
} catch(e) {
return false;
}
const isRequiredResponse = res.request().url().includes('/api/v1/db/meta/projects') &&
['GET'].includes(res.request().method()) &&
json?.title === projectName;
if(isRequiredResponse){
project = json;
}
return isRequiredResponse;
}),
this.get().locator(`.ant-table-cell`,{
hasText: projectName
}).click()
]);
return project;
}
}

136
scripts/playwright/quickTests/quickTests.spec.ts

@ -0,0 +1,136 @@
import { expect, test } from "@playwright/test";
import { DashboardPage } from "../pages/Dashboard";
import { LoginPage } from "../pages/LoginPage";
import { ProjectsPage } from "../pages/ProjectsPage";
// normal fields
let recordCells = {
Name: "Movie-1",
Notes: "Good",
Status: "Todo",
Tags: "Jan",
Phone: "123123123",
Email: "a@b.com",
URL: "www.a.com",
Number: "1",
Value: "$1.00",
Percent: "0.01",
};
// links/ computed fields
let recordsVirtualCells = {
Duration: "00:01",
Done: true,
Date: "2022-05-31",
Rating: 1,
Actor: ["Actor1", "Actor2"],
"Status (from Actor)": ["Todo", "In progress"],
RollUp: "128",
Computation: "4.04",
Producer: ["P1", "P2"],
};
let tn = ["Film", "Actor", "Producer"];
let cn = [
"Name",
"Notes",
"Status",
"Tags",
"Done",
"Date",
"Phone",
"Email",
"URL",
"Number",
"Percent",
"Duration",
"Rating",
"Actor",
"Status (from Actor)",
"RollUp",
"Computation",
"Producer",
];
test.describe("Quick tests", () => {
let dashboard: DashboardPage;
// test.beforeEach(async ({ page }) => {
// });
test("Quick tests test", async ({page}) => {
let cellIndex = 0;
let columnCount = cn.length;
const loginPage = new LoginPage(page);
await loginPage.goto();
await loginPage.fillEmail("user@nocodb.com");
await loginPage.fillPassword("Password123.");
await loginPage.submit();
const projectsPage = new ProjectsPage(page);
const project = await projectsPage.selectAndGetProject("sample");
dashboard = new DashboardPage(page, project);
// verify if all tables exist
for (let i = 0; i < tn.length; i++) {
await dashboard.treeView.verifyTable({ title: tn[i] });
}
await dashboard.treeView.openTable({ title: "Film" });
// for Film table, verify columns
for (let i = 0; i < columnCount; i++) {
await dashboard.grid.column.verify({ title: cn[i] });
}
// normal cells
for (let [key, value] of Object.entries(recordCells)) {
await dashboard.grid.cell.verify({ index: cellIndex, columnHeader: key, value });
}
// checkbox
await dashboard.grid.cell.checkbox.verifyChecked({ index: cellIndex, columnHeader: "Done" });
// duration
await dashboard.grid.cell.verify({ index: cellIndex, columnHeader: "Duration", value: recordsVirtualCells.Duration });
// rating
await dashboard.grid.cell.rating.verify({ index: cellIndex, columnHeader: "Rating", rating: recordsVirtualCells.Rating });
// LinkToAnotherRecord
await dashboard.grid.cell.verifyVirtualCell({ index: cellIndex, columnHeader: "Actor", value: recordsVirtualCells.Actor });
// Status (from Actor)
// todo: Find a way to verify only the elements that are passed in
// await dashboard.grid.cell.verify({ index: cellIndex, columnHeader: "Status (from Actor)", value: recordsVirtualCells["Status (from Actor)"][0] });
// RollUp
await dashboard.grid.cell.verify({ index: cellIndex, columnHeader: "RollUp", value: recordsVirtualCells.RollUp });
// Computation
await dashboard.grid.cell.verify({ index: cellIndex, columnHeader: "Computation", value: recordsVirtualCells.Computation });
// LinkToAnotherRecord
await dashboard.grid.cell.verifyVirtualCell({ index: cellIndex, columnHeader: "Producer", value: recordsVirtualCells.Producer });
// Verify form
await dashboard.viewSidebar.openView({ title: "FormTitle" });
await dashboard.form.verifyHeader({ title: "FormTitle", subtitle: "FormDescription" });
await dashboard.form.verifyFormFieldLabel({ index: 0, label: "DisplayName" });
await dashboard.form.verifyFormFieldHelpText({ index: 0, helpText: "HelpText" });
await dashboard.form.verifyFieldsIsEditable({ index: 0 });
await dashboard.form.verifyAfterSubmitMsg({ msg: "Thank you for submitting the form!" });
await dashboard.form.verifyAfterSubmitMenuState({
emailMe: false,
showBlankForm: true,
submitAnotherForm: true,
});
// Verify webhooks
await dashboard.treeView.openTable({ title: "Actor" });
// await dashboard.webhookForm.open({})
});
});
Loading…
Cancel
Save