Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/__tests__/__snapshots__/options.defaults.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ exports[`options defaults should return specific properties: defaults 1`] = `
---

",
"stats": {
"reportIntervalMs": {
"health": 30000,
"transport": 10000,
},
},
"toolMemoOptions": {
"fetchDocs": {
"cacheErrors": false,
Expand Down
4 changes: 3 additions & 1 deletion src/__tests__/__snapshots__/options.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,9 @@ exports[`parseCliOptions should attempt to parse args with --http and --port 1`]
exports[`parseCliOptions should attempt to parse args with --http and invalid --port 1`] = `
{
"docsHost": false,
"http": {},
"http": {
"port": 0,
},
"isHttp": true,
"logging": {
"level": "info",
Expand Down
30 changes: 30 additions & 0 deletions src/__tests__/__snapshots__/server.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ exports[`runServer should allow server to be stopped, http stop server: diagnost
[
"Server logging enabled.",
],
[
"Server stats enabled.",
],
[
"No external tools loaded.",
],
Expand Down Expand Up @@ -38,6 +41,9 @@ exports[`runServer should allow server to be stopped, stdio stop server: diagnos
[
"Server logging enabled.",
],
[
"Server stats enabled.",
],
[
"No external tools loaded.",
],
Expand Down Expand Up @@ -70,6 +76,9 @@ exports[`runServer should attempt to run server, create transport, connect, and
[
"Server logging enabled.",
],
[
"Server stats enabled.",
],
[
"No external tools loaded.",
],
Expand Down Expand Up @@ -107,6 +116,9 @@ exports[`runServer should attempt to run server, disable SIGINT handler: diagnos
[
"Server logging enabled.",
],
[
"Server stats enabled.",
],
[
"No external tools loaded.",
],
Expand Down Expand Up @@ -139,6 +151,9 @@ exports[`runServer should attempt to run server, enable SIGINT handler explicitl
[
"Server logging enabled.",
],
[
"Server stats enabled.",
],
[
"No external tools loaded.",
],
Expand Down Expand Up @@ -176,6 +191,9 @@ exports[`runServer should attempt to run server, register a tool: diagnostics 1`
[
"Server logging enabled.",
],
[
"Server stats enabled.",
],
[
"No external tools loaded.",
],
Expand Down Expand Up @@ -224,6 +242,9 @@ exports[`runServer should attempt to run server, register multiple tools: diagno
[
"Server logging enabled.",
],
[
"Server stats enabled.",
],
[
"No external tools loaded.",
],
Expand Down Expand Up @@ -282,6 +303,9 @@ exports[`runServer should attempt to run server, use custom options: diagnostics
[
"Server logging enabled.",
],
[
"Server stats enabled.",
],
[
"No external tools loaded.",
],
Expand Down Expand Up @@ -319,6 +343,9 @@ exports[`runServer should attempt to run server, use default tools, http: diagno
[
"Server logging enabled.",
],
[
"Server stats enabled.",
],
[
"No external tools loaded.",
],
Expand Down Expand Up @@ -369,6 +396,9 @@ exports[`runServer should attempt to run server, use default tools, stdio: diagn
[
"Server logging enabled.",
],
[
"Server stats enabled.",
],
[
"No external tools loaded.",
],
Expand Down
1 change: 1 addition & 0 deletions src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ describe('main', () => {
const mockServerInstance = {
stop: jest.fn().mockResolvedValue(undefined),
isRunning: jest.fn().mockReturnValue(true),
getStats: jest.fn().mockReturnValue({}),
onLog: jest.fn()
};

Expand Down
78 changes: 77 additions & 1 deletion src/__tests__/server.helpers.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
import { freezeObject, generateHash, hashCode, isPlainObject, isPromise, isReferenceLike, mergeObjects } from '../server.helpers';
import {
freezeObject,
generateHash,
hashCode,
isPlainObject,
isPromise,
isReferenceLike,
mergeObjects,
portValid
} from '../server.helpers';

describe('freezeObject', () => {
it.each([
Expand Down Expand Up @@ -598,3 +607,70 @@ describe('mergeObjects', () => {
expect((Object.prototype as any).polluted).toBeUndefined();
});
});

describe('portValid', () => {
it.each([
{
description: 'valid',
port: 8080,
expected: 8080
},
{
description: 'zero',
port: 0,
expected: 0
},
{
description: 'upper-range',
port: 65535,
expected: 65535
},
{
description: 'out-of-range',
port: 10_0000,
expected: undefined
},
{
description: 'out-of-range negative',
port: -10_0000,
expected: undefined
},
{
description: 'string',
port: '9000',
expected: 9000
},
{
description: 'empty string',
port: '',
expected: undefined
},
{
description: 'NaN',
port: NaN,
expected: undefined
},
{
description: 'float',
port: 1.088,
expected: undefined
},
{
description: 'out-of-range float',
port: -1.088,
expected: undefined
},
{
description: 'undefined',
port: undefined,
expected: undefined
},
{
description: 'null',
port: null,
expected: undefined
}
])('should validate a port, $description', ({ port, expected }) => {
expect(portValid(port)).toBe(expected);
});
});
94 changes: 94 additions & 0 deletions src/__tests__/server.stats.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import diagnostics_channel from 'node:diagnostics_channel';
import { healthReport, statsReport, transportReport, createServerStats } from '../server.stats';
import { getStatsOptions } from '../options.context';

describe('healthReport', () => {
const statsOptions = getStatsOptions();

it('should generate a health report', () => {
const type = 'health';
const channelName = statsOptions.channels[type];
const channel = diagnostics_channel.channel(channelName);
const handler = jest.fn();

channel.subscribe(handler);

const report = healthReport(statsOptions);

expect(Object.keys(handler.mock.calls[0][0])).toEqual(expect.arrayContaining(['timestamp', 'type', 'memory', 'uptime']));

clearTimeout(report);
});
});

describe('statsReport', () => {
const statsOptions = getStatsOptions();

it.each([
{ description: 'stdio', httpPort: undefined },
{ description: 'http', httpPort: 3030 }
])('should generate a stats report, $description', ({ httpPort }) => {
const report = statsReport({ httpPort }, statsOptions);

expect(Object.keys(report)).toEqual(expect.arrayContaining(['timestamp', 'reports']));
expect(Object.keys(report.reports.transport).includes('port')).toBe(httpPort !== undefined);

expect(report.reports.transport.channelId).toBe(statsOptions.channels.transport);
expect(report.reports.health.channelId).toBe(statsOptions.channels.health);
expect(report.reports.traffic.channelId).toBe(statsOptions.channels.traffic);
});
});

describe('transportReport', () => {
const statsOptions = getStatsOptions();

it('should generate a transport report', () => {
const type = 'transport';
const channelName = statsOptions.channels[type];
const channel = diagnostics_channel.channel(channelName);
const handler = jest.fn();

channel.subscribe(handler);

const report = transportReport({ httpPort: 9999 }, statsOptions);

expect(Object.keys(handler.mock.calls[0][0])).toEqual(expect.arrayContaining(['timestamp', 'type', 'method', 'port']));

clearTimeout(report);
});
});

describe('createServerStats', () => {
const statsOptions = getStatsOptions();

beforeEach(() => {
jest.useFakeTimers();
});

afterEach(() => {
jest.useRealTimers();
});

it('should resolve stats promise after setStats is called', async () => {
const tracker = createServerStats(statsOptions, { isHttp: true } as any);
const httpHandle = { port: 9999, close: jest.fn() };

tracker.setStats(httpHandle as any);

const stats = await tracker.getStats();

expect(stats.reports.transport.port).toBe(9999);
expect(stats.reports.transport.method).toBe('http');

tracker.unsubscribe();
});

it('should correctly clean up timers on unsubscribe', () => {
const tracker = createServerStats();
const spy = jest.spyOn(global, 'clearTimeout');

tracker.unsubscribe();

expect(spy).toHaveBeenCalledTimes(1);
});
});
1 change: 1 addition & 0 deletions src/__tests__/server.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ describe('runServer', () => {
// Mock HTTP transport
mockClose = jest.fn().mockResolvedValue(undefined);
mockHttpHandle = {
port: 0,
close: mockClose
};

Expand Down
Loading
Loading