Skip to content

Commit

Permalink
improve web test (#415)
Browse files Browse the repository at this point in the history
* improve web test

* fix ci

* fix web-test tests

* fix lint
  • Loading branch information
qiweiii authored Sep 28, 2023
1 parent 9b9bcd1 commit 6701b30
Show file tree
Hide file tree
Showing 13 changed files with 1,521 additions and 97 deletions.
4 changes: 2 additions & 2 deletions packages/core/src/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
import { defaultLogger } from './logger'
import { openDb } from './db'

type Options = {
export type SetupOptions = {
endpoint?: string
block?: string | number | null
genesis?: string | Genesis
Expand All @@ -35,7 +35,7 @@ type Options = {
maxMemoryBlockCount?: number
}

export const setup = async (options: Options) => {
export const setup = async (options: SetupOptions) => {
let provider: ProviderInterface
if (options.genesis) {
if (typeof options.genesis === 'string') {
Expand Down
22 changes: 7 additions & 15 deletions packages/web-test/index.html
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
</head>
<body>
<div style="position: absolute; top: 10px; right: 10px">
<a href="/chopsticks/docs">
<button>Go to docs</button>
</a>
</div>

<pre>Open console to access <u>chain</u></pre>
<div id="app" style="font: 16px monospace">Loading...</div>
<div style="display: flex; flex-direction: column; align-items: start">
<pre>Caller 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY</pre>
<textarea placeholder="Call" id="extrinsic" style="font: 16px monospace"></textarea>
<input type="button" id="submit" value="Dry Run Call" />
<pre id="result" style="font: 16px monospace"></pre>
</div>
<script type="module">
import { Buffer } from 'buffer'
window.Buffer = Buffer
</script>
<script type="module" src="src/index.ts"></script>

<div id="root"></div>
<script type="module" src="src/index.tsx"></script>
</body>
</html>
16 changes: 13 additions & 3 deletions packages/web-test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,25 @@
"build": "npx vite build",
"vite:serve": "npx vite --port 3000 --host",
"vite:preview": "npx vite preview --port 3000",
"parcel:serve": "npx parcel serve index.html --port 3000",
"test": "npx playwright test"
"parcel:serve": "parcel serve index.html --port 3000",
"test": "playwright test"
},
"dependencies": {
"@acala-network/chopsticks-core": "workspace:*"
"@acala-network/chopsticks-core": "workspace:*",
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@mui/material": "^5.14.10",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@playwright/test": "^1.37.1",
"@types/react": "^18",
"@types/react-dom": "^18",
"@vitejs/plugin-react": "^4.1.0",
"crypto-browserify": "^3.12.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"path-browserify": "^1.0.1",
"stream-browserify": "^3.0.0",
"typescript": "^5.1.6"
Expand Down
255 changes: 255 additions & 0 deletions packages/web-test/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
import {
Alert,
Box,
CircularProgress,
Container,
FormControl,
Input,
InputLabel,
Button as MuiBtn,
TextField,
Typography,
} from '@mui/material'
import { HexString } from '@polkadot/util/types'
import { setStorage, setup } from '@acala-network/chopsticks-core'
import { styled } from '@mui/system'
import { useEffect, useState } from 'react'
import type { SetupOptions } from '@acala-network/chopsticks-core'

const DocsLink = styled('a')`
position: absolute;
top: 16px;
right: 10px;
`

const Button = styled(MuiBtn)`
border-radius: 8px;
padding: 0.4em 0.8em;
font-weight: 500;
font-family: inherit;
cursor: pointer;
transition: border-color 0.25s;
`

const BlocksContainer = styled('div')`
width: 100%;
display: flex;
flex-direction: column;
justify-content: start;
font: 16px monospace;
overflow-x: scroll;
padding: 5px;
`

const DryRunTextArea = styled(TextField)({
width: '100%',
})

const Pre = styled('pre')`
max-width: 100%;
overflow: auto;
font-size: 14px;
margin: 4px 0;
padding: 4px 6px;
border-radius: 4px;
background-color: #ffe4efb7;
`

const Section = styled('section')`
min-height: 180px;
margin-top: 24px;
display: flex;
flex-direction: column;
align-items: start;
justify-content: start;
max-width: 100%;
`

const Code = styled('code')`
font-size: 14px;
margin: 0 2px;
padding: 4px 5px;
border-radius: 4px;
background-color: #ffe4efb7;
`

function App() {
const [dryRunLoading, setDryRunLoading] = useState(false)
const [chainLoading, setChainLoading] = useState(false)
const [extrinsic, setExtrinsic] = useState('')
const [dryRunResult, setDryRunResult] = useState('')
const [config, setConfig] = useState<SetupOptions>({
endpoint: 'wss://acala-rpc-0.aca-api.network',
block: 4_000_000,
})
const [blocks, setBlocks] = useState<{ number: number; hash: HexString }[]>([])

const resetState = () => {
setBlocks([])
setDryRunLoading(false)
setExtrinsic('0x0a000088dc3417d5058ec4b4503e0c12ea1a0a89be200fe98922423d4334014fa6b0ee0f0090c04bb6db2b')
setDryRunResult('')
}

const setupChain = async () => {
setChainLoading(true)
const chain = await setup({
endpoint: config.endpoint,
block: config.block,
mockSignatureHost: true,
db: 'cache',
})
globalThis.chain = chain

await setStorage(chain, {
System: {
Account: [
[
['5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY'],
{
providers: 1,
data: {
free: '1000000000000000000',
},
},
],
],
},
})

setChainLoading(false)
setBlocks([{ number: chain.head.number, hash: chain.head.hash }])

// build a block
await chain.newBlock().catch(console.error)
setBlocks([...blocks, { number: chain.head.number, hash: chain.head.hash }])
}

useEffect(() => {
resetState()
setupChain()

return () => {
globalThis.chain?.api.disconnect()
globalThis.chain?.close()
}
}, [])

const handleDryRun = async () => {
setDryRunResult('')
setDryRunLoading(true)
const call = extrinsic.trim() as HexString
try {
const { outcome, storageDiff } = await globalThis.chain.dryRunExtrinsic({
call,
address: '5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY',
})
setDryRunResult(JSON.stringify({ outcome: outcome.toHuman(), storageDiff }, null, 2))
} catch (e) {
setDryRunResult((e as Error).toString())
}
setDryRunLoading(false)
}

const handleSaveConfig = async () => {
await chain.api.disconnect()
await chain.close()
resetState()
setupChain()
}

return (
<Container sx={{ mt: 2, width: 700, maxWidth: '70vw' }}>
<DocsLink href="/chopsticks/docs">
<Button variant="outlined">Go to docs</Button>
</DocsLink>

<Alert severity="info" sx={{ borderRadius: 2 }}>
Open console to access <Code>chain</Code>
</Alert>

<Section sx={{ minHeight: 100 }}>
<Typography variant="h5" component="h2">
Configuration
</Typography>
<FormControl variant="standard" sx={{ width: '100%', mt: 1 }}>
<InputLabel shrink htmlFor="block-input">
Block Number or Hash
</InputLabel>
<Input
id="block-input"
placeholder="4000000"
value={config.block}
onChange={(e) => setConfig({ ...config, block: e.target.value })}
/>
</FormControl>
<FormControl variant="standard" sx={{ width: '100%', mt: 1 }}>
<InputLabel shrink htmlFor="endpoint-input">
API Url
</InputLabel>
<Input
id="endpoint-input"
placeholder="wss://acala-rpc-0.aca-api.network"
value={config.endpoint}
onChange={(e) => setConfig({ ...config, endpoint: e.target.value })}
/>
</FormControl>
<Button
variant="outlined"
disabled={chainLoading || !globalThis.chain}
onClick={handleSaveConfig}
sx={{ mt: 1 }}
>
Save
{chainLoading && (
<Box sx={{ display: 'flex', ml: 1 }}>
<CircularProgress size={13} />
</Box>
)}
</Button>
</Section>

<Section id="blocks-section">
<Typography variant="h5" component="h2">
Blocks
</Typography>
<BlocksContainer>
{blocks.map((block) => (
<Pre key={block.number}>
{block.number} {block.hash}
</Pre>
))}
</BlocksContainer>
</Section>

<Section id="extrinsic-section">
<Typography variant="h5" component="h2">
Dry Run
</Typography>
<Pre>Caller 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY</Pre>
<DryRunTextArea
label="Extrinsic"
value={extrinsic}
multiline
minRows={4}
sx={{ mt: 1 }}
onChange={(e) => {
setExtrinsic(e.target.value)
}}
/>
<Button
variant="outlined"
onClick={handleDryRun}
disabled={dryRunLoading || chainLoading || !globalThis.chain}
sx={{ mt: 1, mb: 1 }}
>
Dry Run Call
</Button>
{dryRunResult && <Pre sx={{ fontSize: 13 }}>{dryRunResult}</Pre>}
{dryRunLoading && <Pre>Loading dry run result...</Pre>}
</Section>
</Container>
)
}

export default App
11 changes: 11 additions & 0 deletions packages/web-test/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
}

body {
margin: 0;
display: flex;
min-height: 100vh;
}
Loading

0 comments on commit 6701b30

Please sign in to comment.