diff --git a/packages/frontend/e2e/tests/connect-wallet.test.ts b/packages/frontend/e2e/tests/connect-wallet.test.ts
index e6c7b3bb5..16e0100d5 100644
--- a/packages/frontend/e2e/tests/connect-wallet.test.ts
+++ b/packages/frontend/e2e/tests/connect-wallet.test.ts
@@ -1,34 +1,15 @@
-import { test, expect } from "../utils/fixtures";
-import { acceptAccess } from "@synthetixio/synpress/commands/metamask";
+import { test } from "../utils/fixtures";
+/**
+ *@description Basic connect wallet on Polygon Mumbai network
-test.beforeEach(async ({ page }) => {
- await page.goto("/");
+test.beforeEach(async ({ homePage }) => {
+ await homePage.goToHomePage();
});
-
-test("connect with metamask", async ({ page }) => {
- await test.step("select network drop down", async () => {
- await page.locator("div").getByText("Network").nth(2).click();
- });
-
- await test.step("click sepolia network", async () => {
- await page.getByTestId("Sepolia-network-button").nth(1).click();
- });
-
- await test.step("click connect wallet", async () => {
- await page.getByTestId("connect-wallet-button").nth(1).click();
- });
-
- await test.step("click metamask", async () => {
- await page.getByTestId("metaMask-wallet-button").nth(1).click();
- });
-
+test("connect with metamask", async ({ homePage }) => {
await test.step("connect to metamask", async () => {
- await acceptAccess();
+ await homePage.connectWallet();
});
-
await test.step("verify wallet is connected", async () => {
- await expect(
- page.getByTestId("profile-avatar-button").nth(1),
- ).toBeVisible();
+ await homePage.profileIconVisible();
});
});
diff --git a/packages/frontend/e2e/tests/create-campaign.test.ts b/packages/frontend/e2e/tests/create-campaign.test.ts
new file mode 100644
index 000000000..19b79e701
--- /dev/null
+++ b/packages/frontend/e2e/tests/create-campaign.test.ts
@@ -0,0 +1,73 @@
+import { test } from "../utils/fixtures";
+import { campaignData } from "../utils/data";
+/**
+ *@description Create campaign test
+ */
+
+test.beforeEach(async ({ homePage }) => {
+ await test.step("Navigate to Carrot Home page", async () => {
+ await homePage.goToHomePage();
+ });
+});
+test("Create campaign", async ({ homePage, createCampaign, campaignPage }) => {
+ await test.step("Connect to Metamask", async () => {
+ await homePage.connectWallet();
+ });
+ await test.step("Verify wallet is connected", async () => {
+ await homePage.profileIconVisible();
+ });
+ await test.step("Click create campaign button", async () => {
+ await homePage.clickCreateCampaign();
+ });
+ await test.step("Check text on autorization modal", async () => {
+ await createCampaign.checkAuthenticateModalText();
+ });
+ await test.step("Click Sign on authorization modal", async () => {
+ await createCampaign.clickSign();
+ });
+ await test.step("Sign on Metamask notification", async () => {
+ await createCampaign.confirmSignatureOnMetamask();
+ });
+ // General step
+ await test.step("Enter general data", async () => {
+ await createCampaign.enterGeneralData();
+ });
+ await test.step("Click next on General step", async () => {
+ await createCampaign.clickNextOnStep("general");
+ });
+ // Rewards step
+ await test.step("Enter rewards data", async () => {
+ await createCampaign.enterRewardsData();
+ });
+ await test.step("Click Add to campaign", async () => {
+ await createCampaign.clickAddToCampaign();
+ });
+ await test.step("Click next on Rewards step", async () => {
+ await createCampaign.clickNextOnStep("rewards");
+ });
+ // Oracle step
+ await test.step("Enter oracle data", async () => {
+ await createCampaign.enterOracleData();
+ });
+ await test.step("Click next on Oracle step", async () => {
+ await createCampaign.clickNextOnStep("oracle");
+ });
+ await test.step("Click Approve selected token", async () => {
+ await createCampaign.clickApprove();
+ });
+ await test.step("Approve token on Metamask", async () => {
+ await createCampaign.approveTokenOnMetamask();
+ });
+ // Deploy step
+ await test.step("Click deploy your campaign", async () => {
+ await createCampaign.clickDeployYourCampaign();
+ await homePage.pauseInSec(10);
+ });
+ await test.step("Click go to campaign", async () => {
+ await createCampaign.clickGoToCampaign();
+ await homePage.pauseInSec(10);
+ });
+ await test.step("Assert new campaign title", async () => {
+ await campaignPage.checkCampaignTitle(campaignData.title);
+ });
+});
diff --git a/packages/frontend/e2e/utils/data.ts b/packages/frontend/e2e/utils/data.ts
index 7d47c491a..2d398d931 100644
--- a/packages/frontend/e2e/utils/data.ts
+++ b/packages/frontend/e2e/utils/data.ts
@@ -1,3 +1,4 @@
+import { faker } from "@faker-js/faker";
/**
* @exports different data used in tests
*/
@@ -37,9 +38,21 @@ export const textData = {
footerCommunity: "Community",
walletDisconnected: "Wallet disconnected",
walletRequiredDescription: "A connected wallet is required to continue.",
+ welcomeToCarrot: "Welcome to Carrot",
+ authenticateDescription:
+ "In order to create campaigns it's necessary to sign a message. This request will not trigger a blockchain transaction or cost you any fees.",
};
export const campaignData = {
firstCampaign: "TS01 NOV13",
+ title: "Automatino Test Campaign",
+ description: faker.lorem.words(10),
+ tag: "Automation",
+ expiryDate: "",
+ tokenName: "Automation testing",
+ tokenSymbol: "ATST",
+ tokenSupply: "100",
+ rewardAmount: "100",
+ goalValue: "18",
};
export const templateData = {
erc20Title: "ERC20 KPI token",
diff --git a/packages/frontend/e2e/utils/fixtures.ts b/packages/frontend/e2e/utils/fixtures.ts
index 417dffc20..acdbd744e 100644
--- a/packages/frontend/e2e/utils/fixtures.ts
+++ b/packages/frontend/e2e/utils/fixtures.ts
@@ -3,7 +3,10 @@ import { initialSetup } from "@synthetixio/synpress/commands/metamask";
import { setExpectInstance } from "@synthetixio/synpress/commands/playwright";
import { resetState } from "@synthetixio/synpress/commands/synpress";
import { prepareMetamask } from "@synthetixio/synpress/helpers";
+// Page instances
import { HomePage } from "../utils/pages/homePage";
+import { CreateCampaign } from "./pages/createCampaignPage";
+import { CampaignPage } from "./pages/campaignPage";
/**
* @exports context fixture which sets up Metamask extension before test start
@@ -12,10 +15,9 @@ import { HomePage } from "../utils/pages/homePage";
export const test = base.extend<{
context: BrowserContext;
homePage: HomePage;
+ createCampaign: CreateCampaign;
+ campaignPage: CampaignPage;
}>({
- homePage: async ({ page }, use) => {
- await use(new HomePage(page));
- },
context: async ({}, use) => {
// required for synpress as it shares same expect instance as playwright
await setExpectInstance(expect);
@@ -39,6 +41,7 @@ export const test = base.extend<{
const context = await chromium.launchPersistentContext("", {
headless: false,
args: browserArgs,
+ viewport: { width: 1920, height: 1080 },
});
// wait for metamask
@@ -48,7 +51,7 @@ export const test = base.extend<{
await initialSetup(chromium, {
secretWordsOrPrivateKey:
"test test test test test test test test test test test junk",
- network: "sepolia",
+ network: "Polygon Mumbai",
password: "Tester@1234",
enableAdvancedSettings: true,
});
@@ -59,6 +62,15 @@ export const test = base.extend<{
await resetState();
},
+ homePage: async ({ page }, use) => {
+ await use(new HomePage(page));
+ },
+ createCampaign: async ({ page }, use) => {
+ await use(new CreateCampaign(page));
+ },
+ campaignPage: async ({ page }, use) => {
+ await use(new CampaignPage(page));
+ },
});
export const expect = test.expect;
diff --git a/packages/frontend/e2e/utils/pages/basePage.ts b/packages/frontend/e2e/utils/pages/basePage.ts
index 30cfa1c84..595b10467 100644
--- a/packages/frontend/e2e/utils/pages/basePage.ts
+++ b/packages/frontend/e2e/utils/pages/basePage.ts
@@ -41,8 +41,8 @@ export class BasePage {
async hoverElement(selector: string) {
await this.page.getByTestId(selector).hover();
}
- async isVisible(selector: string) {
- await expect(this.page.getByTestId(selector)).toBeVisible();
+ async isVisible(selector: string, index: number) {
+ await expect(this.page.getByTestId(selector).nth(index)).toBeVisible();
}
async isNotVisible(selector: string) {
await expect(this.page.getByTestId(selector)).not.toBeVisible();
diff --git a/packages/frontend/e2e/utils/pages/campaignPage.ts b/packages/frontend/e2e/utils/pages/campaignPage.ts
new file mode 100644
index 000000000..e62198b72
--- /dev/null
+++ b/packages/frontend/e2e/utils/pages/campaignPage.ts
@@ -0,0 +1,13 @@
+import { BasePage } from "./basePage";
+/**
+ * @exports Selectors and Methods for single Campaign page
+ */
+
+export class CampaignPage extends BasePage {
+ //---Selectors
+ campaignTitle_Text = "";
+ //---Methods
+ async checkCampaignTitle(title: string) {
+ await this.compareText(this.campaignTitle_Text, title, 0);
+ }
+}
diff --git a/packages/frontend/e2e/utils/pages/createCampaignPage.ts b/packages/frontend/e2e/utils/pages/createCampaignPage.ts
new file mode 100644
index 000000000..6f32efb6d
--- /dev/null
+++ b/packages/frontend/e2e/utils/pages/createCampaignPage.ts
@@ -0,0 +1,173 @@
+import { BasePage } from "./basePage";
+import {
+ confirmSignatureRequest,
+ confirmPermissionToApproveAll,
+} from "@synthetixio/synpress/commands/metamask";
+import { campaignData, textData } from "../data";
+/**
+ * @exports Selectors and Methods for create Campaign stepper
+ */
+
+export class CreateCampaign extends BasePage {
+ //---Selectors
+ welcomeToCarrot_Text = "welcome-to-carrot-title-text";
+ createCampaignAuthParagraph_Text = "authenticate-description-text";
+ cancel_Button = "authenticate-cancel-button";
+ signMessage_Button = "authenticate-sign-button";
+ campaingTitle_Field = "generic-data-step-title-input";
+ campaignDescription_Field = "#:rt:";
+ campaignTags_Field = "generic-data-step-tags-input";
+ addTag_Button =
+ "#carrot-template-26833f329b2f1da18c9ce2a9c000ee9c button > div";
+ generalNext_Button = "generic-data-step-next-button";
+ tokenName_Field = "rewards-step-token-name-input";
+ tokenSymbol_Field = "rewards-step-token-symbol-input";
+ tokenSupply_Field = "rewards-step-token-supply-input";
+ rewardPicker_Button = "rewards-step-open-rewards-picker-button";
+ manageList_Button = "";
+ carrotLabsDefault_Button = "";
+ aaaToken_Button = "";
+ tokenSearch_Field = "#token-search";
+ rewardAmount_Field = "rewards-step-reward-amount-input";
+ minimumPayout_Switch = "rewards-step-minimum-payout-switch";
+ addToCampaign_Button = "rewards-step-add-reward-button";
+ rewardsNext_Button = "rewards-step-next-button";
+ metricDropdown_Button = "creation-form-metric-select-input";
+ totalValueLocked_Option = "";
+ expirationDate_Field = "creation-form-measurement-date-input";
+ protocolDropdown_Button = "payload-form-protocol-select-input";
+ lido_Option = "";
+ greaterThan_Button = "creation-form-constraint-3";
+ goalValue_Field = "single-value-form-value0-input";
+ oracleNext_Button = "oracles-configuration-step-next-button";
+ approve_Button = "approve-reward";
+ deployYourCampaign_Button = "deploy-step-create-button";
+ goToCampaign_Button = "";
+ //---Methods
+ async checkAuthenticateModalText() {
+ await this.compareText(
+ this.welcomeToCarrot_Text,
+ textData.welcomeToCarrot,
+ 0,
+ );
+ await this.compareText(
+ this.createCampaignAuthParagraph_Text,
+ textData.authenticateDescription,
+ 0,
+ );
+ }
+ async confirmSignatureOnMetamask() {
+ await confirmSignatureRequest();
+ }
+ async approveTokenOnMetamask() {
+ await confirmPermissionToApproveAll();
+ }
+ // Clicks
+ async clickSign() {
+ await this.click(this.signMessage_Button);
+ }
+ async clickNextOnStep(step: string) {
+ switch (step) {
+ case "general":
+ this.click(this.generalNext_Button);
+ break;
+ case "rewards":
+ this.click(this.rewardsNext_Button);
+ break;
+ case "oracle":
+ this.click(this.generalNext_Button);
+ break;
+ case "deploy":
+ this.click(this.generalNext_Button);
+ break;
+ }
+ }
+ async clickAddToCampaign() {
+ await this.click(this.addToCampaign_Button);
+ }
+ async clickApprove() {
+ await this.click(this.approve_Button);
+ }
+ async clickDeployYourCampaign() {
+ await this.click(this.deployYourCampaign_Button);
+ }
+ async clickGoToCampaign() {
+ await this.click(this.goToCampaign_Button);
+ }
+ // General step
+ async enterTitle() {
+ await this.enterText(this.campaingTitle_Field, campaignData.title);
+ }
+ async enterDescription() {
+ await this.enterText(
+ this.campaignDescription_Field,
+ campaignData.description,
+ );
+ }
+ async enterTag() {
+ await this.enterText(this.campaignTags_Field, campaignData.description);
+ await this.clickFirst(this.addTag_Button);
+ }
+ async enterExpiryDate() {
+ await this.click(this.expirationDate_Field);
+ // todo: figure out how to enter date
+ }
+ async enterGeneralData() {
+ await this.enterTitle();
+ await this.enterDescription();
+ await this.enterTag();
+ }
+ // Rewards step
+ async enterTokenName() {
+ await this.enterText(this.tokenName_Field, campaignData.tokenName);
+ }
+ async enterTokenSymbol() {
+ await this.enterText(this.tokenSymbol_Field, campaignData.tokenSymbol);
+ }
+ async enterTokenSupply() {
+ await this.enterText(this.tokenSupply_Field, campaignData.tokenSupply);
+ }
+ // ATM carrot labs default; todo: improve to be able to select any token
+ async pickRewardToken() {
+ await this.click(this.rewardPicker_Button);
+ await this.click(this.manageList_Button);
+ await this.click(this.carrotLabsDefault_Button);
+ await this.click(this.aaaToken_Button);
+ }
+ async enterRewardAmount() {
+ await this.enterText(
+ this.rewardAmount_Field,
+ campaignData.rewardAmount,
+ );
+ }
+ async enterRewardsData() {
+ await this.enterTokenName();
+ await this.enterTokenSymbol();
+ await this.enterTokenSupply();
+ await this.pickRewardToken();
+ await this.enterRewardAmount();
+ }
+ // Oracle step
+ async selectTotalValueLockedMetric() {
+ await this.click(this.metricDropdown_Button);
+ await this.click(this.totalValueLocked_Option);
+ }
+ async selectProtocol() {
+ await this.click(this.protocolDropdown_Button);
+ await this.click(this.lido_Option);
+ }
+ // todo: improve to be able to select any goal
+ async selectGoal() {
+ await this.click(this.greaterThan_Button);
+ }
+ async enterGoalValue() {
+ await this.enterText(this.goalValue_Field, campaignData.goalValue);
+ }
+ async enterOracleData() {
+ await this.selectTotalValueLockedMetric();
+ await this.enterExpiryDate();
+ await this.selectProtocol();
+ await this.selectGoal();
+ await this.enterGoalValue();
+ }
+}
diff --git a/packages/frontend/e2e/utils/pages/homePage.ts b/packages/frontend/e2e/utils/pages/homePage.ts
index 3bbf15609..d2c649919 100644
--- a/packages/frontend/e2e/utils/pages/homePage.ts
+++ b/packages/frontend/e2e/utils/pages/homePage.ts
@@ -1,4 +1,5 @@
-import { BasePage } from "../pages/basePage";
+import { BasePage } from "./basePage";
+import { acceptAccess } from "@synthetixio/synpress/commands/metamask";
import {
campaignData,
urls,
@@ -53,6 +54,7 @@ export class HomePage extends BasePage {
footerDiscrod_Link = "footer-Discord-button";
footerTwitter_Link = "footer-Twitter-button";
footerCarrotInfoPage_Button = "footer-carrot-info-page-button";
+ profileAvatar_Button = "profile-avatar-button";
// selectors on campaign page
walletDisconnected_Text = "wallet-disconnected-text";
walletRequiredDescription_Text = "connect-wallet-required-text";
@@ -63,13 +65,6 @@ export class HomePage extends BasePage {
async goBack() {
await this.page.goBack();
}
- async checkStagingBanner() {
- await this.compareText(
- this.stagingBanner_Text,
- textData.stagingBannerText,
- 0,
- );
- }
//---Clicks
async clickAbout() {
await this.click(this.about_Button);
@@ -83,6 +78,9 @@ export class HomePage extends BasePage {
async clickConnectWallet() {
await this.clickSecond(this.connectWallet_Button);
}
+ async clickMetamask() {
+ await this.clickSecond(this.metamask_Button);
+ }
async clickSettings() {
await this.click(this.settings_Button);
}
@@ -96,6 +94,13 @@ export class HomePage extends BasePage {
await this.click(this.viewAllCampaigns_Button);
}
//--- Header assertions
+ async checkStagingBanner() {
+ await this.compareText(
+ this.stagingBanner_Text,
+ textData.stagingBannerText,
+ 0,
+ );
+ }
async checkAboutButtonRedirection() {
await this.checkRedirectionToNewTab(
this.about_Button,
@@ -224,7 +229,7 @@ export class HomePage extends BasePage {
}
async checkHowItWorksPreview() {
await this.clickHowItWorks();
- await this.isVisible(this.howItWorksVideo_Preview);
+ await this.isVisible(this.howItWorksVideo_Preview, 0);
await this.clickAnyWhereToClose();
}
// todo: this method should be on create campaign page
@@ -292,4 +297,13 @@ export class HomePage extends BasePage {
urls.carrotInfoPage,
);
}
+ async profileIconVisible() {
+ await this.isVisible(this.profileAvatar_Button, 1);
+ }
+ //---Connect wallet
+ async connectWallet() {
+ await this.clickConnectWallet();
+ await this.clickMetamask();
+ await acceptAccess();
+ }
}
diff --git a/packages/frontend/package.json b/packages/frontend/package.json
index d59d8746f..8d90899aa 100644
--- a/packages/frontend/package.json
+++ b/packages/frontend/package.json
@@ -35,7 +35,8 @@
"config-react-env": "./scripts/config-react-env.js",
"start:staging": "STAGING=true craco start",
"start": "craco start",
- "test:e2e": "yarn prepare-fathom && yarn playwright test"
+ "test:e2e": "yarn prepare-fathom && yarn playwright test",
+ "test:create-campaign": "yarn playwright test packages/frontend/e2e/tests/create-campaign.test.ts"
},
"dependencies": {
"@carrot-kpi/react": "*",
@@ -69,6 +70,7 @@
"@commitlint/cli": "^18.4.1",
"@commitlint/config-conventional": "^18.4.0",
"@craco/craco": "^7.1.0",
+ "@faker-js/faker": "^8.3.1",
"@fontsource/ibm-plex-mono": "^5.0.3",
"@playwright/test": "^1.39.0",
"@react-spring/web": "^9.7.3",
diff --git a/packages/frontend/src/components/authenticate.tsx b/packages/frontend/src/components/authenticate.tsx
index 29a2f81f5..284adcf2e 100644
--- a/packages/frontend/src/components/authenticate.tsx
+++ b/packages/frontend/src/components/authenticate.tsx
@@ -81,6 +81,7 @@ export const Authenticate = ({ onCancel }: AuthenticateProps) => {
<>