Skip to content
10 changes: 10 additions & 0 deletions packages/kusama/src/assetHubKusama.system.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { assetHubKusama, kusama } from '@e2e-test/networks/chains'
import { type RelayTestConfig, registerTestTree, systemE2ETestsViaRelay } from '@e2e-test/shared'

const testConfig: RelayTestConfig = {
testSuiteName: 'Kusama AssetHub System',
addressEncoding: 0,
blockProvider: 'Local',
Copy link
Collaborator

Choose a reason for hiding this comment

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

This needs to be ParaTestConfig, and the block provider is non-local - asset hub scheduler agendas will use the relay chain's block number as their key.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have added both scenarios:

  • using scheduler on relay --> local block provider (from relay perspective)
  • using scheduler on AH (post-AHM) --> NonLocal provider in that case

}

registerTestTree(systemE2ETestsViaRelay(kusama, assetHubKusama, testConfig))
10 changes: 10 additions & 0 deletions packages/kusama/src/bridgeHubKusama.system.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { bridgeHubKusama, kusama } from '@e2e-test/networks/chains'
import { type RelayTestConfig, registerTestTree, systemE2ETestsViaRelay } from '@e2e-test/shared'

const testConfig: RelayTestConfig = {
testSuiteName: 'Kusama BridgeHub System',
addressEncoding: 0,
blockProvider: 'Local',
}

registerTestTree(systemE2ETestsViaRelay(kusama, bridgeHubKusama, testConfig))
10 changes: 10 additions & 0 deletions packages/kusama/src/coretimeKusama.system.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { coretimeKusama, kusama } from '@e2e-test/networks/chains'
import { type RelayTestConfig, registerTestTree, systemE2ETestsViaRelay } from '@e2e-test/shared'

const testConfig: RelayTestConfig = {
testSuiteName: 'Kusama Coretime System',
addressEncoding: 0,
blockProvider: 'Local',
}

registerTestTree(systemE2ETestsViaRelay(kusama, coretimeKusama, testConfig))
10 changes: 10 additions & 0 deletions packages/kusama/src/encointerKusama.system.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { encointerKusama, kusama } from '@e2e-test/networks/chains'
import { type RelayTestConfig, registerTestTree, systemE2ETestsViaRelay } from '@e2e-test/shared'

const testConfig: RelayTestConfig = {
testSuiteName: 'Kusama Encointer System',
addressEncoding: 0,
blockProvider: 'Local',
}

registerTestTree(systemE2ETestsViaRelay(kusama, encointerKusama, testConfig))
10 changes: 10 additions & 0 deletions packages/kusama/src/kusama.system.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { kusama } from '@e2e-test/networks/chains'
import { type RelayTestConfig, registerTestTree, systemE2ETests } from '@e2e-test/shared'

const testConfig: RelayTestConfig = {
testSuiteName: 'Kusama System',
addressEncoding: 0,
blockProvider: 'Local',
}

registerTestTree(systemE2ETests(kusama, testConfig))
10 changes: 10 additions & 0 deletions packages/kusama/src/peopleKusama.system.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { kusama, peopleKusama } from '@e2e-test/networks/chains'
import { type RelayTestConfig, registerTestTree, systemE2ETestsViaRelay } from '@e2e-test/shared'

const testConfig: RelayTestConfig = {
testSuiteName: 'Kusama People System',
addressEncoding: 0,
blockProvider: 'Local',
}

registerTestTree(systemE2ETestsViaRelay(kusama, peopleKusama, testConfig))
10 changes: 10 additions & 0 deletions packages/polkadot/src/assetHubPolkadot.system.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { assetHubPolkadot, polkadot } from '@e2e-test/networks/chains'
import { type RelayTestConfig, registerTestTree, systemE2ETestsViaRelay } from '@e2e-test/shared'

const testConfig: RelayTestConfig = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Similar as for Kusama, I have added both scenarios:

  • using scheduler on relay --> Local block provider (from relay perspective)
  • (to be uncommented post-AHM) using scheduler on AH --> NonLocal provider in that case

testSuiteName: 'Polkadot AssetHub System',
addressEncoding: 0,
blockProvider: 'Local',
}

registerTestTree(systemE2ETestsViaRelay(polkadot, assetHubPolkadot, testConfig))
10 changes: 10 additions & 0 deletions packages/polkadot/src/bridgeHubPolkadot.system.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { bridgeHubPolkadot, polkadot } from '@e2e-test/networks/chains'
import { type RelayTestConfig, registerTestTree, systemE2ETestsViaRelay } from '@e2e-test/shared'

const testConfig: RelayTestConfig = {
testSuiteName: 'Polkadot Collectives System',
addressEncoding: 0,
blockProvider: 'Local',
}

registerTestTree(systemE2ETestsViaRelay(polkadot, bridgeHubPolkadot, testConfig))
10 changes: 10 additions & 0 deletions packages/polkadot/src/collectivesPolkadot.system.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { collectivesPolkadot, polkadot } from '@e2e-test/networks/chains'
import { type RelayTestConfig, registerTestTree, systemE2ETestsViaRelay } from '@e2e-test/shared'

const testConfig: RelayTestConfig = {
testSuiteName: 'Polkadot Collectives System',
addressEncoding: 0,
blockProvider: 'Local',
}

registerTestTree(systemE2ETestsViaRelay(polkadot, collectivesPolkadot, testConfig))
10 changes: 10 additions & 0 deletions packages/polkadot/src/coretimePolkadot.system.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { coretimePolkadot, polkadot } from '@e2e-test/networks/chains'
import { type RelayTestConfig, registerTestTree, systemE2ETestsViaRelay } from '@e2e-test/shared'

const testConfig: RelayTestConfig = {
testSuiteName: 'Polkadot Coretime System',
addressEncoding: 0,
blockProvider: 'Local',
}

registerTestTree(systemE2ETestsViaRelay(polkadot, coretimePolkadot, testConfig))
10 changes: 10 additions & 0 deletions packages/polkadot/src/peoplePolkadot.system.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { peoplePolkadot, polkadot } from '@e2e-test/networks/chains'
import { type RelayTestConfig, registerTestTree, systemE2ETestsViaRelay } from '@e2e-test/shared'

const testConfig: RelayTestConfig = {
testSuiteName: 'Polkadot People System',
addressEncoding: 0,
blockProvider: 'Local',
}

registerTestTree(systemE2ETestsViaRelay(polkadot, peoplePolkadot, testConfig))
10 changes: 10 additions & 0 deletions packages/polkadot/src/polkadot.system.e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { polkadot } from '@e2e-test/networks/chains'
import { type RelayTestConfig, registerTestTree, systemE2ETests } from '@e2e-test/shared'

const testConfig: RelayTestConfig = {
testSuiteName: 'Polkadot System',
addressEncoding: 0,
blockProvider: 'Local',
}

registerTestTree(systemE2ETests(polkadot, testConfig))
111 changes: 110 additions & 1 deletion packages/shared/src/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import type { StorageValues } from '@acala-network/chopsticks'
import { sendTransaction, setupCheck } from '@acala-network/chopsticks-testing'

import { defaultAccounts } from '@e2e-test/networks'
import { type Chain, defaultAccounts } from '@e2e-test/networks'

import type { ApiPromise } from '@polkadot/api'
import type { KeyringPair } from '@polkadot/keyring/types'
import type { EventRecord } from '@polkadot/types/interfaces'
import type { PalletStakingValidatorPrefs } from '@polkadot/types/lookup'
import type { IsEvent } from '@polkadot/types/metadata/decorate/types'
import type { AnyTuple, Codec, IEvent } from '@polkadot/types/types'
import type { HexString } from '@polkadot/util/types'

import { assert, expect } from 'vitest'
Expand Down Expand Up @@ -440,3 +443,109 @@ export interface ParaTestConfig {
* Union type for all test configurations, whether relay or parachain.
*/
export type TestConfig = RelayTestConfig | ParaTestConfig

type ArgMatcher = unknown | ((actual: unknown) => boolean)

type EventMatchCriteria<T extends AnyTuple = AnyTuple, N = unknown> = {
type: IsEvent<T, N>
args?: { [K in keyof N]?: ArgMatcher }
}

/**
* Assert that specific Substrate events were emitted.
*
* Usage:
* - `type`: the event constructor (e.g. `api.events.system.CodeUpdated`)
* - `args` (optional): matchers for event fields
* - literal: compared via `.toString()`
* - function: `(value) => boolean`
*
* Examples:
*
* // Match by literal
* assertExpectedEvents(await api.query.system.events(), [
* { type: api.events.preimage.Noted, args: { hash_: preimageHash } }
* ])
*
* // Match with function
* assertExpectedEvents(await api.query.system.events(), [
* { type: api.events.scheduler.Dispatched, args: { result: (r) => r.isErr } }
* ])
*
* // Match by type only
* assertExpectedEvents(await api.query.system.events(), [
* { type: api.events.system.CodeUpdated }
* ])
*/
export function assertExpectedEvents(actualEvents: EventRecord[], expectedEvents: EventMatchCriteria[]): void {
const missing: string[] = []

for (const expected of expectedEvents) {
const { type, args: expectedArgs } = expected

const match = actualEvents.find(({ event }) => {
if (!type.is(event)) return false

if (!expectedArgs) return true

const namedArgs = (event as IEvent<Codec[]>).data as unknown as Record<string, unknown>

for (const [key, matcher] of Object.entries(expectedArgs)) {
const actualValue = namedArgs[key]

if (typeof matcher === 'function') {
if (!matcher(actualValue)) {
return false
}
} else {
if (matcher?.toString?.() !== actualValue?.toString?.()) {
return false
}
}
}

return true
})

if (!match) {
const name = type.meta?.name.toString() ?? '[unknown event]'
const argDesc = expectedArgs
? `${JSON.stringify(
Object.fromEntries(
Object.entries(expectedArgs).map(([k, v]) => [k, typeof v === 'function' ? '[Function]' : v?.toString()]),
),
)}`
: ''
missing.push(`Event type "${name}" with expected args: ${argDesc}`)
}
}

if (missing.length > 0) {
throw new Error(`Expected events not found:\n- ${missing.join('\n- ')}`)
}
}

/**
* Computes the XCM `MultiLocation` route from a source chain to a destination chain.
*
* @param from - The source chain (the chain initiating the XCM message).
* @param to - The destination chain (the chain intended to receive and execute the XCM message).
*/
export function getXcmRoute(from: Chain, to: Chain) {
let parents: number
let interior: any

if (from.isRelayChain) {
parents = 0
} else {
parents = 1
}

if (to.isRelayChain) {
interior = 'Here'
} else {
interior = { X1: [{ Parachain: to.paraId }] }
}

return { parents, interior }
}
1 change: 1 addition & 0 deletions packages/shared/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export * from './proxy.js'
export * from './scheduler.js'
export * from './setup.js'
export * from './staking.js'
export * from './system.js'
export * from './treasury.js'
export * from './types.js'
export * from './vesting.js'
Loading