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

UX improvements for "Don't ask again" #687

Merged
merged 26 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4db05f0
upgrade to latest near-social-vm in tests
petersalomonsen Mar 5, 2024
d97008b
wip: test case
petersalomonsen Mar 5, 2024
2f7e7c6
configure don't ask again
petersalomonsen Mar 5, 2024
19c6960
test scenarios for like and simple comment to post
petersalomonsen Mar 6, 2024
97c29f2
need access keys also for main contract
petersalomonsen Mar 6, 2024
16d7ec1
triggers don't ask again, but only with bosloader flags not enabled
petersalomonsen Mar 7, 2024
7b21856
don't ask again toast is visible
petersalomonsen Mar 7, 2024
249c61c
instead of bos-loader, mock RPC responses from social.near/get
petersalomonsen Mar 7, 2024
5eaf1ac
hide buttons on submit
petersalomonsen Mar 7, 2024
304d82f
pause inbetween if recording test video
petersalomonsen Mar 7, 2024
880031c
scroll the submit button into the view on the video
petersalomonsen Mar 7, 2024
b435dab
cache test utils in separate file
petersalomonsen Mar 7, 2024
064f5ba
modify response for view_access_key_list RPC call to avoid wallet red…
petersalomonsen Mar 7, 2024
56e32ad
Replace RPC response when viewing access key
petersalomonsen Mar 8, 2024
0780911
trigger VM cache invalidation after tx complete
petersalomonsen Mar 9, 2024
9c4839c
wait for comment editor to close after cache invalidation
petersalomonsen Mar 9, 2024
b9c7861
loading indicator until everything is refreshed
petersalomonsen Mar 9, 2024
91f4097
long thread test case where it is really slow, and this fix matters
petersalomonsen Mar 9, 2024
26eb797
adjustment for video recording
petersalomonsen Mar 9, 2024
9251d83
fully set up like test scenario
petersalomonsen Mar 9, 2024
3c58220
not able to handle transaction confirmation dialog closed
petersalomonsen Mar 9, 2024
235490d
admin spec: pressing escape does not work with latest VM. Click close…
petersalomonsen Mar 9, 2024
3798b4a
Merge branch 'main' into fix/dont-ask-again-ux
petersalomonsen Mar 9, 2024
e18cdfc
test with long thread needs a pause in the end
petersalomonsen Mar 9, 2024
f96ccd4
avoid double click and give indication while like transaction and ref…
petersalomonsen Mar 9, 2024
8ee750f
spinner inside disabled buttons, instead of removing them
petersalomonsen Mar 10, 2024
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
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test-results
1,287 changes: 697 additions & 590 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"devDependencies": {
"@playwright/test": "^1.38.1",
"http-server": "^14.1.1",
"near-bos-webcomponent": "^0.0.2",
"near-bos-webcomponent": "^0.0.5",
"prettier": "^2.8.4",
"replace-in-files": "^3.0.0",
"simple-git-hooks": "^2.9.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"localStorage": [
{
"name": "near-wallet-selector:selectedWalletId",
"value": "near-wallet"
"value": "\"my-near-wallet\""
},
{
"name": "near_app_wallet_auth_key",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"localStorage": [
{
"name": "near-wallet-selector:selectedWalletId",
"value": "near-wallet"
"value": "\"my-near-wallet\""
},
{
"name": "near_app_wallet_auth_key",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"localStorage": [
{
"name": "near-wallet-selector:selectedWalletId",
"value": "near-wallet"
"value": "\"my-near-wallet\""
},
{
"name": "near_app_wallet_auth_key",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"localStorage": [
{
"name": "near-wallet-selector:selectedWalletId",
"value": "near-wallet"
"value": "\"my-near-wallet\""
},
{
"name": "near_app_wallet_auth_key",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"cookies": [],
"origins": [
{
"origin": "http://localhost:8080",
"localStorage": [
{
"name": "near-wallet-selector:selectedWalletId",
"value": "\"my-near-wallet\""
},
{
"name": "near_app_wallet_auth_key",
"value": "{\"accountId\":\"petersalomonsen.near\"}"
},
{
"name": "devgovgigs.near_wallet_auth_key",
"value": "{\"accountId\":\"petersalomonsen.near\",\"allKeys\":[\"ed25519:CziSGowWUKiP5N5pqGUgXCJXtqpySAk29YAU6zEs5RAi\"]}"
},
{
"name": "near-api-js:keystore:petersalomonsen.near:mainnet",
"value": "ed25519:4SViyksDtdDdCPkkyzMg4HYADEQ3t5YGEd3EBoSADxdaAzDasZ7qJbxr2wNSFkWipya6C2eVJJucK1vkyoGndiyt"
},
{
"name": "devgovgigs.near:keystore:petersalomonsen.near:mainnet",
"value": "ed25519:4SViyksDtdDdCPkkyzMg4HYADEQ3t5YGEd3EBoSADxdaAzDasZ7qJbxr2wNSFkWipya6C2eVJJucK1vkyoGndiyt"
},
{
"name": "near-social-vm:v01::accountId:",
"value": "\"petersalomonsen.near\""
},
{
"name": "near-wallet-selector:recentlySignedInWallets",
"value": "[]"
}
]
}
],
"sessionStorage": []
}
2 changes: 1 addition & 1 deletion playwright-tests/storage-states/wallet-connected.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"localStorage": [
{
"name": "near-wallet-selector:selectedWalletId",
"value": "near-wallet"
"value": "\"my-near-wallet\""
},
{
"name": "near_app_wallet_auth_key",
Expand Down
7 changes: 7 additions & 0 deletions playwright-tests/testUtils.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { expect } from "@playwright/test";

export const pauseIfVideoRecording = async (page) => {
let isVideoRecorded = (await page.video()) ? true : false;
if (isVideoRecorded) {
await page.waitForTimeout(500);
}
};

export const setInputAndAssert = async (page, selector, value) => {
await page.fill(selector, value);
const actualValue = await page.inputValue(selector);
Expand Down
7 changes: 2 additions & 5 deletions playwright-tests/tests/admin.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,8 @@ test.describe("Wallet is connected", () => {
await page.getByRole("button", { name: "" }).nth(3).click();
await page.getByRole("button", { name: " Submit" }).click();
await page.getByText("Can't set fewer than 4 communities").click();
await page
.getByText(
"NEAR BOS embeddable custom element /admin /communities /activity feed /about ↓ H"
)
.press("Escape");
await page.getByLabel("Close").click();

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

await page.getByTestId("preview-homepage").click();
Expand Down
264 changes: 264 additions & 0 deletions playwright-tests/tests/dontaskagain.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
import { expect, test } from "@playwright/test";
import { pauseIfVideoRecording } from "../testUtils.js";
import {
getDontAskAgainCacheValues,
setDontAskAgainCacheValues,
findKeysInCache,
} from "../util/cache.js";
import { modifySocialNearGetRPCResponsesInsteadOfGettingWidgetsFromBOSLoader } from "../util/bos-loader.js";
import { mockTransactionSubmitRPCResponses } from "../util/transaction.js";

const RECEIVER_ID = "devgovgigs.near";

test.describe("Wallet is connected with devhub access key", () => {
test.use({
storageState:
"playwright-tests/storage-states/wallet-connected-with-devhub-access-key.json",
});

test("should comment to a post", async ({ page }) => {
await modifySocialNearGetRPCResponsesInsteadOfGettingWidgetsFromBOSLoader(
page
);

await page.goto("/devhub.near/widget/app?page=post&id=2731");
await setDontAskAgainCacheValues(
page,
"devhub.near/widget/devhub.entity.post.PostEditor",
"add_post"
);

await pauseIfVideoRecording(page);
const postToReplyButton = await page.getByRole("button", {
name: "↪ Reply",
});
await postToReplyButton.click();

await pauseIfVideoRecording(page);
const commentButton = await page.getByRole("button", {
name: " Comment Ask a question, provide information, or share a resource that is relevant to the thread.",
});

await commentButton.click();
await pauseIfVideoRecording(page);

const commentArea = await page
.frameLocator("iframe")
.locator(".CodeMirror textarea");
await commentArea.focus();
await commentArea.fill("Some comment");

await pauseIfVideoRecording(page);
expect(
await getDontAskAgainCacheValues(
page,
"devhub.near/widget/devhub.entity.post.PostEditor"
)
).toEqual({ add_post: true });

const submitbutton = await page.getByTestId("submit-create-post");
await submitbutton.scrollIntoViewIfNeeded();
await pauseIfVideoRecording(page);

const cachedValues = await findKeysInCache(page, RECEIVER_ID);
console.log("cached values", cachedValues);
await mockTransactionSubmitRPCResponses(page, RECEIVER_ID);

await submitbutton.click();
await expect(submitbutton).toBeDisabled();
await pauseIfVideoRecording(page);

const loadingIndicator = await page
.locator(".submit-post-loading-indicator")
.first();
await expect(loadingIndicator).toBeVisible();
const callContractToast = await page.getByText(
`Calling contract ${RECEIVER_ID} with method add_post`
);
expect(callContractToast.isVisible()).toBeTruthy();
await callContractToast.waitFor({ state: "detached" });
await expect(loadingIndicator).toBeVisible();

await page
.getByText("Editor Preview Create Comment")
.waitFor({ state: "detached" });

await expect(loadingIndicator).not.toBeVisible();

await pauseIfVideoRecording(page);
});

test("should like a post", async ({ page }) => {
await modifySocialNearGetRPCResponsesInsteadOfGettingWidgetsFromBOSLoader(
page
);

await page.goto("/devhub.near/widget/app?page=post&id=2731");

await setDontAskAgainCacheValues(
page,
"devhub.near/widget/devhub.entity.post.Post",
"add_like"
);

const likeButton = await page.locator(".bi-heart-fill");
await likeButton.waitFor({ state: "visible" });
await mockTransactionSubmitRPCResponses(page, RECEIVER_ID);

await pauseIfVideoRecording(page);
await likeButton.click();
const loadingIndicator = await page
.locator(".like-loading-indicator")
.first();

await expect(loadingIndicator).toBeVisible();
const callContractToast = await page.getByText(
`Calling contract ${RECEIVER_ID} with method add_like`
);
expect(callContractToast.isVisible()).toBeTruthy();
await expect(loadingIndicator).toBeVisible();

await callContractToast.waitFor({ state: "detached" });

await expect(loadingIndicator).toBeVisible();

await page
.getByRole("link", {
name: "WebAssembly Music @webassemblymusic.near",
})
.waitFor({ state: "visible" });

await expect(loadingIndicator).not.toBeVisible();

await page.waitForTimeout(500);
});

test("should comment to a long thread with don't ask again feature enabled", async ({
page,
}) => {
test.setTimeout(60000);
await modifySocialNearGetRPCResponsesInsteadOfGettingWidgetsFromBOSLoader(
page
);

await page.goto("/devhub.near/widget/app?page=post&id=2261");

await setDontAskAgainCacheValues(
page,
"devhub.near/widget/devhub.entity.post.PostEditor",
"add_post"
);

const postToReplyButton = await page
.getByRole("button", { name: "↪ Reply" })
.nth(0);
await postToReplyButton.scrollIntoViewIfNeeded();
await pauseIfVideoRecording(page);
await postToReplyButton.click();
await pauseIfVideoRecording(page);

const commentButton = await page.getByRole("button", {
name: " Comment Ask a question, provide information, or share a resource that is relevant to the thread.",
});
await commentButton.scrollIntoViewIfNeeded();
await commentButton.click();

await pauseIfVideoRecording(page);
const commentArea = await page
.frameLocator("iframe")
.locator(".CodeMirror textarea");
await commentArea.scrollIntoViewIfNeeded();
await commentArea.focus();
await commentArea.fill("Some comment");

await pauseIfVideoRecording(page);
await mockTransactionSubmitRPCResponses(page, RECEIVER_ID);
const submitbutton = await page.getByTestId("submit-create-post");
await submitbutton.scrollIntoViewIfNeeded();
await pauseIfVideoRecording(page);
await submitbutton.click();
await expect(submitbutton).toBeDisabled();

await pauseIfVideoRecording(page);
const loadingIndicator = await page
.locator(".submit-post-loading-indicator")
.first();
await expect(loadingIndicator).toBeVisible();
const callContractToast = await page.getByText(
`Calling contract ${RECEIVER_ID} with method add_post`
);
expect(callContractToast.isVisible()).toBeTruthy();
await callContractToast.waitFor({ state: "detached" });
expect(loadingIndicator).toBeVisible();

await page
.getByText("Editor Preview Create Comment")
.waitFor({ state: "detached" });

expect(loadingIndicator).not.toBeVisible();

await page.waitForTimeout(500);
});
});

test.describe("Wallet is connected", () => {
test.use({
storageState: "playwright-tests/storage-states/wallet-connected.json",
});
test("should comment to a post and cancel the transaction, and get the submit button back again", async ({
page,
}) => {
await modifySocialNearGetRPCResponsesInsteadOfGettingWidgetsFromBOSLoader(
page
);

await page.goto("/devhub.near/widget/app?page=post&id=2731");

await pauseIfVideoRecording(page);
const postToReplyButton = await page.getByRole("button", {
name: "↪ Reply",
});
await postToReplyButton.click();

await pauseIfVideoRecording(page);
const commentButton = await page.getByRole("button", {
name: " Comment Ask a question, provide information, or share a resource that is relevant to the thread.",
});

await commentButton.click();
await pauseIfVideoRecording(page);

const commentArea = await page
.frameLocator("iframe")
.locator(".CodeMirror textarea");
await commentArea.focus();
await commentArea.fill("Some comment");

await pauseIfVideoRecording(page);

const submitbutton = await page.getByTestId("submit-create-post");
await submitbutton.scrollIntoViewIfNeeded();
await pauseIfVideoRecording(page);

await submitbutton.click();
await pauseIfVideoRecording(page);
await expect(submitbutton).toBeDisabled();
const loadingIndicator = await page
.locator(".submit-post-loading-indicator")
.first();
expect(loadingIndicator).toBeVisible();

const closeButton = await page.getByText("Close");
expect(closeButton).toBeVisible();
await page.waitForTimeout(1000);

await closeButton.click();

// There is unfortunately no way to achieve this as long as the VM does not have a callback
// that says the transaction confirmation dialog was closed

// expect(loadingIndicator).not.toBeVisible();

await pauseIfVideoRecording(page);
});
});
Loading
Loading