Skip to content

Commit

Permalink
chore: test ethers verify API + AppKit in iframe verify test case (#2831
Browse files Browse the repository at this point in the history
)

Co-authored-by: Chris Smith <chris@reown.com>
  • Loading branch information
chris13524 and Chris Smith authored Nov 21, 2024
1 parent bf4bf8d commit 29bc14c
Show file tree
Hide file tree
Showing 18 changed files with 375 additions and 73 deletions.
4 changes: 0 additions & 4 deletions .github/workflows/ui_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@ on:
secrets:
NEXT_PUBLIC_PROJECT_ID:
required: true
RELEASE_TOKEN_V2:
required: true
TFC_INFRA_TOKEN:
required: true
TESTS_NEXTAUTH_SECRET:
required: false
TESTS_MAILSAC_API_KEY:
Expand Down
6 changes: 4 additions & 2 deletions apps/laboratory/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@ const SHAKRA_UI = `'sha256-e7MRMmTzLsLQvIy1iizO1lXf7VWYoQ6ysj5fuUzvRwE='`
const secureSiteDomain = process.env.NEXT_PUBLIC_SECURE_SITE_SDK_URL
? new URL(process.env.NEXT_PUBLIC_SECURE_SITE_SDK_URL).origin
: ''
const verifyApiNestedIframesTestOuterDomain =
'https://verify-api-nested-iframes-test-outer-domain.com'
const cspHeader = `
default-src 'self';
script-src 'self' ${SHAKRA_UI} ${process.env.NODE_ENV === 'production' ? '' : "'unsafe-eval'"};
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
img-src * 'self' data: blob: https://walletconnect.org https://walletconnect.com https://secure.walletconnect.com https://secure.walletconnect.org https://tokens-data.1inch.io https://tokens.1inch.io https://ipfs.io https://appkit-lab.reown.org;
font-src 'self' https://fonts.gstatic.com;
connect-src 'self' https://react-wallet.walletconnect.com https://rpc.walletconnect.com https://rpc.walletconnect.org https://relay.walletconnect.com https://relay.walletconnect.org wss://relay.walletconnect.com wss://relay.walletconnect.org https://pulse.walletconnect.com https://pulse.walletconnect.org https://api.web3modal.com https://api.web3modal.org wss://www.walletlink.org https://o1095249.ingest.sentry.io https://quote-api.jup.ag;
frame-src 'self' https://verify.walletconnect.com https://verify.walletconnect.org https://secure.walletconnect.com https://secure.walletconnect.org https://secure.reown.com https://widget.solflare.com/ ${secureSiteDomain}/;
frame-src 'self' https://verify.walletconnect.com https://verify.walletconnect.org https://secure.walletconnect.com https://secure.walletconnect.org https://secure.reown.com https://widget.solflare.com/ ${secureSiteDomain};
object-src 'none';
base-uri 'self';
form-action 'self';
frame-ancestors 'none';
frame-ancestors ${verifyApiNestedIframesTestOuterDomain};
report-uri https://o1095249.ingest.sentry.io/api/4505685639364608/security/?sentry_key=36ff1e79c60877fce6c0273e94a8ed69;
report-to csp-endpoint
`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { createAppKit } from '@reown/appkit/react'
import { EthersAdapter } from '@reown/appkit-adapter-ethers'
import { EthersTests } from '../../components/Ethers/EthersTests'
import { AppKitButtons } from '../../components/AppKitButtons'
import { ThemeStore } from '../../utils/StoreUtil'
import { ConstantsUtil } from '../../utils/ConstantsUtil'
import { EthersModalInfo } from '../../components/Ethers/EthersModalInfo'
import { mainnet } from '@reown/appkit/networks'

// Special project ID with verify enabled on localhost
const projectId = 'e4eae1aad4503db9966a04fd045a7e4d'

const modal = createAppKit({
adapters: [new EthersAdapter()],
networks: ConstantsUtil.EvmNetworks,
defaultNetwork: mainnet,
projectId,
metadata: {
name: 'AppKit',
description: 'AppKit Laboratory',
url: 'https://example.com',
icons: []
},
features: {
analytics: true
},
customWallets: ConstantsUtil.CustomWallets
})

ThemeStore.setModal(modal)

