Skip to content

test(ack-id): add comprehensive A2A module test suite#69

Open
ak68a wants to merge 2 commits intoagentcommercekit:mainfrom
ak68a:test/a2a-module
Open

test(ack-id): add comprehensive A2A module test suite#69
ak68a wants to merge 2 commits intoagentcommercekit:mainfrom
ak68a:test/a2a-module

Conversation

@ak68a
Copy link

@ak68a ak68a commented Mar 25, 2026

Summary

  • Add tests for the entire packages/ack-id/src/a2a/ module which previously had zero test coverage
  • Covers all 4 source files: random.ts, service-endpoints.ts, sign-message.ts, verify.ts
  • 39 tests across 4 test files + shared fixture module

What's tested

Handshake signing — payload construction with nonce correlation for challenge-response flows, JWT wrapping into A2A data-part messages, metadata merge behavior (signature doesn't mess up existing metadata)

Handshake verification — JWT audience/issuer delegation to verifyJwt, schema rejection of malformed messages before any crypto/network calls, payload validation (missing fields, invalid DID URIs)

Signed message verification — content integrity check (signed payload must match message body), rejection of unsigned and improperly signed messages, contextId stripping (A2A servers inject this post-signing, verification must ignore it)

Utilities — UUID format and uniqueness for JTI/nonce generation, service endpoint construction with DID fragment assembly

Test plan

  • pnpm --filter ./packages/ack-id test — 39 tests pass
  • pnpm run check — format, types, lint all clean
  • Mutation tested: 6 source mutations, all caught by tests

Summary by CodeRabbit

  • Tests
    • Added comprehensive test suites for A2A (Agent-to-Agent) functionality including random value generation, service endpoint creation, handshake payload generation, message signing, and JWT verification.
    • Added centralized test fixtures module with identity constants, credential fixtures, and message builder helpers for consistent test scenarios.

ak68a and others added 2 commits March 25, 2026 07:26
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add test-fixtures.ts with shared identity constants, message builders, and mock factories
- Replace inline message construction with typed builder functions
- Use it.each for schema rejection cases
- Derive expected signed payload from signedMessage() to prevent fixture drift
- Add unsignedMessage() builder for explicit unsigned test cases
- Add comments explaining why (contextId stripping, schema-first validation, nonce correlation)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link

coderabbitai bot commented Mar 25, 2026

Walkthrough

This PR adds comprehensive Vitest test coverage for A2A (Agent-to-Agent) functionality across five new files, including unit tests for random generation, service endpoints, signing, verification, and a shared test-fixtures module that centralizes test setup and message builders.

Changes

Cohort / File(s) Summary
A2A Utility Function Tests
packages/ack-id/src/a2a/random.test.ts, packages/ack-id/src/a2a/service-endpoints.test.ts
Tests for random UUID/nonce generation and agent card service endpoint creation, verifying correct output formats and consistency across invocations.
A2A Message Signing Tests
packages/ack-id/src/a2a/sign-message.test.ts
Comprehensive test suite for A2A handshake payload creation, JWT wrapping, message signing, and end-to-end handshake flow with mocked UUID and random generators.
A2A Message Verification Tests
packages/ack-id/src/a2a/verify.test.ts
Extensive test suite for handshake and signed message verification with mocked JWT and DID resolution, covering successful paths, schema validation, JWT failures, and field extraction.
Shared Test Fixtures & Utilities
packages/ack-id/src/a2a/test-fixtures.ts
Centralized test fixtures exporting identity constants (agent/user DIDs), credential fixtures, message builders for different scenarios, and helper functions for creating verified JWT objects.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding comprehensive tests for the A2A module that was previously untested.
Docstring Coverage ✅ Passed Docstring coverage is 85.71% which is sufficient. The required threshold is 80.00%.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
packages/ack-id/src/a2a/verify.test.ts (1)

84-112: Enforce schema-first behavior with an explicit verifyJwt non-call assertion.

The table test currently checks rejection only; it should also prove malformed input is rejected before JWT verification.

Suggested update
 ])("rejects $name", async ({ message }) => {
+  vi.mocked(verifyJwt).mockClear()
   await expect(
     verifyA2AHandshakeMessage(message as never, { did: agentDid }),
   ).rejects.toThrow()
+  expect(verifyJwt).not.toHaveBeenCalled()
 })
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ack-id/src/a2a/verify.test.ts` around lines 84 - 112, The tests in
verify.test.ts currently only assert that malformed messages cause
verifyA2AHandshakeMessage to reject, but they don’t assert that JWT verification
(verifyJwt) is not invoked; update the table-driven test to mock or spy on the
verifyJwt function used by verifyA2AHandshakeMessage and add a non-call
assertion (e.g., expect(verifyJwt).not.toHaveBeenCalled()) after the await
expect(...).rejects.toThrow() so the test proves schema validation occurs before
any JWT verification. Make sure the mock/spy targets the same symbol
imported/used by verifyA2AHandshakeMessage (verifyJwt) so the assertion reliably
detects no calls.
packages/ack-id/src/a2a/random.test.ts (1)

5-6: Consider asserting UUIDv4-specific bits in the regex.

Current pattern validates generic UUID shape only. If generateRandomJti / generateRandomNonce are expected to be UUIDv4, tightening this improves mutation resistance.

Suggested tweak
-const uuidPattern =
-  /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
+const uuidPattern =
+  /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ack-id/src/a2a/random.test.ts` around lines 5 - 6, The current
uuidPattern only checks generic UUID shape; tighten it to assert UUIDv4 version
and RFC-variant bits so tests for generateRandomJti and generateRandomNonce
validate v4 UUIDs. Replace the pattern used in uuidPattern with one that
enforces a '4' in the version position and one of [89ab] in the variant position
(e.g. pattern matching ...-4...-[89ab]...-...), keeping case handling consistent
with the rest of the tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/ack-id/src/a2a/service-endpoints.test.ts`:
- Around line 19-26: Rename the test title to use the approved assertive
pattern: change the it(...) description for the test that calls
createAgentCardServiceEndpoint with DID "did:web:example.com:agents:my-agent" to
an assertive form such as "returns an id with `#agent-card` for colon-separated
DID paths" (or another "creates/returns/throws/requires" phrasing); keep the
test body and expectations
(expect(endpoint.id).toBe("did:web:example.com:agents:my-agent#agent-card"))
unchanged so only the test name is updated.

