{"id":19358410,"url":"https://github.com/paritytech/parachains-integration-tests","last_synced_at":"2025-09-03T01:39:38.956Z","repository":{"id":37824603,"uuid":"452317109","full_name":"paritytech/parachains-integration-tests","owner":"paritytech","description":"Tool to make Parachains integrations tests development easier and faster","archived":false,"fork":false,"pushed_at":"2024-06-03T09:59:09.000Z","size":33994,"stargazers_count":26,"open_issues_count":27,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-02T00:35:39.474Z","etag":null,"topics":["blockchain","kusama","parachains","polkadot","polkadot-development","polkadot-js","substrate"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/paritytech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-26T14:55:32.000Z","updated_at":"2025-08-24T02:06:01.000Z","dependencies_parsed_at":"2023-11-13T23:27:29.939Z","dependency_job_id":"dd3f237c-d0f3-4720-a989-62931194aa2c","html_url":"https://github.com/paritytech/parachains-integration-tests","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/paritytech/parachains-integration-tests","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paritytech%2Fparachains-integration-tests","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paritytech%2Fparachains-integration-tests/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paritytech%2Fparachains-integration-tests/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paritytech%2Fparachains-integration-tests/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/paritytech","download_url":"https://codeload.github.com/paritytech/parachains-integration-tests/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/paritytech%2Fparachains-integration-tests/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273377149,"owners_count":25094526,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-02T02:00:09.530Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blockchain","kusama","parachains","polkadot","polkadot-development","polkadot-js","substrate"],"created_at":"2024-11-10T07:11:40.055Z","updated_at":"2025-09-03T01:39:38.930Z","avatar_url":"https://github.com/paritytech.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Parachains Integration Tests  ✅\nSince the arrival of XCMP-Lite, communication between different consensus systems became a reality in the Polkadot ecosystem.  _Parachains Integration Tests_ is a tool that was created with the ambition of easing testing interactions between Substrate based blockchains.\n\nThis tool allows you to develop tests rapidly describing them in a YAML file. Behind the scenes, the YAML files are converted to [Mocha](https://mochajs.org/) tests with [Chai](https://www.chaijs.com/) assertions.\n\nIt can work alongside with [Zombienet](https://github.com/paritytech/zombienet) or you can run your tests against the testnet of your choice.\n\nUnder the `./examples` folder, this repository contains integration tests for the _System Parachains_. You can take them as examples of how to write tests with this tool.\n\n## Set Up\n### Requirements\n- `node v18` or higher.\n### Versioning\n- `v2.0.0` contains **BREAKING CHANGES**. Tests based on `^1.0.0` will stop working properly from `v2.0.0` onwards. Check the GitHub [release](https://github.com/paritytech/parachains-integration-tests/releases/tag/v2.0.0) for more info and how to migrate the tests.\n\n- `v2.3.0` contains **BREAKING CHANGES**. Polkadot Launch is not supported anymore.\n\n### Installation\nIt can be installed to be run in two different ways:\n- Installing the npm package globally\n  ```\n  yarn global add ts-node\n\n  yarn global add @parity/parachains-integration-tests\n  ```\n- From the repository\n  ```\n  yarn\n  ```\n\n## How to use\nThe tool implements a simple CLI.\n```\nparachains-integration-tests -m \u003cmode\u003e -c \u003cpath\u003e -t \u003cpath\u003e -to \u003cmillisecons\u003e -el \u003cmilliseconds\u003e -qd \u003cmilliseconds\u003e\n```\n- `-e`, `--env`:\n  - `prod`: for compiled TypeScript to Javascript (default)\n  - `dev`: for development environment in TypeScript\n- `-m`, `--mode`:\n  - `checker`: checks the format integtity of the yaml test files\n  - `test`: for running your tests (the checker will be autmatically run prior to the tests)\n  - `zombienet`: only deploy a Zombienet network\n  - `zombienet-test`: deploy a Zombienet testnet and run your tests against it\n- `-c`, `--config`: path to the Zombienet or Polkadot Launch config file.\n- `-t`, `--test`: path to the tests folder or to a single test yaml file. All files under the _path_ with a `yml` extension  will be run. To choose the order, is necessary to add an index in front of the file name. E.g: `0_my_test.yml`, `1_my_other_test.yml`\n- `-to`, `--timeout`: overrides the default Mocha tests timeout set to `300000`\n- `-el`, `--event-listener-timeout`: overrides the default event listener timeout set to `40000`\n- `-ad`, `--action-delay`: delay before state queries, rpc calls and extrinsics. Overrides the default delay set to `40000`. Some delay is necessary to make sure the state is already updated. In the case of extrinsics, it is also necessary until ID hashes are available in [XCM v3](https://github.com/paritytech/polkadot/pull/4756). Without an identifier, it is not possible to distinguish what XCM message event was triggered as a result of a specific extrinsic from another chain/context. For this reason, it is necessary to add a big delay between XCM messages, to avoid interferences from other unrelated events.\n- `-cl`, `--chain-logs`: path to the log file to redirect stdout and stderr from the testnets deployment tool, either Zombienet or Polkadot Launch.\n- `-tl`, `--test-logs`: path to the log file to redirect stdout and stderr from this testing tool.\n\nExamples:\n- **NPM package**\n  - Check the integrity of the tests format\n      ```\n      parachains-integration-tests -m checker -t \u003ctests_path\u003e\n      ```\n\n  - Run tests using other testnet\n      ```\n      parachains-integration-tests -m test -t \u003ctests_path\u003e\n      ```\n\n  - Only deploy a testnet with Zombienet\n      ```\n      parachains-integration-tests -m zombienet -c \u003czombienet_config_path\u003e\n      ```\n\n  - Run tests using Zombienet as testnet\n      ```\n      parachains-integration-tests -m zombienet-test -t \u003ctests_path\u003e -c \u003czombienet_config_path\u003e\n      ```\n\n- **From the repository**\n  - Check the integrity of the tests format\n      ```\n      yarn checker -t \u003ctests_path\u003e\n      ```\n\n  - Run tests using other testnet\n      ```\n      yarn test -t \u003ctests_path\u003e\n      ```\n\n  - Only deploy a testnet with Zombienet\n      ```\n      yarn zombienet -c \u003czombienet_config_path\u003e\n      ```\n\n  - Run tests using  as testnet\n      ```\n      yarn zombienet-test -t \u003ctests_path\u003e -c \u003czombienet_config_path\u003e\n      ```\n## Table of Contents\n- [YAML Schema](#yaml-schema)\n  * [Settings](#settings)\n  * [Tests](#tests)\n  * [Hook \u0026 It](#hook--it)\n  * [Action](#action)\n  * [Extrinsic](#extrinsic)\n  * [Event](#event)\n  * [Query](#query)\n  * [Rpc](#rpc)\n  * [Assert](#assert)\n  * [Custom](#custom)\n\n## YAML Schema\nIt is formed by two main sections: `settings` and `tests`.\n\n```yaml\nsettings:\n  # Declaration of the chains the tests should connect to\n  chains: # { [key: string]: Chain }\n  # Arbitrary declaration of constants to be used across the tests\n  variables: # { [key: string]: any }\n  # Calls that want to be encoded to be used in the tests\n  decodedCalls: # { [key: string]: Call }\n\ntests: # Describe[]\n```\n\n```typescript\nexport interface TestsConfig {\n  settings: Settings;\n  tests: Describe[];\n}\n```\n### Settings\n- `chains`: connection values for all the different chains we want to connect to. Defining `wsPort` should be enough unless you want to override the default `ws` URL (ws://localhost).\n\n- `variables`: section that allows you to define your own variables following the schema that better suits your test's logic.\n\n- `decodedCalls`: declaration of the different calls you want to calculate their encoded call hex value or use them inside a `batch` call. Each result is stored in a variable that will become available in the rest of the file ONLY after its declaration. The way to access those variables is appending a `$` symbol to the defined `decodedCalls` key. For instance, in the following example, the encoded call result for `my_call_id` will be accessible from `$my_call_id`. If you want to use the call inside a `batch` call, the attribute `encode: false` should be added. That attribute indicates if the call should be encoded or if it should be treated as `Submittable` Polkadot JS object.\n\nExample:\n```yaml\nsettings: # Settings\n  chains:\n    my_chain_id: \u0026relay_chain # a Relay Chain, for instance\n      wsPort: 9966\n      ws: ws://my-custom-url\n    my_other_chain_id: \u0026parachain # a Parachain, for instance\n      wsPort: 9988\n      # It is also possible to add the variables that you consider\n      # are useful and related to the chain\n      for_example_paraId: \u0026paraId 2000\n\n  variables:\n    my_variable: \u0026my_variable 0x0011\n    my_arbitrary_schema: \u0026my_schema\n      object:\n        a: 1\n        b: 2\n\n  decodedCalls:\n    my_call_id:\n        chain: *relay_chain\n        pallet: system\n        call: remark\n        args: [ *my_variable ]\n    my_call_id:\n        chain: *relay_chain\n        encode: false # Indicates the call will not be encoded and used instead as Submittable\n        pallet: system\n        call: remark\n        args: [ *my_variable ]\n```\n\n```typescript\ninterface Settings {\n  chains: { [key: string]: Chain };\n  variables: { [key: string]: any };\n  decodedCalls: { [key: string]: Call };\n}\n```\n\n```typescript\ninterface Chain {\n  wsPort: number;\n  ws?: string; // if 'undefined', it fallback to the default value -\u003e ws://localhost\n  paraId: number; // parachain id\n}\n```\n\n```typescript\ninterface Call {\n  chain: Chain;\n  sudo?: boolean; // if 'true', the call will be wrapped with 'sudo.sudo()'\n  pallet: string;\n  call: string;\n  args: any[];\n}\n```\n\n### Tests\nTests are formed by an array of _Describe_ interfaces. Tests can be nested through the `describes` attribute.\n\nExample:\n\n```yaml\ntests: # Describe[]\n  - name: My Describe\n    before: # Before[]\n      - name: 'before' description to console log\n        actions: [...]\n    beforeEach: ... # BeforeEach[]\n    after: ... # After[]\n    afterEach: ... # AfterEach[]\n    its: # It[]\n      - name: It should do something\n        actions: [...]\n    describes: # Describe[]\n      - name: My nested Describe\n\n  - name: My other Describe\n    its: [...] # It[]\n```\n\nInterfaces:\n```typescript\ninterface Describe {\n  name: string;\n  before?: Before[];\n  beforeEach?: BeforeEach[];\n  after?: After[];\n  afterEach?: AfterEach[];\n  its: It[];\n  describes?: Describe[]; // It is possible to nest Describes\n}\n```\n\n### Hook \u0026 It\nBoth have a similar interface. They are formed by a `name` for descriptions and by the `actions` attribute.\n\nThe available hooks are: `before`, `beforeEach`, `after` and `afterEach`\n\nExample:\n\n```yaml\ntests: # Describe[]\n  - name: My Describe\n    before: # Before[]\n      - name: 'before' description to console log\n        actions: [...] # Action[]\n      - name: another description for a 'before'\n        actions: [...] # Action[]\n    its: # It[]\n      - name: It should do something\n        actions: [...] # Action[]\n      - name: It should not do something\n        actions: [...] # Action[]\n    ...\n```\n\nInterfaces:\n```typescript\ntype Hook = Before | BeforeEach | After | AfterEach\n\n // Same for BeforeEach, After, AfterEach\ninterface Before {\n  name?: string; // optional description\n  actions: Action[];\n}\n```\n\n```typescript\ninterface It {\n  name: string;\n  actions: Action[];\n}\n```\n\n### Action\nThere are five available actions types that can be performed inside a _Hook_ or an _It_: `extrinsics`, `queries`, `rpcs`, `asserts` and `customs`. The order they are executed depends on the order they are defined in the _Action_ array. Since `actions` is an array, multiple actions of the same type can be declared.\n\nExample:\n\n```yaml\ntests: # Describe[]\n  - name: My Describe\n    before: # Before[]\n      - name: 'before' description to console log\n        actions: # Action[]\n          - extrinsics: [...] # Extrinsic[]\n          - queries: [...] # Query[]\n          - ...\n    its: # It[]\n      - name: It should do something\n        actions: # Action[]\n          - extrinsics: [...] # Extrinsic[]\n          - rpcs: [...] # RPC[]\n          - asserts: [...] # Assert[]\n          - customs: [...] # Custom[]\n          - queries: [...] # Query []\n          - asserts: [...] # Assert[]\n    ...\n```\n\nInterfaces:\n\n```typescript\nexport type ExtrinsicAction = {\n  extrinsics: Extrinsic[];\n}\n\nexport type QueryAction = {\n  queries: { [key: string]: Query };\n}\n\nexport type RpcAction = {\n  rpcs: { [key: string]: Rpc };\n}\n\nexport type AsserAction = {\n  asserts: { [key: string]: AssertOrCustom };\n}\n\nexport type CustomAction = {\n  customs: Custom[];\n}\n\nexport type Action = ExtrinsicAction | QueryAction | AsserAction | RpcAction | CustomAction;\n```\n\n### Extrinsic\nExtends the _Call_ interface adding two new attributes: `signer` (indispensable) and `events` (optional). A _Extrinsic_ by itself will not perform any chai assertion. Assertions are build based on the `events` that the extrinsic is expected to trigger. Each event defined under the `events` attribute will build and perform its corresponding chai assertion.\n\nExample:\n\n```yaml\nsettings:\n  chains:\n    relay_chain: \u0026relay_chain\n      wsPort: 9900\n    parachain: \u0026parachain\n      wsPort: 9910\n      paraId: \u0026id 2000\n\n  variables:\n    common:\n      require_weight_at_most: \u0026weight_at_most 1000000000\n    relay_chain:\n      signer: \u0026signer \n        uri: //Alice\n      parachain_destination: \u0026dest { v1: { 0, interior: { x1: { parachain: *id }}}}\n      my_variable: \u0026my_variable 0x0011\n\n  decodedCalls:\n    force_create_asset:\n      chain: *parachain\n      pallet: assets\n      call: forceCreate\n      args: [\n        1, # assetId\n        { # owner\n          Id: HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F\n        },\n        true, # isSufficient\n        1000 # minBalance\n      ]\n    to_be_batched:\n      chain: *relay_chain\n      encode: false # Indicates the call will not be encoded and used instead as Submittable instead\n      pallet: system\n      call: remark\n      args: [ *my_variable ]\n\ntests: # Describe[]\n  - name: My Describe\n    its: # It[]\n      - name: It should do something\n        actions: # Action[]\n          - extrinsics: # Extrinsic[]\n            - chain: *relay_chain # Chain\n              signer: *signer\n              sudo: true\n              pallet: xcmPallet\n              call: send\n              args: [\n                *ap_dest, # destination\n                {\n                  v2: [ # message\n                    {\n                      Transact: {\n                        originType: Superuser,\n                        requireWeightAtMost: *weight_at_most,\n                        call: $force_create_asset # encoded call hex\n                      }\n                    }\n                  ]\n                }\n              ]\n              events: [...]\n             - chain: *relay_chain # Chain\n                signer: *signer\n                pallet: utility\n                call: batchAll\n                args: [\n                  [$to_be_batched]\n                ]\n    ...\n```\n\nInterfaces:\n\n```typescript\ninterface Call {\n  encode?: boolean; // Indicates if the Call should be encoded\n  chain: Chain;\n  sudo?: boolean; // if 'true', the call will be wrapped with 'sudo.sudo()'\n  pallet: string;\n  call: string;\n  args: any[];\n}\n\ninterface Extrinsic extends Call {\n  signer: string;\n  delay?: number; // Overrides the default action delay\n  events: Event[];\n}\n```\n\n### Event\nIf the `chain` attribute is not defined, it means the event is expected to happen in the same chain context where the extrinsic was dispatched and as a result of it. Otherwise, the `chain` attribute referring to another context must be defined.\n\nDefault event listener timeout can be overridden by the `timeout` attribute.\n\nThere are two different and compatible ways (you can apply both at the same time) of checking if an event returns the expected values: comparing the \"whole\" `result`, or comparing by `atrributes`.\n\n- `result`: When the event is defined in the _runtime_ as a _Tuple_, the event result is returned as an ordered _array_ of its elements. In case it is defined as a _Struct_, the event result is returned as an _object_.\n\n  E.g:\n  - Tuple\n    ```rust\n    Sent(MultiLocation, MultiLocation, Xcm\u003c()\u003e) // Event from 'pallet_xcm'\n    ```\n    ```yaml\n    result: [..., ..., ...] # order and indexes matters\n    ```\n  - Struct\n    ```rust\n    Transfer { from: T::AccountId, to: T::AccountId, amount: T::Balance } // Event from 'pallet_balances'\n    ```\n    ```yaml\n    result: { from: ..., to: ..., amount: ... }\n    ```\n\n  `strict` is set to `false` by default. It allows to check if `result` is just contained in the event result instead of expecting a perfect match. For a _Tuple_ it means that the provided array is a subset (array items exist \u0026 order and index matter) of the event result array. For a _Struct_ it means that the provided object is also a subset (keys/values exist) of the event result object.\n- `attributes`: Event's attributes must be identified either by `type`, `key` or both. When the event is defined in the _runtime_ as a _Tuple_, the only way to identify the attributes is by their `type`. Be aware that in that case the order you declare the `attributes` in the test matters. That is because there could be multiple attributes with the same `type` in the _Tuple_. However, if the event is defined as a _Struct_, its attributes can be also identified by their `key`.\n\n  By setting `isRange: true` you are letting know to the tool that the expected value should be within the range defined in the `value` attribute. The expected `value`'s format is: `\u003clower_limit\u003e..\u003cupper_limit\u003e`.\n\n  In addition, a `threshold` attribute can be used to define an upper and lower limit the `value` attribute should be within. It is expecting a percentage value. E.g: `threshold: [10, 20]` means that the `value` can be 10% lower and 20% higher.\n  It can be used either for an `attribute` `value` or a `event` `result`. For assessing a `result` treshold should be an object where its keys are the fields to be assessed from `result`. Example below checking `Weight` values `ref_time` and `proof_size`.\n\n  For obvious reason, `isRange` and `threshold` can not be used at the same time. These features are especially useful when checking variables that often change such as _Weights_.\n\n  There is a special treatment for the attribute type `XcmV2TraitsOutcome`. Only in that case, `xcmOutput` and `value` can be set to replace an event `result` with the format `{ outcome: { \u003cxcmOutput\u003e: \u003cvalue\u003e }}`. Valid `xcmOutput` are `Complete`, `Incomplete` and `Error`.\n\nExample:\n\n```yaml\nsettings:\n  chains:\n    relay_chain: \u0026relay_chain\n      wsPort: 9900\n    parachain: \u0026parachain\n      wsPort: 9910\n  variables:\n    ...\n  encodedCalls:\n    my_encoded_call:\n      ...\n\ntests: # Describe[]\n  - name: My Describe\n    its: # It[]\n      - name: It should do something\n        actions: # Action[]\n          - extrinsics: # Extrinsic[]\n           - chain: *relay_chain\n              signer: *signer\n              sudo: true\n              pallet: xcmPallet\n              call: send\n              args: [\n                *dest, # destination\n                {\n                  v2: [ #message\n                    {\n                      Transact: {\n                        originType: Superuser,\n                        requireWeightAtMost: *weight_at_most,\n                        call: $my_encoded_call\n                      }\n                    }\n                  ]\n                }\n              ]\n              events: # Event[]\n                - name: sudo.Sudid\n                  attributes:\n                    - type: Result\u003cNull, SpRuntimeDispatchError\u003e\n                      key: sudoResult\n                      value: Ok\n                - name: xcmPallet.Sent\n                - name: dmpQueue.ExecutedDownward\n                  chain: *collectives_parachain\n                  threshold: { refTime: [10, 10], proofSize: [10, 10] }\n                  result: {\n                    outcome: { Complete: { refTime: '3,000,000,000', proofSize: '1,000,000' }}\n                  }\n                - name: polkadotXcm.Sent\n                  chain: *parachain\n                - name: ump.ExecutedUpward\n                  timeout: 40000\n                  attributes: # Attribute[]\n                    - type: XcmV2TraitsOutcome\n                      xcmOutcome: Complete\n                      isRange: true\n                      value: 4,000,000..5,000,000 # value should be within 4,000,000..5,000,000\n    ...\n```\n\nInterfaces:\n\n```typescript\ninterface Event {\n  chain: Chain;\n  name: string;\n  remote: boolean; // indicates the event is considered as a remote (different chain context)\n  timeout?: number; // overrides de default event listener timeout\n  result?: object; // Either {..} or [..]\n  strict: boolean;\n  attributes?: Attribute[];\n  threshold?: any;\n}\n```\n\n```typescript\ninterface Attribute {\n  type?: string;\n  key?: string;\n  isRange?: boolean; // indicates the value is a range\n  threshold: [number, number]; // defines the percentages a value can vary\n  value?: any;\n  xcmOutcome?: XcmOutcome; // only for 'XcmV2TraitsOutcome' type\n}\n```\n\n```typescript\nexport enum XcmOutcome {\n  Complete = 'Complete',\n  Incomplete = 'Incomplete',\n  Error = 'Error'\n}\n```\n\n### Query\nQuery the chain state. The result of the query will be stored in a new variable based on the key name of the _Query_. The variable naming follows the same format of `decodedCalls`. Therefore, for the following example, the result of the query is stored in: `$balance_sender_before`. The variable becomes available in the rest of the file ONLY after its declaration.\n\nExample:\n\n```yaml\nsettings:\n  chains:\n    relay_chain: \u0026relay_chain\n      wsPort: 9900\n\n  variables:\n    ...\n  encodedCalls:\n    ...\ntests: # Describe[]\n  - name: My Describe\n    before: # Before[]\n      - name: Get the balance of an account\n        actions: # Action[]\n          - queries: # { key: Query }\n              balance_sender_before:\n                chain: *relay_chain\n                pallet: system\n                call: account\n                args: [\n                  HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F\n                ]\n    its: [...]\n```\n\nInterfaces:\n\n```typescript\ninterface Query {\n  chain: Chain;\n  delay?: number;\n  pallet: string;\n  call: string;\n  args: any[];\n}\n```\n\n### Rpc\nRPC call to the chain's node. Same approach as _Query_. For the following example, the result of the RPC call will be stored in `$block`.\n\nExample:\n\n```yaml\nsettings:\n  chains:\n    relay_chain: \u0026relay_chain\n      wsPort: 9900\n\n  variables:\n    ...\n  encodedCalls:\n    ...\ntests: # Describe[]\n  - name: My Describe\n    before: # Before[]\n      - name: Get the last block\n        actions: # Action[]\n          - rpcs: # { key: Rpc }\n              block:\n                chain: *relay_chain\n                method: chain\n                call: getBlock\n                args: []\n                events: []\n    its: [...]\n```\n\nInterfaces:\n\n```typescript\ninterface Rpc {\n  chain: Chain;\n  delay?: number;\n  method: string;\n  call: string;\n  args: any[];\n  events?: Event[];\n}\n```\n\n### Assert\nUnlike _Query_ and _Rpc_ where their keys can be arbitrarily chosen to generate a new variable, _AssertOrCustom_ keys can only be chosen from a list of built-in asserts.\n- `equal`: it has a single attribute `args` which is expecting an array of two values to be `deepEqual()` compared.\n- `isNone`: the argument is null.\n  - `./src/asserts/isNone.ts`\n- `isSome`: the argument is not null.\n  - `./src/asserts/isSome.ts`\n-  `balanceDecreased`: compares balances queried with `system.account`. If `amount` and `fees` are not included as arguments, it will just check that `after` is lower than `before`\n    - `./src/asserts/balanceDecreased.ts`\n- `balanceIncreased`: compares balances queried with `system.account`. If `amount` and `fees`(only for XCM messages) are not included as arguments, it will just check that `after` is bigger than `before`\n  - `./src/asserts/balanceIncreased.ts`\n-  `assetsDecreased`: compares balances queried with `assets.account`. If `amount` and `fees` are not included as arguments, it will just check that `after` is lower than `before`\n    - `./src/asserts/assetsDecreased.ts`\n- `assetsIncreased`: compares balances queried with `assets.account`. If `amount` and `fees`(only for XCM messages) are not included as arguments, it will just check that `after` is bigger than `before`\n  - `./src/asserts/assetsIncreased.ts`\n- `custom`: assertion cases can be endless, therefore they are difficult to standardize. `custom` solves that issue providing the `path` argument. Its value should point to a file where the desired asserts are performed based on the provided `args`. It can not be any kind of file though, and it should export a specific function signature. To learn more about this files see [Custom](#custom). Notice that you will have to include a `tsconfig.json` file with `typeRoots` and `types` attributes pointing to your types in case of adding paths to a typescript file.\n\nThese methods are extensible opening a PR to include them:\n1. Add a new assertion key to `REGISTERED_ASSERTIONS` in `./src/constants.ts`\n2. Add a new assertion file under `./src/asserts`. The filename needs to match with the previously registered assertion key.\n\nExample:\n\n```yaml\nsettings:\n  chains:\n    relay_chain: \u0026relay_chain\n      wsPort: 9900\n\n  variables:\n    relay_chain:\n      sender: \u0026sender HNZata7iMYWmk5RvZRTiAsSDhV8366zq2YGb3tLH5Upf74F\n    ...\n  encodedCalls:\n    ...\ntests: # Describe[]\n  - name: My Describe\n    before: # Before[]\n      - name: Get the balance of an account before an event\n        actions:\n          - queries:\n              balance_sender_before:\n                chain: *relay_chain\n                pallet: system\n                call: account\n                args: [\n                  *sender\n                ]\n    after: # After[]\n      - name: Get the balance of an account after an event\n        actions:\n          - queries:\n              balance_sender_after:\n                chain: *relay_chain\n                pallet: system\n                call: account\n                args: [\n                  *sender\n                ]\n    its: # It[]\n      - name: Something happens here than modifies the balance\n        actions: [...]\n      - name: Should reduce the balance of the sender\n        actions: # Action[]\n          - asserts: # { [key: string]: AssertOrCustom }\n              customs:\n                path: ./asserts/checkSenderBalances.ts\n                args:\n                  {\n                    balances: {\n                      before: $balance_rc_sender_before,\n                      after: $balance_rc_sender_after,\n                    },\n                    amount: *amount,\n                  }\n              equal:\n                args: [true, true]\n```\n\nInterfaces:\n\n```typescript\ninterface Assert {\n  args: any[];\n}\n\ninterface Custom {\n  path: string;\n  args: any;\n}\n\ntype AssertOrCustom = Assert | Custom;\n```\n\n### Custom\n\nThis _Action_ type enables the possibility of referring to your own files to perform those actions that a constrained YAML schema can not provide. The file must export a very specific function signature that the tool is expecting to import: `async (context, ...args)`\n- `context`: corresponds to the test's `this` object. All user created variables (in `encodedCalls`, `queries` and `rpcs`) are stored and accessible from the `this.variables` key. In a similar way, `context` can be used to stored new variables that will become available in the rest of the tests.\n- `args`: the arguments used as input for your custom file function.\n\nThe following example shows how to use a `custom` action to perform an assertion, but there are no limitations about what to achieve.\n\nExample:\n\n```yaml\nsettings:\n  ...\ntests: # Describe[]\n  - name: My Describe\n    before: # I declare $coin_symbol\n    its: # It[]\n      ...\n      - name: My custom action should do something\n        actions: # Action[]\n          customs: # Custom[]\n            - path: ./queryExternalOracle.ts\n              args: [\n                {\n                  url: https://www.my-oracle.com/price/\n                }\n              ]\n              events: []\n          asserts:\n            equal: [$dot_price, 30]\n\n```\n```typescript\n// queryExternalOracle.ts\n\nconst myCustomFunction = async (context, ...args) =\u003e {\n  const { url } = args[0]\n\n  let coinSymbol = context.variables.$coin_symbol\n\n  let price = myApi.get(url + coinSymbol)\n\n  // Save the result in context (this) variables\n  // to make it available for the rests of the tests\n  context.variables['$dot_price'] = price\n}\n\nexport default myCustomFunction\n```\n\nInterfaces:\n\n```typescript\ninterface Custom {\n  path: string;\n  args: any[];\n  events?: Event[];\n}\n```\n\n## Get Help\nOpen an [issue](https://github.com/NachoPal/parachains-integration-tests/issues) if you have problems.\n\n## Contributions\nPRs and contributions are welcome :)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparitytech%2Fparachains-integration-tests","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fparitytech%2Fparachains-integration-tests","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparitytech%2Fparachains-integration-tests/lists"}