Skip to content

Commit

Permalink
Add Integration test for transaction subscriptions (#2193)
Browse files Browse the repository at this point in the history
* fix: transaction subscription mempool mapper and transaction result resolver

* fix: remove console.error - this will log when there are no results

* Add integration test for subscription

* fix: nicely dispose of the connection

* update docker compose file

* update graph test

* update packages

* update packages

* formatting

* Formatting...

* chore: Only update node-fetch for cross fetch

* Formatting....

* feat: add subscription test

* remove comments

---------

Co-authored-by: Nil Amrutlal <nil.amrutlal@deptagency.com>
  • Loading branch information
Ghislain89 and nil-amrutlal-dept committed Jun 3, 2024
1 parent a240f44 commit 42b0a1b
Show file tree
Hide file tree
Showing 8 changed files with 209 additions and 62 deletions.
8 changes: 5 additions & 3 deletions .github/actions/sandbox/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
version: '3'
services:
devnet:
image: kadena/devnet@sha256:b63feb2de2a46c77199569845f9dc5e44609260dcf1e874b5fb04907d1426e64
image: kadena/devnet@sha256:b4af222fc8c2f1e1164cbfb63164d5fe2f19a5840720b63d0f18c44e6125569d
ports:
- 8080:8080 # HTTP
- 1848:1848 # Node Service Port
- 1789:1789 # Chainweb node’s p2p API port
- 1790:1790 # On-Demand Mining API
- 5432:5432 # Postgres
- 8080:8080 # HTTP
- 9999:9999 # Info
- 1789:1789
environment:
- MINING_BATCH_PERIOD=0.05
- MINING_CONFIRMATION_PERIOD=1
Expand Down
2 changes: 1 addition & 1 deletion packages/apps/dev-wallet/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,4 @@
"vite-tsconfig-paths": "^4.2.1",
"vitest": "^1.6.0"
}
}
}
2 changes: 2 additions & 0 deletions packages/e2e/e2e-base/src/constants/network.constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ import type { ChainId } from '@kadena/types';

export const ns = 'common';
export const devnetHost = 'http://localhost:8080';
export const nodeHost = 'http://localhost:1848';
export const networkId = 'development';
export const grapHost = 'http://localhost:4000/graphql';
export const wsHost = 'ws://localhost:4000/graphql';

export const devnetUrl = (chainId: ChainId) => {
return `${devnetHost}/chainweb/0.0/${networkId}/chain/${chainId}/pact`;
Expand Down
17 changes: 17 additions & 0 deletions packages/e2e/e2e-graph/helpers/miner.helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { APIRequestContext } from '@playwright/test';
import { expect } from '@playwright/test';
import { devnetHost } from '../../e2e-base/src/constants/network.constants';

export async function triggerMining(
request: APIRequestContext,
chainId = '0',
numberOfBlocks = 1,
): Promise<void> {
const response = await request.post(`${devnetHost}/make-blocks`, {
data: {
[chainId]: numberOfBlocks,
},
});

expect(response.status()).toBe(200);
}
4 changes: 3 additions & 1 deletion packages/e2e/e2e-graph/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@
"eslint": "^8.45.0",
"eslint-import-resolver-typescript": "3.5.5",
"eslint-plugin-playwright": "1.6.1",
"graphql-ws": "^5.16.0",
"parse-md": "2.0.5",
"playwright-i18next-fixture": "^1.0.0",
"prettier": "~3.2.5"
"prettier": "~3.2.5",
"ws": "^8.16.0"
}
}
25 changes: 25 additions & 0 deletions packages/e2e/e2e-graph/queries/getTransactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,28 @@ export function getTransactionsByRequestKeyQuery(
extensions: {},
};
}

