Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds tests for Near.call #25

Merged
merged 10 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions playwright-tests/code/near-call/object-params.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const { tx } = props;

function handleClick() {
Near.call(tx);
}

return <button onClick={handleClick}>click</button>;
13 changes: 13 additions & 0 deletions playwright-tests/code/near-call/positional-params.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const { contractName, methodName, args, gas, deposit, extra } = props;

function handleClick() {
if (extra) {
Near.call(contractName, methodName, args, gas, deposit, extra);
} else if (contractName && !methodName && !args && !gas && !deposit) {
Near.call(contractName);
} else {
Near.call(contractName, methodName, args, gas, deposit);
}
}

return <button onClick={handleClick}>click</button>;
31 changes: 31 additions & 0 deletions playwright-tests/storage-states/wallet-connected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"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\",\"allKeys\":[\"ed25519:CziSGowWUKiP5N5pqGUgXCJXtqpySAk29YAU6zEs5RAi\"]}}"
},
{
"name": "near-social-vm:v01::accountId:",
"value": "anybody.near"
},
{
"name": "near-api-js:keystore:anybody.near:mainnet",
"value": "ed25519:67p9ygtfVNZz5AzMkeN4bqstCck8RWxWDthcTa7JaBvxkrBRTc6A43SsuPy9LdtiR6XtSRD1HiS4KQTWCZw83FKS"
},
{
"name": "near-wallet-selector:contract",
"value": "{\"contractId\":\"social.near\",\"methodNames\":[]}"
}
]
}
],
"sessionStorage": []
}
10 changes: 10 additions & 0 deletions playwright-tests/storage-states/wallet-not-connected.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"cookies": [],
"origins": [
{
"origin": "http://localhost:3000",
"localStorage": []
}
],
"sessionStorage": []
}
27 changes: 27 additions & 0 deletions playwright-tests/testUtils.js
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -40,3 +42,28 @@ export const escapeHtml = (html) => {
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
};

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}`);
}
};
216 changes: 216 additions & 0 deletions playwright-tests/tests/vm/near-call.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
import { describe, expect, test } from "@playwright/test";
import { pauseIfVideoRecording, useCode } from "../../testUtils";

describe("Near.call", () => {
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("should throw 'No wallet selected' error", async ({ page }) => {
const expectedErrorMessage = "No wallet selected";

await useCode(page, "near-call/positional-params.js", {
contractName: "hello.near-examples.near",
methodName: "set_greeting",
});

// Expect error message to be displayed
const [error] = await Promise.all([
page.waitForEvent("pageerror"),
await page.getByRole("button", { name: "click" }).click(),
]);

await pauseIfVideoRecording(page);

// Verify that the expected error message was logged
expect(error).toBeTruthy();
expect(error.message).toContain(expectedErrorMessage);
});
});

describe("User is logged in", () => {
test.use({
storageState: "playwright-tests/storage-states/wallet-connected.json",
});

describe("arguments: (contractName, methodName, args?, gas?, deposit?)", () => {
test("should throw error if appropriate arguments are not provide (over 5 args)", async ({
page,
}) => {
const expectedErrorMessage =
"Method: Near.call. Required argument: 'contractName'. If the first argument is a string: 'methodName'. Optional: 'args', 'gas' (defaults to 300Tg), 'deposit' (defaults to 0)";

await useCode(page, "near-call/positional-params.js", {
contractName: "hello.near-examples.near",
methodName: "set_greeting",
args: { message: "Hello, World!" },
gas: "300000000000000",
deposit: "1000000000000000000000000",
extra: "extra argument",
});

// Expect error message to be displayed
const [error] = await Promise.all([
page.waitForEvent("pageerror"),
await page.getByRole("button", { name: "click" }).click(),
]);

await pauseIfVideoRecording(page);

// Verify that the expected error message was logged
expect(error).toBeTruthy();
expect(error.message).toContain(expectedErrorMessage);
});
test("should open confirmation modal with appropriate details", async ({
page,
}) => {
const expectedTransactionData = { message: "Hello, World!" };

await useCode(page, "near-call/positional-params.js", {
contractName: "hello.near-examples.near",
methodName: "set_greeting",
args: { message: "Hello, World!" },
gas: "300000000000000",
deposit: "1000000000000000000000000",
});

await page.getByRole("button", { name: "click" }).click();

const transactionObj = JSON.parse(
await page.locator("div.modal-body code").innerText()
);

await pauseIfVideoRecording(page);

// do something with transactionObj
expect(transactionObj).toMatchObject(expectedTransactionData);
});
});

describe("arguments: ({ tx })", () => {
test("should throw error if transaction object argument is invalid (single string provided)", async ({
page,
}) => {
const expectedErrorMessage =
"Method: Near.call. Required argument: 'tx/txs'. A single argument call requires an TX object or an array of TX objects.";

await useCode(page, "near-call/positional-params.js", {
contractName: "hello.near-examples.near",
});

// Expect error message to be displayed
const [error] = await Promise.all([
page.waitForEvent("pageerror"),
await page.getByRole("button", { name: "click" }).click(),
]);

await pauseIfVideoRecording(page);

// Verify that the expected error message was logged
expect(error).toBeTruthy();
expect(error.message).toContain(expectedErrorMessage);
});
test("should open confirmation modal with appropriate details", async ({
page,
}) => {
const expectedTransactionData = { message: "Hello, World!" };

await useCode(page, "near-call/object-params.js", {
tx: {
contractName: "hello.near-examples.near",
methodName: "set_greeting",
args: { message: "Hello, World!" },
gas: "300000000000000",
deposit: "1000000000000000000000000",
},
});

await page.getByRole("button", { name: "click" }).click();

const transactionObj = JSON.parse(
await page.locator("div.modal-body code").innerText()
);
const modalBody = await page.locator(".modal-body");
const transactionNumber = await modalBody.locator("h4").textContent();
const values = await modalBody
.locator(".font-monospace")
.allInnerTexts();
const [contractId, methodName, deposit, gas] = values;

await pauseIfVideoRecording(page);

// do something with transactionObj
expect(transactionObj).toMatchObject(expectedTransactionData);
expect(transactionNumber).toBe("Transaction #1");
expect(contractId).toBe("hello.near-examples.near");
expect(methodName).toBe("set_greeting");
expect(deposit).toBe("1 NEAR");
expect(gas).toBe("300 TGas");
});
});

describe("arguments: [{ tx }, ...]", () => {
test("should open confirmation modal with appropriate details, multiple transactions", async ({
page,
}) => {
await useCode(page, "near-call/object-params.js", {
tx: [
{
contractName: "hello.near-examples.near",
methodName: "set_greeting",
args: { message: "Hello, World!" },
gas: "300000000000000",
deposit: "1000000000000000000000000",
},
{
contractName: "goodbye.near-examples.near",
methodName: "set_goobye",
args: { message: "Goodbye, World!" },
gas: "600000000000000",
deposit: "2000000000000000000000000",
},
],
});

await page.getByRole("button", { name: "click" }).click();

const blocks = await page
.locator("div.modal-body code")
.allInnerTexts();
const modalBody = await page.locator(".modal-body");
const transactionNumbers = await modalBody.locator("h4").allInnerTexts();
const values = await modalBody
.locator(".font-monospace")
.allInnerTexts();

const [firstBlock, secondBlock] = blocks;

await pauseIfVideoRecording(page);

expect(transactionNumbers).toEqual(["Transaction #1", "Transaction #2"]);
expect(values).toEqual([
"hello.near-examples.near",
"set_greeting",
"1 NEAR",
"300 TGas",
"goodbye.near-examples.near",
"set_goobye",
"2 NEAR",
"600 TGas",
]);

expect(JSON.parse(firstBlock)).toMatchObject({
message: "Hello, World!",
});
expect(JSON.parse(secondBlock)).toMatchObject({
message: "Goodbye, World!",
});
});
});
});
});
Loading