• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

cameri / nostream / 25601018106

09 May 2026 12:22PM UTC coverage: 33.99% (-31.1%) from 65.107%
25601018106

Pull #615

github

web-flow
Merge 1ef509ec3 into 36e5af87e
Pull Request #615: test: add unit tests for remaining app workers (#489)

788 of 3170 branches covered (24.86%)

Branch coverage included in aggregate %.

0 of 8 new or added lines in 2 files covered. (0.0%)

1822 existing lines in 87 files now uncovered.

2352 of 6068 relevant lines covered (38.76%)

13.55 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

16.36
/src/controllers/callbacks/zebedee-callback-controller.ts
1
import { Request, Response } from 'express'
2

3
import { Invoice, InvoiceStatus } from '../../@types/invoice'
1✔
4
import { createLogger } from '../../factories/logger-factory'
1✔
5
import { createSettings } from '../../factories/settings-factory'
1✔
6
import { fromZebedeeInvoice } from '../../utils/transform'
1✔
7
import { getRemoteAddress } from '../../utils/http'
1✔
8
import { IController } from '../../@types/controllers'
9
import { IPaymentsService } from '../../@types/services'
10
import { validateSchema } from '../../utils/validation'
1✔
11
import { zebedeeCallbackBodySchema } from '../../schemas/zebedee-callback-schema'
1✔
12

13
const logger = createLogger('zebedee-callback-controller')
1✔
14

15
export class ZebedeeCallbackController implements IController {
1✔
UNCOV
16
  public constructor(private readonly paymentsService: IPaymentsService) {}
×
17

18
  public async handleRequest(request: Request, response: Response) {
UNCOV
19
    logger('request headers: %o', request.headers)
×
UNCOV
20
    logger('request body: %O', request.body)
×
21

UNCOV
22
    const bodyValidation = validateSchema(zebedeeCallbackBodySchema)(request.body)
×
UNCOV
23
    if (bodyValidation.error) {
×
UNCOV
24
      logger('zebedee callback request rejected: invalid body %o', bodyValidation.error)
×
UNCOV
25
      response.status(400).setHeader('content-type', 'text/plain; charset=utf8').send('Malformed body')
×
UNCOV
26
      return
×
27
    }
28

UNCOV
29
    const settings = createSettings()
×
30

UNCOV
31
    const { ipWhitelist = [] } = settings.paymentsProcessors?.zebedee ?? {}
×
UNCOV
32
    const remoteAddress = getRemoteAddress(request, settings)
×
33

UNCOV
34
    if (ipWhitelist.length && !ipWhitelist.includes(remoteAddress)) {
×
UNCOV
35
      logger('unauthorized request from %s to /callbacks/zebedee', remoteAddress)
×
UNCOV
36
      response.status(403).send('Forbidden')
×
UNCOV
37
      return
×
38
    }
39

UNCOV
40
    const invoice = fromZebedeeInvoice(request.body)
×
41

UNCOV
42
    logger('invoice', invoice)
×
43

44
    let updatedInvoice: Invoice
UNCOV
45
    try {
×
UNCOV
46
      updatedInvoice = await this.paymentsService.updateInvoiceStatus(invoice)
×
47
    } catch (error) {
UNCOV
48
      logger.error(`Unable to persist invoice ${invoice.id}`, error)
×
49

UNCOV
50
      throw error
×
51
    }
52

UNCOV
53
    if (updatedInvoice.status !== InvoiceStatus.COMPLETED && !updatedInvoice.confirmedAt) {
×
UNCOV
54
      response.status(200).send()
×
55

UNCOV
56
      return
×
57
    }
58

UNCOV
59
    invoice.amountPaid = invoice.amountRequested
×
UNCOV
60
    invoice.status = updatedInvoice.status
×
UNCOV
61
    updatedInvoice.amountPaid = invoice.amountRequested
×
62

UNCOV
63
    try {
×
UNCOV
64
      await this.paymentsService.confirmInvoice({
×
65
        id: invoice.id,
66
        pubkey: invoice.pubkey,
67
        status: invoice.status,
68
        confirmedAt: invoice.confirmedAt,
69
        amountPaid: invoice.amountRequested,
70
      })
UNCOV
71
      await this.paymentsService.sendInvoiceUpdateNotification(updatedInvoice)
×
72
    } catch (error) {
UNCOV
73
      logger.error(`Unable to confirm invoice ${invoice.id}`, error)
×
74

UNCOV
75
      throw error
×
76
    }
77

UNCOV
78
    response.status(200).setHeader('content-type', 'text/plain; charset=utf8').send('OK')
×
79
  }
80
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc