mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-16 11:33:30 +01:00
refactor(WebSocketManager)!: remove deprecated rest option (#10998)
BREAKING CHANGE: The `rest` option in the `WebSocketManager` constructor has been removed. Pass a `fetchGatewayInformation` function instead.
This commit is contained in:
12
packages/ws/__tests__/gateway.mock.ts
Normal file
12
packages/ws/__tests__/gateway.mock.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import type { RESTGetAPIGatewayBotResult } from 'discord-api-types/v10';
|
||||
|
||||
export const mockGatewayInformation: RESTGetAPIGatewayBotResult = {
|
||||
shards: 1,
|
||||
session_start_limit: {
|
||||
max_concurrency: 3,
|
||||
reset_after: 60,
|
||||
remaining: 3,
|
||||
total: 3,
|
||||
},
|
||||
url: 'wss://gateway.discord.gg',
|
||||
};
|
||||
@@ -1,7 +1,5 @@
|
||||
/* eslint-disable @typescript-eslint/consistent-type-imports */
|
||||
// @ts-nocheck
|
||||
import { REST } from '@discordjs/rest';
|
||||
import { MockAgent, type Interceptable } from 'undici';
|
||||
import { beforeEach, test, vi, expect } from 'vitest';
|
||||
import {
|
||||
managerToFetchingStrategyOptions,
|
||||
@@ -12,15 +10,7 @@ import {
|
||||
type WorkerReceivePayload,
|
||||
type WorkerSendPayload,
|
||||
} from '../../src/index.js';
|
||||
|
||||
let mockAgent: MockAgent;
|
||||
let mockPool: Interceptable;
|
||||
|
||||
beforeEach(() => {
|
||||
mockAgent = new MockAgent();
|
||||
mockAgent.disableNetConnect();
|
||||
mockPool = mockAgent.get('https://discord.com');
|
||||
});
|
||||
import { mockGatewayInformation } from '../gateway.mock.js';
|
||||
|
||||
const session = {
|
||||
shardId: 0,
|
||||
@@ -52,32 +42,13 @@ vi.mock('node:worker_threads', async () => {
|
||||
});
|
||||
|
||||
test('session info', async () => {
|
||||
const rest = new REST().setAgent(mockAgent).setToken('A-Very-Fake-Token');
|
||||
const manager = new WebSocketManager({ token: 'A-Very-Fake-Token', intents: 0, rest });
|
||||
|
||||
mockPool
|
||||
.intercept({
|
||||
path: '/api/v10/gateway/bot',
|
||||
method: 'GET',
|
||||
})
|
||||
.reply(() => ({
|
||||
data: {
|
||||
shards: 1,
|
||||
session_start_limit: {
|
||||
max_concurrency: 3,
|
||||
reset_after: 60,
|
||||
remaining: 3,
|
||||
total: 3,
|
||||
},
|
||||
url: 'wss://gateway.discord.gg',
|
||||
},
|
||||
statusCode: 200,
|
||||
responseOptions: {
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
},
|
||||
}));
|
||||
const manager = new WebSocketManager({
|
||||
token: 'A-Very-Fake-Token',
|
||||
intents: 0,
|
||||
async fetchGatewayInformation() {
|
||||
return mockGatewayInformation;
|
||||
},
|
||||
});
|
||||
|
||||
const strategy = new WorkerContextFetchingStrategy(await managerToFetchingStrategyOptions(manager));
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
/* eslint-disable id-length */
|
||||
import { setImmediate } from 'node:timers';
|
||||
import { REST } from '@discordjs/rest';
|
||||
import type { RESTGetAPIGatewayBotResult, GatewayDispatchPayload, GatewaySendPayload } from 'discord-api-types/v10';
|
||||
import { GatewayDispatchEvents, GatewayOpcodes, Routes } from 'discord-api-types/v10';
|
||||
import { MockAgent, type Interceptable } from 'undici';
|
||||
import { beforeEach, test, vi, expect, afterEach } from 'vitest';
|
||||
import type { GatewayDispatchPayload, GatewaySendPayload } from 'discord-api-types/v10';
|
||||
import { GatewayDispatchEvents, GatewayOpcodes } from 'discord-api-types/v10';
|
||||
import { test, vi, expect, afterEach } from 'vitest';
|
||||
import {
|
||||
WebSocketManager,
|
||||
WorkerSendPayloadOp,
|
||||
@@ -15,9 +13,7 @@ import {
|
||||
type WorkerSendPayload,
|
||||
type SessionInfo,
|
||||
} from '../../src/index.js';
|
||||
|
||||
let mockAgent: MockAgent;
|
||||
let mockPool: Interceptable;
|
||||
import { mockGatewayInformation } from '../gateway.mock.js';
|
||||
|
||||
const mockConstructor = vi.fn();
|
||||
const mockSend = vi.fn();
|
||||
@@ -135,12 +131,6 @@ vi.mock('node:worker_threads', async () => {
|
||||
};
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
mockAgent = new MockAgent();
|
||||
mockAgent.disableNetConnect();
|
||||
mockPool = mockAgent.get('https://discord.com');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mockConstructor.mockClear();
|
||||
mockSend.mockClear();
|
||||
@@ -148,15 +138,13 @@ afterEach(() => {
|
||||
});
|
||||
|
||||
test('spawn, connect, send a message, session info, and destroy', async () => {
|
||||
const rest = new REST().setAgent(mockAgent).setToken('A-Very-Fake-Token');
|
||||
|
||||
const mockRetrieveSessionInfo = vi.fn();
|
||||
const mockUpdateSessionInfo = vi.fn();
|
||||
const manager = new WebSocketManager({
|
||||
token: 'A-Very-Fake-Token',
|
||||
intents: 0,
|
||||
async fetchGatewayInformation() {
|
||||
return rest.get(Routes.gatewayBot()) as Promise<RESTGetAPIGatewayBotResult>;
|
||||
return mockGatewayInformation;
|
||||
},
|
||||
shardIds: [0, 1],
|
||||
retrieveSessionInfo: mockRetrieveSessionInfo,
|
||||
@@ -166,30 +154,6 @@ test('spawn, connect, send a message, session info, and destroy', async () => {
|
||||
|
||||
const managerEmitSpy = vi.spyOn(manager, 'emit');
|
||||
|
||||
mockPool
|
||||
.intercept({
|
||||
path: '/api/v10/gateway/bot',
|
||||
method: 'GET',
|
||||
})
|
||||
.reply(() => ({
|
||||
data: {
|
||||
shards: 1,
|
||||
session_start_limit: {
|
||||
max_concurrency: 3,
|
||||
reset_after: 60,
|
||||
remaining: 3,
|
||||
total: 3,
|
||||
},
|
||||
url: 'wss://gateway.discord.gg',
|
||||
},
|
||||
statusCode: 200,
|
||||
responseOptions: {
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
await manager.connect();
|
||||
expect(mockConstructor).toHaveBeenCalledWith(
|
||||
expect.stringContaining('defaultWorker.js'),
|
||||
|
||||
@@ -1,107 +1,55 @@
|
||||
import { REST } from '@discordjs/rest';
|
||||
import type { RESTGetAPIGatewayBotResult, APIGatewayBotInfo, GatewaySendPayload } from 'discord-api-types/v10';
|
||||
import { GatewayOpcodes, Routes } from 'discord-api-types/v10';
|
||||
import { MockAgent, type Interceptable } from 'undici';
|
||||
import { beforeEach, describe, expect, test, vi } from 'vitest';
|
||||
import type { GatewaySendPayload } from 'discord-api-types/v10';
|
||||
import { GatewayOpcodes } from 'discord-api-types/v10';
|
||||
import { describe, expect, test, vi } from 'vitest';
|
||||
import { WebSocketManager, type IShardingStrategy } from '../../src/index.js';
|
||||
import { mockGatewayInformation } from '../gateway.mock.js';
|
||||
|
||||
vi.useFakeTimers();
|
||||
|
||||
let mockAgent: MockAgent;
|
||||
let mockPool: Interceptable;
|
||||
|
||||
beforeEach(() => {
|
||||
mockAgent = new MockAgent();
|
||||
mockAgent.disableNetConnect();
|
||||
mockPool = mockAgent.get('https://discord.com');
|
||||
});
|
||||
|
||||
const NOW = vi.fn().mockReturnValue(Date.now());
|
||||
global.Date.now = NOW;
|
||||
|
||||
test('fetch gateway information', async () => {
|
||||
const rest = new REST().setAgent(mockAgent).setToken('A-Very-Fake-Token');
|
||||
const fetchGatewayInformation = vi.fn(async () => mockGatewayInformation);
|
||||
|
||||
const manager = new WebSocketManager({
|
||||
token: 'A-Very-Fake-Token',
|
||||
intents: 0,
|
||||
async fetchGatewayInformation() {
|
||||
return rest.get(Routes.gatewayBot()) as Promise<RESTGetAPIGatewayBotResult>;
|
||||
},
|
||||
fetchGatewayInformation,
|
||||
});
|
||||
|
||||
const data: APIGatewayBotInfo = {
|
||||
shards: 1,
|
||||
session_start_limit: {
|
||||
max_concurrency: 3,
|
||||
reset_after: 60,
|
||||
remaining: 3,
|
||||
total: 3,
|
||||
},
|
||||
url: 'wss://gateway.discord.gg',
|
||||
};
|
||||
|
||||
const fetch = vi.fn(() => ({
|
||||
data,
|
||||
statusCode: 200,
|
||||
responseOptions: {
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
mockPool
|
||||
.intercept({
|
||||
path: '/api/v10/gateway/bot',
|
||||
method: 'GET',
|
||||
})
|
||||
.reply(fetch);
|
||||
|
||||
const initial = await manager.fetchGatewayInformation();
|
||||
expect(initial).toEqual(data);
|
||||
expect(fetch).toHaveBeenCalledOnce();
|
||||
expect(initial).toEqual(mockGatewayInformation);
|
||||
expect(fetchGatewayInformation).toHaveBeenCalledOnce();
|
||||
|
||||
fetch.mockClear();
|
||||
fetchGatewayInformation.mockClear();
|
||||
|
||||
const cached = await manager.fetchGatewayInformation();
|
||||
expect(cached).toEqual(data);
|
||||
expect(fetch).not.toHaveBeenCalled();
|
||||
expect(cached).toEqual(mockGatewayInformation);
|
||||
expect(fetchGatewayInformation).not.toHaveBeenCalled();
|
||||
|
||||
fetch.mockClear();
|
||||
mockPool
|
||||
.intercept({
|
||||
path: '/api/v10/gateway/bot',
|
||||
method: 'GET',
|
||||
})
|
||||
.reply(fetch);
|
||||
fetchGatewayInformation.mockClear();
|
||||
|
||||
const forced = await manager.fetchGatewayInformation(true);
|
||||
expect(forced).toEqual(data);
|
||||
expect(fetch).toHaveBeenCalledOnce();
|
||||
expect(forced).toEqual(mockGatewayInformation);
|
||||
expect(fetchGatewayInformation).toHaveBeenCalledOnce();
|
||||
|
||||
fetch.mockClear();
|
||||
mockPool
|
||||
.intercept({
|
||||
path: '/api/v10/gateway/bot',
|
||||
method: 'GET',
|
||||
})
|
||||
.reply(fetch);
|
||||
fetchGatewayInformation.mockClear();
|
||||
|
||||
NOW.mockReturnValue(Number.POSITIVE_INFINITY);
|
||||
const cacheExpired = await manager.fetchGatewayInformation();
|
||||
expect(cacheExpired).toEqual(data);
|
||||
expect(fetch).toHaveBeenCalledOnce();
|
||||
expect(cacheExpired).toEqual(mockGatewayInformation);
|
||||
expect(fetchGatewayInformation).toHaveBeenCalledOnce();
|
||||
});
|
||||
|
||||
describe('get shard count', () => {
|
||||
test('with shard count', async () => {
|
||||
const rest = new REST().setAgent(mockAgent).setToken('A-Very-Fake-Token');
|
||||
const manager = new WebSocketManager({
|
||||
token: 'A-Very-Fake-Token',
|
||||
intents: 0,
|
||||
shardCount: 2,
|
||||
async fetchGatewayInformation() {
|
||||
return rest.get(Routes.gatewayBot()) as Promise<RESTGetAPIGatewayBotResult>;
|
||||
return mockGatewayInformation;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -109,14 +57,13 @@ describe('get shard count', () => {
|
||||
});
|
||||
|
||||
test('with shard ids array', async () => {
|
||||
const rest = new REST().setAgent(mockAgent).setToken('A-Very-Fake-Token');
|
||||
const shardIds = [5, 9];
|
||||
const manager = new WebSocketManager({
|
||||
token: 'A-Very-Fake-Token',
|
||||
intents: 0,
|
||||
shardIds,
|
||||
async fetchGatewayInformation() {
|
||||
return rest.get(Routes.gatewayBot()) as Promise<RESTGetAPIGatewayBotResult>;
|
||||
return mockGatewayInformation;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -124,14 +71,13 @@ describe('get shard count', () => {
|
||||
});
|
||||
|
||||
test('with shard id range', async () => {
|
||||
const rest = new REST().setAgent(mockAgent).setToken('A-Very-Fake-Token');
|
||||
const shardIds = { start: 5, end: 9 };
|
||||
const manager = new WebSocketManager({
|
||||
token: 'A-Very-Fake-Token',
|
||||
intents: 0,
|
||||
shardIds,
|
||||
async fetchGatewayInformation() {
|
||||
return rest.get(Routes.gatewayBot()) as Promise<RESTGetAPIGatewayBotResult>;
|
||||
return mockGatewayInformation;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -140,62 +86,26 @@ describe('get shard count', () => {
|
||||
});
|
||||
|
||||
test('update shard count', async () => {
|
||||
const rest = new REST().setAgent(mockAgent).setToken('A-Very-Fake-Token');
|
||||
const fetchGatewayInformation = vi.fn(async () => mockGatewayInformation);
|
||||
|
||||
const manager = new WebSocketManager({
|
||||
token: 'A-Very-Fake-Token',
|
||||
intents: 0,
|
||||
shardCount: 2,
|
||||
async fetchGatewayInformation() {
|
||||
return rest.get(Routes.gatewayBot()) as Promise<RESTGetAPIGatewayBotResult>;
|
||||
},
|
||||
fetchGatewayInformation,
|
||||
});
|
||||
|
||||
const data: APIGatewayBotInfo = {
|
||||
shards: 1,
|
||||
session_start_limit: {
|
||||
max_concurrency: 3,
|
||||
reset_after: 60,
|
||||
remaining: 3,
|
||||
total: 3,
|
||||
},
|
||||
url: 'wss://gateway.discord.gg',
|
||||
};
|
||||
|
||||
const fetch = vi.fn(() => ({
|
||||
data,
|
||||
statusCode: 200,
|
||||
responseOptions: {
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
mockPool
|
||||
.intercept({
|
||||
path: '/api/v10/gateway/bot',
|
||||
method: 'GET',
|
||||
})
|
||||
.reply(fetch);
|
||||
|
||||
expect(await manager.getShardCount()).toBe(2);
|
||||
expect(fetch).not.toHaveBeenCalled();
|
||||
expect(fetchGatewayInformation).not.toHaveBeenCalled();
|
||||
|
||||
fetch.mockClear();
|
||||
mockPool
|
||||
.intercept({
|
||||
path: '/api/v10/gateway/bot',
|
||||
method: 'GET',
|
||||
})
|
||||
.reply(fetch);
|
||||
fetchGatewayInformation.mockClear();
|
||||
|
||||
await manager.updateShardCount(3);
|
||||
expect(await manager.getShardCount()).toBe(3);
|
||||
expect(fetch).toHaveBeenCalled();
|
||||
expect(fetchGatewayInformation).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('it handles passing in both shardIds and shardCount', async () => {
|
||||
const rest = new REST().setAgent(mockAgent).setToken('A-Very-Fake-Token');
|
||||
const shardIds = { start: 2, end: 3 };
|
||||
const manager = new WebSocketManager({
|
||||
token: 'A-Very-Fake-Token',
|
||||
@@ -203,7 +113,7 @@ test('it handles passing in both shardIds and shardCount', async () => {
|
||||
shardIds,
|
||||
shardCount: 4,
|
||||
async fetchGatewayInformation() {
|
||||
return rest.get(Routes.gatewayBot()) as Promise<RESTGetAPIGatewayBotResult>;
|
||||
return mockGatewayInformation;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -226,44 +136,18 @@ test('strategies', async () => {
|
||||
|
||||
const strategy = new MockStrategy();
|
||||
|
||||
const rest = new REST().setAgent(mockAgent).setToken('A-Very-Fake-Token');
|
||||
const shardIds = [0, 1, 2];
|
||||
|
||||
const manager = new WebSocketManager({
|
||||
token: 'A-Very-Fake-Token',
|
||||
intents: 0,
|
||||
rest,
|
||||
shardIds,
|
||||
async fetchGatewayInformation() {
|
||||
return mockGatewayInformation;
|
||||
},
|
||||
buildStrategy: () => strategy,
|
||||
});
|
||||
|
||||
const data: APIGatewayBotInfo = {
|
||||
shards: 1,
|
||||
session_start_limit: {
|
||||
max_concurrency: 3,
|
||||
reset_after: 60,
|
||||
remaining: 3,
|
||||
total: 3,
|
||||
},
|
||||
url: 'wss://gateway.discord.gg',
|
||||
};
|
||||
|
||||
const fetch = vi.fn(() => ({
|
||||
data,
|
||||
statusCode: 200,
|
||||
responseOptions: {
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
mockPool
|
||||
.intercept({
|
||||
path: '/api/v10/gateway/bot',
|
||||
method: 'GET',
|
||||
})
|
||||
.reply(fetch);
|
||||
|
||||
await manager.connect();
|
||||
expect(strategy.spawn).toHaveBeenCalledWith(shardIds);
|
||||
expect(strategy.connect).toHaveBeenCalled();
|
||||
|
||||
Reference in New Issue
Block a user