Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

feat: added notification snap to methods-snap #137 #166

Merged
merged 8 commits into from
Nov 10, 2022
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
3 changes: 2 additions & 1 deletion src/metamask/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { DappeteerPage } from "../page";

import { acceptDialog } from "../snap/acceptDialog";
import { rejectDialog } from "../snap/rejectDialog";
import { installSnap, invokeSnap } from "../snap";
import { getAllNotifications, installSnap, invokeSnap } from "../snap";
import { addNetwork } from "./addNetwork";
import { addToken } from "./addToken";
import { approve } from "./approve";
Expand Down Expand Up @@ -55,6 +55,7 @@ export const getMetaMask = (page: DappeteerPage): Promise<Dappeteer> => {
deleteNetwork: deleteNetwork(page),
},
snaps: {
getAllNotifications: getAllNotifications(page),
acceptDialog: acceptDialog(page),
rejectDialog: rejectDialog(page),
invokeSnap,
Expand Down
10 changes: 7 additions & 3 deletions src/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ import { DappeteerElementHandle } from "./element";

export interface DappeteerPage<P = unknown> {
$(selector: string): Promise<DappeteerElementHandle | null>;
$eval(
$eval<T>(
selector: string,
evalFn: (e: HTMLElement) => Promise<void> | void
): Promise<void>;
evalFn: (e: HTMLElement) => Promise<T> | T
): Promise<T>;
$$eval<T>(
selector: string,
evalFn: (e: HTMLElement[]) => Promise<T[]> | T[]
): Promise<T[]>;
$$(selector: string): Promise<DappeteerElementHandle[]>;
getSource(): P;
url(): string;
Expand Down
18 changes: 11 additions & 7 deletions src/playwright/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,18 @@ export class DPlaywrightPage implements DappeteerPage<Page> {
);
}

$eval(
$eval<T>(
selector: string,
evalFn: (e: HTMLElement) => void | Promise<void>
): Promise<void> {
return this.page.$eval(
selector,
async (e) => await evalFn(e as HTMLElement)
);
evalFn: (e: HTMLElement) => T | Promise<T>
): Promise<T> {
return this.page.$eval(selector, evalFn);
}

$$eval<T>(
selector: string,
evalFn: (e: HTMLElement[]) => T[] | Promise<T[]>
): Promise<T[]> {
return this.page.$$eval(selector, evalFn);
}

async $$(selector: string): Promise<DappeteerElementHandle<ElementHandle>[]> {
Expand Down
18 changes: 11 additions & 7 deletions src/puppeteer/page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,18 @@ export class DPupeteerPage implements DappeteerPage<Page> {
return new DPuppeteerElementHandle(await this.page.$(selector));
}

$eval(
$eval<T>(
selector: string,
evalFn: (e: HTMLElement) => void | Promise<void>
): Promise<void> {
return this.page.$eval(
selector,
async (e) => await evalFn(e as HTMLElement)
);
evalFn: (e: HTMLElement) => T | Promise<T>
): Promise<T> {
return this.page.$eval<T>(selector, evalFn) as Promise<T>;
}

$$eval<T>(
selector: string,
evalFn: (e: HTMLElement[]) => T[] | Promise<T[]>
): Promise<T[]> {
return this.page.$$eval(selector, evalFn);
}

async $$(selector: string): Promise<DappeteerElementHandle<ElementHandle>[]> {
Expand Down
22 changes: 22 additions & 0 deletions src/snap/getAllNotifications.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { clickOnElement, openProfileDropdown } from "../helpers";
import { DappeteerPage } from "../page";
import { NotificationList } from "./types";

export const getAllNotifications =
(page: DappeteerPage) => async (): Promise<NotificationList> => {
await page.bringToFront();
await openProfileDropdown(page);
await clickOnElement(page, "Notifications");
await page.waitForSelector(".notifications__item__details__message");
const notificationList: NotificationList = await page.$$eval(
".notifications__item__details__message",
(elements) =>
elements.map((element) => ({ message: element.textContent }))
);
const backButton = await page.waitForSelector(
".notifications__header__title-container__back-button"
);

await backButton.click();
return notificationList;
};
1 change: 1 addition & 0 deletions src/snap/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { flaskOnly } from "./utils";
export { installSnap } from "./install";
export { invokeSnap } from "./invokeSnap";
export { getAllNotifications } from "./getAllNotifications";
2 changes: 2 additions & 0 deletions src/snap/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ export interface InstallSnapResult {
};
};
}

export type NotificationList = { message: string }[];
3 changes: 2 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { MetaMaskInpageProvider } from "@metamask/providers";
import { DappeteerPage, Serializable } from "./page";
import { Path } from "./setup/utils/metaMaskDownloader";
import { InstallStep } from "./snap/install";
import { InstallSnapResult } from "./snap/types";
import { InstallSnapResult, NotificationList } from "./snap/types";
import { RECOMMENDED_METAMASK_VERSION } from "./index";

export type DappeteerLaunchOptions = {
Expand Down Expand Up @@ -73,6 +73,7 @@ export type Dappeteer = {
};
page: DappeteerPage;
snaps: {
getAllNotifications: () => Promise<NotificationList>;
invokeSnap: <R = unknown, P extends Serializable = Serializable>(
page: DappeteerPage,
snapId: string,
Expand Down
2 changes: 1 addition & 1 deletion test/flask/methods-snap/snap.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "An example Snap written in TypeScript.",
"proposedName": "Methods Snap\n",
"source": {
"shasum": "BCwqoDyQltaL0dh0IrzN1A66D1jPMLAseJOHmqI1faU=",
"shasum": "xxu7kMfZ4zKgviSZ5K4gZKSDDGEYi2VqOK5bKAqoybo=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
18 changes: 17 additions & 1 deletion test/flask/methods-snap/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { OnRpcRequestHandler } from "@metamask/snap-types";

export const onRpcRequest: OnRpcRequestHandler = ({ origin, request }) => {
export const onRpcRequest: OnRpcRequestHandler = async ({
origin,
request,
}) => {
switch (request.method) {
case "confirm":
return wallet.request({
Expand All @@ -15,6 +18,19 @@ export const onRpcRequest: OnRpcRequestHandler = ({ origin, request }) => {
},
],
});
case "notify_inApp":
{
await wallet.request({
method: "snap_notify",
params: [
{
type: "inApp",
message: `Hello, in App notification`,
},
],
});
}
break;
default:
throw new Error("Method not found.");
}
Expand Down
12 changes: 12 additions & 0 deletions test/flask/snaps.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,17 @@ describe("snaps", function () {

expect(await invokeAction).to.equal(false);
});

it("should invoke IN APP NOTIFICATIONS and check for a text", async function (this: TestContext) {
await metamask.snaps.invokeSnap(
testPage,
getSnapIdByName(this, Snaps.METHODS_SNAP),
"notify_inApp"
);

const notifications = await metamask.snaps.getAllNotifications();

expect(notifications[0].message).to.equal("Hello, in App notification");
});
});
});
1 change: 1 addition & 0 deletions test/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { deployContract, startLocalEthereum, startTestServer } from "./deploy";

export const mochaHooks = {
async beforeAll(this: Mocha.Context): Promise<void> {
this.timeout(100000);
const ethereum = await startLocalEthereum({
wallet: {
mnemonic: LOCAL_PREFUNDED_MNEMONIC,
Expand Down
1 change: 1 addition & 0 deletions test/global_flask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {

export const mochaHooks = {
async beforeAll(this: Mocha.Context): Promise<void> {
this.timeout(100000);
const ethereum = await startLocalEthereum({
wallet: {
mnemonic: LOCAL_PREFUNDED_MNEMONIC,
Expand Down