Skip to content

Commit

Permalink
move over keplr set up
Browse files Browse the repository at this point in the history
  • Loading branch information
Seroxdesign committed Jun 12, 2024
1 parent c5087d0 commit 5829861
Show file tree
Hide file tree
Showing 8 changed files with 321 additions and 0 deletions.
143 changes: 143 additions & 0 deletions wallets/keplr/src/KeplrWallet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import type { Page } from '@playwright/test'
export type Keplr = 'keplr'

export class KeplrWallet {
seedPhrase = ''
wallet: Keplr = 'keplr'

constructor(readonly page: Page) {

Check warning

Code scanning / CodeQL

Useless assignment to property Warning

This write to property 'page' is useless, since
another property write
always overrides it.
this.page = page
}

/**
* Imports wallet from secret phrase and password.
*
* @param secretWords. The secret words to import.
* @param password. The password to set.
*
* @returns true if the wallet was imported successfully.
*/
async importWallet(secretWords, password) {
await playwright.waitAndClickByText(
onboardingElements.createWalletButton,
await playwright.keplrWindow(),
);
await playwright.waitAndClickByText(
onboardingElements.importRecoveryPhraseButton,
await playwright.keplrWindow(),
);
await playwright.waitAndClickByText(
onboardingElements.useRecoveryPhraseButton,
await playwright.keplrWindow(),
);
await playwright.waitAndClickByText(
onboardingElements.phraseCount24,
await playwright.keplrWindow(),
);

for (const [index, word] of secretWords.split(' ').entries()) {
await playwright.waitAndTypeByLocator(
onboardingElements.textAreaSelector,
word,
index,
);
}

await playwright.waitAndClick(
onboardingElements.submitPhraseButton,
await playwright.keplrWindow(),
);

await playwright.waitAndType(
onboardingElements.walletInput,
onboardingElements.walletName,
);
await playwright.waitAndType(onboardingElements.passwordInput, password);
await playwright.waitAndType(
onboardingElements.confirmPasswordInput,
password,
);

await playwright.waitAndClick(
onboardingElements.submitWalletDataButton,
await playwright.keplrWindow(),
{ number: 1 },
);

await playwright.waitForByText(
onboardingElements.phraseSelectChain,
await playwright.keplrWindow(),
);

await playwright.waitAndClick(
onboardingElements.submitChainButton,
await playwright.keplrWindow(),
);

await playwright.waitForByText(
onboardingElements.phraseAccountCreated,
await playwright.keplrWindow(),
);

await playwright.waitAndClick(
onboardingElements.finishButton,
await playwright.keplrWindow(),
{ dontWait: true },
);

return true;
}

/**
* Adds a new account.
*
* @returns true if the account was added successfully.
*/
async acceptAccess() {
const notificationPage = await playwright.switchToKeplrNotification();
await playwright.waitAndClick(
notificationPageElements.approveButton,
notificationPage,
{ waitForEvent: 'close' },
);
return true;
}

/**
* Confirms a transaction.
*
* @returns true if the transaction was confirmed successfully.
*/
async confirmTransaction() {
const notificationPage = await playwright.switchToKeplrNotification();
await playwright.waitAndClick(
notificationPageElements.approveButton,
notificationPage,
{ waitForEvent: 'close' },
);
return true;
}

/**
* Does initial setup for the wallet.
*
* @param playwrightInstance. The playwright instance to use.
* @param secretWordsOrPrivateKey. The secret words or private key to import.
* @param password. The password to set.
*/
async setupWallet(
playwrightInstance,
{ secretWordsOrPrivateKey, password },
) {
if (playwrightInstance) {
await playwright.init(playwrightInstance);
} else {
await playwright.init();
}

await playwright.assignWindows();
await playwright.assignActiveTabName('keplr');
await module.exports.getExtensionDetails();
await module.exports.importWallet(secretWordsOrPrivateKey, password);
}
}
3 changes: 3 additions & 0 deletions wallets/keplr/src/cypress/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const NO_CONTEXT = 'No browser context found. Connect Playwright first - connectPlaywright()'
export const NO_PAGE = 'No page found. Use getPage()'
export const MISSING_INIT = 'Keplr not initialized. Use initKeplrWallet()'
1 change: 1 addition & 0 deletions wallets/keplr/src/cypress/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as installSynpress } from './installSynpress'
77 changes: 77 additions & 0 deletions wallets/keplr/src/cypress/initKeplrWallet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { readFileSync } from 'fs'
import { type BrowserContext, type Page, chromium } from '@playwright/test'

