Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mxiao-cll committed Oct 1, 2024
1 parent 093bdb7 commit ae6da68
Show file tree
Hide file tree
Showing 19 changed files with 508 additions and 4 deletions.
3 changes: 3 additions & 0 deletions .pnp.cjs

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

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added .yarn/cache/fsevents-patch-19706e7e35-10.zip
Binary file not shown.
Binary file added .yarn/cache/fsevents-patch-afc6995412-10.zip
Binary file not shown.
4 changes: 2 additions & 2 deletions packages/sources/tp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ This document was generated automatically. Please see [README Generator](../../s

Context: Often there are issues with the set of credentials not having concurrent (ie: 2+) connections enabled.

- With both all EA instances off, try the following commands to check if this is the case:
- With all EA instances off, try the following commands to check if this is the case:

```bash
wscat -c 'ws://json.mktdata.portal.apac.parametasolutions.com:12000'
Expand Down Expand Up @@ -60,7 +60,7 @@ Supported names for this endpoint are: `commodities`, `forex`, `price`.
| :-------: | :--------: | :------------: | :----------------------------------------------------: | :----: | :--------: | :-----: | :--------: | :------------: |
|| base | `coin`, `from` | The symbol of symbols of the currency to query | string | | | | |
|| quote | `market`, `to` | The symbol of the currency to convert to | string | | | | |
| | streamName | `source` | test | string | `IC`, `TP` | `TP` | | |
| | streamName | `source` | TP or ICAP | string | `IC`, `TP` | `TP` | | |
| | sourceName | `tpSource` | Source of price data for this price pair on the stream | string | | `GBL` | | |

### Example
Expand Down
2 changes: 1 addition & 1 deletion packages/sources/tp/docs/known-issues.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Context: Often there are issues with the set of credentials not having concurrent (ie: 2+) connections enabled.

- With both all EA instances off, try the following commands to check if this is the case:
- With all EA instances off, try the following commands to check if this is the case:

```bash
wscat -c 'ws://json.mktdata.portal.apac.parametasolutions.com:12000'
Expand Down
3 changes: 3 additions & 0 deletions packages/sources/tp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
"@types/jest": "27.5.2",
"@types/node": "16.18.96",
"@types/sinonjs__fake-timers": "8.1.5",
"@types/supertest": "2.0.16",
"mock-socket": "9.3.1",
"supertest": "6.2.4",
"typescript": "5.0.4"
}
}
11 changes: 11 additions & 0 deletions packages/sources/tp/src/config/includes.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
[
{
"from": "CAD",
"to": "USD",
"includes": [
{
"from": "USD",
"to": "CAD",
"inverse": true
}
]
},
{
"from": "AED",
"to": "USD",
Expand Down
2 changes: 1 addition & 1 deletion packages/sources/tp/src/endpoint/price.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const generateInputParams = (): InputParameters<PriceEndpointInputParamet
...priceEndpointInputParametersDefinition,
streamName: {
aliases: ['source'],
description: 'test',
description: 'TP or ICAP',
options: ['TP', 'IC'],
default: 'TP',
required: false,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Price Endpoint should return error on empty base 1`] = `
{
"error": {
"message": "[Param: base] param is required but no value was provided",
"name": "AdapterError",
},
"status": "errored",
"statusCode": 400,
}
`;

exports[`Price Endpoint should return error on empty body 1`] = `
{
"error": {
"message": "[Param: base] param is required but no value was provided",
"name": "AdapterError",
},
"status": "errored",
"statusCode": 400,
}
`;

exports[`Price Endpoint should return error on empty data 1`] = `
{
"error": {
"message": "[Param: base] param is required but no value was provided",
"name": "AdapterError",
},
"status": "errored",
"statusCode": 400,
}
`;

exports[`Price Endpoint should return error on empty quote 1`] = `
{
"error": {
"message": "[Param: quote] param is required but no value was provided",
"name": "AdapterError",
},
"status": "errored",
"statusCode": 400,
}
`;

exports[`Price Endpoint should return error when queried for TP price 1`] = `
{
"error": {
"message": "The EA has not received any values from the Data Provider for the requested data yet. Retry after a short delay, and if the problem persists raise this issue in the relevant channels.",
"name": "AdapterError",
},
"status": "errored",
"statusCode": 504,
}
`;

exports[`Price Endpoint should return error when queried for stale price 1`] = `
{
"error": {
"message": "The EA has not received any values from the Data Provider for the requested data yet. Retry after a short delay, and if the problem persists raise this issue in the relevant channels.",
"name": "AdapterError",
},
"status": "errored",
"statusCode": 504,
}
`;

exports[`Price Endpoint should return price 1`] = `
{
"data": {
"result": 1.0539,
},
"result": 1.0539,
"statusCode": 200,
"timestamps": {
"providerDataReceivedUnixMs": 1678242600000,
"providerDataStreamEstablishedUnixMs": 1678242600000,
},
}
`;

exports[`Price Endpoint should return price for inverse pair 1`] = `
{
"data": {
"result": 1.239771881973717,
},
"result": 1.239771881973717,
"statusCode": 200,
"timestamps": {
"providerDataReceivedUnixMs": 1678242600000,
"providerDataStreamEstablishedUnixMs": 1678242600000,
},
}
`;

exports[`Price Endpoint should return price for specific source 1`] = `
{
"data": {
"result": 1.55,
},
"result": 1.55,
"statusCode": 200,
"timestamps": {
"providerDataReceivedUnixMs": 1678242600000,
"providerDataStreamEstablishedUnixMs": 1678242600000,
},
}
`;

exports[`Price Endpoint should succeed with CAD/USD 1`] = `
{
"data": {
"result": 0.16,
},
"result": 0.16,
"statusCode": 200,
"timestamps": {
"providerDataReceivedUnixMs": 1678242600000,
"providerDataStreamEstablishedUnixMs": 1678242600000,
},
}
`;

exports[`Price Endpoint should succeed with USD/CAD 1`] = `
{
"data": {
"result": 6.25,
},
"result": 6.25,
"statusCode": 200,
"timestamps": {
"providerDataReceivedUnixMs": 1678242600000,
"providerDataStreamEstablishedUnixMs": 1678242600000,
},
}
`;
128 changes: 128 additions & 0 deletions packages/sources/tp/test/integration/icap_adapter.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import * as process from 'process'
import { AddressInfo } from 'net'
import {
mockWebSocketProvider,
mockPriceWebSocketServer,
createAdapter,
setEnvVariables,
} from './setup'
import request, { SuperTest, Test } from 'supertest'
import { Server } from 'mock-socket'
import { expose, ServerInstance } from '@chainlink/external-adapter-framework'
import { sleep } from '@chainlink/external-adapter-framework/util'
import { WebSocketClassProvider } from '@chainlink/external-adapter-framework/transports'
import { mockConnectionTime } from './icap_fixtures'
import { PriceEndpointInputParametersDefinition } from '@chainlink/external-adapter-framework/adapter'
import { TypeFromDefinition } from '@chainlink/external-adapter-framework/validation/input-params'

type AdapterRequest = {
data?: TypeFromDefinition<PriceEndpointInputParametersDefinition>
}

describe('Price Endpoint', () => {
let fastify: ServerInstance | undefined
let req: SuperTest<Test>
let mockPriceWsServer: Server | undefined
let spy: jest.SpyInstance

const makeRequest = (body: AdapterRequest) =>
req
.post('')
.send(body)
.set('Accept', '*/*')
.set('Content-Type', 'application/json')
.expect('Content-Type', /json/)

jest.setTimeout(10000)

let oldEnv: NodeJS.ProcessEnv

beforeAll(async () => {
const wsEndpoint = 'ws://localhost:9099'

oldEnv = JSON.parse(JSON.stringify(process.env))
process.env['WS_SUBSCRIPTION_TTL'] = '5000'
process.env['CACHE_MAX_AGE'] = '5000'
process.env['CACHE_POLLING_MAX_RETRIES'] = '0'
process.env['METRICS_ENABLED'] = 'false'
process.env['WS_API_USERNAME'] = 'test-username'
process.env['WS_API_PASSWORD'] = 'test-password'
process.env['WS_API_ENDPOINT'] = wsEndpoint

spy = jest.spyOn(Date, 'now').mockReturnValue(mockConnectionTime.getTime())

mockWebSocketProvider(WebSocketClassProvider)
mockPriceWsServer = mockPriceWebSocketServer(wsEndpoint)

fastify = await expose(createAdapter())
req = request(
`http://localhost:${(fastify?.server.address() as AddressInfo).port}?streamName=ic`,
)

// Send initial request to start background execute
await req.post('/').send({ data: { base: 'JPY', quote: 'USD' } })
await sleep(5000)
})

