Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into format-abi-methods
Browse files Browse the repository at this point in the history
  • Loading branch information
negar-abbasi committed Sep 6, 2024
2 parents 66920be + 27e2ff8 commit 1ff1ba9
Show file tree
Hide file tree
Showing 24 changed files with 472 additions and 142 deletions.
12 changes: 12 additions & 0 deletions src/features/accounts/pages/account-page.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ import { assetResultMother } from '@/tests/object-mother/asset-result'
import { refreshButtonLabel } from '@/features/common/components/refresh-button'
import { algod } from '@/features/common/data/algo-client'

vi.mock('@/features/common/data/algo-client', async () => {
const original = await vi.importActual('@/features/common/data/algo-client')
return {
...original,
algod: {
accountInformation: vi.fn().mockReturnValue({
do: vi.fn().mockReturnValue({ then: vi.fn() }),
}),
},
}
})

describe('account-page', () => {
describe('when rendering an account using a invalid address', () => {
it('should render an error message', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import { afterEach, beforeEach, describe, expect, it, vitest } from 'vitest'
import { executeComponentTest } from '@/tests/test-component'
import SampleSixAppSpec from '@/tests/test-app-specs/sample-six.arc32.json'
import { fireEvent, getByLabelText, getByText, render, waitFor } from '@/tests/testing-library'
import { Arc32AppSpec } from '../data/types'
import { deployAppLabel, deployButtonLabel } from '@/features/app-interfaces/components/labels'
import { algorandFixture } from '@algorandfoundation/algokit-utils/testing'
import { CreateAppInterfaceDialogBody } from '@/features/app-interfaces/components/create-app-interface-dialog-body'
import { selectOption } from '@/tests/utils/select-option'
import { setWalletAddressAndSigner } from '@/tests/utils/set-wallet-address-and-signer'

describe('create-app-interface-dialog-body', () => {
const localnet = algorandFixture()
beforeEach(localnet.beforeEach, 10e6)
afterEach(() => {
vitest.clearAllMocks()
})

describe('when deploying an app spec that requires template parameters', () => {
const appSpec = SampleSixAppSpec as Arc32AppSpec

beforeEach(async () => {
await setWalletAddressAndSigner(localnet)
})

it('succeeds when all fields have been correctly supplied', () => {
return executeComponentTest(
() => {
return render(<CreateAppInterfaceDialogBody onSuccess={() => {}} />)
},
async (component, user) => {
const appSpecFileInput = await component.findByLabelText(/JSON app spec file/)
await user.upload(appSpecFileInput, new File([JSON.stringify(appSpec)], 'app.json', { type: 'application/json' }))

const deployAppButton = await waitFor(() => {
const button = component.getByRole('button', { name: deployAppLabel })
expect(button).toBeDefined()
expect(button).not.toBeDisabled()
return button!
})
await user.click(deployAppButton)

const versionInput = await waitFor(() => {
const input = component.getByLabelText(/Version/)
expect(input).toBeDefined()
return input!
})
fireEvent.input(versionInput, {
target: { value: '1.0.0' },
})

await selectOption(component.container, user, /On Update/, 'Fail')
await selectOption(component.container, user, /On Schema Break/, 'Fail')

const someStringTemplateParamDiv = await findParentDiv(component.container, 'SOME_STRING')
await selectOption(someStringTemplateParamDiv, user, /Type/, 'String')
const someStringInput = getByLabelText(someStringTemplateParamDiv, /Value/)
fireEvent.input(someStringInput, {
target: { value: 'some-string' },
})

const someBytesTemplateParamDiv = await findParentDiv(component.container, 'SOME_BYTES')
await selectOption(someBytesTemplateParamDiv, user, /Type/, 'Uint8Array')
const someBytesInput = getByLabelText(someBytesTemplateParamDiv!, /Value/)
fireEvent.input(someBytesInput, {
target: { value: 'AQIDBA==' },
})

const someNumberTemplateParamDiv = await findParentDiv(component.container, 'SOME_NUMBER')
await selectOption(someNumberTemplateParamDiv, user, /Type/, 'Number')
const someNumberInput = getByLabelText(someNumberTemplateParamDiv!, /Value/)
fireEvent.input(someNumberInput, {
target: { value: '3' },
})

const deployButton = await waitFor(() => {
const button = component.queryByRole('button', { name: deployButtonLabel })
expect(button).toBeDefined()
return button!
})
await user.click(deployButton)

await waitFor(() => {
const requiredValidationMessages = component.queryAllByText('Required')
expect(requiredValidationMessages.length).toBe(0)
})

await waitFor(() => {
const errorMessage = component.queryByRole('alert', { name: 'error-message' })
expect(errorMessage).toBeNull()
})

await waitFor(() => {
const input = component.getByLabelText(/Application ID/)
expect(input).toBeDefined()
expect(input).toHaveValue()
return input!
})
}
)
})
})
})

const findParentDiv = async (component: HTMLElement, label: string) => {
return await waitFor(() => {
const div = getByText(component, label)
return div.parentElement!
})
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { afterEach, beforeEach, describe, expect, it, vi, vitest } from 'vitest'
import { algorandFixture } from '@algorandfoundation/algokit-utils/testing'
import SampleSixAppSpec from '@/tests/test-app-specs/sample-six.arc32.json'
import { Arc32AppSpec } from '@/features/app-interfaces/data/types'
import { executeComponentTest } from '@/tests/test-component'
import { render, waitFor } from '@/tests/testing-library'
import { CreateAppInterfaceForm } from '@/features/app-interfaces/components/create-app-interface-form'
import { deployAppLabel } from '@/features/app-interfaces/components/labels'
import { setWalletAddressAndSigner } from '@/tests/utils/set-wallet-address-and-signer'
import { useWallet } from '@txnlab/use-wallet'

describe('create-app-interface-form', () => {
const appSpec = SampleSixAppSpec as Arc32AppSpec

const localnet = algorandFixture()
beforeEach(localnet.beforeEach, 10e6)
afterEach(() => {
vitest.clearAllMocks()
})

describe('when a wallet is connected', () => {
beforeEach(async () => {
await setWalletAddressAndSigner(localnet)
})

it('the button to deploy the app is enabled', () => {
return executeComponentTest(
() => {
return render(<CreateAppInterfaceForm appSpec={appSpec} appSpecFile={new File([], 'app.json')} onSuccess={() => {}} />)
},
async (component) => {
await waitFor(() => {
const deployAppButton = component.getByRole('button', { name: deployAppLabel })
expect(deployAppButton).toBeEnabled()
})
}
)
})
})

describe('when a wallet is not connected', () => {
beforeEach(async () => {
const original = await vi.importActual<{ useWallet: () => ReturnType<typeof useWallet> }>('@txnlab/use-wallet')
vi.mocked(useWallet).mockImplementation(() => {
return {
...original.useWallet(),
activeAddress: undefined,
isActive: false,
isReady: true,
}
})
})

it('the button to deploy the app is disabled', () => {
return executeComponentTest(
() => {
return render(<CreateAppInterfaceForm appSpec={appSpec} appSpecFile={new File([], 'app.json')} onSuccess={() => {}} />)
},
async (component) => {
await waitFor(() => {
const deployAppButton = component.getByRole('button', { name: deployAppLabel })
expect(deployAppButton).toBeDisabled()
})
}
)
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { FormFieldHelper } from '@/features/forms/components/form-field-helper'
import { useFormContext, useWatch } from 'react-hook-form'
import { useCreateAppInterfaceStateMachine } from '@/features/app-interfaces/data'
import { Button } from '@/features/common/components/button'
import { deployToNetworkLabel } from '@/features/app-interfaces/components/labels'
import { deployAppLabel } from '@/features/app-interfaces/components/labels'
import { isArc32AppSpec, isArc4AppSpec } from '@/features/common/utils'
import { useLoadableActiveWalletAccount } from '@/features/wallet/data/active-wallet'
import { numberSchema } from '@/features/forms/data/common'
Expand Down Expand Up @@ -166,10 +166,10 @@ function FormInner({ helper, appSpec }: FormInnerProps) {
disabled={deployButtonStatus.disabled}
disabledReason={deployButtonStatus.reason}
className="w-fit"
aria-label={deployToNetworkLabel}
aria-label={deployAppLabel}
onClick={onDeployButtonClick}
>
{deployToNetworkLabel}
{deployAppLabel}
</Button>
</div>
</div>
Expand Down
15 changes: 8 additions & 7 deletions src/features/app-interfaces/components/deploy-app-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { FormFieldHelper } from '@/features/forms/components/form-field-helper'
import { Label } from '@/features/common/components/label'
import { Fieldset } from '@/features/forms/components/fieldset'
import { base64ToBytes } from '@/utils/base64-to-bytes'
import { deployButtonLabel } from '@/features/app-interfaces/components/labels'

type Props = {
className?: string
Expand Down Expand Up @@ -80,7 +81,7 @@ const getTealTemplateParams = (names: string[], formData: DeployAppFormData) =>

export function DeployAppForm({ className, appSpec }: Props) {
const [_, send] = useCreateAppInterfaceStateMachine()
const { signer, activeAccount } = useWallet()
const { signer, activeAddress } = useWallet()

const templateParamNames = useMemo(() => {
const approvalTemplateParams = getTemplateParamNames(appSpec.source?.approval ?? '')
Expand All @@ -92,10 +93,10 @@ export function DeployAppForm({ className, appSpec }: Props) {
async (values: DeployAppFormData) => {
invariant(appSpec.source.approval, 'Approval program is not set')
invariant(appSpec.source.clear, 'Clear program is not set')
invariant(activeAccount, 'No active wallet account is available')
invariant(activeAddress, 'No active wallet account is available')

const signerAccount = {
addr: activeAccount.address,
addr: activeAddress,
signer,
}

Expand Down Expand Up @@ -126,7 +127,7 @@ export function DeployAppForm({ className, appSpec }: Props) {
return Number(deployAppResult.appId)
},
[
activeAccount,
activeAddress,
appSpec.source.approval,
appSpec.source.clear,
appSpec.state.global.num_byte_slices,
Expand Down Expand Up @@ -169,7 +170,7 @@ export function DeployAppForm({ className, appSpec }: Props) {
formAction={
<FormActions>
<CancelButton onClick={onCancel} className="w-28" />
<SubmitButton className="w-28">Deploy</SubmitButton>
<SubmitButton className="w-28">{deployButtonLabel}</SubmitButton>
</FormActions>
}
defaultValues={{
Expand Down Expand Up @@ -257,7 +258,7 @@ export function TemplateParamForm({ className, name, index }: TemplateParamFormP
{helper.selectField({
field: 'type',
label: 'Type',
className: ' content-start',
className: 'content-start',
options: [
{ value: TemplateParamType.String, label: 'String' },
{ value: TemplateParamType.Number, label: 'Number' },
Expand All @@ -267,7 +268,7 @@ export function TemplateParamForm({ className, name, index }: TemplateParamFormP
{helper.textField({
field: 'value',
label: 'Value',
className: ' content-start',
className: 'content-start',
helpText: helpText,
})}
</div>
Expand Down
3 changes: 2 additions & 1 deletion src/features/app-interfaces/components/labels.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export const methodsLabel = 'Methods'
export const appIdLabel = 'App ID'
export const createAppInterfaceLabel = 'Create App Interface'
export const deleteAppInterfaceLabel = 'Delete App Interface'
export const deployToNetworkLabel = 'Deploy App'
export const deployAppLabel = 'Deploy App'
export const deployButtonLabel = 'Deploy'
4 changes: 2 additions & 2 deletions src/features/app-interfaces/data/write.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { useAtomCallback } from 'jotai/utils'
import { useCallback } from 'react'
import { invariant } from '@/utils/invariant'
import { createTimestamp } from '@/features/common/data'
import { getAppInterfaces } from '@/features/app-interfaces/data/index'
import { getAppInterfaces } from '@/features/app-interfaces/data'

export type AppSpecDetails = {
applicationId: ApplicationId
Expand Down Expand Up @@ -56,7 +56,7 @@ export const useCreateAppInterface = () => {
)
}

const createMachine = () =>
export const createMachine = () =>
setup({
types: {
context: {} as {
Expand Down
12 changes: 12 additions & 0 deletions src/features/applications/components/application-program.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@ import { ApplicationProgram, base64ProgramTabLabel, tealProgramTabLabel } from '
import { executeComponentTest } from '@/tests/test-component'
import { algod } from '@/features/common/data/algo-client'

vi.mock('@/features/common/data/algo-client', async () => {
const original = await vi.importActual('@/features/common/data/algo-client')
return {
...original,
algod: {
disassemble: vi.fn().mockReturnValue({
do: vi.fn(),
}),
},
}
})

describe('application-program', () => {
describe('when rendering an application program', () => {
const tabListName = 'test'
Expand Down
28 changes: 28 additions & 0 deletions src/features/applications/pages/application-page.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,34 @@ import { AppInterfaceEntity, dbConnectionAtom } from '@/features/common/data/ind
import { writeAppInterface } from '@/features/app-interfaces/data'
import SampleSevenAppSpec from '@/tests/test-app-specs/sample-seven.arc32.json'
import { AppSpecStandard, Arc32AppSpec } from '@/features/app-interfaces/data/types'
import { searchTransactionsMock } from '@/tests/setup/mocks'

vi.mock('@/features/common/data/algo-client', async () => {
const original = await vi.importActual('@/features/common/data/algo-client')
return {
...original,
algod: {
getApplicationByID: vi.fn().mockReturnValue({
do: vi.fn().mockReturnValue({ then: vi.fn() }),
}),
},
indexer: {
lookupApplications: vi.fn().mockReturnValue({
includeAll: vi.fn().mockReturnValue({
do: vi.fn().mockReturnValue({ then: vi.fn() }),
}),
}),
searchForApplicationBoxes: vi.fn().mockReturnValue({
nextToken: vi.fn().mockReturnValue({
limit: vi.fn().mockReturnValue({
do: vi.fn().mockReturnValue({ then: vi.fn() }),
}),
}),
}),
searchForTransactions: vi.fn().mockImplementation(() => searchTransactionsMock),
},
}
})

describe('application-page', () => {
describe('when rendering an application using an invalid application Id', () => {
Expand Down
10 changes: 10 additions & 0 deletions src/features/assets/components/asset-transaction-history.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ import { getAllByRole } from '@testing-library/dom'
import { ANY_NUMBER, ANY_STRING, searchTransactionsMock } from '@/tests/setup/mocks'
import { RenderResult } from '@testing-library/react'

vi.mock('@/features/common/data/algo-client', async () => {
const original = await vi.importActual('@/features/common/data/algo-client')
return {
...original,
indexer: {
searchForTransactions: vi.fn().mockImplementation(() => searchTransactionsMock),
},
}
})

describe('asset-transaction-history', () => {
const asset = assetResultMother['testnet-642327435']().build()

Expand Down
Loading

0 comments on commit 1ff1ba9

Please sign in to comment.