Skip to content

Commit

Permalink
service: Server integration tests
Browse files Browse the repository at this point in the history
- Fix server tests
- Add request/response tests for following paths: /operator/info,
/subgraphs/health/, /cost, /status
  • Loading branch information
fordN committed May 31, 2024
1 parent fbc026d commit 9a8a949
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 24 deletions.
9 changes: 6 additions & 3 deletions packages/indexer-service/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
testPathIgnorePatterns: ['/node_modules/', '/dist/', '.yalc'],
globals: {
'ts-jest': {
transform: {
'^.+\\.tsx?$': ['ts-jest', {
isolatedModules: true,
},
tsconfig: 'tsconfig.json'
}],
},
globals: {
__DATABASE__: {
host: process.env.POSTGRES_TEST_HOST || bail('POSTGRES_TEST_HOST is not defined'),
port: parseInt(process.env.POSTGRES_TEST_PORT || '5432'),
Expand Down
6 changes: 3 additions & 3 deletions packages/indexer-service/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
"compile": "tsc --build",
"prepare": "yarn format && yarn lint && yarn compile",
"start": "node ./dist/index.js start",
"test": "jest --colors --verbose --detectOpenHandles",
"test:ci": "jest --verbose --ci",
"test:watch": "jest --watch --passWithNoTests --detectOpenHandles --verbose",
"test": "jest --colors --verbose --detectOpenHandles --runInBand",
"test:ci": "jest --verbose --ci --runInBand",
"test:watch": "jest --watch --passWithNoTests --detectOpenHandles --verbose --runInBand",
"clean": "rm -rf ./node_modules ./dist ./tsconfig.tsbuildinfo"
},
"bin": {
Expand Down
133 changes: 115 additions & 18 deletions packages/indexer-service/src/server/__tests__/server.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Assumes a graph-node is running
* Assumes a graph-node is running and is accessible at http://127.0.0.1
*/

import http from 'http'
Expand Down Expand Up @@ -28,11 +28,11 @@ import {
defineQueryFeeModels,
IndexerManagementClient,
IndexerManagementModels,
IndexingStatusResolver,
monitorEligibleAllocations,
NetworkSubgraph,
QueryFeeModels,
getTestProvider,
GraphNode,
} from '@graphprotocol/indexer-common'

// Make global Jest variable available
Expand All @@ -48,7 +48,6 @@ let models: IndexerManagementModels
let queryFeeModels: QueryFeeModels
let address: string
let contracts: NetworkContracts
let indexingStatusResolver: IndexingStatusResolver
let networkSubgraph: NetworkSubgraph
let client: IndexerManagementClient
let receiptManager: AllocationReceiptManager
Expand All @@ -65,25 +64,28 @@ const setup = async () => {
contracts = await connectContracts(getTestProvider('sepolia'), 11155111, undefined)
sequelize = await sequelize.sync({ force: true })
const statusEndpoint = 'http://127.0.0.1:8030/graphql'
indexingStatusResolver = new IndexingStatusResolver({
logger: logger,
statusEndpoint,
})
const queryEndpoint = 'http://127.0.0.1:8000'
networkSubgraph = await NetworkSubgraph.create({
logger,
endpoint:
'https://api.thegraph.com/subgraphs/name/graphprotocol/graph-network-testnet',
'https://api.thegraph.com/subgraphs/name/graphprotocol/graph-network-sepolia',
deployment: undefined,
})
const indexNodeIDs = ['node_1']

const graphNode = new GraphNode(
logger,
// We can use a fake Graph Node admin endpoint here because Indexer Service
// doesn't need to perform management actions on Graph Node.
'http://fake-graph-node-admin-endpoint',
queryEndpoint,
statusEndpoint,
indexNodeIDs,
)
client = await createIndexerManagementClient({
models,
address,
contracts,
indexingStatusResolver,
graphNode,
indexNodeIDs,
deploymentManagementEndpoint: statusEndpoint,
networkSubgraph,
logger,
defaults: {
// This is just a dummy, since we're never writing to the management
Expand All @@ -92,16 +94,15 @@ const setup = async () => {
allocationAmount: BigNumber.from('0'),
},
},
features: {
injectDai: true,
},
multiNetworks: undefined,
})

receiptManager = new AllocationReceiptManager(
sequelize,
queryFeeModels,
logger,
toAddress(address), //update maybe
'eip155:11155111',
)

const release = {
Expand All @@ -113,6 +114,7 @@ const setup = async () => {

// Monitor indexer allocations that we may receive traffic for
const allocations = monitorEligibleAllocations({
protocolNetwork: 'eip155:11155111',
indexer: toAddress(address),
logger,
networkSubgraph,
Expand Down Expand Up @@ -141,10 +143,10 @@ const setup = async () => {
})

server = await createServer({
logger,
logger: logger.child({ component: 'Server' }),
port: 9600,
queryProcessor,
graphNodeStatusEndpoint: 'http://127.0.0.1:8030/graphql',
graphNodeStatusEndpoint: statusEndpoint,
metrics,
freeQueryAuthToken: '',
indexerManagementClient: client,
Expand All @@ -153,6 +155,9 @@ const setup = async () => {
networkSubgraph,
networkSubgraphAuthToken: 'superdupersecrettoken',
serveNetworkSubgraph: false,
infoRateLimit: 3,
statusRateLimit: 2,
bodySizeLimit: 0.1,
})
server.on('connection', socket => {
logger.debug('Connection established', { socket })
Expand Down Expand Up @@ -180,11 +185,103 @@ const teardown = async () => {
await sequelize.drop({})
}

// Helpers for sending test requests
const testGetRequest = async (
path: string,
expectedStatusCode: number,
expectedResponse: object | string,
) => {
const response = await supertest(server).get(path)
expect(response.status).toEqual(expectedStatusCode)
if (response.status === 429 | response.status === 500) {
expect(response.text).toEqual(expectedResponse)
} else if (response.status === 200) {
expect(response.body).toEqual(expectedResponse)
}
}

const testGraphQLRequest = async (
path: string,
query: object,
expectedStatusCode: number,
expectedResponse: object | string,
) => {
const response = await supertest(server)
.post(path)
.send(query)
.set('Accept', 'application/json')

expect(response.status).toEqual(expectedStatusCode)
if (response.status === 429 | response.status === 500) {
expect(response.text).toEqual(expectedResponse)
} else if (response.status === 200) {
expect(response.body).toEqual(expectedResponse)
}
}

describe('Server', () => {
beforeAll(setup)
afterAll(teardown)

it('is ready to roll', done => {
supertest(server).get('/').expect(200, done)
})

it('Operator info endpoint returns expected data', async () => {
const expectedResponses: [number, object | string][] = [
[
200,
{ publicKey: '0x04e68acfc0253a10620dff706b0a1b1f1f5833ea3beb3bde2250d5f271f3563606672ebc45e0b7ea2e816ecb70ca03137b1c9476eec63d4632e990020b7b6fba39'} ,
],
]
for (const [expectedStatus, expectedResponse] of expectedResponses) {
await testGetRequest('/operator/info', expectedStatus, expectedResponse)
}
})

it('Subgraph deployment health endpoint returns expected data', async () => {
const expectedResponses: [number, string][] = [
[
500,
'Invalid indexing status',
],
]
for (const [expectedStatus, expectedResponse] of expectedResponses) {
await testGetRequest('/subgraphs/health/Qmxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', expectedStatus, expectedResponse)
}
})

// Note: the rate limiting part of this test assumes the tests are run in sequence (suggest using --runInBand)
it('Cost endpoint returns expected data and is rate limited correctly', async () => {
const expectedResponses: [number, object | string][] = [
[200, { data: { costModels: []}}],
[429, 'Too many requests, please try again later.'],
]

for (const [expectedStatus, expectedResponse] of expectedResponses) {
await testGraphQLRequest(
'/cost',
{ query: '{costModels(deployments: ["Qmxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]){ deployment model } }'},
expectedStatus,
expectedResponse,
)
}
})

it('Status endpoint returns expected data and is rate limited correctly', async () => {
const expectedResponses: [number, object | string][] = [
[200, { data: { indexingStatuses: []}}],
[200, { data: { indexingStatuses: []}}],
[429, 'Too many requests, please try again later.'],
]

for (const [expectedStatus, expectedResponse] of expectedResponses) {
await testGraphQLRequest(
'/status',
{ query: '{indexingStatuses(subgraphs: ["Qmxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"]){ subgraph health } }'},
expectedStatus,
expectedResponse,
)
}
})
})

0 comments on commit 9a8a949

Please sign in to comment.