import { KeplrWallet } from '../KeplrWallet'
import { SEED_PHRASE, mockEthereum, web3MockPath } from '../utils'
import { MISSING_INIT, NO_CONTEXT, NO_PAGE } from './errors'

let context: BrowserContext | undefined
let cypressPage: Page | undefined
let keplrWallet: KeplrWallet | undefined

let keplrLoaded = false

const getCypressPage = async () => {
if (!context) {
console.error(NO_CONTEXT)
return
}

cypressPage = context.pages()[0]

return cypressPage
}

export async function connectPlaywrightToChrome(port: number) {
const debuggerDetails = await fetch(`http://127.0.0.1:${port}/json/version`)

const debuggerDetailsConfig = (await debuggerDetails.json()) as {
webSocketDebuggerUrl: string
}

const browser = await chromium.connectOverCDP(debuggerDetailsConfig.webSocketDebuggerUrl)

context = browser.contexts()[0]

return browser.isConnected()
}

export async function initKeplrWallet(port: number) {
await connectPlaywrightToChrome(port)

if (!context) {
console.error(NO_CONTEXT)
return
}

await getCypressPage()

if (!cypressPage) {
console.error(NO_PAGE)
return
}

await context.addInitScript({
content: `${readFileSync(web3MockPath, 'utf-8')}\n(${mockEthereum.toString()})();`
})

// As we want to refresh the page after mocking the ethereum object
if (!keplrLoaded) {
await cypressPage.reload()
keplrLoaded = true
}

keplrWallet = new KeplrWallet(cypressPage)
await keplrWallet.setupWallet(SEED_PHRASE, PASSWORD)
}

export function getKeplrWallet() {
if (!context || !cypressPage || !keplrWallet) {
console.error(MISSING_INIT)
return
}

if (keplrWallet) return keplrWallet

Check warning

Code scanning / CodeQL

Useless conditional Warning

This use of variable 'keplrWallet' always evaluates to true.

return new KeplrWallet(cypressPage)
}
30 changes: 30 additions & 0 deletions wallets/keplr/src/cypress/installSynpress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { ensureRdpPort } from '@synthetixio/synpress-core'

// import { initEthereumWalletMock } from './initEthereumWalletMock'
// import setupTasks from './setupTasks'

let port: number

export default function installSynpress(on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions) {
const browsers = config.browsers.filter((b) => b.name === 'chrome')
if (browsers.length === 0) {
throw new Error('No Chrome browser found in the configuration')
}

on('before:browser:launch', async (_, launchOptions) => {
// Enable debug mode to establish playwright connection
const args = Array.isArray(launchOptions) ? launchOptions : launchOptions.args
port = ensureRdpPort(args)
})

on('before:spec', async () => {
await initEthereumWalletMock(port)
})

setupTasks(on)

return {
...config,
browsers
}
}
27 changes: 27 additions & 0 deletions wallets/keplr/src/cypress/setupTasks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { getEthereumWalletMock } from './initEthereumWalletMock'

export default function setupTasks(on: Cypress.PluginEvents) {
on('task', {
importWallet: async function (seedPhrase: string) {
const ethereumWalletMock = getEthereumWalletMock()
if (ethereumWalletMock) {
await ethereumWalletMock.importWallet(seedPhrase)
}
return true
},
addNewAccount: async function () {
const ethereumWalletMock = getEthereumWalletMock()
if (ethereumWalletMock) {
await ethereumWalletMock.addNewAccount()
}
return true
},
getAllAccounts: async function () {
const ethereumWalletMock = getEthereumWalletMock()
if (ethereumWalletMock) {
return await ethereumWalletMock.getAllAccounts()
}
return []
}
})
}
23 changes: 23 additions & 0 deletions wallets/keplr/src/cypress/support/commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/// <reference types="cypress" />
// ***********************************************
// This example commands.ts shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************

import type { WalletMock } from '../../EthereumWalletMock'
import type { Network } from '../../network/Network'

declare global {
namespace Cypress {
interface Chainable {
setupWallet(secretWordsOnPrivateKeys: string, password: string): Chainable<void>
}
}
}

Cypress.Commands.add('setupWallet', (seedPhrase, password) => cy.task('setupWallet', seedPhrase, password))
17 changes: 17 additions & 0 deletions wallets/keplr/src/cypress/support/e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// ***********************************************************
// This example support/e2e.ts is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************

// Import commands.js using ES2015 syntax:
import './commands'

0 comments on commit 5829861

Please sign in to comment.