Skip to content

Commit

Permalink
Fixed bug in the test that is meant to test this (it always passes du…
Browse files Browse the repository at this point in the history
…e to incorrect usage) (#240)

- Fixed bug in the tests that always pass due to incorrect usage
- Switched to sinon-chai to give better readability and debug error message
- 100% code coverage on create-exchange.ts
  • Loading branch information
thehenrytsai authored Apr 10, 2024
1 parent ba92a34 commit 8d8f022
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .changeset/fair-spiders-eat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@tbdex/http-server": patch
---

Fixed bugs in tests involving calledWith() and increased code coverage.
3 changes: 3 additions & 0 deletions packages/http-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,12 @@
"@types/mocha": "10.0.1",
"@types/node": "20.9.4",
"@types/sinon": "^17.0.3",
"@types/sinon-chai": "^3.2.12",
"chai": "4.3.10",
"query-string": "8.2.0",
"rimraf": "5.0.1",
"sinon": "17.0.1",
"sinon-chai": "3.7.0",
"supertest": "6.3.3",
"typescript": "5.2.2"
},
Expand Down
40 changes: 39 additions & 1 deletion packages/http-server/tests/create-exchange.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ErrorDetail, Offering, Order, Rfq } from '@tbdex/http-client'
import type { Server } from 'http'

import { DevTools, RequestContext, TbdexHttpServer } from '../src/main.js'
import { CallbackError, DevTools, RequestContext, TbdexHttpServer } from '../src/main.js'
import { expect } from 'chai'
import { InMemoryExchangesApi } from '../src/in-memory-exchanges-api.js'
import { InMemoryOfferingsApi } from '../src/in-memory-offerings-api.js'
Expand Down Expand Up @@ -342,6 +342,44 @@ describe('POST /exchanges/:exchangeId/rfq', () => {
expect(lastCallbackArg.replyTo).to.be.undefined
})

it('propagates the status code and detail if custom handler throws a custom error', async () => {
const customErrorStatus = 456
const customErrorDetail: ErrorDetail[] = [{ detail: 'custom-error-detail' }]
const callbackSpy = Sinon.spy(
(_ctx: RequestContext, _message: Rfq, _opts: { offering: Offering, replyTo?: string }) => {
return Promise.reject(new CallbackError(customErrorStatus, customErrorDetail))
})
api.onCreateExchange(callbackSpy)

const response = await fetch('http://localhost:8000/exchanges', {
method : 'POST',
body : JSON.stringify({ rfq })
})

expect(response.status).to.equal(customErrorStatus)

const responseBody = await response.json() as { errors: ErrorDetail[] }
expect(responseBody.errors).to.deep.equal(customErrorDetail)
})

it('returns a 500 Internal Server Error if custom handler throws a generic unexpected error', async () => {
const callbackSpy = Sinon.spy(
(_ctx: RequestContext, _message: Rfq, _opts: { offering: Offering, replyTo?: string }) => {
return Promise.reject(new Error('generic unexpected error'))
})
api.onCreateExchange(callbackSpy)

const response = await fetch('http://localhost:8000/exchanges', {
method : 'POST',
body : JSON.stringify({ rfq })
})

expect(response.status).to.equal(500)

const responseBody = await response.json() as { errors: ErrorDetail[] }
expect(responseBody.errors).to.deep.equal([{ detail: 'Internal Server Error' }])
})

it('passes replyTo to the callback if it is provided in the request', async () => {
const callbackSpy = Sinon.spy(
(_ctx: RequestContext, _message: Rfq, _opts: { offering: Offering, replyTo?: string }) =>{
Expand Down
8 changes: 6 additions & 2 deletions packages/http-server/tests/get-exchange.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import type { Server } from 'http'
import Sinon, * as sinon from 'sinon'
import sinonChai from 'sinon-chai'
import chai from 'chai'

import { TbdexHttpServer, RequestContext } from '../src/main.js'
import { BearerDid, DidDht, DidJwk } from '@web5/dids'
import { expect } from 'chai'
import { InMemoryExchangesApi } from '../src/in-memory-exchanges-api.js'
import { DevTools, ErrorDetail, TbdexHttpClient } from '@tbdex/http-client'

chai.use(sinonChai)

describe('GET /exchanges', () => {
let server: Server
let api: TbdexHttpServer
Expand Down Expand Up @@ -112,9 +116,9 @@ describe('GET /exchanges', () => {

expect(resp.ok).to.be.true
expect(exchangesApiSpy.calledOnce).to.be.true
expect(exchangesApiSpy.calledWith({
expect(exchangesApiSpy).to.have.been.calledWith({
id: exchangeId,
})).to.be.true
})

exchangesApiSpy.restore()
})
Expand Down
30 changes: 17 additions & 13 deletions packages/http-server/tests/get-exchanges.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import type { Server } from 'http'
import Sinon, * as sinon from 'sinon'
import queryString from 'query-string'
import sinonChai from 'sinon-chai'
import chai from 'chai'

import { TbdexHttpServer, RequestContext, GetExchangesFilter } from '../src/main.js'
import { DidJwk } from '@web5/dids'
import { expect } from 'chai'
import { InMemoryExchangesApi } from '../src/in-memory-exchanges-api.js'
import { DevTools, ErrorDetail, TbdexHttpClient } from '@tbdex/http-client'

chai.use(sinonChai)

describe('GET /exchanges', () => {
let server: Server
let api: TbdexHttpServer
Expand Down Expand Up @@ -74,11 +79,11 @@ describe('GET /exchanges', () => {

expect(resp.ok).to.be.true
expect(exchangesApiSpy.calledOnce).to.be.true
expect(exchangesApiSpy.calledWith({
expect(exchangesApiSpy).to.have.been.calledWith({
filter: {
from: alice.uri
}
})).to.be.true
})

exchangesApiSpy.restore()
})
Expand All @@ -100,39 +105,38 @@ describe('GET /exchanges', () => {

expect(resp.ok).to.be.true
expect(exchangesApiSpy.calledOnce).to.be.true
expect(exchangesApiSpy.calledWith({
expect(exchangesApiSpy).to.have.been.calledWith({
filter: {
from : alice.uri,
id : [idQueryParam]
}
}))
})

exchangesApiSpy.restore()
})

it('passes the id array query param as an array to the filter of ExchangesApi.getExchanges', async () => {
it.only('passes the id array query param as an array to the filter of ExchangesApi.getExchanges', async () => {
const alice = await DidJwk.create()

const exchangesApiSpy = sinon.spy(api.exchangesApi, 'getExchanges')

const requestToken = await TbdexHttpClient.generateRequestToken({ requesterDid: alice, pfiDid: api.pfiDid })

// `id` query param contains an array
const idQueryParam = ['1234', '5678']
const resp = await fetch(`http://localhost:8000/exchanges?id=[${idQueryParam.join(',')}]`, {
const queryParams = { id: ['1234', '5678'] }
const queryParamsString = queryString.stringify(queryParams)
const resp = await fetch(`http://localhost:8000/exchanges?${queryParamsString}`, {
headers: {
'Authorization': `Bearer ${requestToken}`
}
})

expect(resp.ok).to.be.true
expect(exchangesApiSpy.calledOnce).to.be.true
expect(exchangesApiSpy.calledWith({
expect(exchangesApiSpy).to.have.been.calledWith({
filter: {
from : alice.uri,
id : idQueryParam
from: alice.uri,
...queryParams
}
}))
})

exchangesApiSpy.restore()
})
Expand Down
30 changes: 26 additions & 4 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 8d8f022

Please sign in to comment.