Update playwright (#10927)
Update twenty-e2e-testing to reflect actual state of app
This commit is contained in:
@ -4,17 +4,3 @@ BACKEND_BASE_URL=http://localhost:3000
|
|||||||
DEFAULT_LOGIN=tim@apple.dev
|
DEFAULT_LOGIN=tim@apple.dev
|
||||||
DEFAULT_PASSWORD=Applecar2025
|
DEFAULT_PASSWORD=Applecar2025
|
||||||
WEBSITE_URL=https://twenty.com
|
WEBSITE_URL=https://twenty.com
|
||||||
|
|
||||||
# === DO NOT USE, WORK IN PROGRESS ===
|
|
||||||
# This URL must have trailing forward slash as all REST API endpoints have object after it
|
|
||||||
# Documentation for REST API: https://twenty.com/developers/rest-api/core#/
|
|
||||||
# REST_API_BASE_URL=http://localhost:3000/rest/
|
|
||||||
|
|
||||||
# Documentation for GraphQL API: https://twenty.com/developers/graphql/core
|
|
||||||
# GRAPHQL_BASE_URL=http://localhost:3000/graphql
|
|
||||||
|
|
||||||
# Without this key, all API tests will fail, to generate this key
|
|
||||||
# Log in to Twenty workspace, go to Settings > Developers, generate new key and paste it here
|
|
||||||
# In order to use it, header Authorization: Bearer token must be used
|
|
||||||
# This key works for both REST and GraphQL API
|
|
||||||
# API_DEV_KEY=fill_with_proper_key
|
|
||||||
@ -25,7 +25,7 @@ export const test = base.extend<{ screenshotHook: void }>({
|
|||||||
),
|
),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
{ auto: true }, // automatic fixture runs with every test
|
{ auto: true },
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -44,7 +44,7 @@ export class InsertFieldData {
|
|||||||
'//label[contains(., "POST CODE")]/../div[last()]/input',
|
'//label[contains(., "POST CODE")]/../div[last()]/input',
|
||||||
);
|
);
|
||||||
this.countrySelect = page.locator(
|
this.countrySelect = page.locator(
|
||||||
'//span[contains(., "COUNTRY")]/../div[last()]/input',
|
'//span[contains(., "COUNTRY")]/../div[last()]/div',
|
||||||
);
|
);
|
||||||
this.arrayValueInput = page.locator("//input[@placeholder='Enter value']");
|
this.arrayValueInput = page.locator("//input[@placeholder='Enter value']");
|
||||||
this.arrayAddValueButton = page.locator(
|
this.arrayAddValueButton = page.locator(
|
||||||
|
|||||||
@ -1,5 +1,55 @@
|
|||||||
import { Locator, Page } from '@playwright/test';
|
import { Locator, Page } from '@playwright/test';
|
||||||
|
|
||||||
export class StripePage {
|
export class StripePage {
|
||||||
// TODO: implement all necessary methods (staging/sandbox page - does it differ anyhow from normal page?)
|
private readonly cardNumberInput: Locator;
|
||||||
|
private readonly cardExpiryInput: Locator;
|
||||||
|
private readonly cardCvcInput: Locator;
|
||||||
|
private readonly cardholderNameInput: Locator;
|
||||||
|
private readonly startTrialButton: Locator;
|
||||||
|
private readonly cancelSubscriptionButton: Locator;
|
||||||
|
private readonly confirmButton: Locator;
|
||||||
|
private readonly returnToTwentyLink: Locator;
|
||||||
|
|
||||||
|
constructor(public readonly page: Page) {
|
||||||
|
this.cardNumberInput = page.getByPlaceholder('1234 1234 1234 1234');
|
||||||
|
this.cardExpiryInput = page.getByPlaceholder('MM / YY');
|
||||||
|
this.cardCvcInput = page.getByPlaceholder('CVC');
|
||||||
|
this.cardholderNameInput = page.getByPlaceholder('Full name on card');
|
||||||
|
this.startTrialButton = page.getByTestId('hosted-payment-submit-button');
|
||||||
|
this.cancelSubscriptionButton = page.locator(
|
||||||
|
'a[data-test="cancel-subscription"]',
|
||||||
|
);
|
||||||
|
this.confirmButton = page.getByTestId('confirm');
|
||||||
|
this.returnToTwentyLink = page.getByTestId('return-to-business-link');
|
||||||
|
}
|
||||||
|
|
||||||
|
async fillCardNumber(number: string) {
|
||||||
|
await this.cardNumberInput.fill(number);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fillCardExpiry(expiry: string) {
|
||||||
|
await this.cardExpiryInput.fill(expiry);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fillCardCvc(cvc: string) {
|
||||||
|
await this.cardCvcInput.fill(cvc);
|
||||||
|
}
|
||||||
|
|
||||||
|
async fillCardholderName(name: string) {
|
||||||
|
await this.cardholderNameInput.fill(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
async startTrial() {
|
||||||
|
await this.startTrialButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async clickCancelSubscription() {
|
||||||
|
await this.cancelSubscriptionButton.click();
|
||||||
|
await this.confirmButton.click();
|
||||||
|
await this.page.getByTestId('cancellation_reason_cancel').click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async returnToTwenty() {
|
||||||
|
await this.returnToTwentyLink.click();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ export class AccountsSection {
|
|||||||
private readonly addBlocklistField: Locator;
|
private readonly addBlocklistField: Locator;
|
||||||
private readonly addBlocklistButton: Locator;
|
private readonly addBlocklistButton: Locator;
|
||||||
private readonly connectWithGoogleButton: Locator;
|
private readonly connectWithGoogleButton: Locator;
|
||||||
|
private readonly connectWithMicrosoftButton: Locator;
|
||||||
|
|
||||||
constructor(public readonly page: Page) {
|
constructor(public readonly page: Page) {
|
||||||
this.page = page;
|
this.page = page;
|
||||||
@ -22,6 +23,9 @@ export class AccountsSection {
|
|||||||
this.connectWithGoogleButton = page.getByRole('button', {
|
this.connectWithGoogleButton = page.getByRole('button', {
|
||||||
name: 'Connect with Google',
|
name: 'Connect with Google',
|
||||||
});
|
});
|
||||||
|
this.connectWithMicrosoftButton = page.getByRole('button', {
|
||||||
|
name: 'Connect with Microsoft',
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async clickAddAccount() {
|
async clickAddAccount() {
|
||||||
@ -51,4 +55,8 @@ export class AccountsSection {
|
|||||||
async linkGoogleAccount() {
|
async linkGoogleAccount() {
|
||||||
await this.connectWithGoogleButton.click();
|
await this.connectWithGoogleButton.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async linkMicrosoftAccount() {
|
||||||
|
await this.connectWithMicrosoftButton.click();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
64
packages/twenty-e2e-testing/lib/pom/settings/apisSection.ts
Normal file
64
packages/twenty-e2e-testing/lib/pom/settings/apisSection.ts
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import { Locator, Page } from '@playwright/test';
|
||||||
|
|
||||||
|
export class APIsSection {
|
||||||
|
private readonly createAPIKeyButton: Locator;
|
||||||
|
private readonly regenerateAPIKeyButton: Locator;
|
||||||
|
private readonly nameOfAPIKeyInput: Locator;
|
||||||
|
private readonly expirationDateAPIKeySelect: Locator;
|
||||||
|
private readonly cancelButton: Locator;
|
||||||
|
private readonly saveButton: Locator;
|
||||||
|
private readonly deleteButton: Locator;
|
||||||
|
|
||||||
|
constructor(public readonly page: Page) {
|
||||||
|
this.page = page;
|
||||||
|
this.createAPIKeyButton = page.getByRole('link', {
|
||||||
|
name: 'Create API Key',
|
||||||
|
});
|
||||||
|
this.nameOfAPIKeyInput = page
|
||||||
|
.getByPlaceholder('E.g. backoffice integration')
|
||||||
|
.first();
|
||||||
|
this.expirationDateAPIKeySelect = page.locator(
|
||||||
|
'div[aria-controls="object-field-type-select-options"]',
|
||||||
|
);
|
||||||
|
this.regenerateAPIKeyButton = page.getByRole('button', {
|
||||||
|
name: 'Regenerate Key',
|
||||||
|
});
|
||||||
|
this.cancelButton = page.getByRole('button', { name: 'Cancel' });
|
||||||
|
this.saveButton = page.getByRole('button', { name: 'Save' });
|
||||||
|
this.deleteButton = page.getByRole('button', { name: 'Delete' });
|
||||||
|
}
|
||||||
|
|
||||||
|
async createAPIKey() {
|
||||||
|
await this.createAPIKeyButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async typeAPIKeyName(name: string) {
|
||||||
|
await this.nameOfAPIKeyInput.clear();
|
||||||
|
await this.nameOfAPIKeyInput.fill(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
async selectAPIExpirationDate(date: string) {
|
||||||
|
await this.expirationDateAPIKeySelect.click();
|
||||||
|
await this.page.getByText(date, { exact: true }).click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async regenerateAPIKey() {
|
||||||
|
await this.regenerateAPIKeyButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteAPIKey() {
|
||||||
|
await this.deleteButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async clickCancelButton() {
|
||||||
|
await this.cancelButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async clickSaveButton() {
|
||||||
|
await this.saveButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkAPIKeyDetails(name: string) {
|
||||||
|
await this.page.locator(`//a/div[contains(.,'${name}')][first()]`).click();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,123 +0,0 @@
|
|||||||
import { Locator, Page } from '@playwright/test';
|
|
||||||
|
|
||||||
export class DevelopersSection {
|
|
||||||
private readonly readDocumentationButton: Locator;
|
|
||||||
private readonly createAPIKeyButton: Locator;
|
|
||||||
private readonly regenerateAPIKeyButton: Locator;
|
|
||||||
private readonly nameOfAPIKeyInput: Locator;
|
|
||||||
private readonly expirationDateAPIKeySelect: Locator;
|
|
||||||
private readonly createWebhookButton: Locator;
|
|
||||||
private readonly webhookURLInput: Locator;
|
|
||||||
private readonly webhookDescription: Locator;
|
|
||||||
private readonly webhookFilterObjectSelect: Locator;
|
|
||||||
private readonly webhookFilterActionSelect: Locator;
|
|
||||||
private readonly cancelButton: Locator;
|
|
||||||
private readonly saveButton: Locator;
|
|
||||||
private readonly deleteButton: Locator;
|
|
||||||
|
|
||||||
constructor(public readonly page: Page) {
|
|
||||||
this.page = page;
|
|
||||||
this.readDocumentationButton = page.getByRole('link', {
|
|
||||||
name: 'Read documentation',
|
|
||||||
});
|
|
||||||
this.createAPIKeyButton = page.getByRole('link', {
|
|
||||||
name: 'Create API Key',
|
|
||||||
});
|
|
||||||
this.createWebhookButton = page.getByRole('link', {
|
|
||||||
name: 'Create Webhook',
|
|
||||||
});
|
|
||||||
this.nameOfAPIKeyInput = page
|
|
||||||
.getByPlaceholder('E.g. backoffice integration')
|
|
||||||
.first();
|
|
||||||
this.expirationDateAPIKeySelect = page
|
|
||||||
.locator('div')
|
|
||||||
.filter({ hasText: /^Never$/ })
|
|
||||||
.nth(3); // good enough if expiration date will change only 1 time
|
|
||||||
this.regenerateAPIKeyButton = page.getByRole('button', {
|
|
||||||
name: 'Regenerate Key',
|
|
||||||
});
|
|
||||||
this.webhookURLInput = page.getByPlaceholder('URL');
|
|
||||||
this.webhookDescription = page.getByPlaceholder('Write a description');
|
|
||||||
this.webhookFilterObjectSelect = page
|
|
||||||
.locator('div')
|
|
||||||
.filter({ hasText: /^All Objects$/ })
|
|
||||||
.nth(3); // works only for first filter
|
|
||||||
this.webhookFilterActionSelect = page
|
|
||||||
.locator('div')
|
|
||||||
.filter({ hasText: /^All Actions$/ })
|
|
||||||
.nth(3); // works only for first filter
|
|
||||||
this.cancelButton = page.getByRole('button', { name: 'Cancel' });
|
|
||||||
this.saveButton = page.getByRole('button', { name: 'Save' });
|
|
||||||
this.deleteButton = page.getByRole('button', { name: 'Delete' });
|
|
||||||
}
|
|
||||||
|
|
||||||
async openDocumentation() {
|
|
||||||
await this.readDocumentationButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async createAPIKey() {
|
|
||||||
await this.createAPIKeyButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async typeAPIKeyName(name: string) {
|
|
||||||
await this.nameOfAPIKeyInput.clear();
|
|
||||||
await this.nameOfAPIKeyInput.fill(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
async selectAPIExpirationDate(date: string) {
|
|
||||||
await this.expirationDateAPIKeySelect.click();
|
|
||||||
await this.page.getByText(date, { exact: true }).click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async regenerateAPIKey() {
|
|
||||||
await this.regenerateAPIKeyButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteAPIKey() {
|
|
||||||
await this.deleteButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteWebhook() {
|
|
||||||
await this.deleteButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async createWebhook() {
|
|
||||||
await this.createWebhookButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async typeWebhookURL(url: string) {
|
|
||||||
await this.webhookURLInput.fill(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
async typeWebhookDescription(description: string) {
|
|
||||||
await this.webhookDescription.fill(description);
|
|
||||||
}
|
|
||||||
|
|
||||||
async selectWebhookObject(object: string) {
|
|
||||||
// TODO: finish
|
|
||||||
}
|
|
||||||
|
|
||||||
async selectWebhookAction(action: string) {
|
|
||||||
// TODO: finish
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteWebhookFilter() {
|
|
||||||
// TODO: finish
|
|
||||||
}
|
|
||||||
|
|
||||||
async clickCancelButton() {
|
|
||||||
await this.cancelButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async clickSaveButton() {
|
|
||||||
await this.saveButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async checkAPIKeyDetails(name: string) {
|
|
||||||
await this.page.locator(`//a/div[contains(.,'${name}')][first()]`).click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async checkWebhookDetails(name: string) {
|
|
||||||
await this.page.locator(`//a/div[contains(.,'${name}')][first()]`).click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -7,11 +7,12 @@ export class ExperienceSection {
|
|||||||
private readonly dateFormatDropdown: Locator;
|
private readonly dateFormatDropdown: Locator;
|
||||||
private readonly timeFormatDropdown: Locator;
|
private readonly timeFormatDropdown: Locator;
|
||||||
private readonly searchInput: Locator;
|
private readonly searchInput: Locator;
|
||||||
|
private readonly languageDropdown: Locator;
|
||||||
|
|
||||||
constructor(public readonly page: Page) {
|
constructor(public readonly page: Page) {
|
||||||
this.page = page;
|
this.page = page;
|
||||||
this.lightThemeButton = page.getByText('AaLight'); // it works
|
this.lightThemeButton = page.locator('div[variant="Light"]').first();
|
||||||
this.darkThemeButton = page.getByText('AaDark');
|
this.darkThemeButton = page.locator('div[variant="Dark"]').first();
|
||||||
this.timezoneDropdown = page.locator(
|
this.timezoneDropdown = page.locator(
|
||||||
'//span[contains(., "Time zone")]/../div/div/div',
|
'//span[contains(., "Time zone")]/../div/div/div',
|
||||||
);
|
);
|
||||||
@ -22,6 +23,9 @@ export class ExperienceSection {
|
|||||||
'//span[contains(., "Time format")]/../div/div/div',
|
'//span[contains(., "Time format")]/../div/div/div',
|
||||||
);
|
);
|
||||||
this.searchInput = page.getByPlaceholder('Search');
|
this.searchInput = page.getByPlaceholder('Search');
|
||||||
|
this.languageDropdown = page.locator(
|
||||||
|
'//h2[contains(., "Language")]/../../../div/div/div',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async changeThemeToLight() {
|
async changeThemeToLight() {
|
||||||
@ -52,4 +56,9 @@ export class ExperienceSection {
|
|||||||
await this.timeFormatDropdown.click();
|
await this.timeFormatDropdown.click();
|
||||||
await this.page.getByText(timeFormat, { exact: true }).click();
|
await this.page.getByText(timeFormat, { exact: true }).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async selectLanguage(language: string) {
|
||||||
|
await this.languageDropdown.click();
|
||||||
|
await this.page.getByText(language, { exact: true }).click();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,159 +0,0 @@
|
|||||||
import { Locator, Page } from '@playwright/test';
|
|
||||||
|
|
||||||
export class FunctionsSection {
|
|
||||||
private readonly newFunctionButton: Locator;
|
|
||||||
private readonly functionNameInput: Locator;
|
|
||||||
private readonly functionDescriptionInput: Locator;
|
|
||||||
private readonly editorTab: Locator;
|
|
||||||
private readonly codeEditorField: Locator;
|
|
||||||
private readonly resetButton: Locator;
|
|
||||||
private readonly publishButton: Locator;
|
|
||||||
private readonly testButton: Locator;
|
|
||||||
private readonly testTab: Locator;
|
|
||||||
private readonly runFunctionButton: Locator;
|
|
||||||
private readonly inputField: Locator;
|
|
||||||
private readonly settingsTab: Locator;
|
|
||||||
private readonly searchVariableInput: Locator;
|
|
||||||
private readonly addVariableButton: Locator;
|
|
||||||
private readonly nameVariableInput: Locator;
|
|
||||||
private readonly valueVariableInput: Locator;
|
|
||||||
private readonly cancelVariableButton: Locator;
|
|
||||||
private readonly saveVariableButton: Locator;
|
|
||||||
private readonly editVariableButton: Locator;
|
|
||||||
private readonly deleteVariableButton: Locator;
|
|
||||||
private readonly cancelButton: Locator;
|
|
||||||
private readonly saveButton: Locator;
|
|
||||||
private readonly deleteButton: Locator;
|
|
||||||
|
|
||||||
constructor(public readonly page: Page) {
|
|
||||||
this.newFunctionButton = page.getByRole('button', { name: 'New Function' });
|
|
||||||
this.functionNameInput = page.getByPlaceholder('Name');
|
|
||||||
this.functionDescriptionInput = page.getByPlaceholder('Description');
|
|
||||||
this.editorTab = page.getByTestId('tab-editor');
|
|
||||||
this.codeEditorField = page.getByTestId('dummyInput'); // TODO: fix
|
|
||||||
this.resetButton = page.getByRole('button', { name: 'Reset' });
|
|
||||||
this.publishButton = page.getByRole('button', { name: 'Publish' });
|
|
||||||
this.testButton = page.getByRole('button', { name: 'Test' });
|
|
||||||
this.testTab = page.getByTestId('tab-test');
|
|
||||||
this.runFunctionButton = page.getByRole('button', { name: 'Run Function' });
|
|
||||||
this.inputField = page.getByTestId('dummyInput'); // TODO: fix
|
|
||||||
this.settingsTab = page.getByTestId('tab-settings');
|
|
||||||
this.searchVariableInput = page.getByPlaceholder('Search a variable');
|
|
||||||
this.addVariableButton = page.getByRole('button', { name: 'Add Variable' });
|
|
||||||
this.nameVariableInput = page.getByPlaceholder('Name').nth(1);
|
|
||||||
this.valueVariableInput = page.getByPlaceholder('Value');
|
|
||||||
this.cancelVariableButton = page.locator('.css-uwqduk').first(); // TODO: fix
|
|
||||||
this.saveVariableButton = page.locator('.css-uwqduk').nth(1); // TODO: fix
|
|
||||||
this.editVariableButton = page.getByText('Edit', { exact: true });
|
|
||||||
this.deleteVariableButton = page.getByText('Delete', { exact: true });
|
|
||||||
this.cancelButton = page.getByRole('button', { name: 'Cancel' });
|
|
||||||
this.saveButton = page.getByRole('button', { name: 'Save' });
|
|
||||||
this.deleteButton = page.getByRole('button', { name: 'Delete function' });
|
|
||||||
}
|
|
||||||
|
|
||||||
async clickNewFunction() {
|
|
||||||
await this.newFunctionButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async typeFunctionName(name: string) {
|
|
||||||
await this.functionNameInput.fill(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
async typeFunctionDescription(description: string) {
|
|
||||||
await this.functionDescriptionInput.fill(description);
|
|
||||||
}
|
|
||||||
|
|
||||||
async checkFunctionDetails(name: string) {
|
|
||||||
await this.page.getByRole('link', { name: `${name} nodejs18.x` }).click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async clickEditorTab() {
|
|
||||||
await this.editorTab.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async clickResetButton() {
|
|
||||||
await this.resetButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async clickPublishButton() {
|
|
||||||
await this.publishButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async clickTestButton() {
|
|
||||||
await this.testButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async typeFunctionCode() {
|
|
||||||
// TODO: finish once utils are merged
|
|
||||||
}
|
|
||||||
|
|
||||||
async clickTestTab() {
|
|
||||||
await this.testTab.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async runFunction() {
|
|
||||||
await this.runFunctionButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async typeFunctionInput() {
|
|
||||||
// TODO: finish once utils are merged
|
|
||||||
}
|
|
||||||
|
|
||||||
async clickSettingsTab() {
|
|
||||||
await this.settingsTab.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async searchVariable(name: string) {
|
|
||||||
await this.searchVariableInput.fill(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
async addVariable() {
|
|
||||||
await this.addVariableButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async typeVariableName(name: string) {
|
|
||||||
await this.nameVariableInput.fill(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
async typeVariableValue(value: string) {
|
|
||||||
await this.valueVariableInput.fill(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
async editVariable(name: string) {
|
|
||||||
await this.page
|
|
||||||
.locator(
|
|
||||||
`//div[@data-testid='tooltip' and contains(., '${name}')]/../../div[last()]/div/div/button`,
|
|
||||||
)
|
|
||||||
.click();
|
|
||||||
await this.editVariableButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteVariable(name: string) {
|
|
||||||
await this.page
|
|
||||||
.locator(
|
|
||||||
`//div[@data-testid='tooltip' and contains(., '${name}')]/../../div[last()]/div/div/button`,
|
|
||||||
)
|
|
||||||
.click();
|
|
||||||
await this.deleteVariableButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async cancelVariable() {
|
|
||||||
await this.cancelVariableButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async saveVariable() {
|
|
||||||
await this.saveVariableButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async clickCancelButton() {
|
|
||||||
await this.cancelButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async clickSaveButton() {
|
|
||||||
await this.saveButton.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
async clickDeleteButton() {
|
|
||||||
await this.deleteButton.click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -4,6 +4,8 @@ export class GeneralSection {
|
|||||||
private readonly workspaceNameField: Locator;
|
private readonly workspaceNameField: Locator;
|
||||||
private readonly supportSwitch: Locator;
|
private readonly supportSwitch: Locator;
|
||||||
private readonly deleteWorkspaceButton: Locator;
|
private readonly deleteWorkspaceButton: Locator;
|
||||||
|
private readonly customizeDomainButton: Locator;
|
||||||
|
private readonly subdomainInput: Locator;
|
||||||
|
|
||||||
constructor(public readonly page: Page) {
|
constructor(public readonly page: Page) {
|
||||||
this.page = page;
|
this.page = page;
|
||||||
@ -12,6 +14,12 @@ export class GeneralSection {
|
|||||||
this.deleteWorkspaceButton = page.getByRole('button', {
|
this.deleteWorkspaceButton = page.getByRole('button', {
|
||||||
name: 'Delete workspace',
|
name: 'Delete workspace',
|
||||||
});
|
});
|
||||||
|
this.customizeDomainButton = page.getByRole('button', {
|
||||||
|
name: 'Customize domain',
|
||||||
|
});
|
||||||
|
this.subdomainInput = page.locator(
|
||||||
|
'//div[contains(.,".twenty-main.com")]/../input',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async changeWorkspaceName(workspaceName: string) {
|
async changeWorkspaceName(workspaceName: string) {
|
||||||
@ -26,4 +34,10 @@ export class GeneralSection {
|
|||||||
async clickDeleteWorkSpaceButton() {
|
async clickDeleteWorkSpaceButton() {
|
||||||
await this.deleteWorkspaceButton.click();
|
await this.deleteWorkspaceButton.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async changeSubdomain(subdomain: string) {
|
||||||
|
await this.customizeDomainButton.click();
|
||||||
|
await this.subdomainInput.fill(subdomain);
|
||||||
|
await this.page.getByRole('button', { name: 'Save' }).click();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,6 +29,7 @@ export class NewFieldSection {
|
|||||||
private readonly relationFieldLink: Locator;
|
private readonly relationFieldLink: Locator;
|
||||||
private readonly relationTypeSelect: Locator;
|
private readonly relationTypeSelect: Locator;
|
||||||
private readonly objectDestinationSelect: Locator;
|
private readonly objectDestinationSelect: Locator;
|
||||||
|
private readonly relationIconSelect: Locator;
|
||||||
private readonly relationFieldNameInput: Locator;
|
private readonly relationFieldNameInput: Locator;
|
||||||
private readonly fullNameFieldLink: Locator;
|
private readonly fullNameFieldLink: Locator;
|
||||||
private readonly UUIDFieldLink: Locator;
|
private readonly UUIDFieldLink: Locator;
|
||||||
@ -225,6 +226,11 @@ export class NewFieldSection {
|
|||||||
await this.page.getByTestId('tooltip').filter({ hasText: name }).click();
|
await this.page.getByTestId('tooltip').filter({ hasText: name }).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async selectRelationIcon(name: string) {
|
||||||
|
await this.relationIconSelect.click();
|
||||||
|
await this.page.getByTitle(name).click();
|
||||||
|
}
|
||||||
|
|
||||||
async typeRelationName(name: string) {
|
async typeRelationName(name: string) {
|
||||||
await this.relationFieldNameInput.clear();
|
await this.relationFieldNameInput.clear();
|
||||||
await this.relationFieldNameInput.fill(name);
|
await this.relationFieldNameInput.fill(name);
|
||||||
|
|||||||
22
packages/twenty-e2e-testing/lib/pom/settings/rolesSection.ts
Normal file
22
packages/twenty-e2e-testing/lib/pom/settings/rolesSection.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { Locator, Page } from '@playwright/test';
|
||||||
|
|
||||||
|
export class RolesSection {
|
||||||
|
private readonly page: Page;
|
||||||
|
private readonly createRoleButton: Locator;
|
||||||
|
private readonly defaultRoleDropdown: Locator;
|
||||||
|
|
||||||
|
constructor(page: Page) {
|
||||||
|
this.page = page;
|
||||||
|
this.createRoleButton = page.getByRole('button', { name: 'Create Role' });
|
||||||
|
this.defaultRoleDropdown = page.getByTestId('tooltip');
|
||||||
|
}
|
||||||
|
|
||||||
|
async clickCreateRoleButton() {
|
||||||
|
await this.createRoleButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async selectDefaultRole(role: string) {
|
||||||
|
await this.defaultRoleDropdown.click();
|
||||||
|
await this.page.getByTestId('tooltip').getByText(role).click();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,10 +1,28 @@
|
|||||||
import { Locator, Page } from '@playwright/test';
|
import { Locator, Page } from '@playwright/test';
|
||||||
|
|
||||||
export class SecuritySection {
|
export class SecuritySection {
|
||||||
|
private readonly googleToggle: Locator;
|
||||||
|
private readonly microsoftToggle: Locator;
|
||||||
|
private readonly passwordToggle: Locator;
|
||||||
private readonly inviteByLinkToggle: Locator;
|
private readonly inviteByLinkToggle: Locator;
|
||||||
|
|
||||||
constructor(public readonly page: Page) {
|
constructor(public readonly page: Page) {
|
||||||
this.inviteByLinkToggle = page.locator('input[type="checkbox"]').nth(1);
|
this.googleToggle = page.getByLabel('Google');
|
||||||
|
this.microsoftToggle = page.getByLabel('Microsoft');
|
||||||
|
this.passwordToggle = page.getByLabel('Password');
|
||||||
|
this.inviteByLinkToggle = page.getByLabel('Invite by Link');
|
||||||
|
}
|
||||||
|
|
||||||
|
async toggleGoogle() {
|
||||||
|
await this.googleToggle.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async toggleMicrosoft() {
|
||||||
|
await this.microsoftToggle.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async togglePassword() {
|
||||||
|
await this.passwordToggle.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
async toggleInviteByLink() {
|
async toggleInviteByLink() {
|
||||||
|
|||||||
@ -0,0 +1,65 @@
|
|||||||
|
import { Locator, Page } from '@playwright/test';
|
||||||
|
|
||||||
|
export class WebhooksSection {
|
||||||
|
private readonly createWebhookButton: Locator;
|
||||||
|
private readonly webhookURLInput: Locator;
|
||||||
|
private readonly webhookDescription: Locator;
|
||||||
|
private readonly deleteButton: Locator;
|
||||||
|
|
||||||
|
constructor(public readonly page: Page) {
|
||||||
|
this.page = page;
|
||||||
|
this.createWebhookButton = page.getByRole('link', {
|
||||||
|
name: 'Create Webhook',
|
||||||
|
});
|
||||||
|
this.webhookURLInput = page.getByPlaceholder('URL');
|
||||||
|
this.webhookDescription = page.getByPlaceholder('Write a description');
|
||||||
|
this.deleteButton = page.getByRole('button', { name: 'Delete' });
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteWebhook() {
|
||||||
|
await this.deleteButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async createWebhook() {
|
||||||
|
await this.createWebhookButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async typeWebhookURL(url: string) {
|
||||||
|
await this.webhookURLInput.clear();
|
||||||
|
await this.webhookURLInput.fill(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
async typeWebhookDescription(description: string) {
|
||||||
|
await this.webhookDescription.fill(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
async selectWebhookObject(index: number, object: string) {
|
||||||
|
await this.page
|
||||||
|
.locator(
|
||||||
|
`//div[aria-controls="object-webhook-type-select-${index}-options"]`,
|
||||||
|
)
|
||||||
|
.click();
|
||||||
|
await this.page.getByRole('option').getByText(object).click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async selectWebhookAction(index: number, action: string) {
|
||||||
|
await this.page
|
||||||
|
.locator(
|
||||||
|
`//div[aria-controls="operation-webhook-type-select-${index}-options"]`,
|
||||||
|
)
|
||||||
|
.click();
|
||||||
|
await this.page.getByRole('option').getByText(action).click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteWebhookFilter(index: number) {
|
||||||
|
await this.page
|
||||||
|
.locator(
|
||||||
|
`//div[aria-controls="object-webhook-type-select-${index}-options"]/../..//button`,
|
||||||
|
)
|
||||||
|
.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkWebhookDetails(name: string) {
|
||||||
|
await this.page.locator(`//a/div[contains(.,'${name}')][first()]`).click();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,11 +9,14 @@ export class SettingsPage {
|
|||||||
private readonly calendarsLink: Locator;
|
private readonly calendarsLink: Locator;
|
||||||
private readonly generalLink: Locator;
|
private readonly generalLink: Locator;
|
||||||
private readonly membersLink: Locator;
|
private readonly membersLink: Locator;
|
||||||
|
private readonly rolesLink: Locator;
|
||||||
private readonly dataModelLink: Locator;
|
private readonly dataModelLink: Locator;
|
||||||
private readonly developersLink: Locator;
|
|
||||||
private readonly functionsLink: Locator;
|
|
||||||
private readonly securityLink: Locator;
|
|
||||||
private readonly integrationsLink: Locator;
|
private readonly integrationsLink: Locator;
|
||||||
|
private readonly securityLink: Locator;
|
||||||
|
private readonly apisLink: Locator;
|
||||||
|
private readonly webhooksLink: Locator;
|
||||||
|
private readonly adminPanelLink: Locator;
|
||||||
|
private readonly labLink: Locator;
|
||||||
private readonly releasesLink: Locator;
|
private readonly releasesLink: Locator;
|
||||||
private readonly logoutLink: Locator;
|
private readonly logoutLink: Locator;
|
||||||
private readonly advancedToggle: Locator;
|
private readonly advancedToggle: Locator;
|
||||||
@ -28,11 +31,14 @@ export class SettingsPage {
|
|||||||
this.calendarsLink = page.getByRole('link', { name: 'Calendars' });
|
this.calendarsLink = page.getByRole('link', { name: 'Calendars' });
|
||||||
this.generalLink = page.getByRole('link', { name: 'General' });
|
this.generalLink = page.getByRole('link', { name: 'General' });
|
||||||
this.membersLink = page.getByRole('link', { name: 'Members' });
|
this.membersLink = page.getByRole('link', { name: 'Members' });
|
||||||
|
this.rolesLink = page.getByRole('link', { name: 'Roles' });
|
||||||
this.dataModelLink = page.getByRole('link', { name: 'Data model' });
|
this.dataModelLink = page.getByRole('link', { name: 'Data model' });
|
||||||
this.developersLink = page.getByRole('link', { name: 'Developers' });
|
|
||||||
this.functionsLink = page.getByRole('link', { name: 'Functions' });
|
|
||||||
this.integrationsLink = page.getByRole('link', { name: 'Integrations' });
|
this.integrationsLink = page.getByRole('link', { name: 'Integrations' });
|
||||||
this.securityLink = page.getByRole('link', { name: 'Security' });
|
this.securityLink = page.getByRole('link', { name: 'Security' });
|
||||||
|
this.apisLink = page.getByRole('link', { name: 'APIs' });
|
||||||
|
this.webhooksLink = page.getByRole('link', { name: 'Webhooks' });
|
||||||
|
this.adminPanelLink = page.getByRole('link', { name: 'Admin Panel' });
|
||||||
|
this.labLink = page.getByRole('link', { name: 'Lab' });
|
||||||
this.releasesLink = page.getByRole('link', { name: 'Releases' });
|
this.releasesLink = page.getByRole('link', { name: 'Releases' });
|
||||||
this.logoutLink = page.getByText('Logout');
|
this.logoutLink = page.getByText('Logout');
|
||||||
this.advancedToggle = page.locator('input[type="checkbox"]').first();
|
this.advancedToggle = page.locator('input[type="checkbox"]').first();
|
||||||
@ -70,24 +76,36 @@ export class SettingsPage {
|
|||||||
await this.membersLink.click();
|
await this.membersLink.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async goToRolesSection() {
|
||||||
|
await this.rolesLink.click();
|
||||||
|
}
|
||||||
|
|
||||||
async goToDataModelSection() {
|
async goToDataModelSection() {
|
||||||
await this.dataModelLink.click();
|
await this.dataModelLink.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
async goToDevelopersSection() {
|
async goToIntegrationsSection() {
|
||||||
await this.developersLink.click();
|
await this.integrationsLink.click();
|
||||||
}
|
|
||||||
|
|
||||||
async goToFunctionsSection() {
|
|
||||||
await this.functionsLink.click();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async goToSecuritySection() {
|
async goToSecuritySection() {
|
||||||
await this.securityLink.click();
|
await this.securityLink.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
async goToIntegrationsSection() {
|
async goToAPIsSection() {
|
||||||
await this.integrationsLink.click();
|
await this.apisLink.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async goToWebhooksSection() {
|
||||||
|
await this.webhooksLink.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async goToAdminPanelSection() {
|
||||||
|
await this.adminPanelLink.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
async goToLabSection() {
|
||||||
|
await this.labLink.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
async goToReleasesIntegration() {
|
async goToReleasesIntegration() {
|
||||||
|
|||||||
@ -6,6 +6,6 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.49.0"
|
"@playwright/test": "^1.51.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
30
yarn.lock
30
yarn.lock
@ -11360,14 +11360,14 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@playwright/test@npm:^1.49.0":
|
"@playwright/test@npm:^1.51.0":
|
||||||
version: 1.49.1
|
version: 1.51.0
|
||||||
resolution: "@playwright/test@npm:1.49.1"
|
resolution: "@playwright/test@npm:1.51.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
playwright: "npm:1.49.1"
|
playwright: "npm:1.51.0"
|
||||||
bin:
|
bin:
|
||||||
playwright: cli.js
|
playwright: cli.js
|
||||||
checksum: 10c0/2fca0bb7b334f7a23c7c5dfa5dbe37b47794c56f39b747c8d74a2f95c339e7902a296f2f1dd32c47bdd723cfa92cee05219f1a5876725dc89a1871b9137a286d
|
checksum: 10c0/ae83dd2c3a32133de58f44a9dbcd73a8059155ebd8acc736ba8bd0a7ca99b194afe2e8f5a500861d18b1c8f06b4e4ea8de4a2402297c59053d4becc404b47e0a
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@ -44555,12 +44555,12 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"playwright-core@npm:1.49.1":
|
"playwright-core@npm:1.51.0":
|
||||||
version: 1.49.1
|
version: 1.51.0
|
||||||
resolution: "playwright-core@npm:1.49.1"
|
resolution: "playwright-core@npm:1.51.0"
|
||||||
bin:
|
bin:
|
||||||
playwright-core: cli.js
|
playwright-core: cli.js
|
||||||
checksum: 10c0/990b619c75715cd98b2c10c1180a126e3a454b247063b8352bc67792fe01183ec07f31d30c8714c3768cefed12886d1d64ac06da701f2baafc2cad9b439e3919
|
checksum: 10c0/8f5de23088c5e97c00327f356b17e0223181e921baf99f4e38d9a3b18d0693db288f8b5389e96d0cb4a1b55f03870f140dd7346128a0c02ce36d11eb92153841
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@ -44579,18 +44579,18 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"playwright@npm:1.49.1":
|
"playwright@npm:1.51.0":
|
||||||
version: 1.49.1
|
version: 1.51.0
|
||||||
resolution: "playwright@npm:1.49.1"
|
resolution: "playwright@npm:1.51.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
fsevents: "npm:2.3.2"
|
fsevents: "npm:2.3.2"
|
||||||
playwright-core: "npm:1.49.1"
|
playwright-core: "npm:1.51.0"
|
||||||
dependenciesMeta:
|
dependenciesMeta:
|
||||||
fsevents:
|
fsevents:
|
||||||
optional: true
|
optional: true
|
||||||
bin:
|
bin:
|
||||||
playwright: cli.js
|
playwright: cli.js
|
||||||
checksum: 10c0/2368762c898920d4a0a5788b153dead45f9c36c3f5cf4d2af5228d0b8ea65823e3bbe998877950a2b9bb23a211e4633996f854c6188769dc81a25543ac818ab5
|
checksum: 10c0/e8509ea500e03e8051fd243f2347ac3196ff8dde4c20ae3aba4cf723e2b647a0158d209fba062995dab90590229a483d723562cf1ea8b2fc11698617027416fd
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@ -51273,7 +51273,7 @@ __metadata:
|
|||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "twenty-e2e-testing@workspace:packages/twenty-e2e-testing"
|
resolution: "twenty-e2e-testing@workspace:packages/twenty-e2e-testing"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@playwright/test": "npm:^1.49.0"
|
"@playwright/test": "npm:^1.51.0"
|
||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user