Skip to content

Commit

Permalink
add more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Melisa Anabella Rossi committed Jan 16, 2024
1 parent ffb41fc commit 55efe05
Show file tree
Hide file tree
Showing 9 changed files with 257 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default function EnsMapAddressModal(props: Props) {
}, [])

return (
<Modal closeIcon={<Close />} onClose={onClose} size="tiny">
<Modal closeIcon={isLoading ? undefined : <Close />} onClose={isLoading ? undefined : onClose} size="tiny">
<div className={styles.main}>
<div className={styles.info}>
<h1 className={styles.title}>{t('ens_map_address_modal.title')}</h1>
Expand All @@ -39,6 +39,8 @@ export default function EnsMapAddressModal(props: Props) {
value={address}
placeholder={t('ens_map_address_modal.address.placeholder')}
onChange={handleAddressChange}
type="address"
disabled={isLoading}
/>
<div className={styles.network}>
<span className="ui header sub">{t('ens_map_address_modal.network')}</span>
Expand Down
95 changes: 93 additions & 2 deletions src/modules/ens/reducer.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
import { FETCH_EXTERNAL_NAMES_REQUEST, fetchExternalNamesFailure, fetchExternalNamesRequest, fetchExternalNamesSuccess } from './actions'
import { ChainId } from '@dcl/schemas'
import {
FETCH_EXTERNAL_NAMES_REQUEST,
SET_ENS_ADDRESS_SUCCESS,
fetchExternalNamesFailure,
fetchExternalNamesRequest,
fetchExternalNamesSuccess,
setENSAddressFailure,
setENSAddressRequest
} from './actions'
import { ENSState, INITIAL_STATE, ensReducer } from './reducer'
import { ENS, ENSError } from './types'
import { fetchTransactionSuccess } from 'decentraland-dapps/dist/modules/transaction/actions'
import { Transaction } from 'decentraland-dapps/dist/modules/transaction/types'

let state: ENSState

beforeEach(() => {
state = INITIAL_STATE
state = { ...INITIAL_STATE }
})

describe('when handling the fetch external names actions', () => {
Expand Down Expand Up @@ -86,3 +97,83 @@ describe('when handling the fetch external names actions', () => {
})
})
})

