diff --git a/aliases.mainnet.json b/aliases.mainnet.json index 50c01a79..708cfe5e 100644 --- a/aliases.mainnet.json +++ b/aliases.mainnet.json @@ -5,5 +5,6 @@ "socialdb": "social.near", "gateway_url": "https://nearbuilders.org", "new": "builddao.near", - "old": "buildhub.near" + "old": "buildhub.near", + "potlock": "potlock.near" } diff --git a/aliases.testnet.json b/aliases.testnet.json index ef50d07f..d09075f1 100644 --- a/aliases.testnet.json +++ b/aliases.testnet.json @@ -5,5 +5,6 @@ "socialdb": "v1.social08.testnet", "gateway_url": "https://test.nearbuilders.org", "new": "builddao.testnet", - "old": "buildhub.testnet" + "old": "buildhub.testnet", + "potlock": "potlock.testnet" } diff --git a/apps/new/widget/components/project/Card.jsx b/apps/new/widget/components/project/Card.jsx index a8565647..9946140e 100644 --- a/apps/new/widget/components/project/Card.jsx +++ b/apps/new/widget/components/project/Card.jsx @@ -116,6 +116,7 @@ const EditButton = ({ item }) => { id: item.path, }, })} + onClick={(e) => e.stopPropagation()} type="icon" className={"rounded-3"} variant="primary" diff --git a/apps/new/widget/page/projects/MainViewContainer.jsx b/apps/new/widget/page/projects/MainViewContainer.jsx index 5f802ca2..16046119 100644 --- a/apps/new/widget/page/projects/MainViewContainer.jsx +++ b/apps/new/widget/page/projects/MainViewContainer.jsx @@ -93,7 +93,10 @@ const ProjectCardWrapper = ({ children, project }) => { return (
setShowQuickView(project)} + onClick={(e) => { + e.stopPropagation(); + setShowQuickView(project); + }} > {children}
diff --git a/apps/new/widget/page/projects/PotlockImport.jsx b/apps/new/widget/page/projects/PotlockImport.jsx index 5809eb59..fc9b5726 100644 --- a/apps/new/widget/page/projects/PotlockImport.jsx +++ b/apps/new/widget/page/projects/PotlockImport.jsx @@ -2,7 +2,7 @@ const { Button } = VM.require("${alias_old}/widget/components") || { Button: () => <>, }; const { getTagsFromSocialProfileData, getTeamMembersFromSocialProfileData } = - VM.require("potlock.near/widget/utils") || { + VM.require("${alias_potlock}/widget/utils") || { getTagsFromSocialProfileData: () => [], getTeamMembersFromSocialProfileData: () => [], }; @@ -10,7 +10,7 @@ const { getTagsFromSocialProfileData, getTeamMembersFromSocialProfileData } = const bootstrapTheme = props.bootstrapTheme || "dark"; let ListsSDK = - VM.require("potlock.near/widget/SDK.lists") || + VM.require("${alias_potlock}/widget/SDK.lists") || (() => ({ getRegistrations: () => {}, })); diff --git a/apps/new/widget/page/projects/PotlockProjectCard.jsx b/apps/new/widget/page/projects/PotlockProjectCard.jsx index 93cc098a..267556f2 100644 --- a/apps/new/widget/page/projects/PotlockProjectCard.jsx +++ b/apps/new/widget/page/projects/PotlockProjectCard.jsx @@ -1,6 +1,6 @@ const { potId, potDetail, payoutDetails, projects } = props; const { nearToUsd, ipfsUrlFromCid, yoctosToNear, yoctosToUsdWithFallback } = - VM.require("potlock.near/widget/utils") || { + VM.require("${alias_potlock}/widget/utils") || { ipfsUrlFromCid: () => "", yoctosToNear: () => "", yoctosToUsdWithFallback: () => "", @@ -8,30 +8,30 @@ const { nearToUsd, ipfsUrlFromCid, yoctosToNear, yoctosToUsdWithFallback } = }; const { _address } = VM.require( - `potlock.near/widget/Components.DonorsUtils`, + "${alias_potlock}/widget/Components.DonorsUtils", ) || { _address: (address) => address, }; const { ownerId, NADA_BOT_URL, SUPPORTED_FTS } = VM.require( - "potlock.near/widget/constants", + "${alias_potlock}/widget/constants", ) || { ownerId: "", NADA_BOT_URL: "", SUPPORTED_FTS: {}, }; const { getTagsFromSocialProfileData } = VM.require( - "potlock.near/widget/utils", + "${alias_potlock}/widget/utils", ) || { getTagsFromSocialProfileData: () => [], }; -const PotSDK = VM.require("potlock.near/widget/SDK.pot") || { +const PotSDK = VM.require("${alias_potlock}/widget/SDK.pot") || { getDonationsForProject: () => {}, }; let DonateSDK = - VM.require("potlock.near/widget/SDK.donate") || + VM.require("${alias_potlock}/widget/SDK.donate") || (() => ({ getDonationsForRecipient: () => {}, })); @@ -363,7 +363,10 @@ const profileImageStyle = { const tags = getTagsFromSocialProfileData(profile); return ( -
props.setShowCreateModalProjectId(projectId)}> +
props.setShowCreateModalProjectId(projectId)} + > diff --git a/apps/old/widget/components/Button.jsx b/apps/old/widget/components/Button.jsx index 10ddb78e..8e82be49 100644 --- a/apps/old/widget/components/Button.jsx +++ b/apps/old/widget/components/Button.jsx @@ -103,6 +103,7 @@ function Button({ className={linkClassName} style={{ textDecoration: "none" }} target={target} + onClick={(e) => e.stopPropagation()} > e.stopPropagation()} > { - test.beforeEach(async ({ page }) => { - await page.goto(`/${ROOT_SRC}?page=projects&tab=editor`); - }); - - test.describe("User is not logged in", () => { - test.use({ - storageState: "playwright-tests/storage-states/wallet-not-connected.json", + test.describe("Editor", () => { + test.beforeEach(async ({ page }) => { + await page.goto(`/${ROOT_SRC}?page=projects&tab=editor`); }); - test("editor page should prompt user to log in", async ({ page }) => { - const requireLogin = await page.getByText( - "Please log in in order to see create or edit a project.", - ); + test.describe("User is not logged in", () => { + test.use({ + storageState: + "playwright-tests/storage-states/wallet-not-connected.json", + }); - await expect(requireLogin).toBeVisible(); - }); - }); + test("editor page should prompt user to log in", async ({ page }) => { + const requireLogin = await page.getByText( + "Please log in in order to see create or edit a project.", + ); - test.describe("User is logged in", () => { - test.use({ - storageState: "playwright-tests/storage-states/wallet-connected.json", + await expect(requireLogin).toBeVisible(); + }); }); - test.beforeEach(async ({ page }) => { - // Intercept IPFS requests - await page.route("**/add", async (route) => { - const modifiedResponse = { - status: 200, - contentType: "application/json", - body: JSON.stringify({ cid: "simple_cid" }), - }; + test.describe("User is logged in", () => { + test.use({ + storageState: "playwright-tests/storage-states/wallet-connected.json", + }); - // Fulfill the route with the modified response - await route.fulfill(modifiedResponse); + test.beforeEach(async ({ page }) => { + // Intercept IPFS requests + await page.route("**/add", async (route) => { + const modifiedResponse = { + status: 200, + contentType: "application/json", + body: JSON.stringify({ cid: "simple_cid" }), + }; + + // Fulfill the route with the modified response + await route.fulfill(modifiedResponse); + }); }); - }); - test("should not allow next when empty required fields", async ({ - page, - }) => { - const nextButton = await page.getByRole("button", { name: "Next" }); - await expect(nextButton).toBeDisabled(); + test("should not allow next when empty required fields", async ({ + page, + }) => { + const nextButton = await page.getByRole("button", { name: "Next" }); + await expect(nextButton).toBeDisabled(); - const projectAccountAddress = await page.getByPlaceholder( - "Enter Project Account Address", - ); + const projectAccountAddress = await page.getByPlaceholder( + "Enter Project Account Address", + ); - const title = await page.getByPlaceholder("Enter Project Title"); - const description = await page - .frameLocator("iframe") - .locator('textarea[name="textarea"]'); + const title = await page.getByPlaceholder("Enter Project Title"); + const description = await page + .frameLocator("iframe") + .locator('textarea[name="textarea"]'); - // Fill required fields - await projectAccountAddress.fill("anyproject.near"); - await title.fill("Sample project"); + // Fill required fields + await projectAccountAddress.fill("anyproject.near"); + await title.fill("Sample project"); - await description.click(); - await description.fill("This is a sample project"); + await description.click(); + await description.fill("This is a sample project"); - await expect(nextButton).toBeEnabled(); + await expect(nextButton).toBeEnabled(); - // Clear title - await title.clear(); - await expect(nextButton).toBeDisabled(); + // Clear title + await title.clear(); + await expect(nextButton).toBeDisabled(); - await title.fill("Sample project"); - await expect(nextButton).toBeEnabled(); + await title.fill("Sample project"); + await expect(nextButton).toBeEnabled(); - await description.click(); - await description.clear(); - await expect(nextButton).toBeDisabled(); - }); + await description.click(); + await description.clear(); + await expect(nextButton).toBeDisabled(); + }); - test("should not allow invalid project account address", async ({ - page, - }) => { - // Project Account Address - await page - .getByPlaceholder("Enter Project Account Address") - .fill("anyproject"); + test("should not allow invalid project account address", async ({ + page, + }) => { + // Project Account Address + await page + .getByPlaceholder("Enter Project Account Address") + .fill("anyproject"); + + const errorMsg = await page.getByText( + "Invalid Near Address, please enter a valid near address", + ); + await expect(errorMsg).toBeVisible(); + }); - const errorMsg = await page.getByText( - "Invalid Near Address, please enter a valid near address", - ); - await expect(errorMsg).toBeVisible(); - }); + test("cancel should navigate to main projects page", async ({ page }) => { + await page.getByRole("button", { name: "Cancel" }).click(); + expect(page.url()).toContain("?page=projects"); + }); - test("cancel should navigate to main projects page", async ({ page }) => { - await page.getByRole("button", { name: "Cancel" }).click(); - expect(page.url()).toContain("?page=projects"); - }); + test("should complete flow and save data correctly with images populated", async ({ + page, + }) => { + const expectedProjectData = { + // TODO: We will want to get rid of this + title: "Sample project", + description: "This is a sample project", + profileImage: { + ipfs_cid: "simple_cid", + }, + backgroundImage: { + ipfs_cid: "simple_cid", + }, + tags: { + test: "", + }, + linktree: { + twitter: "SampleTwitter", + github: "SampleGithub", + telegram: "SampleTelegram", + website: "https://www.samplewebsite.com", + }, + // End remove + contributors: ["anybody.near", "nobody.near"], + tabs: ["overview", "tasks", "activity"], + projectAccountId: "anyproject.near", + teamSize: "1-10", + location: "anywhere", + }; - test("should complete flow and save data correctly with images populated", async ({ - page, - }) => { - const expectedProjectData = { - // TODO: We will want to get rid of this - title: "Sample project", - description: "This is a sample project", - profileImage: { - ipfs_cid: "simple_cid", - }, - backgroundImage: { - ipfs_cid: "simple_cid", - }, - tags: { - test: "", - }, - linktree: { - twitter: "SampleTwitter", - github: "SampleGithub", - telegram: "SampleTelegram", - website: "https://www.samplewebsite.com", - }, - // End remove - contributors: ["anybody.near", "nobody.near"], - tabs: ["overview", "tasks", "activity"], - projectAccountId: "anyproject.near", - teamSize: "1-10", - location: "anywhere", - }; - - const expectedTransactionData = { - "anybody.near": { - project: { - "sample-project": { - "": JSON.stringify(expectedProjectData), - metadata: { - name: "Sample project", - description: "This is a sample project", - image: { - ipfs_cid: "simple_cid", - }, - backgroundImage: { - ipfs_cid: "simple_cid", - }, - tags: { - test: "", - }, - linktree: { - github: "https://github.com/SampleGithub", - telegram: "https://t.me/SampleTelegram", - twitter: "https://twitter.com/SampleTwitter", - website: "https://www.samplewebsite.com", + const expectedTransactionData = { + "anybody.near": { + project: { + "sample-project": { + "": JSON.stringify(expectedProjectData), + metadata: { + name: "Sample project", + description: "This is a sample project", + image: { + ipfs_cid: "simple_cid", + }, + backgroundImage: { + ipfs_cid: "simple_cid", + }, + tags: { + test: "", + }, + linktree: { + github: "https://github.com/SampleGithub", + telegram: "https://t.me/SampleTelegram", + twitter: "https://twitter.com/SampleTwitter", + website: "https://www.samplewebsite.com", + }, }, }, }, - }, - "builddao.testnet": { - project: { - "anybody.near_project_sample-project": "", + "builddao.testnet": { + project: { + "anybody.near_project_sample-project": "", + }, }, }, - }, - }; - - // Page one // - - // Project Account Address - await page - .getByPlaceholder("Enter Project Account Address") - .fill("anyproject.near"); - - // Title - await page.getByPlaceholder("Enter Project Title").fill("Sample project"); - - // Description - await page - .frameLocator("iframe") - .locator('textarea[name="textarea"]') - .click(); - await page - .frameLocator("iframe") - .locator('textarea[name="textarea"]') - .fill("This is a sample project"); - - await page.getByPlaceholder("Enter location").fill("anywhere"); // Location - - await page.getByRole("combobox").selectOption("1-10"); - - await page.getByLabel("Twitter").fill("SampleTwitter"); - await page.getByLabel("Github").fill("SampleGithub"); - await page.getByLabel("Telegram").fill("SampleTelegram"); - await page.getByLabel("Website").fill("https://www.samplewebsite.com"); - - // Next page - await page.getByRole("button", { name: "Next" }).click(); - - // Page two // - - // Contributors - await page.getByRole("combobox").nth(0).click(); - await page.getByRole("combobox").nth(0).fill("nobody.near"); - await page.getByLabel("nobody.near").click(); - - // Avatar - const avatarInput = await page.locator("input[type=file]").nth(0); - await avatarInput.setInputFiles( - path.join(__dirname, "./assets/black.png"), - ); - - // Background - const backgroundInput = await page.locator("input[type=file]").nth(1); - await backgroundInput.setInputFiles( - path.join(__dirname, "./assets/black.png"), - ); - - await page.getByLabel("Updates Feed").uncheck(); - await page.getByLabel("Feedback Feed").uncheck(); + }; - await page.getByRole("combobox").nth(1).click(); - await page.getByRole("combobox").nth(1).fill("test"); - await page.getByLabel("test").click(); + // Page one // + + // Project Account Address + await page + .getByPlaceholder("Enter Project Account Address") + .fill("anyproject.near"); + + // Title + await page + .getByPlaceholder("Enter Project Title") + .fill("Sample project"); + + // Description + await page + .frameLocator("iframe") + .locator('textarea[name="textarea"]') + .click(); + await page + .frameLocator("iframe") + .locator('textarea[name="textarea"]') + .fill("This is a sample project"); + + await page.getByPlaceholder("Enter location").fill("anywhere"); // Location + + await page.getByRole("combobox").selectOption("1-10"); + + await page.getByLabel("Twitter").fill("SampleTwitter"); + await page.getByLabel("Github").fill("SampleGithub"); + await page.getByLabel("Telegram").fill("SampleTelegram"); + await page.getByLabel("Website").fill("https://www.samplewebsite.com"); + + // Next page + await page.getByRole("button", { name: "Next" }).click(); + + // Page two // + + // Contributors + await page.getByRole("combobox").nth(0).click(); + await page.getByRole("combobox").nth(0).fill("nobody.near"); + await page.getByLabel("nobody.near").click(); + + // Avatar + const avatarInput = await page.locator("input[type=file]").nth(0); + await avatarInput.setInputFiles( + path.join(__dirname, "./assets/black.png"), + ); + + // Background + const backgroundInput = await page.locator("input[type=file]").nth(1); + await backgroundInput.setInputFiles( + path.join(__dirname, "./assets/black.png"), + ); + + await page.getByLabel("Updates Feed").uncheck(); + await page.getByLabel("Feedback Feed").uncheck(); + + await page.getByRole("combobox").nth(1).click(); + await page.getByRole("combobox").nth(1).fill("test"); + await page.getByLabel("test").click(); + + await page.getByRole("button", { name: "Create" }).click(); + await page.getByRole("dialog").getByLabel("Close").click(); + + // click button that triggers transaction + await page.getByRole("button", { name: "Create" }).nth(0).click(); + const transactionObj = JSON.parse( + await page.locator("div.modal-body code").innerText(), + ); + // do something with transactionObj + expect(transactionObj).toMatchObject(expectedTransactionData); + }); + }); + }); - await page.getByRole("button", { name: "Create" }).click(); - await page.getByRole("dialog").getByLabel("Close").click(); + test.describe("Import project from Potlock", () => { + test.beforeEach(async ({ page }) => { + await page.goto(`/${ROOT_SRC}?page=projects&tab=potlockImport`); + }); + test.use({ + storageState: "playwright-tests/storage-states/wallet-connected.json", + }); - // click button that triggers transaction - await page.getByRole("button", { name: "Create" }).nth(0).click(); - const transactionObj = JSON.parse( - await page.locator("div.modal-body code").innerText(), + test("should have warning text on testnet", async ({ page }) => { + const warningText = page.getByText( + "Network issue: Couldn't fetch any projects, please try again later", ); - // do something with transactionObj - expect(transactionObj).toMatchObject(expectedTransactionData); + expect(warningText).toBeHidden(); }); }); }); diff --git a/playwright-tests/tests/projects.spec.js b/playwright-tests/tests/projects.spec.js index f2d09978..24ccbfad 100644 --- a/playwright-tests/tests/projects.spec.js +++ b/playwright-tests/tests/projects.spec.js @@ -57,6 +57,49 @@ test.describe("?page=projects", () => { expect(page.url()).toContain("?page=project&id="); }); + test("should filter projects by team size and tags", async ({ page }) => { + // wait for data to load + const projectGridCard = await page + .getByTestId("project-grid-card") + .nth(1); + await expect(projectGridCard).toBeVisible({ timeout: 10000 }); + + const filterBtn = await page.getByRole("button", { + name: "Filter", + }); + await expect(filterBtn).toBeVisible(); + await filterBtn.click(); + await page.getByRole("combobox").nth(0).selectOption("1-10"); + await page.getByPlaceholder("Start Typing").fill("test"); + await page.getByLabel("test").click(); + await page.getByRole("button", { name: "Filter", exact: true }).click(); + const filteredProjectCounts = await page + .getByText("test", { exact: true }) + .count(); + expect(filteredProjectCounts).toBeGreaterThan(0); + }); + + test("should search projects by title", async ({ page }) => { + // wait for data to load + const projectGridCard = await page + .getByTestId("project-grid-card") + .nth(1); + await expect(projectGridCard).toBeVisible({ timeout: 10000 }); + + const searchInput = await page.getByPlaceholder( + "Search by project ID or name", + ); + await expect(searchInput).toBeVisible(); + const title = "Testing project on Build DAO"; + await searchInput.fill(title); + // only one projects should be found + const filteredProject = await page.getByTestId("project-grid-card"); + await expect(filteredProject).toBeVisible({ timeout: 10000 }); + await expect(page.getByRole("heading", { name: title })).toBeVisible({ + timeout: 10000, + }); + }); + test.describe("User is not logged in", () => { test.use({ storageState: @@ -148,27 +191,17 @@ test.describe("?page=projects", () => { expect(page.url()).toContain("?page=projects&tab=editor"); }); - test("should be able to edit a project'", async ({ page }) => { + test("should be able to edit a project", async ({ page }) => { // wait for data to be fetched await page.waitForTimeout(5000); const expectedTransactionData = { "meghagoel.testnet": { project: { "testing-project-on-builddao": { - "": '{"title":"New project title","description":"New Project description","profileImage":{"ipfs_cid":"bafkreifk42ibqsg5sfky5tlhkfty6rkup5leqite5koenhesnuwq55kufi"},"backgroundImage":{"ipfs_cid":"bafkreidbfu7uxtr4is7wxileg3mrbajve6cgkfmrqemc6pxsr6nnczz7ly"},"tags":{"test":""},"linktree":{"twitter":"https://test.nearbuilders.org/","github":"https://test.nearbuilders.org/","telegram":"https://test.nearbuilders.org/","website":"https://test.nearbuilders.org/"},"contributors":["megha19.testnet"],"tabs":["overview","activity","tasks"],"projectAccountId":"meghagoel.testnet","teamSize":"1-10","location":"New Location"}', + "": '{"title":"New project title","description":"New Project description","profileImage":{"ipfs_cid":"bafkreifk42ibqsg5sfky5tlhkfty6rkup5leqite5koenhesnuwq55kufi"},"backgroundImage":{"ipfs_cid":"bafkreidbfu7uxtr4is7wxileg3mrbajve6cgkfmrqemc6pxsr6nnczz7ly"},"tags":{"test":""},"linktree":{"twitter":"https://test.nearbuilders.org/","github":"https://test.nearbuilders.org/","telegram":"https://test.nearbuilders.org/","website":"https://test.nearbuilders.org/"},"contributors":["meghagoel.testnet"],"tabs":["overview","activity","tasks","updatesfeed","feedbackfeed"],"projectAccountId":"meghagoel.testnet","teamSize":"1-10","location":"New Location"}', metadata: { name: "New project title", description: "New Project description", - - tags: { - test: "", - }, - linktree: { - twitter: - "https://twitter.com/https://test.nearbuilders.org/", - github: "https://github.com/https://test.nearbuilders.org/", - telegram: "https://t.me/https://test.nearbuilders.org/", - }, }, }, }, @@ -181,7 +214,9 @@ test.describe("?page=projects", () => { const descriptionInput = await page .frameLocator("iframe") .locator('textarea[name="textarea"]'); - await expect(descriptionInput).toHaveText("This is the description"); + await expect(descriptionInput).toHaveText("This is the description", { + timeout: 20000, + }); await descriptionInput.click(); await descriptionInput.fill("New Project description"); const locationInput = page.getByPlaceholder("Enter location"); @@ -222,4 +257,89 @@ test.describe("?page=projects", () => { }); }); }); + + test.describe("Watchlist", () => { + test.beforeEach(async ({ page }) => { + await page.goto(`/${ROOT_SRC}?page=projects&tab=watchList`); + }); + + test.describe("User is not logged in", () => { + test.use({ + storageState: + "playwright-tests/storage-states/wallet-not-connected.json", + }); + + test("should see login screen", async ({ page }) => { + const requireLogin = await page.getByText( + "Please log in in order to see watchlist projects!", + ); + await expect(requireLogin).toBeVisible(); + }); + }); + + test.describe("User is logged in with bookmarked project", () => { + test.use({ + storageState: + "playwright-tests/storage-states/wallet-connected-project-owner.json", + }); + test("should see their bookmarked projects", async ({ page }) => { + const projectTitle = await page.getByText( + "Testing project on Build DAO", + ); + await expect(projectTitle).toBeVisible({ timeout: 10000 }); + }); + }); + + test.describe("User without bookmarked projects is logged in", () => { + test.use({ + storageState: "playwright-tests/storage-states/wallet-connected.json", + }); + test("should see empty page", async ({ page }) => { + const noProjectFound = await page.getByText("No Projects Found"); + await expect(noProjectFound).toBeVisible(); + }); + }); + }); + + test.describe("Projects Involved", () => { + test.beforeEach(async ({ page }) => { + await page.goto(`/${ROOT_SRC}?page=projects&tab=involvedProjects`); + }); + + test.describe("User is not logged in", () => { + test.use({ + storageState: + "playwright-tests/storage-states/wallet-not-connected.json", + }); + test("should see login screen", async ({ page }) => { + const requireLogin = await page.getByText( + "Please log in in order to see involved projects!", + ); + await expect(requireLogin).toBeVisible(); + }); + }); + + test.describe("User involved in projects is logged in", () => { + test.use({ + storageState: + "playwright-tests/storage-states/wallet-connected-project-owner.json", + }); + test("should see their involved project", async ({ page }) => { + const projectTitle = await page.getByText( + "Testing project on Build DAO", + ); + await expect(projectTitle).toBeVisible({ timeout: 10000 }); + }); + }); + + test.describe("User not involved in projects is logged in", () => { + test.use({ + storageState: "playwright-tests/storage-states/wallet-connected.json", + }); + test("should see empty screen", async ({ page }) => { + const noProjectFound = await page.getByText("No Projects Found"); + await expect(noProjectFound).toBeVisible(); + }); + }); + }); });