afterAll((done) => {
spy.mockRestore()
setEnvVariables(oldEnv)
mockPriceWsServer?.close()
fastify?.close(done())
})

it('should succeed with CAD/USD', async () => {
const response = await makeRequest({ data: { base: 'CAD', quote: 'USD' } })
expect(response.body).toMatchSnapshot()
}, 30000)

it('should succeed with USD/CAD', async () => {
const response = await makeRequest({ data: { base: 'USD', quote: 'CAD' } })
expect(response.body).toMatchSnapshot()
}, 30000)

it('should return price', async () => {
const response = await makeRequest({ data: { base: 'EUR', quote: 'USD' } })
expect(response.body).toMatchSnapshot()
}, 30000)

it('should return price for inverse pair', async () => {
const response = await makeRequest({ data: { base: 'IDR', quote: 'USD' } })
expect(response.body).toMatchSnapshot()
}, 30000)

it('should return price for specific source', async () => {
const response = await makeRequest({ data: { base: 'EUR', quote: 'USD', sourceName: 'BGK' } })
expect(response.body).toMatchSnapshot()
}, 30000)

it('should return error when queried for TP price', async () => {
const response = await makeRequest({ data: { base: 'ABC', quote: 'USD' } })
expect(response.body).toMatchSnapshot()
}, 30000)

it('should return error when queried for stale price', async () => {
const response = await makeRequest({ data: { base: 'JPY', quote: 'USD' } })
expect(response.body).toMatchSnapshot()
}, 30000)

it('should return error on empty body', async () => {
const response = await makeRequest({})
expect(response.body).toMatchSnapshot()
}, 30000)

it('should return error on empty data', async () => {
const response = await makeRequest({ data: {} })
expect(response.body).toMatchSnapshot()
}, 30000)

it('should return error on empty base', async () => {
const response = await makeRequest({ data: { quote: 'USD' } })
expect(response.body).toMatchSnapshot()
}, 30000)

it('should return error on empty quote', async () => {
const response = await makeRequest({ data: { base: 'EUR' } })
expect(response.body).toMatchSnapshot()
}, 30000)
})
Loading

0 comments on commit ae6da68

Please sign in to comment.