describe('when handling set ens address actions', () => {
let ens: ENS
let address: string

beforeEach(() => {
state = { ...INITIAL_STATE }
address = '0xtest'
ens = {
name: 'test',
subdomain: 'test.dcl.eth',
nftOwnerAddress: address
} as ENS
})

describe('when handling the set ens address request action', () => {
it('should add the set ens address request action to the loading state', () => {
const action = setENSAddressRequest(ens, address)
const newState = ensReducer(state, action)
expect(newState.loading[0]).toEqual(action)
})

it('should set the error as null', () => {
const action = setENSAddressRequest(ens, address)
const newState = ensReducer({ ...state, error: { message: 'some error' } }, action)
expect(newState.error).toEqual(null)
})
})

describe('when handling the set ens address failure action', () => {
let error: ENSError
beforeEach(() => {
error = { message: 'some error' }
state = {
...state,
loading: [setENSAddressRequest(ens, address)]
}
})

it('should remove the set ens address request action from the loading state', () => {
const action = setENSAddressFailure(ens, address, error)
const newState = ensReducer(state, action)
expect(newState.loading.length).toEqual(0)
})

it('should add the error to the state', () => {
const action = setENSAddressFailure(ens, address, error)
const newState = ensReducer(state, action)
expect(newState.error).toEqual(error)
})
})

describe('when handling the set ens address success action', () => {
beforeEach(() => {
state = {
...state,
error: { message: 'some error' },
loading: [setENSAddressRequest(ens, address)]
}
})

it('should remove the set ens address request action from the loading state', () => {
const txSuccessAction = fetchTransactionSuccess({
actionType: SET_ENS_ADDRESS_SUCCESS,
payload: { ens, address, chainId: ChainId.ETHEREUM_SEPOLIA, hash: 'hash' }
} as Transaction)
const newState = ensReducer(state, txSuccessAction)
expect(newState.loading.length).toEqual(0)
})

it('should set the error as null', () => {
const txSuccessAction = fetchTransactionSuccess({
actionType: SET_ENS_ADDRESS_SUCCESS,
payload: { ens, address, chainId: ChainId.ETHEREUM_SEPOLIA, hash: 'hash' }
} as Transaction)
const newState = ensReducer(state, txSuccessAction)
expect(newState.error).toEqual(null)
})
})
})
7 changes: 4 additions & 3 deletions src/modules/ens/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ import {
SET_ENS_ADDRESS_FAILURE,
SetENSAddressRequestAction,
SetENSAddressFailureAction,
SetENSAddressSuccessAction
SetENSAddressSuccessAction,
setENSAddressSuccess
} from './actions'
import { ENS, ENSError, Authorization } from './types'
import { isExternalName } from './utils'
Expand Down Expand Up @@ -297,10 +298,10 @@ export function ensReducer(state: ENSState = INITIAL_STATE, action: ENSReducerAc
}
}
case SET_ENS_ADDRESS_SUCCESS: {
const { ens, address } = transaction.payload
const { ens, address, chainId, txHash } = transaction.payload
return {
...state,
loading: loadingReducer(state.loading, action),
loading: loadingReducer(state.loading, setENSAddressSuccess(ens, address, chainId, txHash)),
error: null,
data: {
...state.data,
Expand Down
60 changes: 56 additions & 4 deletions src/modules/ens/sagas.spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
import * as matchers from 'redux-saga-test-plan/matchers'
import { throwError } from 'redux-saga-test-plan/providers'
import { expectSaga } from 'redux-saga-test-plan'
import { namehash } from '@ethersproject/hash'
import { call, select } from 'redux-saga/effects'
import { ethers } from 'ethers'
import { Signer, ethers } from 'ethers'
import { BuilderClient } from '@dcl/builder-client'
import { ChainId, Network } from '@dcl/schemas'
import { ERC20__factory, ERC20, DCLController__factory, DCLRegistrar__factory, ENS__factory } from 'contracts'
import {
ERC20__factory,
ERC20,
DCLController__factory,
DCLRegistrar__factory,
ENS__factory,
ENSResolver__factory,
ENSResolver
} from 'contracts'
import { getChainIdByNetwork, getSigner } from 'decentraland-dapps/dist/lib/eth'
import { getAddress } from 'decentraland-dapps/dist/modules/wallet/selectors'
import { connectWalletSuccess } from 'decentraland-dapps/dist/modules/wallet/actions'
import { waitForTx } from 'decentraland-dapps/dist/modules/transaction/utils'
import { closeModal } from 'modules/modal/actions'
import { Wallet } from 'decentraland-dapps/dist/modules/wallet/types'
import { CONTROLLER_V2_ADDRESS, ENS_ADDRESS, MANA_ADDRESS, REGISTRAR_ADDRESS } from 'modules/common/contracts'
import { fetchWorldDeploymentsRequest } from 'modules/deployment/actions'
Expand All @@ -29,7 +40,9 @@ import {
fetchENSWorldStatusSuccess,
fetchExternalNamesFailure,
fetchExternalNamesRequest,
fetchExternalNamesSuccess
fetchExternalNamesSuccess,
setENSAddressRequest,
setENSAddressSuccess
} from './actions'
import { ensSaga } from './sagas'
import { ENS, ENSError, WorldStatus } from './types'
Expand All @@ -43,6 +56,7 @@ const MockBuilderClient = BuilderClient as jest.MockedClass<typeof BuilderClient
let builderClient: BuilderClient
let ensApi: ENSApi
let manaContract: ERC20
let ensResolverContract: ENSResolver
let dclRegistrarContract: DCLRegistrar__factory
let ensFactoryContract: ENS__factory

Expand Down Expand Up @@ -70,6 +84,10 @@ beforeEach(() => {
resolver: jest.fn().mockResolvedValue(ethers.constants.AddressZero),
owner: jest.fn().mockResolvedValue('address')
} as unknown as ENS__factory
ensResolverContract = {
'setAddr(bytes32,address)': jest.fn().mockResolvedValue(''),
'addr(bytes32)': jest.fn().mockResolvedValue('0xaddr')
} as unknown as ENSResolver
})

describe('when handling the approve claim mana request', () => {
Expand Down Expand Up @@ -130,6 +148,7 @@ describe('when handling the claim name request', () => {
beforeEach(() => {
address = '0xanAddress'
jest.spyOn(WorldsAPI.prototype, 'fetchWorld').mockResolvedValue(null)
ENSResolver__factory.connect = jest.fn().mockReturnValue(ensResolverContract)
})
afterEach(() => {
jest.restoreAllMocks()
Expand All @@ -146,7 +165,7 @@ describe('when handling the claim name request', () => {
content: '',
landId: undefined,
worldStatus: null,
ensAddressRecord: ''
ensAddressRecord: '0xaddr'
}
const ENSList: ENS[] = validDomains.map(domain => ({
name: domain,
Expand Down Expand Up @@ -368,3 +387,36 @@ describe('when handling the wallet connection', () => {
.silentRun()
})
})

describe('when handling the set ens address request', () => {
let signer: Signer
let address: string
let ens: ENS
let hash: string

beforeEach(() => {
ens = {
subdomain: 'test.dcl.eth',
name: 'test'
} as ENS
signer = {} as Signer
address = '0xtest'
hash = 'tx-hash'

ENSResolver__factory.connect = jest.fn().mockReturnValue(ensResolverContract)
})

it('should call resolver contract with the ens domain and address', () => {
return expectSaga(ensSaga, builderClient, ensApi)
.provide([
[call(getWallet), { address: 'address', chainId: ChainId.ETHEREUM_GOERLI }],
[call(getSigner), { signer }],
[call([ensResolverContract, 'setAddr(bytes32,address)'], namehash(ens.subdomain), address), { hash } as ethers.ContractTransaction],
[call(waitForTx, hash), true]
])
.put(setENSAddressSuccess(ens, address, ChainId.ETHEREUM_GOERLI, hash))
.put(closeModal('EnsMapAddressModal'))
.dispatch(setENSAddressRequest(ens, address))
.silentRun()
})
})
8 changes: 4 additions & 4 deletions src/modules/ens/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -312,13 +312,13 @@ export function* ensSaga(builderClient: BuilderClient, ensApi: ENSApi) {
function* handleSetENSAddressRequest(action: SetENSAddressRequestAction) {
const { ens, address } = action.payload
try {
const wallet: Wallet = yield getWallet()
const signer: ethers.Signer = yield getSigner()

const wallet: Wallet = yield call(getWallet)
const signer: ethers.Signer = yield call(getSigner)
const nodehash = namehash(ens.subdomain)
const resolverContract = ENSResolver__factory.connect(ENS_RESOLVER_ADDRESS, signer)

const transaction: ethers.ContractTransaction = yield call(() => resolverContract['setAddr(bytes32,address)'](nodehash, address))
const transaction: ethers.ContractTransaction = yield call([resolverContract, 'setAddr(bytes32,address)'], nodehash, address)

yield put(setENSAddressSuccess(ens, address, wallet.chainId, transaction.hash))
yield call(waitForTx, transaction.hash)
yield put(closeModal('EnsMapAddressModal'))
Expand Down
77 changes: 76 additions & 1 deletion src/modules/ens/selectors.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { RootState } from 'modules/common/types'
import { getExternalNames, getExternalNamesForConnectedWallet, getExternalNamesForWallet } from './selectors'
import { TransactionState } from 'decentraland-dapps/dist/modules/transaction/reducer'
import { Transaction, TransactionStatus } from 'decentraland-dapps/dist/modules/transaction/types'
import { getExternalNames, getExternalNamesForConnectedWallet, getExternalNamesForWallet, isWaitingTxSetAddress } from './selectors'
import { ENSState } from './reducer'
import { SET_ENS_ADDRESS_SUCCESS, SET_ENS_CONTENT_SUCCESS } from './actions'

let state: RootState
let wallet1: string
Expand Down Expand Up @@ -109,3 +112,75 @@ describe('when getting the external names for a provided wallet', () => {
})
})
})

describe('when using isWaitingTxSetAddress selector', () => {
describe('and there are no pending transactions', () => {
beforeEach(() => {
state = {
transaction: { data: [], loading: [], error: null } as TransactionState,
wallet: {
data: {
address: wallet1
}
}
} as RootState
})
it('should return false', () => {
expect(isWaitingTxSetAddress(state)).toEqual(false)
})
})

describe('and there are pending transactions', () => {
describe('and the transaction actionType is SET_ENS_ADDRESS_SUCCESS', () => {
beforeEach(() => {
state = {
transaction: {
data: [
{
actionType: SET_ENS_ADDRESS_SUCCESS,
status: TransactionStatus.PENDING,
from: wallet1
} as Transaction
],
loading: [],
error: null
} as TransactionState,
wallet: {
data: {
address: wallet1
}
}
} as RootState
})
it('should return true', () => {
expect(isWaitingTxSetAddress(state)).toEqual(true)
})
})

describe('and the transaction actionType is not SET_ENS_ADDRESS_SUCCESS', () => {
beforeEach(() => {
state = {
transaction: {
data: [
{
actionType: SET_ENS_CONTENT_SUCCESS,
status: TransactionStatus.PENDING,
from: wallet1
} as Transaction
],
loading: [],
error: null
} as TransactionState,
wallet: {
data: {
address: wallet1
}
}
} as RootState
})
it('should return false', () => {
expect(isWaitingTxSetAddress(state)).toEqual(false)
})
})
})
})
2 changes: 1 addition & 1 deletion src/modules/translation/languages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@
"use_as_alias": "Use as Alias",
"add_to_avatar": "Add to Avatar",
"link_to_address": "Link to an Ethereum Address",
"assign_to_land": "Assign to Land o WORLDs"
"assign_to_land": "Assign to Land or World"
},
"empty_names": "It looks like you don't have any Names.{br} {link} to get started.",
"items": "{count} {count, plural, one {result} other {results}}",
Expand Down
Loading

0 comments on commit 55efe05

Please sign in to comment.