From 7aa096d5742f958651baefc6f732516fc8046e37 Mon Sep 17 00:00:00 2001 From: Elliot Braem <16282460+elliotBraem@users.noreply.github.com> Date: Mon, 1 Jul 2024 12:53:08 -0400 Subject: [PATCH 1/6] init --- playwright-tests/code/auth/wallet.js | 16 +++++++ .../storage-states/wallet-connected.json | 23 +++++++++ .../storage-states/wallet-not-connected.json | 10 ++++ playwright-tests/testUtils.js | 27 +++++++++++ playwright-tests/tests/auth.spec.js | 48 +++++++++++++++++++ public/webcomponentapp.js | 6 ++- src/App.js | 6 ++- src/auth/Wallet.js | 14 ++++++ 8 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 playwright-tests/code/auth/wallet.js create mode 100644 playwright-tests/storage-states/wallet-connected.json create mode 100644 playwright-tests/storage-states/wallet-not-connected.json create mode 100644 playwright-tests/tests/auth.spec.js create mode 100644 src/auth/Wallet.js diff --git a/playwright-tests/code/auth/wallet.js b/playwright-tests/code/auth/wallet.js new file mode 100644 index 0000000..e796faf --- /dev/null +++ b/playwright-tests/code/auth/wallet.js @@ -0,0 +1,16 @@ +return ( + <> +

{context.accountId}

+ { + return context.accountId ? ( + + ) : ( + + ); + }} + /> + +); diff --git a/playwright-tests/storage-states/wallet-connected.json b/playwright-tests/storage-states/wallet-connected.json new file mode 100644 index 0000000..acf19af --- /dev/null +++ b/playwright-tests/storage-states/wallet-connected.json @@ -0,0 +1,23 @@ +{ + "cookies": [], + "origins": [ + { + "origin": "http://localhost:3000", + "localStorage": [ + { + "name": "near-wallet-selector:selectedWalletId", + "value": "\"my-near-wallet\"" + }, + { + "name": "near_app_wallet_auth_key", + "value": "{\"accountId\":\"anybody.near\"}" + }, + { + "name": "near-social-vm:v01::accountId:", + "value": "anybody.near" + } + ] + } + ], + "sessionStorage": [] +} \ No newline at end of file diff --git a/playwright-tests/storage-states/wallet-not-connected.json b/playwright-tests/storage-states/wallet-not-connected.json new file mode 100644 index 0000000..0b4ed34 --- /dev/null +++ b/playwright-tests/storage-states/wallet-not-connected.json @@ -0,0 +1,10 @@ +{ + "cookies": [], + "origins": [ + { + "origin": "http://localhost:3000", + "localStorage": [] + } + ], + "sessionStorage": [] +} \ No newline at end of file diff --git a/playwright-tests/testUtils.js b/playwright-tests/testUtils.js index 7c89430..09280dd 100644 --- a/playwright-tests/testUtils.js +++ b/playwright-tests/testUtils.js @@ -1,4 +1,6 @@ import { expect } from "@playwright/test"; +import path from "path"; +import fs from "fs"; export const pauseIfVideoRecording = async (page) => { let isVideoRecorded = (await page.video()) ? true : false; @@ -40,3 +42,28 @@ export const escapeHtml = (html) => { .replace(/"/g, """) .replace(/'/g, "'"); }; + +export const useCode = async (page, filePath, props) => { + const fullPath = path.join(__dirname, "code", filePath); + try { + const code = fs.readFileSync(fullPath, "utf8"); + const initialProps = props ? JSON.stringify(props) : ""; + + // Set code and initialProps attribute + await page.evaluate( + ({ code, initialProps }) => { + const viewer = document.querySelector("near-social-viewer"); + viewer.setAttribute("code", code); + viewer.setAttribute("initialprops", initialProps); + }, + { code, initialProps } + ); + + // Verify the viewer is visible + await waitForSelectorToBeVisible(page, "near-social-viewer"); + + await pauseIfVideoRecording(page); + } catch (err) { + throw new Error(`Error loading file: ${err.message}`); + } +}; \ No newline at end of file diff --git a/playwright-tests/tests/auth.spec.js b/playwright-tests/tests/auth.spec.js new file mode 100644 index 0000000..4d44863 --- /dev/null +++ b/playwright-tests/tests/auth.spec.js @@ -0,0 +1,48 @@ +import { expect, test, describe } from "@playwright/test"; + +describe("auth", () => { + test.beforeEach(async ({ page }) => { + await page.goto("/"); + }); + + describe("User is not logged in", () => { + test.use({ + storageState: "playwright-tests/storage-states/wallet-not-connected.json", + }); + + test("'context.accountId' should be null and show login button", async ({ page }) => { + await useCode(page, "auth/wallet.js"); + + const accountId = await page.textContent('[data-testid="accountId"]'); + expect(accountId).toBe("null"); + }); + + test("should show wallet modal after clicking login button", async ({ page }) => { + await useCode(page, "auth/wallet.js"); + + await page.click("#open-walletselector-button"); + + const modal = await page.waitForSelector("near-wallet-selector"); + expect(modal).not.toBeNull(); + }); + }); + + describe("User is logged in", () => { + test.use({ + storageState: "playwright-tests/storage-states/wallet-connected.json", + }); + + test("should have 'context.accountId' be non null and show logout button", async ({ page }) => { + await useCode(page, "auth/wallet.js"); + + const accountId = await page.textContent('[data-testid="accountId"]'); + expect(accountId).toBe("anybody.near"); + }); + + test("should prompt to disconnect wallet after clicking logout button", async ({ page }) => { + await useCode(page, "auth/wallet.js"); + + await page.getByRole("button", { name: "Log out" }).click(); + }); + }); +}); \ No newline at end of file diff --git a/public/webcomponentapp.js b/public/webcomponentapp.js index b7b4cb3..823373c 100644 --- a/public/webcomponentapp.js +++ b/public/webcomponentapp.js @@ -14,7 +14,11 @@ const modal = setupModal(selector, { contractId: "social.near", }); -document.getElementById('open-walletselector-button').addEventListener('click', () => modal.show()); +document.body.addEventListener('click', (event) => { + if (event.target && event.target.id === 'open-walletselector-button') { + modal.show(); + } +}); const viewer = document.querySelector('near-social-viewer'); viewer.selector = selector; \ No newline at end of file diff --git a/src/App.js b/src/App.js index ecacc2b..4a96ce3 100644 --- a/src/App.js +++ b/src/App.js @@ -13,8 +13,9 @@ import { RouterProvider, useLocation, } from "react-router-dom"; +import Wallet from "./auth/Wallet"; -const SESSION_STORAGE_REDIRECT_MAP_KEY = 'nearSocialVMredirectMap'; +const SESSION_STORAGE_REDIRECT_MAP_KEY = "nearSocialVMredirectMap"; function Viewer({ widgetSrc, code, initialProps }) { const location = useLocation(); @@ -85,6 +86,9 @@ function App(props) { } return ; }, + Wallet: (props) => { + return ; + }, }, features: { enableComponentSrcDataKey: true, diff --git a/src/auth/Wallet.js b/src/auth/Wallet.js new file mode 100644 index 0000000..f7f95c4 --- /dev/null +++ b/src/auth/Wallet.js @@ -0,0 +1,14 @@ +import { useNear } from "near-social-vm"; +import { useCallback } from "react"; + +function Wallet({ provides }) { + const near = useNear(); + const logOut = useCallback(async () => { + const wallet = await (await near.selector).wallet(); + wallet.signOut(); + }, [near]); + + return provides({ logOut }); +} + +export default Wallet; From 49be94833a7bad14f3df82eaea73f964d155c62b Mon Sep 17 00:00:00 2001 From: Elliot Braem <16282460+elliotBraem@users.noreply.github.com> Date: Mon, 1 Jul 2024 15:23:57 -0400 Subject: [PATCH 2/6] tests --- playwright-tests/code/auth/wallet.js | 4 +- .../storage-states/wallet-connected.json | 12 +++- playwright-tests/tests/auth.spec.js | 56 +++++++++++++++---- src/auth/Wallet.js | 4 +- 4 files changed, 58 insertions(+), 18 deletions(-) diff --git a/playwright-tests/code/auth/wallet.js b/playwright-tests/code/auth/wallet.js index e796faf..0d88b9d 100644 --- a/playwright-tests/code/auth/wallet.js +++ b/playwright-tests/code/auth/wallet.js @@ -2,9 +2,9 @@ return ( <>

{context.accountId}

{ + provides={({ signOut }) => { return context.accountId ? ( - + ) : ( ) : ( - ); diff --git a/playwright-tests/storage-states/wallet-connected.json b/playwright-tests/storage-states/wallet-connected.json index 685dd20..e3593d7 100644 --- a/playwright-tests/storage-states/wallet-connected.json +++ b/playwright-tests/storage-states/wallet-connected.json @@ -4,17 +4,17 @@ { "origin": "http://localhost:3000", "localStorage": [ + { + "name": "near-wallet-selector:recentlySignedInWallets", + "value": "[\"my-near-wallet\"]" + }, { "name": "near-wallet-selector:selectedWalletId", "value": "\"my-near-wallet\"" }, { "name": "near_app_wallet_auth_key", - "value": "{\"accountId\":\"anybody.near\",\"allKeys\":[\"ed25519:CziSGowWUKiP5N5pqGUgXCJXtqpySAk29YAU6zEs5RAi\"]}}" - }, - { - "name": "near-social-vm:v01::accountId:", - "value": "anybody.near" + "value": "{\"accountId\":\"anybody.near\",\"allKeys\":[\"ed25519:CziSGowWUKiP5N5pqGUgXCJXtqpySAk29YAU6zEs5RAi\"]}" }, { "name": "near-api-js:keystore:anybody.near:mainnet", @@ -23,6 +23,10 @@ { "name": "near-wallet-selector:contract", "value": "{\"contractId\":\"social.near\",\"methodNames\":[]}" + }, + { + "name": "near-social-vm:v01::accountId:", + "value": "anybody.near" } ] } diff --git a/playwright-tests/testUtils.js b/playwright-tests/testUtils.js index dd04514..e02bc05 100644 --- a/playwright-tests/testUtils.js +++ b/playwright-tests/testUtils.js @@ -47,14 +47,14 @@ export const useCode = async (page, filePath, props) => { const fullPath = path.join(__dirname, "code", filePath); try { const code = fs.readFileSync(fullPath, "utf8"); - const initialProps = props ? JSON.stringify(props) : ""; + const initialProps = props ? JSON.stringify(props) : null; // Set code and initialProps attribute await page.evaluate( ({ code, initialProps }) => { const viewer = document.querySelector("near-social-viewer"); viewer.setAttribute("code", code); - viewer.setAttribute("initialprops", initialProps); + initialProps && viewer.setAttribute("initialprops", initialProps); }, { code, initialProps } ); diff --git a/playwright-tests/tests/auth.spec.js b/playwright-tests/tests/auth.spec.js index aa5e60a..6603e11 100644 --- a/playwright-tests/tests/auth.spec.js +++ b/playwright-tests/tests/auth.spec.js @@ -42,7 +42,7 @@ describe("auth", () => { }) => { await useCode(page, "auth/wallet.js"); - const accountId = await page.getByTestId("accountId"); + const accountId = page.getByTestId("accountId"); expect(accountId).toHaveText("anybody.near"); }); @@ -52,16 +52,13 @@ describe("auth", () => { await useCode(page, "auth/wallet.js"); // Verify auth keys exist - const initialCheck = await page.evaluate(() => ({ + const authKey = await page.evaluate(() => ({ near_app_wallet_auth_key: localStorage.getItem( "near_app_wallet_auth_key" ), })); - expect(initialCheck).toEqual({ - near_app_wallet_auth_key: - '{"accountId":"anybody.near","allKeys":["ed25519:CziSGowWUKiP5N5pqGUgXCJXtqpySAk29YAU6zEs5RAi"]}}', - }); + expect(authKey).not.toBeNull(); await page.getByRole("button", { name: "Log out" }).click(); diff --git a/src/auth/Wallet.js b/src/auth/Wallet.js index cf6a51f..179c63b 100644 --- a/src/auth/Wallet.js +++ b/src/auth/Wallet.js @@ -1,14 +1,34 @@ import { useNear } from "near-social-vm"; import { useCallback } from "react"; +import { setupModal } from "@near-wallet-selector/modal-ui-js"; -function Wallet({ provides }) { +function Wallet({ provides, config }) { const near = useNear(); + const signOut = useCallback(async () => { const wallet = await (await near.selector).wallet(); wallet.signOut(); }, [near]); - return provides({ signOut }); + const signIn = useCallback(async () => { + const modal = setupModal( + await near.selector, + config + ); + modal.show(); + }, [near]); + + return provides({ signIn, signOut }); } +Wallet.defaultProps = { + provides: { + signIn: () => console.log("signIn"), + signOut: () => console.log("signOut"), + }, + config: { + contractId: "social.near", + }, +}; + export default Wallet; diff --git a/yarn.lock b/yarn.lock index 8348ea7..7e9330b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3095,6 +3095,25 @@ bn.js "5.2.1" borsh "^0.7.0" +"@near-wallet-selector/core@8.9.10": + version "8.9.10" + resolved "https://registry.npmjs.org/@near-wallet-selector/core/-/core-8.9.10.tgz#0e19b22bbe69208c9e82b149682be37f6f9b76c5" + integrity sha512-do+DDahRHPzr5VKiFS7NWKyNbspXu64/w7CuSBi8IUDsDsclmV7Os6Hp5HcVAq+X3Whi//NxKGX6mPMb+SRPqw== + dependencies: + borsh "0.7.0" + events "3.3.0" + js-sha256 "0.9.0" + rxjs "7.8.1" + +"@near-wallet-selector/modal-ui-js@^8.9.10": + version "8.9.10" + resolved "https://registry.npmjs.org/@near-wallet-selector/modal-ui-js/-/modal-ui-js-8.9.10.tgz#9caa6e06e8c9a3b41227d8a018f022e28c7b40f2" + integrity sha512-NrtwRZwMotQ/XeULRe3tCfSyMwtVlnwVqUaHi0vJ1CKijSc5xR9fmVv1Bl9+xjP1bykhniWchb4O1wE1lTm3MQ== + dependencies: + "@near-wallet-selector/core" "8.9.10" + copy-to-clipboard "3.3.3" + qrcode "1.5.3" + "@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3": version "2.1.8-no-fsevents.3" resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz#323d72dd25103d0c4fbdce89dadf574a787b1f9b" @@ -6278,7 +6297,7 @@ bootstrap@^5.3.1: resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.1.tgz#8ca07040ad15d7f75891d1504cf14c5dedfb1cfe" integrity sha512-jzwza3Yagduci2x0rr9MeFSORjcHpt0lRZukZPZQJT1Dth5qzV7XcgGqYzi39KGAVYR8QEDVoO0ubFKOxzMG+g== -borsh@^0.7.0: +borsh@0.7.0, borsh@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/borsh/-/borsh-0.7.0.tgz#6e9560d719d86d90dc589bca60ffc8a6c51fec2a" integrity sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA== @@ -6989,6 +7008,13 @@ cookies@~0.9.0: depd "~2.0.0" keygrip "~1.1.0" +copy-to-clipboard@3.3.3: + version "3.3.3" + resolved "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz#55ac43a1db8ae639a4bd99511c148cdd1b83a1b0" + integrity sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA== + dependencies: + toggle-selection "^1.0.6" + copy-webpack-plugin@^9.0.1: version "9.1.0" resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-9.1.0.tgz#2d2c460c4c4695ec0a58afb2801a1205256c4e6b" @@ -9703,7 +9729,7 @@ joi@17.9.1: "@sideway/formula" "^3.0.1" "@sideway/pinpoint" "^2.0.0" -js-sha256@^0.9.0: +js-sha256@0.9.0, js-sha256@^0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/js-sha256/-/js-sha256-0.9.0.tgz#0b89ac166583e91ef9123644bd3c5334ce9d0966" integrity sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA== @@ -12823,6 +12849,13 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +rxjs@7.8.1, rxjs@^7.5.2, rxjs@^7.5.5: + version "7.8.1" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" + integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + dependencies: + tslib "^2.1.0" + rxjs@^6.6.3: version "6.6.7" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" @@ -12830,13 +12863,6 @@ rxjs@^6.6.3: dependencies: tslib "^1.9.0" -rxjs@^7.5.2, rxjs@^7.5.5: - version "7.8.1" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" - integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== - dependencies: - tslib "^2.1.0" - sade@^1.7.3, sade@^1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" @@ -13687,6 +13713,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +toggle-selection@^1.0.6: + version "1.0.6" + resolved "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" + integrity sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ== + toidentifier@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" From c260fe10e79ddbf4bd1674e175574ba76f4093da Mon Sep 17 00:00:00 2001 From: Elliot Braem <16282460+elliotBraem@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:50:24 -0400 Subject: [PATCH 4/6] formatting --- src/auth/Wallet.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/auth/Wallet.js b/src/auth/Wallet.js index 179c63b..ac473fe 100644 --- a/src/auth/Wallet.js +++ b/src/auth/Wallet.js @@ -1,6 +1,6 @@ +import { setupModal } from "@near-wallet-selector/modal-ui-js"; import { useNear } from "near-social-vm"; import { useCallback } from "react"; -import { setupModal } from "@near-wallet-selector/modal-ui-js"; function Wallet({ provides, config }) { const near = useNear(); @@ -11,10 +11,7 @@ function Wallet({ provides, config }) { }, [near]); const signIn = useCallback(async () => { - const modal = setupModal( - await near.selector, - config - ); + const modal = setupModal(await near.selector, config); modal.show(); }, [near]); From 0ee39479bf6f35c2a001acc7f8feb517b9c9e282 Mon Sep 17 00:00:00 2001 From: Elliot Braem <16282460+elliotBraem@users.noreply.github.com> Date: Tue, 9 Jul 2024 18:13:44 -0400 Subject: [PATCH 5/6] formatting --- playwright-tests/code/auth/wallet.js | 4 +--- playwright-tests/tests/web3.spec.js | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/playwright-tests/code/auth/wallet.js b/playwright-tests/code/auth/wallet.js index f75f942..a79821e 100644 --- a/playwright-tests/code/auth/wallet.js +++ b/playwright-tests/code/auth/wallet.js @@ -6,9 +6,7 @@ return ( return context.accountId ? ( ) : ( - + ); }} /> diff --git a/playwright-tests/tests/web3.spec.js b/playwright-tests/tests/web3.spec.js index 632920a..822d81f 100644 --- a/playwright-tests/tests/web3.spec.js +++ b/playwright-tests/tests/web3.spec.js @@ -27,7 +27,5 @@ test("should be possible to interact with web3 widgets", async ({ page }) => { await Web3ConnectButton.click(); - await expect( - page.getByRole("button", { name: "Connecting" }) - ).toBeVisible(); + await expect(page.getByRole("button", { name: "Connecting" })).toBeVisible(); }); From cad8eac573d68df6f32dc7603d6c225e07892c95 Mon Sep 17 00:00:00 2001 From: Elliot Braem <16282460+elliotBraem@users.noreply.github.com> Date: Tue, 9 Jul 2024 18:18:57 -0400 Subject: [PATCH 6/6] revert open-walletselector-button --- public/webcomponentapp.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/public/webcomponentapp.js b/public/webcomponentapp.js index 35756dc..1723360 100644 --- a/public/webcomponentapp.js +++ b/public/webcomponentapp.js @@ -37,11 +37,9 @@ const modal = setupModal(selector, { contractId: "social.near", }); -document.body.addEventListener('click', (event) => { - if (event.target && event.target.id === 'open-walletselector-button') { - modal.show(); - } -}); +document + .getElementById("open-walletselector-button") + .addEventListener("click", () => modal.show()); const viewer = document.querySelector("near-social-viewer"); viewer.selector = selector;