From 119e3056406a926676dc4f59cd42889b44fa3322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gergely=20B=C3=A9k=C3=A9si?= Date: Wed, 6 May 2026 14:00:47 +0200 Subject: [PATCH 01/11] test: use mock instead of real bee.js calls --- test/command/stamp.spec.ts | 81 +++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 31 deletions(-) diff --git a/test/command/stamp.spec.ts b/test/command/stamp.spec.ts index 4be1c9a4..1ca8ac98 100644 --- a/test/command/stamp.spec.ts +++ b/test/command/stamp.spec.ts @@ -1,8 +1,10 @@ -import { System, Types } from 'cafe-utility' +import { Types } from 'cafe-utility' import inquirer from 'inquirer' import { Buy } from '../../src/command/stamp/buy' import { toMatchLinesInOrder } from '../custom-matcher' import { describeCommand, invokeTestCli } from '../utility' +import { BatchId, Bee } from '@ethersphere/bee-js' +import { randomBytes } from 'crypto' expect.extend({ toMatchLinesInOrder, @@ -11,6 +13,12 @@ expect.extend({ describeCommand( 'Test Stamp command', ({ consoleMessages, getLastMessage, getNthLastMessage, hasMessageContaining }) => { + const fakeBatchIdHash = randomBytes(32).toString('hex') + + afterEach(() => { + jest.clearAllMocks() + }) + it('should list stamps', async () => { await invokeTestCli(['stamp', 'list']) const pattern = [['Stamp ID'], ['Usage'], ['Capacity'], ['TTL']] @@ -26,23 +34,28 @@ describeCommand( it('should not allow buying stamp with amount 0', async () => { await invokeTestCli(['stamp', 'buy', '--amount', '0', '--depth', '20']) expect(getLastMessage()).toContain('[amount] must be at least 1') - await System.sleepMillis(11_000) }) it('should not allow buying stamp with depth 16', async () => { await invokeTestCli(['stamp', 'buy', '--amount', '1', '--depth', '16']) expect(getLastMessage()).toContain('[depth] must be at least 17') - await System.sleepMillis(11_000) }) it('should buy stamp', async () => { + const createPostageBatch = jest + .spyOn(Bee.prototype, 'createPostageBatch') + .mockResolvedValue(new BatchId(fakeBatchIdHash)) await invokeTestCli(['stamp', 'buy', '--amount', '600_000_000', '--depth', '20', '--yes']) + expect(createPostageBatch).toHaveBeenCalledWith('600000000', 20, expect.objectContaining({ immutableFlag: true })) expect(getLastMessage()).toContain('Stamp ID:') - await System.sleepMillis(11_000) + expect(getLastMessage()).toContain(fakeBatchIdHash) }) it('should buy stamp with immutable flag', async () => { - const execution = await invokeTestCli([ + const createPostageBatch = jest + .spyOn(Bee.prototype, 'createPostageBatch') + .mockResolvedValue(new BatchId(fakeBatchIdHash)) + await invokeTestCli([ 'stamp', 'buy', '--amount', @@ -53,13 +66,10 @@ describeCommand( '--wait-usable', '--yes', ]) - const command = execution.runnable as Buy - const id = command.postageBatchId - await invokeTestCli(['stamp', 'show', id.toHex(), '--verbose']) - const pattern = [['Capacity (immutable)']] - expect(consoleMessages).toMatchLinesInOrder(pattern) - await System.sleepMillis(11_000) + expect(createPostageBatch).toHaveBeenCalledWith('600000000', 20, expect.objectContaining({ immutableFlag: true })) + expect(getLastMessage()).toContain('Stamp ID:') + expect(getLastMessage()).toContain(fakeBatchIdHash) }) it('should print custom message when there are no stamps', async () => { @@ -74,7 +84,10 @@ describeCommand( }) it('should wait until stamp is usable', async () => { - const execution = await invokeTestCli([ + const createPostageBatch = jest + .spyOn(Bee.prototype, 'createPostageBatch') + .mockResolvedValue(new BatchId(fakeBatchIdHash)) + await invokeTestCli([ 'stamp', 'buy', '--depth', @@ -86,39 +99,44 @@ describeCommand( '--label', 'Alice', ]) - const command = execution.runnable as Buy - expect(command.yes).toBe(true) - const id = command.postageBatchId - await invokeTestCli(['stamp', 'show', id.toHex(), '--verbose']) - const pattern = [ - ['Stamp ID', id.toHex()], - ['Label', 'Alice'], - ['Usable', 'true'], - ] - expect(consoleMessages).toMatchLinesInOrder(pattern) + expect(createPostageBatch).toHaveBeenCalledWith( + '555000000', + 20, + expect.objectContaining({ label: 'Alice', waitForUsable: true }), + ) }) it('should accept estimate cost prompt', async () => { - jest.spyOn(inquirer, 'prompt').mockClear().mockResolvedValueOnce({ value: true }) + jest.spyOn(inquirer, 'prompt').mockResolvedValueOnce({ value: true }) + const createPostageBatch = jest + .spyOn(Bee.prototype, 'createPostageBatch') + .mockResolvedValue(new BatchId(fakeBatchIdHash)) const execution = await invokeTestCli(['stamp', 'buy', '--depth', '20', '--amount', '1b']) const command = execution.runnable as Buy expect(command.yes).toBe(true) expect(inquirer.prompt).toHaveBeenCalledTimes(1) - await System.sleepMillis(11_000) + expect(createPostageBatch).toHaveBeenCalledWith('1000000000', 20, expect.anything()) }) it('should reject estimate cost prompt', async () => { - jest.spyOn(inquirer, 'prompt').mockClear().mockResolvedValueOnce({ value: false }) + // jest.restoreAllMocks() + jest.spyOn(inquirer, 'prompt').mockResolvedValueOnce({ value: false }) + const createPostageBatch = jest + .spyOn(Bee.prototype, 'createPostageBatch') + .mockResolvedValue(new BatchId(fakeBatchIdHash)) const execution = await invokeTestCli(['stamp', 'buy', '--depth', '20', '--amount', '1b']) const command = execution.runnable as Buy expect(command.yes).toBe(false) expect(inquirer.prompt).toHaveBeenCalledTimes(1) - await System.sleepMillis(11_000) + expect(createPostageBatch).not.toHaveBeenCalled() }) it('should be possible to buy with underscores and units', async () => { - const execution = await invokeTestCli([ + const createPostageBatch = jest + .spyOn(Bee.prototype, 'createPostageBatch') + .mockResolvedValue(new BatchId(fakeBatchIdHash)) + await invokeTestCli([ 'stamp', 'buy', '--amount', @@ -129,10 +147,11 @@ describeCommand( '100_000_000', '--yes', ]) - const command = execution.runnable as Buy - expect(command.yes).toBe(true) - expect(getLastMessage()).toContain('Stamp ID:') - await System.sleepMillis(11_000) + expect(createPostageBatch).toHaveBeenCalledWith( + '600000000', + 17, + expect.objectContaining({ gasPrice: '100000000' }), + ) }) it.skip('should only be able to dilute stamp with greater depth', async () => { From 6e97ab827972ef4d3f43251d1bf936a69a30a05d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gergely=20B=C3=A9k=C3=A9si?= Date: Wed, 6 May 2026 10:31:28 +0200 Subject: [PATCH 02/11] ci: update deposit command --- .github/workflows/tests-rc.yaml | 10 +++++----- .github/workflows/tests.yaml | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/tests-rc.yaml b/.github/workflows/tests-rc.yaml index 83c8ddc2..47cb462d 100644 --- a/.github/workflows/tests-rc.yaml +++ b/.github/workflows/tests-rc.yaml @@ -58,11 +58,11 @@ jobs: - name: Deposit to chequebook run: | - swarm-cli cheque deposit 100000000000000000 - swarm-cli cheque deposit 100000000000000000 --bee-api-url http://localhost:11633 - swarm-cli cheque deposit 100000000000000000 --bee-api-url http://localhost:21633 - swarm-cli cheque deposit 100000000000000000 --bee-api-url http://localhost:31633 - swarm-cli cheque deposit 100000000000000000 --bee-api-url http://localhost:41633 + swarm-cli cheque deposit 10 + swarm-cli cheque deposit 10 --bee-api-url http://localhost:11633 + swarm-cli cheque deposit 10 --bee-api-url http://localhost:21633 + swarm-cli cheque deposit 10 --bee-api-url http://localhost:31633 + swarm-cli cheque deposit 10 --bee-api-url http://localhost:41633 - name: Print swarm-cli status continue-on-error: true diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index e752252a..7e8863bc 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -42,11 +42,11 @@ jobs: - name: Deposit to chequebook run: | - swarm-cli cheque deposit 100000000000000000 - swarm-cli cheque deposit 100000000000000000 --bee-api-url http://localhost:11633 - swarm-cli cheque deposit 100000000000000000 --bee-api-url http://localhost:21633 - swarm-cli cheque deposit 100000000000000000 --bee-api-url http://localhost:31633 - swarm-cli cheque deposit 100000000000000000 --bee-api-url http://localhost:41633 + swarm-cli cheque deposit 10 + swarm-cli cheque deposit 10 --bee-api-url http://localhost:11633 + swarm-cli cheque deposit 10 --bee-api-url http://localhost:21633 + swarm-cli cheque deposit 10 --bee-api-url http://localhost:31633 + swarm-cli cheque deposit 10 --bee-api-url http://localhost:41633 - name: Print swarm-cli status continue-on-error: true From 87f23c214a3db5245f3e30b6e54639110eb1d213 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 6 May 2026 12:09:03 +0000 Subject: [PATCH 03/11] test: update test coverage --- test/coverage/coverage-summary.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/coverage/coverage-summary.json b/test/coverage/coverage-summary.json index ed815663..46bd282b 100644 --- a/test/coverage/coverage-summary.json +++ b/test/coverage/coverage-summary.json @@ -1,4 +1,4 @@ -{"total": {"lines":{"total":2863,"covered":2186,"skipped":0,"pct":76.35},"statements":{"total":2884,"covered":2200,"skipped":0,"pct":76.28},"functions":{"total":343,"covered":271,"skipped":0,"pct":79},"branches":{"total":621,"covered":353,"skipped":0,"pct":56.84},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} +{"total": {"lines":{"total":2863,"covered":2185,"skipped":0,"pct":76.31},"statements":{"total":2884,"covered":2199,"skipped":0,"pct":76.24},"functions":{"total":343,"covered":271,"skipped":0,"pct":79},"branches":{"total":621,"covered":352,"skipped":0,"pct":56.68},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/home/runner/work/swarm-cli/swarm-cli/src/application.ts": {"lines":{"total":2,"covered":0,"skipped":0,"pct":0},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":0,"skipped":0,"pct":0},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/home/runner/work/swarm-cli/swarm-cli/src/config.ts": {"lines":{"total":33,"covered":32,"skipped":0,"pct":96.96},"functions":{"total":1,"covered":0,"skipped":0,"pct":0},"statements":{"total":33,"covered":32,"skipped":0,"pct":96.96},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/home/runner/work/swarm-cli/swarm-cli/src/curl.ts": {"lines":{"total":24,"covered":24,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":25,"covered":25,"skipped":0,"pct":100},"branches":{"total":13,"covered":12,"skipped":0,"pct":92.3}} @@ -96,7 +96,7 @@ ,"/home/runner/work/swarm-cli/swarm-cli/src/service/identity/index.ts": {"lines":{"total":36,"covered":32,"skipped":0,"pct":88.88},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":36,"covered":32,"skipped":0,"pct":88.88},"branches":{"total":9,"covered":6,"skipped":0,"pct":66.66}} ,"/home/runner/work/swarm-cli/swarm-cli/src/service/identity/types/identity.ts": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/home/runner/work/swarm-cli/swarm-cli/src/service/identity/types/index.ts": {"lines":{"total":1,"covered":1,"skipped":0,"pct":100},"functions":{"total":2,"covered":1,"skipped":0,"pct":50},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/home/runner/work/swarm-cli/swarm-cli/src/service/stamp/index.ts": {"lines":{"total":32,"covered":30,"skipped":0,"pct":93.75},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":32,"covered":30,"skipped":0,"pct":93.75},"branches":{"total":11,"covered":8,"skipped":0,"pct":72.72}} +,"/home/runner/work/swarm-cli/swarm-cli/src/service/stamp/index.ts": {"lines":{"total":32,"covered":29,"skipped":0,"pct":90.62},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":32,"covered":29,"skipped":0,"pct":90.62},"branches":{"total":11,"covered":7,"skipped":0,"pct":63.63}} ,"/home/runner/work/swarm-cli/swarm-cli/src/utils/bzz-address.ts": {"lines":{"total":30,"covered":24,"skipped":0,"pct":80},"functions":{"total":3,"covered":2,"skipped":0,"pct":66.66},"statements":{"total":30,"covered":24,"skipped":0,"pct":80},"branches":{"total":6,"covered":3,"skipped":0,"pct":50}} ,"/home/runner/work/swarm-cli/swarm-cli/src/utils/chainsync.ts": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/home/runner/work/swarm-cli/swarm-cli/src/utils/contracts.ts": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} From a91be68a9e5f764264dd1cc1b8f6b7c08f1ba5b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gergely=20B=C3=A9k=C3=A9si?= Date: Thu, 7 May 2026 09:49:33 +0200 Subject: [PATCH 04/11] test: add e2e test for stamp creation --- test/e2e/stamp-e2e.spec.ts | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 test/e2e/stamp-e2e.spec.ts diff --git a/test/e2e/stamp-e2e.spec.ts b/test/e2e/stamp-e2e.spec.ts new file mode 100644 index 00000000..ced7ed35 --- /dev/null +++ b/test/e2e/stamp-e2e.spec.ts @@ -0,0 +1,39 @@ +import { Buy } from '../../src/command/stamp/buy' +import { toMatchLinesInOrder } from '../custom-matcher' +import { describeCommand, invokeTestCli } from '../utility' + +expect.extend({ + toMatchLinesInOrder, +}) + +describeCommand('Test Stamp command end-to-end', ({ consoleMessages }) => { + it('should buy stamp with right capacity and properties', async () => { + const execution = await invokeTestCli([ + 'stamp', + 'buy', + '--depth', + '20', + '--amount', + '555m', + '--gas-price', + '100_000_000', + '--wait-usable', + '--yes', + '--label', + 'Alice', + ]) + const command = execution.runnable as Buy + expect(command.yes).toBe(true) + + const id = command.postageBatchId + await invokeTestCli(['stamp', 'show', id.toHex(), '--verbose']) + const pattern = [ + ['Type', 'Immutable'], + ['Stamp ID', id.toHex()], + ['Label', 'Alice'], + ['Depth', '20'], + ['Usable', 'true'], + ] + expect(consoleMessages).toMatchLinesInOrder(pattern) + }) +}) From 0133a0712dbabb2b38673a07474cd9a77bd6f2ce Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 7 May 2026 08:06:01 +0000 Subject: [PATCH 05/11] test: update test coverage --- test/coverage/coverage-summary.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/coverage/coverage-summary.json b/test/coverage/coverage-summary.json index 46bd282b..ed815663 100644 --- a/test/coverage/coverage-summary.json +++ b/test/coverage/coverage-summary.json @@ -1,4 +1,4 @@ -{"total": {"lines":{"total":2863,"covered":2185,"skipped":0,"pct":76.31},"statements":{"total":2884,"covered":2199,"skipped":0,"pct":76.24},"functions":{"total":343,"covered":271,"skipped":0,"pct":79},"branches":{"total":621,"covered":352,"skipped":0,"pct":56.68},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} +{"total": {"lines":{"total":2863,"covered":2186,"skipped":0,"pct":76.35},"statements":{"total":2884,"covered":2200,"skipped":0,"pct":76.28},"functions":{"total":343,"covered":271,"skipped":0,"pct":79},"branches":{"total":621,"covered":353,"skipped":0,"pct":56.84},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/home/runner/work/swarm-cli/swarm-cli/src/application.ts": {"lines":{"total":2,"covered":0,"skipped":0,"pct":0},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":0,"skipped":0,"pct":0},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/home/runner/work/swarm-cli/swarm-cli/src/config.ts": {"lines":{"total":33,"covered":32,"skipped":0,"pct":96.96},"functions":{"total":1,"covered":0,"skipped":0,"pct":0},"statements":{"total":33,"covered":32,"skipped":0,"pct":96.96},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/home/runner/work/swarm-cli/swarm-cli/src/curl.ts": {"lines":{"total":24,"covered":24,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":25,"covered":25,"skipped":0,"pct":100},"branches":{"total":13,"covered":12,"skipped":0,"pct":92.3}} @@ -96,7 +96,7 @@ ,"/home/runner/work/swarm-cli/swarm-cli/src/service/identity/index.ts": {"lines":{"total":36,"covered":32,"skipped":0,"pct":88.88},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":36,"covered":32,"skipped":0,"pct":88.88},"branches":{"total":9,"covered":6,"skipped":0,"pct":66.66}} ,"/home/runner/work/swarm-cli/swarm-cli/src/service/identity/types/identity.ts": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/home/runner/work/swarm-cli/swarm-cli/src/service/identity/types/index.ts": {"lines":{"total":1,"covered":1,"skipped":0,"pct":100},"functions":{"total":2,"covered":1,"skipped":0,"pct":50},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/home/runner/work/swarm-cli/swarm-cli/src/service/stamp/index.ts": {"lines":{"total":32,"covered":29,"skipped":0,"pct":90.62},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":32,"covered":29,"skipped":0,"pct":90.62},"branches":{"total":11,"covered":7,"skipped":0,"pct":63.63}} +,"/home/runner/work/swarm-cli/swarm-cli/src/service/stamp/index.ts": {"lines":{"total":32,"covered":30,"skipped":0,"pct":93.75},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":32,"covered":30,"skipped":0,"pct":93.75},"branches":{"total":11,"covered":8,"skipped":0,"pct":72.72}} ,"/home/runner/work/swarm-cli/swarm-cli/src/utils/bzz-address.ts": {"lines":{"total":30,"covered":24,"skipped":0,"pct":80},"functions":{"total":3,"covered":2,"skipped":0,"pct":66.66},"statements":{"total":30,"covered":24,"skipped":0,"pct":80},"branches":{"total":6,"covered":3,"skipped":0,"pct":50}} ,"/home/runner/work/swarm-cli/swarm-cli/src/utils/chainsync.ts": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/home/runner/work/swarm-cli/swarm-cli/src/utils/contracts.ts": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} From d1a171c007f722913ebe5647ba32462664c9d311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gergely=20B=C3=A9k=C3=A9si?= Date: Thu, 7 May 2026 10:22:25 +0200 Subject: [PATCH 06/11] test: fire up a bee node for e2e environment --- .github/workflows/tests-e2e.yaml | 6 ++++++ jest-e2e.config.ts | 21 +++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests-e2e.yaml b/.github/workflows/tests-e2e.yaml index 813caf76..9cc9c9c3 100644 --- a/.github/workflows/tests-e2e.yaml +++ b/.github/workflows/tests-e2e.yaml @@ -24,6 +24,12 @@ jobs: - name: Install local dependencies run: npm ci + - name: Install global dependencies + run: npm install --global bee-dev + + - name: Run bee-dev + run: bee-dev --port 1633 & + - name: Tests run: npm run test.e2e diff --git a/jest-e2e.config.ts b/jest-e2e.config.ts index c985be76..8f9b56d5 100644 --- a/jest-e2e.config.ts +++ b/jest-e2e.config.ts @@ -3,9 +3,26 @@ * https://jestjs.io/docs/en/configuration.html */ import type { Config } from '@jest/types' -import { Dates } from 'cafe-utility' +import { Dates, System } from 'cafe-utility' +import { CommandLog, VerbosityLevel } from './src/command/root-command/command-log' +import { Bee } from '@ethersphere/bee-js' + +export default async (): Promise => { + const port = 1633 + const bee = new Bee(`http://localhost:${port}`) + const console = new CommandLog(VerbosityLevel.Normal) + + const startedAt = Date.now() + console.log('Waiting for Bee node to warm up on port', port) + + await System.waitFor(async () => (await bee.getStatus()).isWarmingUp === false, { + attempts: 300, + waitMillis: Dates.seconds(1), + requiredConsecutivePasses: 3, + }) + const elapsed = Date.now() - startedAt + console.log(`Bee node on port ${port} warmed up in ${elapsed} milliseconds`) -export default (): Config.InitialOptions => { return { collectCoverage: false, forceExit: true, From 549ee942d9486f38065adcc1961afbd292496126 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 7 May 2026 08:35:55 +0000 Subject: [PATCH 07/11] test: update test coverage From ae9f0ffc53c184c0b8db81bc0408b930b41a6351 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gergely=20B=C3=A9k=C3=A9si?= Date: Thu, 7 May 2026 11:14:09 +0200 Subject: [PATCH 08/11] test: move e2e case to stable environment --- .github/workflows/tests-e2e.yaml | 6 ----- test/command/stamp.spec.ts | 33 ++++++++++++++++++++++++++- test/e2e/stamp-e2e.spec.ts | 39 -------------------------------- 3 files changed, 32 insertions(+), 46 deletions(-) delete mode 100644 test/e2e/stamp-e2e.spec.ts diff --git a/.github/workflows/tests-e2e.yaml b/.github/workflows/tests-e2e.yaml index 9cc9c9c3..813caf76 100644 --- a/.github/workflows/tests-e2e.yaml +++ b/.github/workflows/tests-e2e.yaml @@ -24,12 +24,6 @@ jobs: - name: Install local dependencies run: npm ci - - name: Install global dependencies - run: npm install --global bee-dev - - - name: Run bee-dev - run: bee-dev --port 1633 & - - name: Tests run: npm run test.e2e diff --git a/test/command/stamp.spec.ts b/test/command/stamp.spec.ts index 1ca8ac98..afc7c193 100644 --- a/test/command/stamp.spec.ts +++ b/test/command/stamp.spec.ts @@ -19,6 +19,38 @@ describeCommand( jest.clearAllMocks() }) + describe('e2e', () => { + it('should buy stamp with right capacity and properties', async () => { + const execution = await invokeTestCli([ + 'stamp', + 'buy', + '--depth', + '20', + '--amount', + '555m', + '--label', + 'Alice', + '--gas-price', + '100_000_000', + '--wait-usable', + '--yes', + ]) + const command = execution.runnable as Buy + expect(command.yes).toBe(true) + + const id = command.postageBatchId + await invokeTestCli(['stamp', 'show', id.toHex(), '--verbose']) + const pattern = [ + ['Type', 'Immutable'], + ['Stamp ID', id.toHex()], + ['Label', 'Alice'], + ['Depth', '20'], + ['Usable', 'true'], + ] + expect(consoleMessages).toMatchLinesInOrder(pattern) + }) + }) + it('should list stamps', async () => { await invokeTestCli(['stamp', 'list']) const pattern = [['Stamp ID'], ['Usage'], ['Capacity'], ['TTL']] @@ -120,7 +152,6 @@ describeCommand( }) it('should reject estimate cost prompt', async () => { - // jest.restoreAllMocks() jest.spyOn(inquirer, 'prompt').mockResolvedValueOnce({ value: false }) const createPostageBatch = jest .spyOn(Bee.prototype, 'createPostageBatch') diff --git a/test/e2e/stamp-e2e.spec.ts b/test/e2e/stamp-e2e.spec.ts deleted file mode 100644 index ced7ed35..00000000 --- a/test/e2e/stamp-e2e.spec.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Buy } from '../../src/command/stamp/buy' -import { toMatchLinesInOrder } from '../custom-matcher' -import { describeCommand, invokeTestCli } from '../utility' - -expect.extend({ - toMatchLinesInOrder, -}) - -describeCommand('Test Stamp command end-to-end', ({ consoleMessages }) => { - it('should buy stamp with right capacity and properties', async () => { - const execution = await invokeTestCli([ - 'stamp', - 'buy', - '--depth', - '20', - '--amount', - '555m', - '--gas-price', - '100_000_000', - '--wait-usable', - '--yes', - '--label', - 'Alice', - ]) - const command = execution.runnable as Buy - expect(command.yes).toBe(true) - - const id = command.postageBatchId - await invokeTestCli(['stamp', 'show', id.toHex(), '--verbose']) - const pattern = [ - ['Type', 'Immutable'], - ['Stamp ID', id.toHex()], - ['Label', 'Alice'], - ['Depth', '20'], - ['Usable', 'true'], - ] - expect(consoleMessages).toMatchLinesInOrder(pattern) - }) -}) From 0bd18a30787c84eb9bbf857e8d3328283446df8c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 7 May 2026 09:30:52 +0000 Subject: [PATCH 09/11] test: update test coverage --- test/coverage/coverage-summary.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/coverage/coverage-summary.json b/test/coverage/coverage-summary.json index ed815663..7f0a027a 100644 --- a/test/coverage/coverage-summary.json +++ b/test/coverage/coverage-summary.json @@ -1,4 +1,4 @@ -{"total": {"lines":{"total":2863,"covered":2186,"skipped":0,"pct":76.35},"statements":{"total":2884,"covered":2200,"skipped":0,"pct":76.28},"functions":{"total":343,"covered":271,"skipped":0,"pct":79},"branches":{"total":621,"covered":353,"skipped":0,"pct":56.84},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} +{"total": {"lines":{"total":2863,"covered":2188,"skipped":0,"pct":76.42},"statements":{"total":2884,"covered":2202,"skipped":0,"pct":76.35},"functions":{"total":343,"covered":272,"skipped":0,"pct":79.3},"branches":{"total":621,"covered":355,"skipped":0,"pct":57.16},"branchesTrue":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/home/runner/work/swarm-cli/swarm-cli/src/application.ts": {"lines":{"total":2,"covered":0,"skipped":0,"pct":0},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":2,"covered":0,"skipped":0,"pct":0},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/home/runner/work/swarm-cli/swarm-cli/src/config.ts": {"lines":{"total":33,"covered":32,"skipped":0,"pct":96.96},"functions":{"total":1,"covered":0,"skipped":0,"pct":0},"statements":{"total":33,"covered":32,"skipped":0,"pct":96.96},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/home/runner/work/swarm-cli/swarm-cli/src/curl.ts": {"lines":{"total":24,"covered":24,"skipped":0,"pct":100},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":25,"covered":25,"skipped":0,"pct":100},"branches":{"total":13,"covered":12,"skipped":0,"pct":92.3}} @@ -77,7 +77,7 @@ ,"/home/runner/work/swarm-cli/swarm-cli/src/command/stamp/dilute.ts": {"lines":{"total":27,"covered":12,"skipped":0,"pct":44.44},"functions":{"total":2,"covered":1,"skipped":0,"pct":50},"statements":{"total":27,"covered":12,"skipped":0,"pct":44.44},"branches":{"total":5,"covered":0,"skipped":0,"pct":0}} ,"/home/runner/work/swarm-cli/swarm-cli/src/command/stamp/extend.ts": {"lines":{"total":51,"covered":10,"skipped":0,"pct":19.6},"functions":{"total":3,"covered":1,"skipped":0,"pct":33.33},"statements":{"total":52,"covered":10,"skipped":0,"pct":19.23},"branches":{"total":13,"covered":0,"skipped":0,"pct":0}} ,"/home/runner/work/swarm-cli/swarm-cli/src/command/stamp/index.ts": {"lines":{"total":11,"covered":11,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":11,"covered":11,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/home/runner/work/swarm-cli/swarm-cli/src/command/stamp/list.ts": {"lines":{"total":31,"covered":28,"skipped":0,"pct":90.32},"functions":{"total":6,"covered":4,"skipped":0,"pct":66.66},"statements":{"total":32,"covered":29,"skipped":0,"pct":90.62},"branches":{"total":11,"covered":9,"skipped":0,"pct":81.81}} +,"/home/runner/work/swarm-cli/swarm-cli/src/command/stamp/list.ts": {"lines":{"total":31,"covered":29,"skipped":0,"pct":93.54},"functions":{"total":6,"covered":5,"skipped":0,"pct":83.33},"statements":{"total":32,"covered":30,"skipped":0,"pct":93.75},"branches":{"total":11,"covered":9,"skipped":0,"pct":81.81}} ,"/home/runner/work/swarm-cli/swarm-cli/src/command/stamp/show.ts": {"lines":{"total":14,"covered":13,"skipped":0,"pct":92.85},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":14,"covered":13,"skipped":0,"pct":92.85},"branches":{"total":1,"covered":0,"skipped":0,"pct":0}} ,"/home/runner/work/swarm-cli/swarm-cli/src/command/stamp/stamp-command.ts": {"lines":{"total":7,"covered":3,"skipped":0,"pct":42.85},"functions":{"total":1,"covered":0,"skipped":0,"pct":0},"statements":{"total":7,"covered":3,"skipped":0,"pct":42.85},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/home/runner/work/swarm-cli/swarm-cli/src/command/stamp/topup.ts": {"lines":{"total":23,"covered":11,"skipped":0,"pct":47.82},"functions":{"total":2,"covered":1,"skipped":0,"pct":50},"statements":{"total":23,"covered":11,"skipped":0,"pct":47.82},"branches":{"total":4,"covered":0,"skipped":0,"pct":0}} @@ -96,7 +96,7 @@ ,"/home/runner/work/swarm-cli/swarm-cli/src/service/identity/index.ts": {"lines":{"total":36,"covered":32,"skipped":0,"pct":88.88},"functions":{"total":7,"covered":7,"skipped":0,"pct":100},"statements":{"total":36,"covered":32,"skipped":0,"pct":88.88},"branches":{"total":9,"covered":6,"skipped":0,"pct":66.66}} ,"/home/runner/work/swarm-cli/swarm-cli/src/service/identity/types/identity.ts": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":2,"covered":2,"skipped":0,"pct":100}} ,"/home/runner/work/swarm-cli/swarm-cli/src/service/identity/types/index.ts": {"lines":{"total":1,"covered":1,"skipped":0,"pct":100},"functions":{"total":2,"covered":1,"skipped":0,"pct":50},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} -,"/home/runner/work/swarm-cli/swarm-cli/src/service/stamp/index.ts": {"lines":{"total":32,"covered":30,"skipped":0,"pct":93.75},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":32,"covered":30,"skipped":0,"pct":93.75},"branches":{"total":11,"covered":8,"skipped":0,"pct":72.72}} +,"/home/runner/work/swarm-cli/swarm-cli/src/service/stamp/index.ts": {"lines":{"total":32,"covered":30,"skipped":0,"pct":93.75},"functions":{"total":4,"covered":4,"skipped":0,"pct":100},"statements":{"total":32,"covered":30,"skipped":0,"pct":93.75},"branches":{"total":11,"covered":9,"skipped":0,"pct":81.81}} ,"/home/runner/work/swarm-cli/swarm-cli/src/utils/bzz-address.ts": {"lines":{"total":30,"covered":24,"skipped":0,"pct":80},"functions":{"total":3,"covered":2,"skipped":0,"pct":66.66},"statements":{"total":30,"covered":24,"skipped":0,"pct":80},"branches":{"total":6,"covered":3,"skipped":0,"pct":50}} ,"/home/runner/work/swarm-cli/swarm-cli/src/utils/chainsync.ts": {"lines":{"total":4,"covered":4,"skipped":0,"pct":100},"functions":{"total":1,"covered":1,"skipped":0,"pct":100},"statements":{"total":4,"covered":4,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/home/runner/work/swarm-cli/swarm-cli/src/utils/contracts.ts": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} @@ -108,5 +108,5 @@ ,"/home/runner/work/swarm-cli/swarm-cli/src/utils/option.ts": {"lines":{"total":3,"covered":3,"skipped":0,"pct":100},"functions":{"total":0,"covered":0,"skipped":0,"pct":100},"statements":{"total":3,"covered":3,"skipped":0,"pct":100},"branches":{"total":0,"covered":0,"skipped":0,"pct":100}} ,"/home/runner/work/swarm-cli/swarm-cli/src/utils/rpc.ts": {"lines":{"total":37,"covered":9,"skipped":0,"pct":24.32},"functions":{"total":6,"covered":0,"skipped":0,"pct":0},"statements":{"total":37,"covered":9,"skipped":0,"pct":24.32},"branches":{"total":5,"covered":0,"skipped":0,"pct":0}} ,"/home/runner/work/swarm-cli/swarm-cli/src/utils/spinner.ts": {"lines":{"total":15,"covered":15,"skipped":0,"pct":100},"functions":{"total":2,"covered":2,"skipped":0,"pct":100},"statements":{"total":15,"covered":15,"skipped":0,"pct":100},"branches":{"total":5,"covered":3,"skipped":0,"pct":60}} -,"/home/runner/work/swarm-cli/swarm-cli/src/utils/text.ts": {"lines":{"total":21,"covered":18,"skipped":0,"pct":85.71},"functions":{"total":9,"covered":7,"skipped":0,"pct":77.77},"statements":{"total":22,"covered":19,"skipped":0,"pct":86.36},"branches":{"total":5,"covered":3,"skipped":0,"pct":60}} +,"/home/runner/work/swarm-cli/swarm-cli/src/utils/text.ts": {"lines":{"total":21,"covered":19,"skipped":0,"pct":90.47},"functions":{"total":9,"covered":7,"skipped":0,"pct":77.77},"statements":{"total":22,"covered":20,"skipped":0,"pct":90.9},"branches":{"total":5,"covered":4,"skipped":0,"pct":80}} } From f9d62d9cf26550bd4e6724e52e0ffb1c3d2137e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gergely=20B=C3=A9k=C3=A9si?= Date: Thu, 7 May 2026 12:22:10 +0200 Subject: [PATCH 10/11] test: revert e2e jest config --- jest-e2e.config.ts | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/jest-e2e.config.ts b/jest-e2e.config.ts index 8f9b56d5..c985be76 100644 --- a/jest-e2e.config.ts +++ b/jest-e2e.config.ts @@ -3,26 +3,9 @@ * https://jestjs.io/docs/en/configuration.html */ import type { Config } from '@jest/types' -import { Dates, System } from 'cafe-utility' -import { CommandLog, VerbosityLevel } from './src/command/root-command/command-log' -import { Bee } from '@ethersphere/bee-js' - -export default async (): Promise => { - const port = 1633 - const bee = new Bee(`http://localhost:${port}`) - const console = new CommandLog(VerbosityLevel.Normal) - - const startedAt = Date.now() - console.log('Waiting for Bee node to warm up on port', port) - - await System.waitFor(async () => (await bee.getStatus()).isWarmingUp === false, { - attempts: 300, - waitMillis: Dates.seconds(1), - requiredConsecutivePasses: 3, - }) - const elapsed = Date.now() - startedAt - console.log(`Bee node on port ${port} warmed up in ${elapsed} milliseconds`) +import { Dates } from 'cafe-utility' +export default (): Config.InitialOptions => { return { collectCoverage: false, forceExit: true, From 2d458beb71ba0bb16e5961224fe5bd1782345255 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 7 May 2026 10:27:11 +0000 Subject: [PATCH 11/11] test: update test coverage