mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-15 11:03:30 +01:00
refactor: use eslint-config-neon for packages. (#8579)
Co-authored-by: Noel <buechler.noel@outlook.com>
This commit is contained in:
@@ -1,14 +1,17 @@
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/dot-notation */
|
||||
import { Buffer } from 'node:buffer';
|
||||
import { once } from 'node:events';
|
||||
import process from 'node:process';
|
||||
import { Readable } from 'node:stream';
|
||||
import { NoSubscriberBehavior } from '../src';
|
||||
import { addAudioPlayer, deleteAudioPlayer } from '../src/DataStore';
|
||||
import { VoiceConnection, VoiceConnectionStatus } from '../src/VoiceConnection';
|
||||
import { createAudioPlayer, AudioPlayerStatus, AudioPlayer, SILENCE_FRAME } from '../src/audio/AudioPlayer';
|
||||
import { createAudioPlayer, AudioPlayerStatus, SILENCE_FRAME, type AudioPlayerState } from '../src/audio/AudioPlayer';
|
||||
import { AudioPlayerError } from '../src/audio/AudioPlayerError';
|
||||
import { AudioResource } from '../src/audio/AudioResource';
|
||||
import { NoSubscriberBehavior } from '../src/index';
|
||||
|
||||
jest.mock('../src/DataStore');
|
||||
jest.mock('../src/VoiceConnection');
|
||||
@@ -39,7 +42,8 @@ function createVoiceConnectionMock() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
function wait() {
|
||||
async function wait() {
|
||||
// eslint-disable-next-line no-promise-executor-return
|
||||
return new Promise((resolve) => process.nextTick(resolve));
|
||||
}
|
||||
|
||||
@@ -47,6 +51,7 @@ async function started(resource: AudioResource) {
|
||||
while (!resource.started) {
|
||||
await wait();
|
||||
}
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
@@ -197,6 +202,7 @@ describe('State transitions', () => {
|
||||
if (connection.state.status !== VoiceConnectionStatus.Signalling) {
|
||||
throw new Error('Voice connection should have been Signalling');
|
||||
}
|
||||
|
||||
connection.state = {
|
||||
...connection.state,
|
||||
status: VoiceConnectionStatus.Ready,
|
||||
@@ -216,18 +222,18 @@ describe('State transitions', () => {
|
||||
expect(player.checkPlayable()).toEqual(true);
|
||||
|
||||
// Run through a few packet cycles
|
||||
for (let i = 1; i <= 5; i++) {
|
||||
for (let index = 1; index <= 5; index++) {
|
||||
player['_stepDispatch']();
|
||||
expect(connection.dispatchAudio).toHaveBeenCalledTimes(i);
|
||||
expect(connection.dispatchAudio).toHaveBeenCalledTimes(index);
|
||||
|
||||
await wait(); // Wait for the stream
|
||||
|
||||
player['_stepPrepare']();
|
||||
expect(connection.prepareAudioPacket).toHaveBeenCalledTimes(i);
|
||||
expect(connection.prepareAudioPacket).toHaveBeenCalledTimes(index);
|
||||
expect(connection.prepareAudioPacket).toHaveBeenLastCalledWith(buffer);
|
||||
expect(player.state.status).toEqual(AudioPlayerStatus.Playing);
|
||||
if (player.state.status === AudioPlayerStatus.Playing) {
|
||||
expect(player.state.playbackDuration).toStrictEqual(i * 20);
|
||||
expect(player.state.playbackDuration).toStrictEqual(index * 20);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,6 +260,7 @@ describe('State transitions', () => {
|
||||
if (connection.state.status !== VoiceConnectionStatus.Signalling) {
|
||||
throw new Error('Voice connection should have been Signalling');
|
||||
}
|
||||
|
||||
connection.state = {
|
||||
...connection.state,
|
||||
status: VoiceConnectionStatus.Ready,
|
||||
@@ -275,20 +282,21 @@ describe('State transitions', () => {
|
||||
player.stop();
|
||||
|
||||
// Run through a few packet cycles
|
||||
for (let i = 1; i <= 5; i++) {
|
||||
for (let index = 1; index <= 5; index++) {
|
||||
player['_stepDispatch']();
|
||||
expect(connection.dispatchAudio).toHaveBeenCalledTimes(i);
|
||||
expect(connection.dispatchAudio).toHaveBeenCalledTimes(index);
|
||||
|
||||
await wait(); // Wait for the stream
|
||||
|
||||
player['_stepPrepare']();
|
||||
expect(connection.prepareAudioPacket).toHaveBeenCalledTimes(i);
|
||||
expect(connection.prepareAudioPacket).toHaveBeenCalledTimes(index);
|
||||
expect(connection.prepareAudioPacket).toHaveBeenLastCalledWith(SILENCE_FRAME);
|
||||
expect(player.state.status).toEqual(AudioPlayerStatus.Playing);
|
||||
if (player.state.status === AudioPlayerStatus.Playing) {
|
||||
expect(player.state.playbackDuration).toStrictEqual(i * 20);
|
||||
expect(player.state.playbackDuration).toStrictEqual(index * 20);
|
||||
}
|
||||
}
|
||||
|
||||
await wait();
|
||||
expect(player.checkPlayable()).toEqual(false);
|
||||
const prepareAudioPacket = connection.prepareAudioPacket as unknown as jest.Mock<
|
||||
@@ -307,6 +315,7 @@ describe('State transitions', () => {
|
||||
if (connection.state.status !== VoiceConnectionStatus.Signalling) {
|
||||
throw new Error('Voice connection should have been Signalling');
|
||||
}
|
||||
|
||||
connection.state = {
|
||||
...connection.state,
|
||||
status: VoiceConnectionStatus.Ready,
|
||||
@@ -328,16 +337,16 @@ describe('State transitions', () => {
|
||||
>;
|
||||
|
||||
// Run through a few packet cycles
|
||||
for (let i = 1; i <= 5; i++) {
|
||||
for (let index = 1; index <= 5; index++) {
|
||||
expect(player.state.status).toEqual(AudioPlayerStatus.Playing);
|
||||
if (player.state.status !== AudioPlayerStatus.Playing) throw new Error('Error');
|
||||
expect(player.state.playbackDuration).toStrictEqual((i - 1) * 20);
|
||||
expect(player.state.missedFrames).toEqual(i - 1);
|
||||
expect(player.state.playbackDuration).toStrictEqual((index - 1) * 20);
|
||||
expect(player.state.missedFrames).toEqual(index - 1);
|
||||
player['_stepDispatch']();
|
||||
expect(connection.dispatchAudio).toHaveBeenCalledTimes(i);
|
||||
expect(connection.dispatchAudio).toHaveBeenCalledTimes(index);
|
||||
player['_stepPrepare']();
|
||||
expect(prepareAudioPacket).toHaveBeenCalledTimes(i);
|
||||
expect(prepareAudioPacket.mock.calls[i - 1][0]).toEqual(silence().next().value);
|
||||
expect(prepareAudioPacket).toHaveBeenCalledTimes(index);
|
||||
expect(prepareAudioPacket.mock.calls[index - 1][0]).toEqual(silence().next().value);
|
||||
}
|
||||
|
||||
expect(player.state.status).toEqual(AudioPlayerStatus.Idle);
|
||||
@@ -352,10 +361,11 @@ describe('State transitions', () => {
|
||||
player.play(resource);
|
||||
expect(player.checkPlayable()).toEqual(true);
|
||||
expect(player.state.status).toEqual(AudioPlayerStatus.Playing);
|
||||
for (let i = 0; i < 3; i++) {
|
||||
for (let index = 0; index < 3; index++) {
|
||||
resource.playStream.read();
|
||||
await wait();
|
||||
}
|
||||
|
||||
expect(resource.playStream.readableEnded).toEqual(true);
|
||||
expect(player.checkPlayable()).toEqual(false);
|
||||
expect(player.state.status).toEqual(AudioPlayerStatus.Idle);
|
||||
@@ -367,10 +377,11 @@ test('play() throws when playing a resource that has already ended', async () =>
|
||||
player = createAudioPlayer();
|
||||
player.play(resource);
|
||||
expect(player.state.status).toEqual(AudioPlayerStatus.Playing);
|
||||
for (let i = 0; i < 3; i++) {
|
||||
for (let index = 0; index < 3; index++) {
|
||||
resource.playStream.read();
|
||||
await wait();
|
||||
}
|
||||
|
||||
expect(resource.playStream.readableEnded).toEqual(true);
|
||||
player.stop(true);
|
||||
expect(player.state.status).toEqual(AudioPlayerStatus.Idle);
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
/* eslint-disable no-promise-executor-return */
|
||||
import { Buffer } from 'node:buffer';
|
||||
import { SILENCE_FRAME } from '../src/audio/AudioPlayer';
|
||||
import { AudioReceiveStream, EndBehaviorType } from '../src/receive/AudioReceiveStream';
|
||||
|
||||
const DUMMY_BUFFER = Buffer.allocUnsafe(16);
|
||||
|
||||
function wait(ms: number) {
|
||||
async function wait(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
@@ -52,13 +54,13 @@ describe('AudioReceiveStream', () => {
|
||||
const stream = new AudioReceiveStream({ end: { behavior: EndBehaviorType.AfterInactivity, duration: 100 } });
|
||||
stream.resume();
|
||||
|
||||
for (let i = increment; i < duration / 2; i += increment) {
|
||||
for (let index = increment; index < duration / 2; index += increment) {
|
||||
await stepSilence(stream, increment);
|
||||
}
|
||||
|
||||
stream.push(DUMMY_BUFFER);
|
||||
|
||||
for (let i = increment; i < duration; i += increment) {
|
||||
for (let index = increment; index < duration; index += increment) {
|
||||
await stepSilence(stream, increment);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
import { Buffer } from 'node:buffer';
|
||||
import process from 'node:process';
|
||||
import { PassThrough, Readable } from 'node:stream';
|
||||
import { opus, VolumeTransformer } from 'prism-media';
|
||||
import { SILENCE_FRAME } from '../src/audio/AudioPlayer';
|
||||
import { AudioResource, createAudioResource, NO_CONSTRAINT, VOLUME_CONSTRAINT } from '../src/audio/AudioResource';
|
||||
import { Edge, findPipeline as _findPipeline, StreamType, TransformerType } from '../src/audio/TransformerGraph';
|
||||
import { findPipeline as _findPipeline, StreamType, TransformerType, type Edge } from '../src/audio/TransformerGraph';
|
||||
|
||||
jest.mock('prism-media');
|
||||
jest.mock('../src/audio/TransformerGraph');
|
||||
|
||||
function wait() {
|
||||
async function wait() {
|
||||
// eslint-disable-next-line no-promise-executor-return
|
||||
return new Promise((resolve) => process.nextTick(resolve));
|
||||
}
|
||||
|
||||
@@ -16,12 +19,14 @@ async function started(resource: AudioResource) {
|
||||
while (!resource.started) {
|
||||
await wait();
|
||||
}
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
const findPipeline = _findPipeline as unknown as jest.MockedFunction<typeof _findPipeline>;
|
||||
|
||||
beforeAll(() => {
|
||||
// @ts-expect-error no type
|
||||
findPipeline.mockImplementation((from: StreamType, constraint: (path: Edge[]) => boolean) => {
|
||||
const base = [
|
||||
{
|
||||
@@ -38,6 +43,7 @@ beforeAll(() => {
|
||||
type: TransformerType.InlineVolume,
|
||||
});
|
||||
}
|
||||
|
||||
return base as any[];
|
||||
});
|
||||
});
|
||||
@@ -113,11 +119,12 @@ describe('createAudioResource', () => {
|
||||
await started(resource);
|
||||
expect(resource.readable).toEqual(true);
|
||||
expect(resource.read()).toEqual(Buffer.from([1]));
|
||||
for (let i = 0; i < 5; i++) {
|
||||
for (let index = 0; index < 5; index++) {
|
||||
await wait();
|
||||
expect(resource.readable).toEqual(true);
|
||||
expect(resource.read()).toEqual(SILENCE_FRAME);
|
||||
}
|
||||
|
||||
await wait();
|
||||
expect(resource.readable).toEqual(false);
|
||||
expect(resource.read()).toEqual(null);
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
/* eslint-disable @typescript-eslint/dot-notation */
|
||||
import { GatewayOpcodes } from 'discord-api-types/v10';
|
||||
import * as DataStore from '../src/DataStore';
|
||||
import { VoiceConnection } from '../src/VoiceConnection';
|
||||
import type { VoiceConnection } from '../src/VoiceConnection';
|
||||
import * as _AudioPlayer from '../src/audio/AudioPlayer';
|
||||
|
||||
jest.mock('../src/VoiceConnection');
|
||||
jest.mock('../src/audio/AudioPlayer');
|
||||
|
||||
@@ -15,8 +16,9 @@ function createVoiceConnection(joinConfig: Pick<DataStore.JoinConfig, 'group' |
|
||||
} as any;
|
||||
}
|
||||
|
||||
function waitForEventLoop() {
|
||||
return new Promise((res) => setImmediate(res));
|
||||
async function waitForEventLoop() {
|
||||
// eslint-disable-next-line no-promise-executor-return
|
||||
return new Promise((resolve) => setImmediate(resolve));
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -24,6 +26,7 @@ beforeEach(() => {
|
||||
for (const groupKey of groups.keys()) {
|
||||
groups.delete(groupKey);
|
||||
}
|
||||
|
||||
groups.set('default', new Map());
|
||||
});
|
||||
|
||||
@@ -41,6 +44,7 @@ describe('DataStore', () => {
|
||||
};
|
||||
expect(DataStore.createJoinVoiceChannelPayload(joinConfig)).toStrictEqual({
|
||||
op: GatewayOpcodes.VoiceStateUpdate,
|
||||
// eslint-disable-next-line id-length
|
||||
d: {
|
||||
guild_id: joinConfig.guildId,
|
||||
channel_id: joinConfig.channelId,
|
||||
@@ -60,7 +64,7 @@ describe('DataStore', () => {
|
||||
|
||||
expect([...DataStore.getVoiceConnections().values()]).toEqual([voiceConnectionDefault]);
|
||||
expect([...DataStore.getVoiceConnections('default').values()]).toEqual([voiceConnectionDefault]);
|
||||
expect([...DataStore.getVoiceConnections('abc').values()]).toEqual([voiceConnectionAbc]);
|
||||
expect([...DataStore.getVoiceConnections('abc')!.values()]).toEqual([voiceConnectionAbc]);
|
||||
|
||||
DataStore.untrackVoiceConnection(voiceConnectionDefault);
|
||||
expect(DataStore.getVoiceConnection('123')).toBeUndefined();
|
||||
@@ -73,6 +77,7 @@ describe('DataStore', () => {
|
||||
expect(DataStore.hasAudioPlayer(player)).toEqual(true);
|
||||
expect(DataStore.addAudioPlayer(player)).toEqual(player);
|
||||
DataStore.deleteAudioPlayer(player);
|
||||
// eslint-disable-next-line @typescript-eslint/no-confusing-void-expression
|
||||
expect(DataStore.deleteAudioPlayer(player)).toBeUndefined();
|
||||
expect(DataStore.hasAudioPlayer(player)).toEqual(false);
|
||||
// Tests audio cycle with nextTime === -1
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
import EventEmitter, { once } from 'node:events';
|
||||
import { SSRCMap, VoiceUserData } from '../src/receive/SSRCMap';
|
||||
import type EventEmitter from 'node:events';
|
||||
import { once } from 'node:events';
|
||||
import process from 'node:process';
|
||||
import { SSRCMap, type VoiceUserData } from '../src/receive/SSRCMap';
|
||||
|
||||
function onceOrThrow<T extends EventEmitter>(target: T, event: string, after: number) {
|
||||
async function onceOrThrow<T extends EventEmitter>(target: T, event: string, after: number) {
|
||||
return new Promise((resolve, reject) => {
|
||||
target.on(event, resolve);
|
||||
setTimeout(() => reject(new Error('Time up')), after);
|
||||
|
||||
@@ -3,6 +3,6 @@ import { methods } from '../src/util/Secretbox';
|
||||
jest.mock('tweetnacl');
|
||||
|
||||
test('Does not throw error with a package installed', () => {
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error: Unknown type
|
||||
expect(() => methods.open()).not.toThrowError();
|
||||
});
|
||||
|
||||
@@ -14,7 +14,7 @@ describe('SpeakingMap', () => {
|
||||
speaking.on('start', (userId) => void starts.push(userId));
|
||||
speaking.on('end', (userId) => void ends.push(userId));
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
for (let index = 0; index < 10; index++) {
|
||||
speaking.onPacket(userId);
|
||||
setTimeout(noop, SpeakingMap.DELAY / 2);
|
||||
jest.advanceTimersToNextTimer();
|
||||
@@ -22,6 +22,7 @@ describe('SpeakingMap', () => {
|
||||
expect(starts).toEqual([userId]);
|
||||
expect(ends).toEqual([]);
|
||||
}
|
||||
|
||||
jest.advanceTimersToNextTimer();
|
||||
expect(ends).toEqual([userId]);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Edge, findPipeline, StreamType, TransformerType } from '../src/audio/TransformerGraph';
|
||||
import { findPipeline, StreamType, TransformerType, type Edge } from '../src/audio/TransformerGraph';
|
||||
|
||||
const noConstraint = () => true;
|
||||
|
||||
@@ -12,6 +12,7 @@ function reducePath(pipeline: Edge[]) {
|
||||
for (const edge of pipeline.slice(1)) {
|
||||
streams.push(edge.from.type);
|
||||
}
|
||||
|
||||
streams.push(pipeline[pipeline.length - 1].to.type);
|
||||
return streams;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable @typescript-eslint/unbound-method */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
@@ -8,13 +9,12 @@ import * as _DataStore from '../src/DataStore';
|
||||
import {
|
||||
createVoiceConnection,
|
||||
VoiceConnection,
|
||||
VoiceConnectionConnectingState,
|
||||
VoiceConnectionDisconnectReason,
|
||||
VoiceConnectionReadyState,
|
||||
VoiceConnectionSignallingState,
|
||||
VoiceConnectionStatus,
|
||||
type VoiceConnectionConnectingState,
|
||||
type VoiceConnectionReadyState,
|
||||
type VoiceConnectionSignallingState,
|
||||
} from '../src/VoiceConnection';
|
||||
|
||||
import * as _AudioPlayer from '../src/audio/AudioPlayer';
|
||||
import { PlayerSubscription as _PlayerSubscription } from '../src/audio/PlayerSubscription';
|
||||
import * as _Networking from '../src/networking/Networking';
|
||||
@@ -129,6 +129,7 @@ describe('createVoiceConnection', () => {
|
||||
|
||||
const stateSetter = jest.spyOn(existingVoiceConnection, 'state', 'set');
|
||||
|
||||
// @ts-expect-error: We're testing
|
||||
DataStore.getVoiceConnection.mockImplementation((guildId, group = 'default') =>
|
||||
guildId === existingJoinConfig.guildId && group === existingJoinConfig.group ? existingVoiceConnection : null,
|
||||
);
|
||||
@@ -167,6 +168,7 @@ describe('createVoiceConnection', () => {
|
||||
|
||||
const rejoinSpy = jest.spyOn(existingVoiceConnection, 'rejoin');
|
||||
|
||||
// @ts-expect-error: We're testing
|
||||
DataStore.getVoiceConnection.mockImplementation((guildId, group = 'default') =>
|
||||
guildId === existingJoinConfig.guildId && group === existingJoinConfig.group ? existingVoiceConnection : null,
|
||||
);
|
||||
@@ -198,6 +200,7 @@ describe('createVoiceConnection', () => {
|
||||
adapterCreator: existingAdapter.creator,
|
||||
});
|
||||
|
||||
// @ts-expect-error: We're testing
|
||||
DataStore.getVoiceConnection.mockImplementation((guildId, group = 'default') =>
|
||||
guildId === existingJoinConfig.guildId && group === existingJoinConfig.group ? existingVoiceConnection : null,
|
||||
);
|
||||
@@ -355,17 +358,17 @@ describe('VoiceConnection#onNetworkingClose', () => {
|
||||
voiceConnection.state = {
|
||||
status: VoiceConnectionStatus.Destroyed,
|
||||
};
|
||||
voiceConnection['onNetworkingClose'](1000);
|
||||
voiceConnection['onNetworkingClose'](1_000);
|
||||
expect(voiceConnection.state.status).toEqual(VoiceConnectionStatus.Destroyed);
|
||||
expect(adapter.sendPayload).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('Disconnects for code 4014', () => {
|
||||
const { voiceConnection, adapter } = createFakeVoiceConnection();
|
||||
voiceConnection['onNetworkingClose'](4014);
|
||||
voiceConnection['onNetworkingClose'](4_014);
|
||||
expect(voiceConnection.state).toMatchObject({
|
||||
status: VoiceConnectionStatus.Disconnected,
|
||||
closeCode: 4014,
|
||||
closeCode: 4_014,
|
||||
});
|
||||
expect(adapter.sendPayload).not.toHaveBeenCalled();
|
||||
});
|
||||
@@ -376,7 +379,7 @@ describe('VoiceConnection#onNetworkingClose', () => {
|
||||
DataStore.createJoinVoiceChannelPayload.mockImplementation((config) =>
|
||||
config === joinConfig ? dummyPayload : undefined,
|
||||
);
|
||||
voiceConnection['onNetworkingClose'](1234);
|
||||
voiceConnection['onNetworkingClose'](1_234);
|
||||
expect(voiceConnection.state.status).toEqual(VoiceConnectionStatus.Signalling);
|
||||
expect(adapter.sendPayload).toHaveBeenCalledWith(dummyPayload);
|
||||
expect(voiceConnection.rejoinAttempts).toEqual(1);
|
||||
@@ -389,7 +392,7 @@ describe('VoiceConnection#onNetworkingClose', () => {
|
||||
config === joinConfig ? dummyPayload : undefined,
|
||||
);
|
||||
adapter.sendPayload.mockReturnValue(false);
|
||||
voiceConnection['onNetworkingClose'](1234);
|
||||
voiceConnection['onNetworkingClose'](1_234);
|
||||
expect(voiceConnection.state.status).toEqual(VoiceConnectionStatus.Disconnected);
|
||||
expect(adapter.sendPayload).toHaveBeenCalledWith(dummyPayload);
|
||||
expect(voiceConnection.rejoinAttempts).toEqual(1);
|
||||
@@ -552,7 +555,7 @@ describe('VoiceConnection#rejoin', () => {
|
||||
...(voiceConnection.state as VoiceConnectionSignallingState),
|
||||
status: VoiceConnectionStatus.Disconnected,
|
||||
reason: VoiceConnectionDisconnectReason.WebSocketClose,
|
||||
closeCode: 1000,
|
||||
closeCode: 1_000,
|
||||
};
|
||||
expect(voiceConnection.rejoin()).toEqual(true);
|
||||
expect(voiceConnection.rejoinAttempts).toEqual(1);
|
||||
@@ -584,7 +587,7 @@ describe('VoiceConnection#rejoin', () => {
|
||||
...(voiceConnection.state as VoiceConnectionSignallingState),
|
||||
status: VoiceConnectionStatus.Disconnected,
|
||||
reason: VoiceConnectionDisconnectReason.WebSocketClose,
|
||||
closeCode: 1000,
|
||||
closeCode: 1_000,
|
||||
};
|
||||
adapter.sendPayload.mockReturnValue(false);
|
||||
expect(voiceConnection.rejoin()).toEqual(false);
|
||||
@@ -751,7 +754,7 @@ describe('Adapter', () => {
|
||||
const { adapter, voiceConnection } = createFakeVoiceConnection();
|
||||
voiceConnection['addServerPacket'] = jest.fn();
|
||||
const dummy = Symbol('dummy') as any;
|
||||
adapter.libMethods.onVoiceServerUpdate(dummy);
|
||||
adapter.libMethods.onVoiceServerUpdate!(dummy);
|
||||
expect(voiceConnection['addServerPacket']).toHaveBeenCalledWith(dummy);
|
||||
});
|
||||
|
||||
@@ -759,13 +762,13 @@ describe('Adapter', () => {
|
||||
const { adapter, voiceConnection } = createFakeVoiceConnection();
|
||||
voiceConnection['addStatePacket'] = jest.fn();
|
||||
const dummy = Symbol('dummy') as any;
|
||||
adapter.libMethods.onVoiceStateUpdate(dummy);
|
||||
adapter.libMethods.onVoiceStateUpdate!(dummy);
|
||||
expect(voiceConnection['addStatePacket']).toHaveBeenCalledWith(dummy);
|
||||
});
|
||||
|
||||
test('destroy', () => {
|
||||
const { adapter, voiceConnection } = createFakeVoiceConnection();
|
||||
adapter.libMethods.destroy();
|
||||
adapter.libMethods.destroy!();
|
||||
expect(voiceConnection.state.status).toEqual(VoiceConnectionStatus.Destroyed);
|
||||
expect(adapter.sendPayload).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
/* eslint-disable id-length */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable @typescript-eslint/dot-notation */
|
||||
import { Buffer } from 'node:buffer';
|
||||
import { once } from 'node:events';
|
||||
import process from 'node:process';
|
||||
import { VoiceOpcodes } from 'discord-api-types/voice/v4';
|
||||
import { RTP_PACKET_DESKTOP, RTP_PACKET_CHROME, RTP_PACKET_ANDROID } from '../__mocks__/rtp';
|
||||
import { VoiceConnection as _VoiceConnection, VoiceConnectionStatus } from '../src/VoiceConnection';
|
||||
@@ -16,7 +19,8 @@ openSpy.mockImplementation((buffer) => buffer);
|
||||
|
||||
const VoiceConnection = _VoiceConnection as unknown as jest.Mocked<typeof _VoiceConnection>;
|
||||
|
||||
function nextTick() {
|
||||
async function nextTick() {
|
||||
// eslint-disable-next-line no-promise-executor-return
|
||||
return new Promise((resolve) => process.nextTick(resolve));
|
||||
}
|
||||
|
||||
@@ -178,7 +182,7 @@ describe('VoiceReceiver', () => {
|
||||
|
||||
// Assert
|
||||
expect(nonce.equals(range(29, 32))).toEqual(true);
|
||||
expect(decrypted.equals(range(13, 28))).toEqual(true);
|
||||
expect(decrypted!.equals(range(13, 28))).toEqual(true);
|
||||
});
|
||||
|
||||
test('decrypt: xsalsa20_poly1305_suffix', () => {
|
||||
@@ -191,7 +195,7 @@ describe('VoiceReceiver', () => {
|
||||
|
||||
// Assert
|
||||
expect(nonce.equals(range(41, 64))).toEqual(true);
|
||||
expect(decrypted.equals(range(13, 40))).toEqual(true);
|
||||
expect(decrypted!.equals(range(13, 40))).toEqual(true);
|
||||
});
|
||||
|
||||
test('decrypt: xsalsa20_poly1305', () => {
|
||||
@@ -204,7 +208,7 @@ describe('VoiceReceiver', () => {
|
||||
|
||||
// Assert
|
||||
expect(nonce.equals(range(1, 12))).toEqual(true);
|
||||
expect(decrypted.equals(range(13, 64))).toEqual(true);
|
||||
expect(decrypted!.equals(range(13, 64))).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||
import { Buffer } from 'node:buffer';
|
||||
import { createSocket as _createSocket } from 'node:dgram';
|
||||
import EventEmitter, { once } from 'node:events';
|
||||
import { VoiceUDPSocket } from '../src/networking/VoiceUDPSocket';
|
||||
@@ -16,6 +17,7 @@ beforeEach(() => {
|
||||
|
||||
class FakeSocket extends EventEmitter {
|
||||
public send(buffer: Buffer, port: number, address: string) {}
|
||||
|
||||
public close() {
|
||||
this.emit('close');
|
||||
}
|
||||
@@ -29,7 +31,7 @@ const VALID_RESPONSE = Buffer.from([
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd3, 0x84,
|
||||
]);
|
||||
|
||||
function wait() {
|
||||
async function wait() {
|
||||
return new Promise((resolve) => {
|
||||
setImmediate(resolve);
|
||||
jest.advanceTimersToNextTimer();
|
||||
@@ -52,13 +54,13 @@ describe('VoiceUDPSocket#performIPDiscovery', () => {
|
||||
fake.emit('message', VALID_RESPONSE);
|
||||
});
|
||||
createSocket.mockImplementation((type) => fake as any);
|
||||
socket = new VoiceUDPSocket({ ip: '1.2.3.4', port: 25565 });
|
||||
socket = new VoiceUDPSocket({ ip: '1.2.3.4', port: 25_565 });
|
||||
|
||||
expect(createSocket).toHaveBeenCalledWith('udp4');
|
||||
expect(fake.listenerCount('message')).toEqual(1);
|
||||
await expect(socket.performIPDiscovery(1234)).resolves.toEqual({
|
||||
await expect(socket.performIPDiscovery(1_234)).resolves.toEqual({
|
||||
ip: '91.90.123.93',
|
||||
port: 54148,
|
||||
port: 54_148,
|
||||
});
|
||||
// Ensure clean up occurs
|
||||
expect(fake.listenerCount('message')).toEqual(1);
|
||||
@@ -77,13 +79,13 @@ describe('VoiceUDPSocket#performIPDiscovery', () => {
|
||||
fake.emit('message', VALID_RESPONSE);
|
||||
});
|
||||
createSocket.mockImplementation(() => fake as any);
|
||||
socket = new VoiceUDPSocket({ ip: '1.2.3.4', port: 25565 });
|
||||
socket = new VoiceUDPSocket({ ip: '1.2.3.4', port: 25_565 });
|
||||
|
||||
expect(createSocket).toHaveBeenCalledWith('udp4');
|
||||
expect(fake.listenerCount('message')).toEqual(1);
|
||||
await expect(socket.performIPDiscovery(1234)).resolves.toEqual({
|
||||
await expect(socket.performIPDiscovery(1_234)).resolves.toEqual({
|
||||
ip: '91.90.123.93',
|
||||
port: 54148,
|
||||
port: 54_148,
|
||||
});
|
||||
// Ensure clean up occurs
|
||||
expect(fake.listenerCount('message')).toEqual(1);
|
||||
@@ -96,10 +98,10 @@ describe('VoiceUDPSocket#performIPDiscovery', () => {
|
||||
fake.close();
|
||||
});
|
||||
createSocket.mockImplementation(() => fake as any);
|
||||
socket = new VoiceUDPSocket({ ip: '1.2.3.4', port: 25565 });
|
||||
socket = new VoiceUDPSocket({ ip: '1.2.3.4', port: 25_565 });
|
||||
|
||||
expect(createSocket).toHaveBeenCalledWith('udp4');
|
||||
await expect(socket.performIPDiscovery(1234)).rejects.toThrowError();
|
||||
await expect(socket.performIPDiscovery(1_234)).rejects.toThrowError();
|
||||
});
|
||||
|
||||
test('Stays alive when messages are echoed back', async () => {
|
||||
@@ -109,13 +111,12 @@ describe('VoiceUDPSocket#performIPDiscovery', () => {
|
||||
fake.emit('message', buffer);
|
||||
});
|
||||
createSocket.mockImplementation(() => fake as any);
|
||||
socket = new VoiceUDPSocket({ ip: '1.2.3.4', port: 25565 });
|
||||
socket = new VoiceUDPSocket({ ip: '1.2.3.4', port: 25_565 });
|
||||
|
||||
let closed = false;
|
||||
// @ts-expect-error
|
||||
socket.on('close', () => (closed = true));
|
||||
|
||||
for (let i = 0; i < 30; i++) {
|
||||
for (let index = 0; index < 30; index++) {
|
||||
jest.advanceTimersToNextTimer();
|
||||
await wait();
|
||||
}
|
||||
@@ -127,13 +128,12 @@ describe('VoiceUDPSocket#performIPDiscovery', () => {
|
||||
const fake = new FakeSocket();
|
||||
fake.send = jest.fn();
|
||||
createSocket.mockImplementation(() => fake as any);
|
||||
socket = new VoiceUDPSocket({ ip: '1.2.3.4', port: 25565 });
|
||||
socket = new VoiceUDPSocket({ ip: '1.2.3.4', port: 25_565 });
|
||||
|
||||
let closed = false;
|
||||
// @ts-expect-error
|
||||
socket.on('close', () => (closed = true));
|
||||
|
||||
for (let i = 0; i < 15; i++) {
|
||||
for (let index = 0; index < 15; index++) {
|
||||
jest.advanceTimersToNextTimer();
|
||||
await wait();
|
||||
}
|
||||
@@ -146,25 +146,27 @@ describe('VoiceUDPSocket#performIPDiscovery', () => {
|
||||
const fakeSend = jest.fn();
|
||||
fake.send = fakeSend;
|
||||
createSocket.mockImplementation(() => fake as any);
|
||||
socket = new VoiceUDPSocket({ ip: '1.2.3.4', port: 25565 });
|
||||
socket = new VoiceUDPSocket({ ip: '1.2.3.4', port: 25_565 });
|
||||
|
||||
let closed = false;
|
||||
// @ts-expect-error
|
||||
|
||||
socket.on('close', () => (closed = true));
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
for (let index = 0; index < 10; index++) {
|
||||
jest.advanceTimersToNextTimer();
|
||||
await wait();
|
||||
}
|
||||
|
||||
fakeSend.mockImplementation(async (buffer: Buffer) => {
|
||||
await wait();
|
||||
fake.emit('message', buffer);
|
||||
});
|
||||
expect(closed).toEqual(false);
|
||||
for (let i = 0; i < 30; i++) {
|
||||
for (let index = 0; index < 30; index++) {
|
||||
jest.advanceTimersToNextTimer();
|
||||
await wait();
|
||||
}
|
||||
|
||||
expect(closed).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
import EventEmitter, { once } from 'node:events';
|
||||
import { type EventEmitter, once } from 'node:events';
|
||||
import { VoiceOpcodes } from 'discord-api-types/voice/v4';
|
||||
import WS from 'jest-websocket-mock';
|
||||
import { VoiceWebSocket } from '../src/networking/VoiceWebSocket';
|
||||
@@ -9,13 +9,13 @@ beforeEach(() => {
|
||||
WS.clean();
|
||||
});
|
||||
|
||||
function onceIgnoreError<T extends EventEmitter>(target: T, event: string) {
|
||||
async function onceIgnoreError<T extends EventEmitter>(target: T, event: string) {
|
||||
return new Promise((resolve) => {
|
||||
target.on(event, resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function onceOrThrow<T extends EventEmitter>(target: T, event: string, after: number) {
|
||||
async function onceOrThrow<T extends EventEmitter>(target: T, event: string, after: number) {
|
||||
return new Promise((resolve, reject) => {
|
||||
target.on(event, resolve);
|
||||
setTimeout(() => reject(new Error('Time up')), after);
|
||||
@@ -46,7 +46,7 @@ describe.skip('VoiceWebSocket: packet parsing', () => {
|
||||
server.send('asdf');
|
||||
await expect(rcv).rejects.toThrowError();
|
||||
|
||||
const dummy = { op: 1234 };
|
||||
const dummy = { op: 1_234 };
|
||||
rcv = once(ws, 'packet');
|
||||
server.send(JSON.stringify(dummy));
|
||||
await expect(rcv).resolves.toEqual([dummy]);
|
||||
@@ -94,17 +94,19 @@ describe.skip('VoiceWebSocket: heartbeating', () => {
|
||||
await server.connected;
|
||||
const rcv = onceOrThrow(ws, 'close', 750);
|
||||
ws.setHeartbeatInterval(50);
|
||||
for (let i = 0; i < 10; i++) {
|
||||
for (let index = 0; index < 10; index++) {
|
||||
const packet: any = await server.nextMessage;
|
||||
expect(packet).toMatchObject({
|
||||
op: VoiceOpcodes.Heartbeat,
|
||||
});
|
||||
server.send({
|
||||
op: VoiceOpcodes.HeartbeatAck,
|
||||
// eslint-disable-next-line id-length
|
||||
d: packet.d,
|
||||
});
|
||||
expect(ws.ping).toBeGreaterThanOrEqual(0);
|
||||
}
|
||||
|
||||
ws.setHeartbeatInterval(-1);
|
||||
await expect(rcv).rejects.toThrowError();
|
||||
});
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
import { Buffer } from 'node:buffer';
|
||||
import EventEmitter, { once } from 'node:events';
|
||||
import process from 'node:process';
|
||||
import { Readable } from 'node:stream';
|
||||
import { opus as _opus } from 'prism-media';
|
||||
import { StreamType } from '../src/audio';
|
||||
import { StreamType } from '../src/audio/index';
|
||||
import { demuxProbe } from '../src/util/demuxProbe';
|
||||
|
||||
jest.mock('prism-media');
|
||||
@@ -12,19 +14,21 @@ jest.mock('prism-media');
|
||||
const WebmDemuxer = _opus.WebmDemuxer as unknown as jest.Mock<_opus.WebmDemuxer>;
|
||||
const OggDemuxer = _opus.OggDemuxer as unknown as jest.Mock<_opus.OggDemuxer>;
|
||||
|
||||
function nextTick() {
|
||||
async function nextTick() {
|
||||
// eslint-disable-next-line no-promise-executor-return
|
||||
return new Promise((resolve) => process.nextTick(resolve));
|
||||
}
|
||||
|
||||
async function* gen(n: number) {
|
||||
for (let i = 0; i < n; i++) {
|
||||
yield Buffer.from([i]);
|
||||
async function* gen(num: number) {
|
||||
for (let index = 0; index < num; index++) {
|
||||
yield Buffer.from([index]);
|
||||
await nextTick();
|
||||
}
|
||||
}
|
||||
|
||||
function range(n: number) {
|
||||
return Buffer.from(Array.from(Array(n).keys()));
|
||||
function range(num: number) {
|
||||
// eslint-disable-next-line unicorn/no-new-array
|
||||
return Buffer.from(Array.from(new Array(num).keys()));
|
||||
}
|
||||
|
||||
const validHead = Buffer.from([
|
||||
@@ -41,6 +45,7 @@ async function collectStream(stream: Readable): Promise<Buffer> {
|
||||
for await (const data of stream) {
|
||||
output = Buffer.concat([output, data]);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@@ -107,10 +112,10 @@ describe('demuxProbe', () => {
|
||||
});
|
||||
|
||||
test('Gives up on larger streams', async () => {
|
||||
const stream = Readable.from(gen(8192), { objectMode: false });
|
||||
const stream = Readable.from(gen(8_192), { objectMode: false });
|
||||
const probe = await demuxProbe(stream);
|
||||
expect(probe.type).toEqual(StreamType.Arbitrary);
|
||||
await expect(collectStream(probe.stream)).resolves.toEqual(range(8192));
|
||||
await expect(collectStream(probe.stream)).resolves.toEqual(range(8_192));
|
||||
});
|
||||
|
||||
test('Propagates errors', async () => {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
import EventEmitter from 'node:events';
|
||||
import { VoiceConnection, VoiceConnectionStatus } from '../src/VoiceConnection';
|
||||
import process from 'node:process';
|
||||
import { VoiceConnectionStatus, type VoiceConnection } from '../src/VoiceConnection';
|
||||
import { entersState } from '../src/util/entersState';
|
||||
|
||||
function createFakeVoiceConnection(status = VoiceConnectionStatus.Signalling) {
|
||||
@@ -20,13 +21,13 @@ describe('entersState', () => {
|
||||
const vc = createFakeVoiceConnection();
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
||||
process.nextTick(() => vc.emit(VoiceConnectionStatus.Ready, null as any, null as any));
|
||||
const result = await entersState(vc, VoiceConnectionStatus.Ready, 1000);
|
||||
const result = await entersState(vc, VoiceConnectionStatus.Ready, 1_000);
|
||||
expect(result).toEqual(vc);
|
||||
});
|
||||
|
||||
test('Rejects once the timeout is exceeded', async () => {
|
||||
const vc = createFakeVoiceConnection();
|
||||
const promise = entersState(vc, VoiceConnectionStatus.Ready, 1000);
|
||||
const promise = entersState(vc, VoiceConnectionStatus.Ready, 1_000);
|
||||
jest.runAllTimers();
|
||||
await expect(promise).rejects.toThrowError();
|
||||
});
|
||||
@@ -51,6 +52,6 @@ describe('entersState', () => {
|
||||
|
||||
test('Resolves immediately when target already in desired state', async () => {
|
||||
const vc = createFakeVoiceConnection();
|
||||
await expect(entersState(vc, VoiceConnectionStatus.Signalling, 1000)).resolves.toEqual(vc);
|
||||
await expect(entersState(vc, VoiceConnectionStatus.Signalling, 1_000)).resolves.toEqual(vc);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user