From 855fcc71ad052d67a5761d2625058e9ae8d87235 Mon Sep 17 00:00:00 2001 From: Alexey Yarmosh Date: Mon, 6 Nov 2023 19:05:41 +0300 Subject: [PATCH] test: add adopted-probes tests --- src/probe/types.ts | 2 +- test/tests/unit/adopted-probes.test.ts | 267 ++++++++++++++++++------- 2 files changed, 198 insertions(+), 71 deletions(-) diff --git a/src/probe/types.ts b/src/probe/types.ts index 04352fd7..ba2fd523 100644 --- a/src/probe/types.ts +++ b/src/probe/types.ts @@ -8,7 +8,7 @@ export type ProbeLocation = { asn: number; latitude: number; longitude: number; - state: string | undefined; + state?: string | undefined; network: string; normalizedNetwork: string; isHosting?: boolean | undefined; diff --git a/test/tests/unit/adopted-probes.test.ts b/test/tests/unit/adopted-probes.test.ts index eaa4173c..1735a16f 100644 --- a/test/tests/unit/adopted-probes.test.ts +++ b/test/tests/unit/adopted-probes.test.ts @@ -2,6 +2,57 @@ import { expect } from 'chai'; import type { Knex } from 'knex'; import * as sinon from 'sinon'; import { AdoptedProbes } from '../../../src/lib/adopted-probes.js'; +import type { Probe } from '../../../src/probe/types.js'; + +const defaultAdoptedProbe = { + username: 'jimaek', + ip: '1.1.1.1', + uuid: '1-1-1-1-1', + lastSyncDate: '1970-01-01', + tags: '["dashboardtag"]', + isCustomCity: 0, + status: 'ready', + version: '0.26.0', + country: 'IE', + city: 'Dublin', + latitude: 53.3331, + longitude: -6.2489, + asn: 16509, + network: 'Amazon.com, Inc.', +}; + +const defaultConnectedProbe: Probe = { + ipAddress: '1.1.1.1', + uuid: '1-1-1-1-1', + status: 'ready', + version: '0.26.0', + nodeVersion: 'v18.17.0', + location: { + continent: 'EU', + region: 'Northern Europe', + normalizedRegion: 'northern europe', + country: 'IE', + city: 'Dublin', + normalizedCity: 'dublin', + asn: 16509, + latitude: 53.3331, + longitude: -6.2489, + network: 'Amazon.com, Inc.', + normalizedNetwork: 'amazon.com, inc.', + }, + tags: [], + index: [], + client: '', + host: '', + resolvers: [], + stats: { + cpu: { + count: 0, + load: [], + }, + jobs: { count: 0 }, + }, +}; const selectStub = sinon.stub(); const updateStub = sinon.stub(); @@ -10,10 +61,11 @@ const whereStub = sinon.stub().returns({ update: updateStub, delete: deleteStub, }); +const joinStub = sinon.stub().returns({ + select: selectStub, +}); const sqlStub = sinon.stub().returns({ - join: sinon.stub().returns({ - select: selectStub, - }), + join: joinStub, where: whereStub, }); const fetchSocketsStub = sinon.stub().resolves([]); @@ -31,7 +83,7 @@ describe('AdoptedProbes', () => { it('syncDashboardData method should sync the data', async () => { const adoptedProbes = new AdoptedProbes(sqlStub as unknown as Knex, fetchSocketsStub); - selectStub.resolves([{ ip: '1.1.1.1', uuid: '1-1-1-1-1', lastSyncDate: '1970-01-01' }]); + selectStub.resolves([{ ...defaultAdoptedProbe }]); expect(sqlStub.callCount).to.equal(0); expect(selectStub.callCount).to.equal(0); @@ -40,6 +92,9 @@ describe('AdoptedProbes', () => { expect(sqlStub.callCount).to.equal(1); expect(sqlStub.args[0]).deep.equal([ 'adopted_probes' ]); + expect(joinStub.callCount).to.equal(1); + expect(joinStub.args[0]).deep.equal([ 'directus_users', 'adopted_probes.userId', '=', 'directus_users.id' ]); + expect(selectStub.callCount).to.equal(1); expect(selectStub.args[0]).deep.equal([ @@ -64,8 +119,8 @@ describe('AdoptedProbes', () => { it('class should update uuid if it is wrong', async () => { const adoptedProbes = new AdoptedProbes(sqlStub as unknown as Knex, fetchSocketsStub); - selectStub.resolves([{ ip: '1.1.1.1', uuid: '1-1-1-1-1', lastSyncDate: '1970-01-01' }]); - fetchSocketsStub.resolves([{ data: { probe: { ipAddress: '1.1.1.1', uuid: '2-2-2-2-2' } } }]); + selectStub.resolves([{ ...defaultAdoptedProbe }]); + fetchSocketsStub.resolves([{ data: { probe: { ...defaultConnectedProbe, uuid: '2-2-2-2-2' } } }]); await adoptedProbes.syncDashboardData(); @@ -77,8 +132,8 @@ describe('AdoptedProbes', () => { it('class should update ip if it is wrong', async () => { const adoptedProbes = new AdoptedProbes(sqlStub as unknown as Knex, fetchSocketsStub); - selectStub.resolves([{ ip: '1.1.1.1', uuid: '1-1-1-1-1', lastSyncDate: '1970-01-01' }]); - fetchSocketsStub.resolves([{ data: { probe: { ipAddress: '2.2.2.2', uuid: '1-1-1-1-1' } } }]); + selectStub.resolves([{ ...defaultAdoptedProbe }]); + fetchSocketsStub.resolves([{ data: { probe: { ...defaultConnectedProbe, ipAddress: '2.2.2.2' } } }]); await adoptedProbes.syncDashboardData(); @@ -90,7 +145,7 @@ describe('AdoptedProbes', () => { it('class should do nothing if adopted probe was not found and lastSyncDate < 30 days away', async () => { const adoptedProbes = new AdoptedProbes(sqlStub as unknown as Knex, fetchSocketsStub); - selectStub.resolves([{ ip: '1.1.1.1', uuid: '1-1-1-1-1', lastSyncDate: '1969-12-15' }]); + selectStub.resolves([{ ...defaultAdoptedProbe, lastSyncDate: '1969-12-15' }]); fetchSocketsStub.resolves([]); await adoptedProbes.syncDashboardData(); @@ -102,7 +157,7 @@ describe('AdoptedProbes', () => { it('class should delete adoption if adopted probe was not found and lastSyncDate > 30 days away', async () => { const adoptedProbes = new AdoptedProbes(sqlStub as unknown as Knex, fetchSocketsStub); - selectStub.resolves([{ ip: '1.1.1.1', uuid: '1-1-1-1-1', lastSyncDate: '1969-11-15' }]); + selectStub.resolves([{ ...defaultAdoptedProbe, lastSyncDate: '1969-11-15' }]); fetchSocketsStub.resolves([]); await adoptedProbes.syncDashboardData(); @@ -113,21 +168,10 @@ describe('AdoptedProbes', () => { expect(deleteStub.callCount).to.equal(1); }); - it('class should do nothing if probe data is actual', async () => { + it('class should update lastSyncDate if probe is connected and lastSyncDate < 30 days away', async () => { const adoptedProbes = new AdoptedProbes(sqlStub as unknown as Knex, fetchSocketsStub); - selectStub.resolves([{ ip: '1.1.1.1', uuid: '1-1-1-1-1', lastSyncDate: '1970-01-01' }]); - fetchSocketsStub.resolves([{ data: { probe: { ipAddress: '1.1.1.1', uuid: '1-1-1-1-1' } } }]); - - await adoptedProbes.syncDashboardData(); - - expect(whereStub.callCount).to.equal(0); - expect(updateStub.callCount).to.equal(0); - }); - - it('class update lastSyncDate if probe is connected and lastSyncDate < 30 days away', async () => { - const adoptedProbes = new AdoptedProbes(sqlStub as unknown as Knex, fetchSocketsStub); - selectStub.resolves([{ ip: '1.1.1.1', uuid: '1-1-1-1-1', lastSyncDate: '1969-12-31' }]); - fetchSocketsStub.resolves([{ data: { probe: { ipAddress: '1.1.1.1', uuid: '1-1-1-1-1' } } }]); + selectStub.resolves([{ ...defaultAdoptedProbe, lastSyncDate: '1969-12-31' }]); + fetchSocketsStub.resolves([{ data: { probe: { ...defaultConnectedProbe } } }]); await adoptedProbes.syncDashboardData(); @@ -138,10 +182,10 @@ describe('AdoptedProbes', () => { expect(deleteStub.callCount).to.equal(0); }); - it('class update lastSyncDate if probe is connected and lastSyncDate > 30 days away', async () => { + it('class should update lastSyncDate if probe is connected and lastSyncDate > 30 days away', async () => { const adoptedProbes = new AdoptedProbes(sqlStub as unknown as Knex, fetchSocketsStub); - selectStub.resolves([{ ip: '1.1.1.1', uuid: '1-1-1-1-1', lastSyncDate: '1969-11-15' }]); - fetchSocketsStub.resolves([{ data: { probe: { ipAddress: '1.1.1.1', uuid: '1-1-1-1-1' } } }]); + selectStub.resolves([{ ...defaultAdoptedProbe, lastSyncDate: '1969-11-15' }]); + fetchSocketsStub.resolves([{ data: { probe: { ...defaultConnectedProbe } } }]); await adoptedProbes.syncDashboardData(); @@ -152,10 +196,10 @@ describe('AdoptedProbes', () => { expect(deleteStub.callCount).to.equal(0); }); - it('class update lastSyncDate should not update anything if lastSyncDate is today', async () => { + it('class should update lastSyncDate should not update anything if lastSyncDate is today', async () => { const adoptedProbes = new AdoptedProbes(sqlStub as unknown as Knex, fetchSocketsStub); - selectStub.resolves([{ ip: '1.1.1.1', uuid: '1-1-1-1-1', lastSyncDate: '1970-01-01' }]); - fetchSocketsStub.resolves([{ data: { probe: { ipAddress: '1.1.1.1', uuid: '1-1-1-1-1' } } }]); + selectStub.resolves([{ ...defaultAdoptedProbe }]); + fetchSocketsStub.resolves([{ data: { probe: { ...defaultConnectedProbe } } }]); await adoptedProbes.syncDashboardData(); @@ -164,21 +208,9 @@ describe('AdoptedProbes', () => { expect(deleteStub.callCount).to.equal(0); }); - it('class should update probe meta info if it is outdated', async () => { + it('class should update probe meta info if it is outdated and "isCustomCity: false"', async () => { const adoptedProbes = new AdoptedProbes(sqlStub as unknown as Knex, fetchSocketsStub); - selectStub.resolves([{ - ip: '1.1.1.1', - uuid: '1-1-1-1-1', - lastSyncDate: '1970-01-01', - status: 'ready', - version: '0.26.0', - country: 'IE', - city: 'Dublin', - latitude: 53.3331, - longitude: -6.2489, - asn: 16509, - network: 'Amazon.com, Inc.', - }]); + selectStub.resolves([{ ...defaultAdoptedProbe }]); fetchSocketsStub.resolves([{ data: { @@ -194,8 +226,8 @@ describe('AdoptedProbes', () => { country: 'GB', city: 'London', asn: 20473, - latitude: 53.3331, - longitude: -6.2489, + latitude: 51.50853, + longitude: -0.12574, network: 'The Constant Company, LLC', }, }, @@ -211,46 +243,36 @@ describe('AdoptedProbes', () => { expect(updateStub.args[0]).to.deep.equal([{ status: 'initializing', version: '0.27.0', - country: 'GB', - city: 'London', asn: 20473, network: 'The Constant Company, LLC', + country: 'GB', + city: 'London', + latitude: 51.50853, + longitude: -0.12574, }]); }); - it('class should update probe meta info if it is outdated', async () => { + it('class should partially update probe meta info if it is outdated and "isCustomCity: true"', async () => { const adoptedProbes = new AdoptedProbes(sqlStub as unknown as Knex, fetchSocketsStub); - selectStub.resolves([{ - ip: '1.1.1.1', - uuid: '1-1-1-1-1', - lastSyncDate: '1970-01-01', - status: 'ready', - version: '0.26.0', - country: 'IE', - city: 'Dublin', - latitude: 53.3331, - longitude: -6.2489, - asn: 16509, - network: 'Amazon.com, Inc.', - }]); + selectStub.resolves([{ ...defaultAdoptedProbe, isCustomCity: true }]); fetchSocketsStub.resolves([{ data: { probe: { ipAddress: '1.1.1.1', uuid: '1-1-1-1-1', - status: 'ready', - version: '0.26.0', + status: 'initializing', + version: '0.27.0', nodeVersion: 'v18.17.0', location: { continent: 'EU', region: 'Northern Europe', - country: 'IE', - city: 'Dublin', - asn: 16509, - latitude: 53.3331, - longitude: -6.2489, - network: 'Amazon.com, Inc.', + country: 'GB', + city: 'London', + asn: 20473, + latitude: 51.50853, + longitude: -0.12574, + network: 'The Constant Company, LLC', }, }, }, @@ -258,8 +280,113 @@ describe('AdoptedProbes', () => { await adoptedProbes.syncDashboardData(); + expect(whereStub.callCount).to.equal(1); + expect(whereStub.args[0]).to.deep.equal([{ ip: '1.1.1.1' }]); + expect(updateStub.callCount).to.equal(1); + + expect(updateStub.args[0]).to.deep.equal([{ + status: 'initializing', + version: '0.27.0', + asn: 20473, + network: 'The Constant Company, LLC', + }]); + }); + + it('class should not update probe meta info if it is actual', async () => { + const adoptedProbes = new AdoptedProbes(sqlStub as unknown as Knex, fetchSocketsStub); + selectStub.resolves([{ ...defaultAdoptedProbe }]); + fetchSocketsStub.resolves([{ data: { probe: { ...defaultConnectedProbe } } }]); + + await adoptedProbes.syncDashboardData(); + expect(whereStub.callCount).to.equal(0); expect(updateStub.callCount).to.equal(0); expect(deleteStub.callCount).to.equal(0); }); + + it('getByIp method should return adopted probe data', async () => { + const adoptedProbes = new AdoptedProbes(sqlStub as unknown as Knex, fetchSocketsStub); + selectStub.resolves([{ ...defaultAdoptedProbe }]); + + await adoptedProbes.syncDashboardData(); + + const adoptedProbe = adoptedProbes.getByIp('1.1.1.1'); + expect(adoptedProbe).to.deep.equal({ ...defaultAdoptedProbe, tags: [ 'dashboardtag' ], isCustomCity: false }); + }); + + it('getUpdatedLocation method should return updated location', async () => { + const adoptedProbes = new AdoptedProbes(sqlStub as unknown as Knex, fetchSocketsStub); + selectStub.resolves([{ + ...defaultAdoptedProbe, + city: 'Dundalk', + isCustomCity: true, + latitude: 54, + longitude: -6.41667, + }]); + + await adoptedProbes.syncDashboardData(); + const updatedLocation = adoptedProbes.getUpdatedLocation({ ...defaultConnectedProbe }); + expect(updatedLocation).to.deep.equal({ + continent: 'EU', + region: 'Northern Europe', + normalizedRegion: 'northern europe', + country: 'IE', + city: 'Dundalk', + normalizedCity: 'dundalk', + asn: 16509, + latitude: 54, + longitude: -6.41667, + network: 'Amazon.com, Inc.', + normalizedNetwork: 'amazon.com, inc.', + }); + }); + + it('getUpdatedLocation method should return same location object if country is different', async () => { + const adoptedProbes = new AdoptedProbes(sqlStub as unknown as Knex, fetchSocketsStub); + selectStub.resolves([{ + ...defaultAdoptedProbe, + country: 'GB', + city: 'London', + isCustomCity: true, + latitude: 51.50853, + longitude: -0.12574, + }]); + + await adoptedProbes.syncDashboardData(); + const updatedLocation = adoptedProbes.getUpdatedLocation(defaultConnectedProbe); + expect(updatedLocation).to.equal(updatedLocation); + }); + + it('getUpdatedLocation method should return same location object if "isCustomCity: false"', async () => { + const adoptedProbes = new AdoptedProbes(sqlStub as unknown as Knex, fetchSocketsStub); + selectStub.resolves([{ + ...defaultAdoptedProbe, + city: 'Dundalk', + isCustomCity: false, + latitude: 54, + longitude: -6.41667, + }]); + + await adoptedProbes.syncDashboardData(); + const updatedLocation = adoptedProbes.getUpdatedLocation(defaultConnectedProbe); + expect(updatedLocation).to.equal(defaultConnectedProbe.location); + }); + + it('getUpdatedTags method should return updated tags', async () => { + const adoptedProbes = new AdoptedProbes(sqlStub as unknown as Knex, fetchSocketsStub); + selectStub.resolves([{ ...defaultAdoptedProbe }]); + + await adoptedProbes.syncDashboardData(); + const updatedTags = adoptedProbes.getUpdatedTags({ ...defaultConnectedProbe }); + expect(updatedTags).to.deep.equal([{ type: 'user', value: 'u-jimaek-dashboardtag' }]); + }); + + it('getUpdatedTags method should return same tags array if user tags are empty', async () => { + const adoptedProbes = new AdoptedProbes(sqlStub as unknown as Knex, fetchSocketsStub); + selectStub.resolves([{ ...defaultAdoptedProbe, tags: undefined }]); + + await adoptedProbes.syncDashboardData(); + const updatedTags = adoptedProbes.getUpdatedTags(defaultConnectedProbe); + expect(updatedTags).to.equal(defaultConnectedProbe.tags); + }); });