2023-05-09 20:33:55 +03:00
|
|
|
import 'cypress-hardhat/lib/browser'
|
|
|
|
|
|
|
|
import { Eip1193Bridge } from '@ethersproject/experimental/lib/eip1193-bridge'
|
|
|
|
|
2023-06-08 04:16:57 +03:00
|
|
|
import { FeatureFlag } from '../../src/featureFlags'
|
2023-05-09 20:33:55 +03:00
|
|
|
import { UserState } from '../../src/state/user/reducer'
|
|
|
|
import { CONNECTED_WALLET_USER_STATE } from '../utils/user-state'
|
|
|
|
|
|
|
|
declare global {
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
|
|
namespace Cypress {
|
|
|
|
interface ApplicationWindow {
|
|
|
|
ethereum: Eip1193Bridge
|
|
|
|
}
|
2023-08-03 21:33:16 +03:00
|
|
|
interface Chainable<Subject> {
|
|
|
|
/**
|
|
|
|
* Wait for a specific event to be sent to amplitude. If the event is found, the subject will be the event.
|
|
|
|
*
|
|
|
|
* @param {string} eventName - The type of the event to search for e.g. SwapEventName.SWAP_TRANSACTION_COMPLETED
|
|
|
|
* @param {number} timeout - The maximum amount of time (in ms) to wait for the event.
|
|
|
|
* @returns {Chainable<Subject>}
|
|
|
|
*/
|
|
|
|
waitForAmplitudeEvent(eventName: string, timeout?: number): Chainable<Subject>
|
|
|
|
}
|
2023-05-09 20:33:55 +03:00
|
|
|
interface VisitOptions {
|
|
|
|
serviceWorker?: true
|
|
|
|
featureFlags?: Array<FeatureFlag>
|
|
|
|
/**
|
|
|
|
* Initial user state.
|
|
|
|
* @default {@type import('../utils/user-state').CONNECTED_WALLET_USER_STATE}
|
|
|
|
*/
|
|
|
|
userState?: Partial<UserState>
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// sets up the injected provider to be a mock ethereum provider with the given mnemonic/index
|
|
|
|
// eslint-disable-next-line no-undef
|
|
|
|
Cypress.Commands.overwrite(
|
|
|
|
'visit',
|
|
|
|
(original, url: string | Partial<Cypress.VisitOptions>, options?: Partial<Cypress.VisitOptions>) => {
|
|
|
|
if (typeof url !== 'string') throw new Error('Invalid arguments. The first argument to cy.visit must be the path.')
|
|
|
|
|
|
|
|
// Add a hash in the URL if it is not present (to use hash-based routing correctly with queryParams).
|
2023-08-02 08:13:19 +03:00
|
|
|
const hashUrl = url.startsWith('/') && url.length > 2 && !url.startsWith('/#') ? `/#${url}` : url
|
2023-05-09 20:33:55 +03:00
|
|
|
|
|
|
|
return cy
|
|
|
|
.intercept('/service-worker.js', options?.serviceWorker ? undefined : { statusCode: 404 })
|
|
|
|
.provider()
|
|
|
|
.then((provider) =>
|
|
|
|
original({
|
|
|
|
...options,
|
|
|
|
url: hashUrl,
|
|
|
|
onBeforeLoad(win) {
|
|
|
|
options?.onBeforeLoad?.(win)
|
|
|
|
|
|
|
|
// We want to test from a clean state, so we clear the local storage (which clears redux).
|
|
|
|
win.localStorage.clear()
|
|
|
|
|
|
|
|
// Set initial user state.
|
|
|
|
win.localStorage.setItem(
|
|
|
|
'redux_localstorage_simple_user', // storage key for the user reducer using 'redux-localstorage-simple'
|
2023-07-07 00:01:13 +03:00
|
|
|
JSON.stringify({ ...CONNECTED_WALLET_USER_STATE, ...(options?.userState ?? {}) })
|
2023-05-09 20:33:55 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
// Set feature flags, if configured.
|
|
|
|
if (options?.featureFlags) {
|
|
|
|
const featureFlags = options.featureFlags.reduce((flags, flag) => ({ ...flags, [flag]: 'enabled' }), {})
|
|
|
|
win.localStorage.setItem('featureFlags', JSON.stringify(featureFlags))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Inject the mock ethereum provider.
|
2023-08-02 08:13:19 +03:00
|
|
|
win.ethereum = provider
|
2023-05-09 20:33:55 +03:00
|
|
|
},
|
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
|
|
|
)
|
2023-08-03 21:33:16 +03:00
|
|
|
|
|
|
|
Cypress.Commands.add('waitForAmplitudeEvent', (eventName, timeout = 5000 /* 5s */) => {
|
|
|
|
const startTime = new Date().getTime()
|
|
|
|
|
|
|
|
function checkRequest() {
|
|
|
|
return cy.wait('@amplitude', { timeout }).then((interception) => {
|
|
|
|
const events = interception.request.body.events
|
|
|
|
const event = events.find((event: any) => event.event_type === eventName)
|
|
|
|
|
|
|
|
if (event) {
|
|
|
|
return cy.wrap(event)
|
|
|
|
} else if (new Date().getTime() - startTime > timeout) {
|
|
|
|
throw new Error(`Event ${eventName} not found within the specified timeout`)
|
|
|
|
} else {
|
|
|
|
return checkRequest()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
return checkRequest()
|
|
|
|
})
|