export default function Ethers() {
return (
<>
<AppKitButtons />
<EthersModalInfo />
<EthersTests />
</>
)
}
34 changes: 34 additions & 0 deletions apps/laboratory/src/pages/library/ethers-verify-evil.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { createAppKit } from '@reown/appkit/react'
import { EthersAdapter } from '@reown/appkit-adapter-ethers'
import { EthersTests } from '../../components/Ethers/EthersTests'
import { AppKitButtons } from '../../components/AppKitButtons'
import { ThemeStore } from '../../utils/StoreUtil'
import { ConstantsUtil } from '../../utils/ConstantsUtil'
import { EthersModalInfo } from '../../components/Ethers/EthersModalInfo'
import { mainnet } from '@reown/appkit/networks'

// Special project ID with https://malicious-app-verify-simulation.vercel.app/ as the verified domain and this domain is marked as a scam
const projectId = '9d176efa3150a1df0a76c8c138b6b657'

const modal = createAppKit({
adapters: [new EthersAdapter()],
networks: ConstantsUtil.EvmNetworks,
defaultNetwork: mainnet,
projectId,
features: {
analytics: true
},
customWallets: ConstantsUtil.CustomWallets
})

ThemeStore.setModal(modal)

export default function Ethers() {
return (
<>
<AppKitButtons />
<EthersModalInfo />
<EthersTests />
</>
)
}
34 changes: 34 additions & 0 deletions apps/laboratory/src/pages/library/ethers-verify-valid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { createAppKit } from '@reown/appkit/react'
import { EthersAdapter } from '@reown/appkit-adapter-ethers'
import { EthersTests } from '../../components/Ethers/EthersTests'
import { AppKitButtons } from '../../components/AppKitButtons'
import { ThemeStore } from '../../utils/StoreUtil'
import { ConstantsUtil } from '../../utils/ConstantsUtil'
import { EthersModalInfo } from '../../components/Ethers/EthersModalInfo'
import { mainnet } from '@reown/appkit/networks'

// Special project ID with verify enabled on localhost
const projectId = 'e4eae1aad4503db9966a04fd045a7e4d'

const modal = createAppKit({
adapters: [new EthersAdapter()],
networks: ConstantsUtil.EvmNetworks,
defaultNetwork: mainnet,
projectId,
features: {
analytics: true
},
customWallets: ConstantsUtil.CustomWallets
})

ThemeStore.setModal(modal)

export default function Ethers() {
return (
<>
<AppKitButtons />
<EthersModalInfo />
<EthersTests />
</>
)
}
Original file line number Diff line number Diff line change
@@ -1,23 +1,14 @@
import { createAppKit } from '@reown/appkit/react'
import { WagmiAdapter } from '@reown/appkit-adapter-wagmi'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { WagmiProvider } from 'wagmi'
import { AppKitButtons } from '../../components/AppKitButtons'
import { WagmiTests } from '../../components/Wagmi/WagmiTests'
import { ThemeStore } from '../../utils/StoreUtil'
import { WagmiModalInfo } from '../../components/Wagmi/WagmiModalInfo'
import { WagmiAdapter } from '@reown/appkit-adapter-wagmi'
import { ConstantsUtil } from '../../utils/ConstantsUtil'
import { mainnet } from '@reown/appkit/networks'

const metadata = {
name: 'AppKit',
description: 'AppKit Laboratory',
// Allow localhost
url: 'http://localhost:3000',
icons: ['https://avatars.githubusercontent.com/u/37784886'],
verifyUrl: ''
}

// Special project ID with verify enabled on localhost
const projectId = 'e4eae1aad4503db9966a04fd045a7e4d'

Expand All @@ -34,11 +25,14 @@ const wagmiAdapter = new WagmiAdapter({
const modal = createAppKit({
adapters: [wagmiAdapter],
networks,
projectId,
defaultNetwork: mainnet,
metadata,
termsConditionsUrl: 'https://reown.com/terms-of-service',
privacyPolicyUrl: 'https://reown.com/privacy-policy'
projectId,
metadata: {
name: 'AppKit',
description: 'AppKit Laboratory',
url: 'https://example.com',
icons: []
}
})

ThemeStore.setModal(modal)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,6 @@ import { WagmiAdapter } from '@reown/appkit-adapter-wagmi'
import { ConstantsUtil } from '../../utils/ConstantsUtil'
import { mainnet } from '@reown/appkit/networks'

const metadata = {
name: 'Evil AppKit',
description: 'Evil AppKit Laboratory',
url: 'https://malicious-app-verify-simulation.vercel.app/',
icons: ['https://avatars.githubusercontent.com/u/37784886'],
verifyUrl: ''
}

// Special project ID with https://malicious-app-verify-simulation.vercel.app/ as the verified domain and this domain is marked as a scam
const projectId = '9d176efa3150a1df0a76c8c138b6b657'

Expand All @@ -35,7 +27,6 @@ const modal = createAppKit({
networks,
defaultNetwork: mainnet,
projectId,
metadata,
termsConditionsUrl: 'https://reown.com/terms-of-service',
privacyPolicyUrl: 'https://reown.com/privacy-policy'
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { createAppKit } from '@reown/appkit/react'
import { WagmiAdapter } from '@reown/appkit-adapter-wagmi'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { WagmiProvider } from 'wagmi'
import { AppKitButtons } from '../../components/AppKitButtons'
import { WagmiTests } from '../../components/Wagmi/WagmiTests'
import { ThemeStore } from '../../utils/StoreUtil'
import { WagmiModalInfo } from '../../components/Wagmi/WagmiModalInfo'
import { WagmiAdapter } from '@reown/appkit-adapter-wagmi'
import { ConstantsUtil } from '../../utils/ConstantsUtil'
import { mainnet } from '@reown/appkit/networks'

Expand All @@ -25,8 +25,8 @@ const wagmiAdapter = new WagmiAdapter({
const modal = createAppKit({
adapters: [wagmiAdapter],
networks,
defaultNetwork: mainnet,
projectId,
defaultNetwork: mainnet,
termsConditionsUrl: 'https://reown.com/terms-of-service',
privacyPolicyUrl: 'https://reown.com/privacy-policy'
})
Expand Down
2 changes: 1 addition & 1 deletion apps/laboratory/tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ We use Playwright as our functional test runner. It's configured to try multiple

- Make sure your `.env.local` is set up (see `.env.example` for reference)
- Run `pnpm playwright:install` to install the browsers required to run the tests
- Build AppKit by running `pnpm build` in the root directory
- Build AppKit & the Lab by running `pnpm build:laboratory` in the root directory

## Running Tests

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { ModalFixture } from './w3m-fixture'
import { ModalPage } from '../pages/ModalPage'
import { timingFixture } from './timing-fixture'

export const testMEthersVerifyDomainMismatch = timingFixture.extend<ModalFixture>({
library: ['ethers', { option: true }],
modalPage: async ({ page, library }, use) => {
const modalPage = new ModalPage(page, library, 'ethers-verify-domain-mismatch')
await modalPage.load()
await use(modalPage)
}
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { ModalFixture } from './w3m-fixture'
import { ModalPage } from '../pages/ModalPage'
import { timingFixture } from './timing-fixture'

export const testMEthersVerifyEvil = timingFixture.extend<ModalFixture>({
library: ['ethers', { option: true }],
modalPage: async ({ page, library }, use) => {
const modalPage = new ModalPage(page, library, 'ethers-verify-evil')
await modalPage.load()
await use(modalPage)
}
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { ModalFixture } from './w3m-fixture'
import { ModalPage } from '../pages/ModalPage'
import { timingFixture } from './timing-fixture'

export const testMEthersVerifyValid = timingFixture.extend<ModalFixture>({
library: ['ethers', { option: true }],
modalPage: async ({ page, library }, use) => {
const modalPage = new ModalPage(page, library, 'ethers-verify-valid')
await modalPage.load()
await use(modalPage)
}
})
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import type { ModalFixture } from './w3m-fixture'
import { ModalPage } from '../pages/ModalPage'
import { timingFixture } from './timing-fixture'

export const testMVerifyDomainMismatch = timingFixture.extend<ModalFixture>({
export const testMWagmiVerifyDomainMismatch = timingFixture.extend<ModalFixture>({
library: ['wagmi', { option: true }],
modalPage: async ({ page, library }, use) => {
const modalPage = new ModalPage(page, library, 'verify-domain-mismatch')
const modalPage = new ModalPage(page, library, 'wagmi-verify-domain-mismatch')
await modalPage.load()
await use(modalPage)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import type { ModalFixture } from './w3m-fixture'
import { ModalPage } from '../pages/ModalPage'
import { timingFixture } from './timing-fixture'

export const testMVerifyEvil = timingFixture.extend<ModalFixture>({
export const testMWagmiVerifyEvil = timingFixture.extend<ModalFixture>({
library: ['wagmi', { option: true }],
modalPage: async ({ page, library }, use) => {
const modalPage = new ModalPage(page, library, 'verify-evil')
const modalPage = new ModalPage(page, library, 'wagmi-verify-evil')
await modalPage.load()
await use(modalPage)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import type { ModalFixture } from './w3m-fixture'
import { ModalPage } from '../pages/ModalPage'
import { timingFixture } from './timing-fixture'

export const testMVerifyValid = timingFixture.extend<ModalFixture>({
export const testMWagmiVerifyValid = timingFixture.extend<ModalFixture>({
library: ['wagmi', { option: true }],
modalPage: async ({ page, library }, use) => {
const modalPage = new ModalPage(page, library, 'verify-valid')
const modalPage = new ModalPage(page, library, 'wagmi-verify-valid')
await modalPage.load()
await use(modalPage)
}
Expand Down
25 changes: 17 additions & 8 deletions apps/laboratory/tests/shared/pages/ModalPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ export type ModalFlavor =
| 'default'
| 'external'
| 'debug-mode'
| 'verify-valid'
| 'verify-domain-mismatch'
| 'verify-evil'
| 'wagmi-verify-valid'
| 'wagmi-verify-domain-mismatch'
| 'wagmi-verify-evil'
| 'ethers-verify-valid'
| 'ethers-verify-domain-mismatch'
| 'ethers-verify-evil'
| 'no-email'
| 'no-socials'
| 'siwe'
Expand All @@ -28,9 +31,12 @@ function getUrlByFlavor(baseUrl: string, library: string, flavor: ModalFlavor) {
const urlsByFlavor: Partial<Record<ModalFlavor, string>> = {
default: `${baseUrl}library/${library}/`,
external: `${baseUrl}library/external/`,
'verify-valid': `${baseUrl}library/verify-valid/`,
'verify-domain-mismatch': `${baseUrl}library/verify-domain-mismatch/`,
'verify-evil': maliciousUrl
'wagmi-verify-valid': `${baseUrl}library/wagmi-verify-valid/`,
'wagmi-verify-domain-mismatch': `${baseUrl}library/wagmi-verify-domain-mismatch/`,
'wagmi-verify-evil': maliciousUrl,
'ethers-verify-valid': `${baseUrl}library/ethers-verify-valid/`,
'ethers-verify-domain-mismatch': `${baseUrl}library/ethers-verify-domain-mismatch/`,
'ethers-verify-evil': maliciousUrl
}

return urlsByFlavor[flavor] || `${baseUrl}library/${library}-${flavor}/`
Expand All @@ -57,8 +63,11 @@ export class ModalPage {
}

async load() {
if (this.flavor === 'verify-evil') {
await routeInterceptUrl(this.page, maliciousUrl, this.baseURL, '/library/verify-evil/')
if (this.flavor === 'wagmi-verify-evil') {
await routeInterceptUrl(this.page, maliciousUrl, this.baseURL, '/library/wagmi-verify-evil/')
}
if (this.flavor === 'ethers-verify-evil') {
await routeInterceptUrl(this.page, maliciousUrl, this.baseURL, '/library/ethers-verify-evil/')
}

await this.page.goto(this.url)
Expand Down
3 changes: 2 additions & 1 deletion apps/laboratory/tests/shared/utils/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ const SINGLE_ADAPTER_EVM_TESTS = [
'siwe.spec.ts',
'smart-account.spec.ts',
'wallet-features.spec.ts',
'wallet.spec.ts'
'wallet.spec.ts',
'verify.spec.ts'
]

const SINGLE_ADAPTER_EVM_MOBILE_TESTS = ['mobile-wallet-features.spec.ts']
Expand Down
Loading

0 comments on commit 29bc14c

Please sign in to comment.