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

chore: test modal components #3495

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Next Next commit
chore: add accoubnt-button modal and button missing tests
  • Loading branch information
tomiir committed Dec 15, 2024
commit b7966d0c44eab139231728e4ed9a1c988eba855e
1 change: 1 addition & 0 deletions packages/core/src/controllers/OptionsController.ts
Original file line number Diff line number Diff line change
@@ -296,6 +296,7 @@ export const OptionsController = {
},

setEnableEmbedded(enableEmbedded: OptionsControllerState['enableEmbedded']) {
console.log('>> Setting enableEmbedded', enableEmbedded)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Log

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

xD

state.enableEmbedded = enableEmbedded
},

4 changes: 2 additions & 2 deletions packages/scaffold-ui/src/modal/w3m-account-button/index.ts
Original file line number Diff line number Diff line change
@@ -83,7 +83,7 @@ class W3mAccountButtonBase extends LitElement {
return null
}

const showBalance = this.balance === 'show'
const shouldShowBalance = this.balance === 'show'

return html`
<wui-account-button
@@ -95,7 +95,7 @@ class W3mAccountButtonBase extends LitElement {
profileName=${ifDefined(this.profileName)}
networkSrc=${ifDefined(this.networkImage)}
avatarSrc=${ifDefined(this.profileImage)}
balance=${showBalance
balance=${shouldShowBalance
? CoreHelperUtil.formatBalance(this.balanceVal, this.balanceSymbol)
: ''}
@click=${this.onClick.bind(this)}
60 changes: 0 additions & 60 deletions packages/scaffold-ui/src/modal/w3m-modal/index.test.ts

This file was deleted.

98 changes: 98 additions & 0 deletions packages/scaffold-ui/test/modal/w3m-button.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { fixture, expect, html } from '@open-wc/testing'
import { vi, describe, it, beforeEach, afterEach } from 'vitest'
import { W3mButton } from '../../src/modal/w3m-button'
import {
ChainController,
ModalController,
type ChainControllerState,
type ModalControllerState
} from '@reown/appkit-core'
import { HelpersUtil } from '../utils/HelpersUtil'
import type { W3mAccountButton } from '../../exports'

describe('W3mButton', () => {
beforeEach(() => {
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
activeCaipAddress: null
} as unknown as ChainControllerState)

vi.spyOn(ModalController, 'state', 'get').mockReturnValue({
loading: false
} as ModalControllerState)

vi.spyOn(ChainController, 'subscribeKey').mockImplementation(() => () => {})
vi.spyOn(ModalController, 'subscribeKey').mockImplementation(() => () => {})
})

afterEach(() => {
vi.clearAllMocks()
})

it('renders connect button when not connected', async () => {
const element: W3mButton = await fixture(html`<appkit-button></appkit-button>`)
const connectButton = HelpersUtil.querySelect(element, 'appkit-connect-button')
const accountButton = HelpersUtil.querySelect(element, 'appkit-account-button')

expect(connectButton).to.exist
expect(accountButton).to.not.exist
})

it('renders account button when connected', async () => {
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
activeCaipAddress: 'eip155:1:0x123'
} as unknown as ChainControllerState)

const element: W3mButton = await fixture(html`<appkit-button></appkit-button>`)
const accountButton = HelpersUtil.querySelect(element, 'appkit-account-button')
const connectButton = HelpersUtil.querySelect(element, 'appkit-connect-button')

expect(accountButton).to.exist
expect(connectButton).to.not.exist
})

it('renders connect button when loading', async () => {
vi.spyOn(ModalController, 'state', 'get').mockReturnValue({
loading: true
} as ModalControllerState)

const element: W3mButton = await fixture(html`<appkit-button></appkit-button>`)
const connectButton = HelpersUtil.querySelect(element, 'appkit-connect-button')

expect(connectButton).to.exist
})

it('passes properties to account button correctly', async () => {
vi.spyOn(ChainController, 'state', 'get').mockReturnValue({
activeCaipAddress: 'eip155:1:0x123'
} as unknown as ChainControllerState)

const element: W3mButton = await fixture(
html`<appkit-button
.disabled=${true}
balance="1 ETH"
.charsStart=${2}
.charsEnd=${4}
></appkit-button>`
)

const accountButton = HelpersUtil.querySelect(
element,
'appkit-account-button'
) as W3mAccountButton | null
expect(accountButton?.getAttribute('balance')).to.equal('1 ETH')
expect(accountButton?.charsStart).to.equal(2)
expect(accountButton?.charsEnd).to.equal(4)
expect(accountButton?.disabled).to.equal(true)
})

it('passes properties to connect button correctly', async () => {
const element: W3mButton = await fixture(
html`<appkit-button size="md" label="Connect" loadingLabel="Connecting..."></appkit-button>`
)

const connectButton = HelpersUtil.querySelect(element, 'appkit-connect-button')
expect(connectButton?.getAttribute('size')).to.equal('md')
expect(connectButton?.getAttribute('label')).to.equal('Connect')
expect(connectButton?.getAttribute('loadingLabel')).to.equal('Connecting...')
})
})
201 changes: 201 additions & 0 deletions packages/scaffold-ui/test/modal/w3m-modal.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
import { W3mModal } from '../../src/modal/w3m-modal'
import { describe, it, expect, vi, beforeEach, beforeAll, afterEach } from 'vitest'
import { elementUpdated, fixture } from '@open-wc/testing'
import { html } from 'lit'
import {
ModalController,
OptionsController,
ChainController,
RouterController,
ApiController,
EventsController
} from '@reown/appkit-core'
import { HelpersUtil } from '../utils/HelpersUtil'
import type { RouterControllerState } from '@reown/appkit-core'
import type { CaipNetwork } from '@reown/appkit-common'

// Mock ResizeObserver
beforeAll(() => {
global.ResizeObserver = vi.fn().mockImplementation(() => ({
observe: vi.fn(),
unobserve: vi.fn(),
disconnect: vi.fn()
}))
})

describe('W3mModal', () => {
describe('Embedded Mode', () => {
let element: W3mModal

beforeEach(async () => {
OptionsController.setEnableEmbedded(true)
ModalController.close()
element = await fixture(html`<w3m-modal .enableEmbedded=${true}></w3m-modal>`)
})

afterEach(() => {
vi.clearAllMocks()
})

it('should be visible when embedded is enabled', () => {
expect(element).toBeTruthy()
const card = HelpersUtil.getByTestId(element, 'w3m-modal-card')
expect(card).toBeTruthy()
expect(HelpersUtil.querySelect(element, 'w3m-header')).toBeTruthy()
expect(HelpersUtil.querySelect(element, 'w3m-router')).toBeTruthy()
expect(HelpersUtil.querySelect(element, 'w3m-snackbar')).toBeTruthy()
expect(HelpersUtil.querySelect(element, 'w3m-alertbar')).toBeTruthy()
expect(HelpersUtil.querySelect(element, 'w3m-tooltip')).toBeTruthy()
})

it('should not render overlay in embedded mode', () => {
const overlay = HelpersUtil.getByTestId(element, 'w3m-modal-overlay')
expect(overlay).toBeNull()
})

it('should close modal when wallet is connected', async () => {
ModalController.open()
element.requestUpdate()
await elementUpdated(element)
;(element as any).caipAddress = 'eip155:1:0x123...'
element.requestUpdate()
await elementUpdated(element)

expect(ModalController.state.open).toBe(false)
})
})

describe('Standard Mode', () => {
let element: W3mModal

beforeEach(async () => {
OptionsController.setEnableEmbedded(false)
ModalController.close()
vi.spyOn(ApiController, 'prefetch').mockImplementation(() => Promise.resolve())
element = await fixture(html`<w3m-modal></w3m-modal>`)
})

it('should not be visible when closed', () => {
expect(HelpersUtil.getByTestId(element, 'w3m-modal-overlay')).toBeNull()
})

it('should be visible when opened', async () => {
await ModalController.open()

element.requestUpdate()
await elementUpdated(element)

expect(HelpersUtil.getByTestId(element, 'w3m-modal-overlay')).toBeTruthy()
expect(HelpersUtil.getByTestId(element, 'w3m-modal-card')).toBeTruthy()
})

it('should handle overlay click', async () => {
ModalController.open()
element.requestUpdate()
await elementUpdated(element)

const overlay = HelpersUtil.getByTestId(element, 'w3m-modal-overlay')
overlay?.click()
element.requestUpdate()
await elementUpdated(element)

expect(ModalController.state.open).toBe(false)
})

it('should add shake class when shaking', async () => {
ModalController.open()
element.requestUpdate()
await elementUpdated(element)

ModalController.shake()
element.requestUpdate()
await elementUpdated(element)

const card = HelpersUtil.getByTestId(element, 'w3m-modal-card')
expect(card?.getAttribute('shake')).toBe('true')
})

it('prevents closing on unsupported chain', async () => {
vi.spyOn(RouterController, 'state', 'get').mockReturnValue({
view: 'UnsupportedChain'
} as RouterControllerState)
const shakeSpy = vi.spyOn(ModalController, 'shake')

ModalController.open()
element.requestUpdate()
await elementUpdated(element)

const overlay = HelpersUtil.getByTestId(element, 'w3m-modal-overlay')
overlay?.click()

expect(shakeSpy).toHaveBeenCalled()
expect(ModalController.state.open).toBe(true)
})
})

describe('Network Changes', () => {
let element: W3mModal

beforeEach(async () => {
element = await fixture(html`<w3m-modal></w3m-modal>`)
})

it('should handle network change when not connected', async () => {
const goBackSpy = vi.spyOn(RouterController, 'goBack')
const nextNetwork = {
id: '2',
name: 'Network 2',
caipNetworkId: 'eip155:2'
} as unknown as CaipNetwork

ChainController.setActiveCaipNetwork(nextNetwork)
element.requestUpdate()
await elementUpdated(element)

expect(goBackSpy).toHaveBeenCalled()
})

it('should handle network change when connected', async () => {
const goBackSpy = vi.spyOn(RouterController, 'goBack')
;(element as any).caipAddress = 'eip155:1:0x123'
;(element as any).caipNetwork = { id: '1', name: 'Network 1', caipNetworkId: 'eip155:1' }

const nextNetwork = {
id: '2',
name: 'Network 2',
caipNetworkId: 'eip155:2'
} as unknown as CaipNetwork
ChainController.setActiveCaipNetwork(nextNetwork)
element.requestUpdate()
await elementUpdated(element)

expect(goBackSpy).toHaveBeenCalled()
})
})

describe('Initialization', () => {
it('should send modal loaded event', async () => {
const eventSpy = vi.spyOn(EventsController, 'sendEvent')
await fixture(html`<w3m-modal></w3m-modal>`)

expect(eventSpy).toHaveBeenCalledWith({ type: 'track', event: 'MODAL_LOADED' })
})

it('should prefetch API data', async () => {
const prefetchSpy = vi.spyOn(ApiController, 'prefetch')
await fixture(html`<w3m-modal></w3m-modal>`)

expect(prefetchSpy).toHaveBeenCalled()
})

it('should clean up subscriptions on disconnect', async () => {
const element: W3mModal = await fixture(html`<w3m-modal></w3m-modal>`)
const abortSpy = vi.fn()
;(element as any).abortController = { abort: abortSpy }

element.disconnectedCallback()

expect(abortSpy).toHaveBeenCalled()
})
})
})