In `@packages/ack-id/src/a2a/sign-message.test.ts`:
- Around line 45-151: Rename the test titles to use assertive verbs
(creates/returns/throws/requires) so they follow the project's naming
convention: update the it(...) strings in tests referencing
createA2AHandshakePayload ("echoes the request nonce..." → "returns the request
nonce and creates a new reply nonce"), createA2AHandshakeMessageFromJwt ("wraps
a JWT..." → "returns an A2A data-part message containing a JWT" and "respects
the role parameter" → "returns the provided role"), createSignedA2AMessage
("produces a JWT signature..." → "creates a JWT signature and attaches it to
message metadata", "preserves original message content..." → "returns original
message content alongside the signature", "merges the signature..." → "creates
merged metadata without clobbering existing fields"), and
createA2AHandshakeMessage ("signs a credential handshake and returns the
nonce..." → "creates a signed credential handshake and returns the nonce",
"embeds the signed JWT..." → "returns a message embedding the signed JWT"); keep
the test logic and assertions unchanged, only change the human-readable it(...)
description strings.

In `@packages/ack-id/src/a2a/verify.test.ts`:
- Around line 40-250: The tests use non-assertive "it(...)" titles; rename each
test title in this suite to use the mandated assertive prefixes (creates...,
throws..., requires..., or returns...) so they conform to the guideline.
Specifically update the it(...) descriptions in the verifyA2AHandshakeMessage
and verifyA2ASignedMessage blocks (tests referencing verifyA2AHandshakeMessage,
verifyA2ASignedMessage, mockValidSignature, handshakeMessage, signedMessage,
unsignedMessage) — e.g. change "extracts issuer, nonce, and credential from a
valid handshake" to "returns issuer, nonce, and credential from a valid
handshake", "verifies the JWT with audience=self and issuer=counterparty" to
"requires JWT verification with audience=self and issuer=counterparty" or
similar, and similarly convert "rejects ..." to "throws ..." where appropriate;
apply consistent pattern across all test titles.

---

Nitpick comments:
In `@packages/ack-id/src/a2a/random.test.ts`:
- Around line 5-6: The current uuidPattern only checks generic UUID shape;
tighten it to assert UUIDv4 version and RFC-variant bits so tests for
generateRandomJti and generateRandomNonce validate v4 UUIDs. Replace the pattern
used in uuidPattern with one that enforces a '4' in the version position and one
of [89ab] in the variant position (e.g. pattern matching
...-4...-[89ab]...-...), keeping case handling consistent with the rest of the
tests.

In `@packages/ack-id/src/a2a/verify.test.ts`:
- Around line 84-112: The tests in verify.test.ts currently only assert that
malformed messages cause verifyA2AHandshakeMessage to reject, but they don’t
assert that JWT verification (verifyJwt) is not invoked; update the table-driven
test to mock or spy on the verifyJwt function used by verifyA2AHandshakeMessage
and add a non-call assertion (e.g., expect(verifyJwt).not.toHaveBeenCalled())
after the await expect(...).rejects.toThrow() so the test proves schema
validation occurs before any JWT verification. Make sure the mock/spy targets
the same symbol imported/used by verifyA2AHandshakeMessage (verifyJwt) so the
assertion reliably detects no calls.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4865f10f-67ef-40dd-9209-a61e6396a477

📥 Commits

Reviewing files that changed from the base of the PR and between f0e8c6c and dd65b30.

📒 Files selected for processing (5)
  • packages/ack-id/src/a2a/random.test.ts
  • packages/ack-id/src/a2a/service-endpoints.test.ts
  • packages/ack-id/src/a2a/sign-message.test.ts
  • packages/ack-id/src/a2a/test-fixtures.ts
  • packages/ack-id/src/a2a/verify.test.ts

Comment on lines +19 to +26
it("handles DIDs with colon-separated path components", () => {
const endpoint = createAgentCardServiceEndpoint(
"did:web:example.com:agents:my-agent",
"https://example.com/agents/my-agent/agent.json",
)

expect(endpoint.id).toBe("did:web:example.com:agents:my-agent#agent-card")
})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Rename test title to the approved assertive pattern.

Use creates..., throws..., requires..., or returns... for this case (e.g., returns an id with #agent-card for colon-separated DID paths).

As per coding guidelines, **/*.test.ts: Use assertive test names with patterns: "it("creates...")" , "it("throws...")" , "it("requires...")" , "it("returns...")".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ack-id/src/a2a/service-endpoints.test.ts` around lines 19 - 26,
Rename the test title to use the approved assertive pattern: change the it(...)
description for the test that calls createAgentCardServiceEndpoint with DID
"did:web:example.com:agents:my-agent" to an assertive form such as "returns an
id with `#agent-card` for colon-separated DID paths" (or another
"creates/returns/throws/requires" phrasing); keep the test body and expectations
(expect(endpoint.id).toBe("did:web:example.com:agents:my-agent#agent-card"))
unchanged so only the test name is updated.

Comment on lines +45 to +151
it("echoes the request nonce and generates a new reply nonce for responses", () => {
const payload = createA2AHandshakePayload({
recipient: userDid,
vc: testCredential,
requestNonce: "original-nonce",
})

// The initiator's nonce becomes ours so they can correlate the reply
expect(payload.nonce).toBe("original-nonce")
// We generate a fresh nonce for the next leg of the handshake
expect(payload.replyNonce).toBe("test-nonce-1234")
})
})

describe("createA2AHandshakeMessageFromJwt", () => {
it("wraps a JWT in an A2A data-part message", () => {
const jwt = "eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.test.sig"

expect(createA2AHandshakeMessageFromJwt("agent", jwt)).toEqual({
kind: "message",
messageId: "test-uuid-1234",
role: "agent",
parts: [{ kind: "data", data: { jwt } }],
})
})

it("respects the role parameter", () => {
const message = createA2AHandshakeMessageFromJwt("user", "any.jwt")
expect(message.role).toBe("user")
})
})

describe("createSignedA2AMessage", () => {
let jwtSigner: JwtSigner

beforeEach(async () => {
const keypair = await generateKeypair("secp256k1")
jwtSigner = createJwtSigner(keypair)
})

it("produces a JWT signature and attaches it to message metadata", async () => {
const result = await createSignedA2AMessage(makeTextMessage(), {
did: agentDid,
jwtSigner,
})

expect(result.sig).toEqual(expect.any(String))
expect(result.jti).toBe("test-jti-1234")
expect(result.message.metadata?.sig).toBe(result.sig)
})

it("preserves original message content alongside the signature", async () => {
const original = makeTextMessage("agent")
const result = await createSignedA2AMessage(original, {
did: agentDid,
jwtSigner,
})

expect(result.message.kind).toBe("message")
expect(result.message.role).toBe("agent")
expect(result.message.parts).toEqual(original.parts)
})

it("merges the signature into existing metadata without clobbering", async () => {
const message = makeTextMessage("user", { traceId: "abc" })
const result = await createSignedA2AMessage(message, {
did: agentDid,
jwtSigner,
})

expect(result.message.metadata?.sig).toBe(result.sig)
expect(result.message.metadata?.traceId).toBe("abc")
})
})

describe("createA2AHandshakeMessage", () => {
let jwtSigner: JwtSigner

beforeEach(async () => {
const keypair = await generateKeypair("secp256k1")
jwtSigner = createJwtSigner(keypair)
})

it("signs a credential handshake and returns the nonce for correlation", async () => {
const result = await createA2AHandshakeMessage(
"agent",
{ recipient: userDid, vc: testCredential },
{ did: agentDid, jwtSigner },
)

expect(result.sig).toEqual(expect.any(String))
expect(result.jti).toBe("test-jti-1234")
expect(result.nonce).toBe("test-nonce-1234")
expect(result.message.role).toBe("agent")
})

it("embeds the signed JWT in the message data part", async () => {
const result = await createA2AHandshakeMessage(
"agent",
{ recipient: userDid, vc: testCredential },
{ did: agentDid, jwtSigner },
)

expect(result.message.parts[0]).toEqual(
expect.objectContaining({ kind: "data", data: { jwt: result.sig } }),
)
})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Normalize it(...) titles to the required assertive verbs.

Several cases use verbs outside the allowed naming pattern; please rename to creates..., throws..., requires..., or returns....

As per coding guidelines, **/*.test.ts: Use assertive test names with patterns: "it("creates...")" , "it("throws...")" , "it("requires...")" , "it("returns...")".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ack-id/src/a2a/sign-message.test.ts` around lines 45 - 151, Rename
the test titles to use assertive verbs (creates/returns/throws/requires) so they
follow the project's naming convention: update the it(...) strings in tests
referencing createA2AHandshakePayload ("echoes the request nonce..." → "returns
the request nonce and creates a new reply nonce"),
createA2AHandshakeMessageFromJwt ("wraps a JWT..." → "returns an A2A data-part
message containing a JWT" and "respects the role parameter" → "returns the
provided role"), createSignedA2AMessage ("produces a JWT signature..." →
"creates a JWT signature and attaches it to message metadata", "preserves
original message content..." → "returns original message content alongside the
signature", "merges the signature..." → "creates merged metadata without
clobbering existing fields"), and createA2AHandshakeMessage ("signs a credential
handshake and returns the nonce..." → "creates a signed credential handshake and
returns the nonce", "embeds the signed JWT..." → "returns a message embedding
the signed JWT"); keep the test logic and assertions unchanged, only change the
human-readable it(...) description strings.

Comment on lines +40 to +250
it("extracts issuer, nonce, and credential from a valid handshake", async () => {
vi.mocked(verifyJwt).mockResolvedValueOnce(
mockVerifiedJwt({
iss: userDid,
nonce: "challenge-nonce",
vc: testCredential,
}),
)

const result = await verifyA2AHandshakeMessage(handshakeMessage(), {
did: agentDid,
counterparty: userDid,
})

expect(result.iss).toBe(userDid)
expect(result.nonce).toBe("challenge-nonce")
expect(result.vc).toEqual(testCredential)
})

it("verifies the JWT with audience=self and issuer=counterparty", async () => {
vi.mocked(verifyJwt).mockResolvedValueOnce(
mockVerifiedJwt({
iss: userDid,
nonce: "n",
vc: testCredential,
}),
)

await verifyA2AHandshakeMessage(handshakeMessage("the.jwt"), {
did: agentDid,
counterparty: userDid,
})

expect(verifyJwt).toHaveBeenCalledWith("the.jwt", {
audience: agentDid,
issuer: userDid,
resolver: expect.anything(),
})
})

// The message schema uses valibot's v.parse(), which rejects structurally
// invalid input before any JWT verification happens. This matters because
// a malformed message should fail fast, not trigger a network call to
// resolve a DID.
it.each([
{ name: "null message", message: null },
{
name: "empty parts array",
message: { kind: "message", messageId: "m", role: "user", parts: [] },
},
{
name: "text part instead of data part",
message: {
kind: "message",
messageId: "m",
role: "user",
parts: [{ kind: "text", text: "x" }],
},
},
{
name: "data part without jwt field",
message: {
kind: "message",
messageId: "m",
role: "user",
parts: [{ kind: "data", data: { notJwt: "x" } }],
},
},
])("rejects $name", async ({ message }) => {
await expect(
verifyA2AHandshakeMessage(message as never, { did: agentDid }),
).rejects.toThrow()
})

it("rejects when JWT verification fails", async () => {
vi.mocked(verifyJwt).mockRejectedValueOnce(
new Error("JWT verification failed"),
)

await expect(
verifyA2AHandshakeMessage(handshakeMessage(), { did: agentDid }),
).rejects.toThrow("JWT verification failed")
})

it("rejects when the verified payload is missing required handshake fields", async () => {
// JWT is valid but payload lacks nonce and vc — not a proper handshake
vi.mocked(verifyJwt).mockResolvedValueOnce(
mockVerifiedJwt({ iss: userDid }),
)

await expect(
verifyA2AHandshakeMessage(handshakeMessage(), {
did: agentDid,
counterparty: userDid,
}),
).rejects.toThrow()
})

it("rejects when issuer is not a valid DID URI", async () => {
// The handshake payload schema requires iss to be a did: URI.
// A compromised or misconfigured peer might send a plain string.
vi.mocked(verifyJwt).mockResolvedValueOnce(
mockVerifiedJwt({
iss: "not-a-did",
nonce: "n",
vc: testCredential,
}),
)

await expect(
verifyA2AHandshakeMessage(handshakeMessage(), { did: agentDid }),
).rejects.toThrow()
})
})

// --- Signed message verification ---

describe("verifyA2ASignedMessage", () => {
function mockValidSignature() {
vi.mocked(verifyJwt).mockResolvedValueOnce(
mockVerifiedJwt(expectedSignedPayload()),
)
}

it("verifies that a message's content matches its JWT signature", async () => {
mockValidSignature()

const result = await verifyA2ASignedMessage(signedMessage(), {
did: agentDid,
counterparty: userDid,
})

expect(result.verified).toBe(true)
})

it("verifies the signature JWT with audience=self and issuer=counterparty", async () => {
mockValidSignature()

await verifyA2ASignedMessage(signedMessage("hello", "the.sig"), {
did: agentDid,
counterparty: userDid,
})

expect(verifyJwt).toHaveBeenCalledWith("the.sig", {
audience: agentDid,
issuer: userDid,
resolver: expect.anything(),
})
})

it("rejects unsigned messages (no metadata at all)", async () => {
await expect(
verifyA2ASignedMessage(unsignedMessage(), { did: agentDid }),
).rejects.toThrow()
})

it("rejects messages with metadata but no sig field", async () => {
const noSig = { ...unsignedMessage(), metadata: { traceId: "abc" } }

await expect(
verifyA2ASignedMessage(noSig as never, { did: agentDid }),
).rejects.toThrow()
})

it("detects tampering: rejects when message content diverges from signed payload", async () => {
// Signature covers "original content" but the message body says "tampered"
vi.mocked(verifyJwt).mockResolvedValueOnce(
mockVerifiedJwt({
message: {
kind: "message",
messageId: "msg-1",
role: "user",
parts: [{ kind: "text", text: "original content" }],
},
}),
)

await expect(
verifyA2ASignedMessage(signedMessage("tampered"), {
did: agentDid,
counterparty: userDid,
}),
).rejects.toThrow("Message parts do not match")
})

it("rejects when the underlying JWT signature is invalid", async () => {
vi.mocked(verifyJwt).mockRejectedValueOnce(new Error("Signature invalid"))

await expect(
verifyA2ASignedMessage(signedMessage(), { did: agentDid }),
).rejects.toThrow("Signature invalid")
})

it("ignores server-injected contextId when comparing content", async () => {
// A2A servers may auto-assign a contextId after the client signs the
// message. The verification must strip it before comparing, otherwise
// every message routed through a server would fail validation.
mockValidSignature()

const messageWithContextId = {
...signedMessage(),
contextId: "ctx-server-assigned",
}

const result = await verifyA2ASignedMessage(messageWithContextId, {
did: agentDid,
counterparty: userDid,
})

expect(result.verified).toBe(true)
})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Rename tests to match the required assertive naming convention.

Please standardize it(...) titles to creates..., throws..., requires..., or returns... across this suite.

As per coding guidelines, **/*.test.ts: Use assertive test names with patterns: "it("creates...")" , "it("throws...")" , "it("requires...")" , "it("returns...")".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ack-id/src/a2a/verify.test.ts` around lines 40 - 250, The tests use
non-assertive "it(...)" titles; rename each test title in this suite to use the
mandated assertive prefixes (creates..., throws..., requires..., or returns...)
so they conform to the guideline. Specifically update the it(...) descriptions
in the verifyA2AHandshakeMessage and verifyA2ASignedMessage blocks (tests
referencing verifyA2AHandshakeMessage, verifyA2ASignedMessage,
mockValidSignature, handshakeMessage, signedMessage, unsignedMessage) — e.g.
change "extracts issuer, nonce, and credential from a valid handshake" to
"returns issuer, nonce, and credential from a valid handshake", "verifies the
JWT with audience=self and issuer=counterparty" to "requires JWT verification
with audience=self and issuer=counterparty" or similar, and similarly convert
"rejects ..." to "throws ..." where appropriate; apply consistent pattern across
all test titles.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant