From 9486adfc3ed9f45b4abdd245eadcf9c5dc4fbf3b Mon Sep 17 00:00:00 2001 From: Juanma Hidalgo Date: Fri, 15 Nov 2024 12:48:22 +0100 Subject: [PATCH] feat: remove ping handler and add tests to squid-controller --- src/controllers/handlers/ping-handler.ts | 17 ---- src/controllers/routes.ts | 2 - src/ports/squids/component.ts | 2 +- src/ports/squids/{utilts.ts => utils.ts} | 0 test/unit/ping-controller.spec.ts | 30 -------- test/unit/squid-controller.spec.ts | 98 ++++++++++++++++++++++++ 6 files changed, 99 insertions(+), 50 deletions(-) delete mode 100644 src/controllers/handlers/ping-handler.ts rename src/ports/squids/{utilts.ts => utils.ts} (100%) delete mode 100644 test/unit/ping-controller.spec.ts create mode 100644 test/unit/squid-controller.spec.ts diff --git a/src/controllers/handlers/ping-handler.ts b/src/controllers/handlers/ping-handler.ts deleted file mode 100644 index 26a3bd0..0000000 --- a/src/controllers/handlers/ping-handler.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { HandlerContextWithPath } from '../../types' - -// handlers arguments only type what they need, to make unit testing easier -export async function pingHandler(context: Pick, 'url' | 'components'>) { - const { - url, - components: { metrics } - } = context - - metrics.increment('test_ping_counter', { - pathname: url.pathname - }) - - return { - body: url.pathname - } -} diff --git a/src/controllers/routes.ts b/src/controllers/routes.ts index 54fa143..6c9e73f 100644 --- a/src/controllers/routes.ts +++ b/src/controllers/routes.ts @@ -1,13 +1,11 @@ import { Router } from '@well-known-components/http-server' import { GlobalContext } from '../types' -import { pingHandler } from './handlers/ping-handler' import { squidsHandler } from './handlers/squid-handler' // We return the entire router because it will be easier to test than a whole server export async function setupRouter(): Promise> { const router = new Router() - router.get('/ping', pingHandler) router.get('/list', squidsHandler) return router diff --git a/src/ports/squids/component.ts b/src/ports/squids/component.ts index 1f96599..83ff4aa 100644 --- a/src/ports/squids/component.ts +++ b/src/ports/squids/component.ts @@ -12,7 +12,7 @@ import { IPgComponent } from '@well-known-components/pg-component' import { Network } from '@dcl/schemas' import { getPromoteQuery } from './queries' import { ISquidComponent, Squid, SquidMetric } from './types' -import { getMetricValue, getSquidsNetworksMapping } from './utilts' +import { getMetricValue, getSquidsNetworksMapping } from './utils' const AWS_REGION = 'us-east-1' diff --git a/src/ports/squids/utilts.ts b/src/ports/squids/utils.ts similarity index 100% rename from src/ports/squids/utilts.ts rename to src/ports/squids/utils.ts diff --git a/test/unit/ping-controller.spec.ts b/test/unit/ping-controller.spec.ts deleted file mode 100644 index 892551d..0000000 --- a/test/unit/ping-controller.spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { createTestMetricsComponent } from '@well-known-components/metrics' -import { pingHandler } from '../../src/controllers/handlers/ping-handler' -import { metricDeclarations } from '../../src/metrics' - -describe('ping-controller-unit', () => { - it('must return the pathname of a URL', async () => { - const url = new URL('https://github.com/well-known-components') - const metrics = createTestMetricsComponent(metricDeclarations) - expect((await metrics.getValue('test_ping_counter')).values).toEqual([]) - expect(await pingHandler({ url, components: { metrics } })).toEqual({ body: url.pathname }) - expect((await metrics.getValue('test_ping_counter')).values).toEqual([{ labels: { pathname: '/well-known-components' }, value: 1 }]) - }) - - it('metrics should create a brand new registry', async () => { - const url = new URL('https://github.com/well-known-components') - const metrics = createTestMetricsComponent(metricDeclarations) - expect((await metrics.getValue('test_ping_counter')).values).toEqual([]) - expect(await pingHandler({ url, components: { metrics } })).toEqual({ body: url.pathname }) - expect((await metrics.getValue('test_ping_counter')).values).toEqual([{ labels: { pathname: '/well-known-components' }, value: 1 }]) - }) - - it('calling twice should increment twice the metrics', async () => { - const url = new URL('https://github.com/well-known-components') - const metrics = createTestMetricsComponent(metricDeclarations) - expect((await metrics.getValue('test_ping_counter')).values).toEqual([]) - expect(await pingHandler({ url, components: { metrics } })).toEqual({ body: url.pathname }) - expect(await pingHandler({ url, components: { metrics } })).toEqual({ body: url.pathname }) - expect((await metrics.getValue('test_ping_counter')).values).toEqual([{ labels: { pathname: '/well-known-components' }, value: 2 }]) - }) -}) diff --git a/test/unit/squid-controller.spec.ts b/test/unit/squid-controller.spec.ts new file mode 100644 index 0000000..3c79fcc --- /dev/null +++ b/test/unit/squid-controller.spec.ts @@ -0,0 +1,98 @@ +import { ECSClient, UpdateServiceCommand } from '@aws-sdk/client-ecs' +import { IFetchComponent, IConfigComponent } from '@well-known-components/interfaces' +import { IPgComponent } from '@well-known-components/pg-component' +import { createSubsquidComponent } from '../../src/ports/squids/component' +import { getPromoteQuery } from '../../src/ports/squids/queries' + +jest.mock('@aws-sdk/client-ecs') +jest.mock('../../src/ports/squids/queries') + +describe('createSubsquidComponent', () => { + let fetchMock: IFetchComponent + let dappsDatabaseMock: IPgComponent + let configMock: IConfigComponent + let ecsClientMock: ECSClient + + beforeEach(() => { + fetchMock = { fetch: jest.fn() } as IFetchComponent + dappsDatabaseMock = { query: jest.fn() } as unknown as IPgComponent + configMock = { requireString: jest.fn().mockResolvedValue('test-cluster') } as unknown as IConfigComponent + + ecsClientMock = new ECSClient({ region: 'us-east-1' }) + ;(ECSClient as jest.Mock).mockImplementation(() => ecsClientMock) + }) + + describe('list', () => { + it('should list squid services', async () => { + const services = [{ serviceName: 'test-squid-service' }] + const tasks = [ + { + version: 1, + createdAt: new Date(), + healthStatus: 'HEALTHY', + lastStatus: 'RUNNING', + attachments: [ + { + type: 'ElasticNetworkInterface', + details: [{ name: 'privateIPv4Address', value: '127.0.0.1' }] + } + ] + } + ] + + ;(ecsClientMock.send as jest.Mock) + .mockResolvedValueOnce({ serviceArns: ['arn:aws:squid-service'] }) // ListServicesCommand + .mockResolvedValueOnce({ services }) // DescribeServicesCommand + .mockResolvedValueOnce({ taskArns: ['arn:aws:ecs:task/test'] }) // ListTasksCommand + .mockResolvedValueOnce({ tasks }) // DescribeTasksCommand + ;(fetchMock.fetch as jest.Mock).mockResolvedValue({ + text: jest.fn().mockResolvedValue('sqd_processor_last_block 1000') + }) + + const subsquid = await createSubsquidComponent({ + fetch: fetchMock, + dappsDatabase: dappsDatabaseMock, + config: configMock + }) + const result = await subsquid.list() + + expect(result).toHaveLength(1) + expect(result[0].name).toBe('test-squid-service') + expect(result[0].metrics?.ETHEREUM?.sqd_processor_last_block).toBe(1000) + }) + }) + + describe('promote', () => { + it('should execute the promote query', async () => { + ;(getPromoteQuery as jest.Mock).mockReturnValue('PROMOTE QUERY') + ;(dappsDatabaseMock.query as jest.Mock).mockResolvedValue({}) + + const subsquid = await createSubsquidComponent({ + fetch: fetchMock, + dappsDatabase: dappsDatabaseMock, + config: configMock + }) + await subsquid.promote('test-service-name') + + expect(getPromoteQuery).toHaveBeenCalledWith('test-service-name', expect.any(String), expect.any(String)) + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(dappsDatabaseMock.query).toHaveBeenCalledWith('PROMOTE QUERY') + }) + }) + + describe('downgrade', () => { + it('should set desiredCount to 0', async () => { + ;(ecsClientMock.send as jest.Mock).mockResolvedValue({}) + + const subsquid = await createSubsquidComponent({ + fetch: fetchMock, + dappsDatabase: dappsDatabaseMock, + config: configMock + }) + await subsquid.downgrade('test-service-name') + + // eslint-disable-next-line @typescript-eslint/unbound-method + expect(ecsClientMock.send).toHaveBeenCalledWith(expect.any(UpdateServiceCommand)) + }) + }) +})