export function getTransactionsByRequestKeySubscription(
requestKey: string | undefined,
chainId: string,
) {
return {
query: `subscription tx($requestKey: String! $chainId: String!) {
transaction(requestKey: $requestKey chainId: $chainId){
result {
__typename
... on TransactionMempoolInfo {
status
}
...on TransactionResult {
badResult
goodResult
}
}
}
}`,
variables: { requestKey: requestKey, chainId: chainId },
operationName: 'tx',
extensions: {},
};
}
122 changes: 119 additions & 3 deletions packages/e2e/e2e-graph/tests/transaction.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { devnetMiner } from '@kadena-dev/e2e-base/src/constants/accounts.constants';
import {
devnetMiner,
sender00Account,
} from '@kadena-dev/e2e-base/src/constants/accounts.constants';
import { transferAmount } from '@kadena-dev/e2e-base/src/constants/amounts.constants';
import { coinModuleHash } from '@kadena-dev/e2e-base/src/constants/coin.constants';
import {
networkId,
nodeHost,
wsHost,
} from '@kadena-dev/e2e-base/src/constants/network.constants';
import {
createAccount,
generateAccount,
Expand All @@ -10,12 +18,21 @@ import {
transferFundsCrossChain,
} from '@kadena-dev/e2e-base/src/helpers/client-utils/transfer.helper';
import type { IAccount } from '@kadena-dev/e2e-base/src/types/account.types';
import type { ICommandResult } from '@kadena/client';
import type { ICommandResult, IKeyPair } from '@kadena/client';
import { createSignWithKeypair } from '@kadena/client';
import { transferCreate } from '@kadena/client-utils/coin';
import { expect, test } from '@playwright/test';
import type { SubscribePayload } from 'graphql-ws';
import { createClient } from 'graphql-ws';
import WebSocket from 'ws';
import { getBlockHash } from '../helpers/block.helper';
import { base64Encode } from '../helpers/cryptography.helper';
import { triggerMining } from '../helpers/miner.helper';
import { sendQuery } from '../helpers/request.helper';
import { getTransactionsQuery } from '../queries/getTransactions';
import {
getTransactionsByRequestKeySubscription,
getTransactionsQuery,
} from '../queries/getTransactions';

test.describe('Query: getTransactions', () => {
test('Query: getTransactions - Same Chain Transfer', async ({ request }) => {
Expand Down Expand Up @@ -462,3 +479,102 @@ test.describe('Query: getTransactions', () => {
});
});
});

const wsClient = createClient({
url: wsHost,
webSocketImpl: WebSocket,
});

test.describe('Subscription: getTransactions', () => {
test('Subscriptions: getTransactions - Subscribe to transactions by requestKey', async ({
request,
}) => {
let txTask;
let account: IAccount;
let preflightResponse: ICommandResult;
let query: SubscribePayload;
let subscription;

await test.step('Create Transfer Task and execute preflight', async () => {
account = await generateAccount(1, ['0', '1']);
txTask = transferCreate(
{
sender: {
account: sender00Account.account,
publicKeys: sender00Account.keys.map(
(keyPair: IKeyPair) => keyPair.publicKey,
),
},
receiver: {
account: account.account,
keyset: {
keys: account.keys.map((keyPair) => keyPair.publicKey),
pred: 'keys-all',
},
},
amount: '100',
chainId: account.chains[0],
},
{
host: nodeHost,
defaults: {
networkId: networkId,
},
sign: createSignWithKeypair(sender00Account.keys),
},
);
preflightResponse = await txTask.executeTo('preflight');
});

await test.step('Subscribe to events', async () => {
query = getTransactionsByRequestKeySubscription(
preflightResponse.reqKey,
account.chains[0],
);
subscription = wsClient.iterate(query);
});

await test.step('Assert the first event to not contain any transactions and then submit the transaction', async () => {
const emptyEvent = (await subscription.next()).value.data;
expect(emptyEvent).toEqual({
transaction: null,
});
await txTask.executeTo('submit');
});

await test.step('Assert the second event to contain the pending transaction and then trigger mining', async () => {
const secondEvent = (await subscription.next()).value.data;
expect(secondEvent).toEqual({
transaction: {
result: {
__typename: 'TransactionMempoolInfo',
status: 'Pending',
},
},
});

await triggerMining(request, account.chains[0], 2);
const listenResult = await txTask.executeTo('listen');
expect(listenResult.result).toEqual({
status: 'success',
data: 'Write succeeded',
});
});

await test.step('Assert the third event to contain the successful transaction', async () => {});

const thirdEvent = (await subscription.next()).value.data;
expect(thirdEvent).toEqual({
transaction: {
result: {
__typename: 'TransactionResult',
badResult: null,
goodResult: JSON.stringify('Write succeeded'),
},
},
});
});
test.afterEach(async () => {
wsClient.terminate();
});
});
Loading

0 comments on commit 42b0a1b

Please sign in to comment.