feat: implement media echo fix and YouTube screenshare design
- Introduced a new `ScreenShareController` to manage YouTube screenshare functionality. - Updated `DiscordPlayer` to track ownership of audio streams, preventing conflicts between music playback and screenshare. - Added error handling for various states including voice connection checks and media busy states. - Created unit tests for `ScreenShareController` and `DiscordPlayer` ownership rules to ensure correct functionality. - Added documentation for the new media echo fix and screenshare design.
This commit is contained in:
82
tests/player.test.ts
Normal file
82
tests/player.test.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { Readable } from "node:stream";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
// Mock @discordjs/voice
|
||||
vi.mock("@discordjs/voice", () => {
|
||||
const mockPlayer = {
|
||||
play: vi.fn(),
|
||||
pause: vi.fn(),
|
||||
unpause: vi.fn().mockReturnValue(true),
|
||||
stop: vi.fn(),
|
||||
on: vi.fn(),
|
||||
state: { status: "idle" },
|
||||
};
|
||||
const mockConnection = {
|
||||
subscribe: vi.fn().mockReturnValue({}),
|
||||
};
|
||||
return {
|
||||
AudioPlayerStatus: { Idle: "idle", Playing: "playing", Paused: "paused" },
|
||||
createAudioPlayer: vi.fn(() => mockPlayer),
|
||||
createAudioResource: vi.fn(() => ({})),
|
||||
StreamType: { OggOpus: "OggOpus" },
|
||||
AudioPlayer: vi.fn(),
|
||||
VoiceConnection: vi.fn(),
|
||||
__mockPlayer: mockPlayer,
|
||||
__mockConnection: mockConnection,
|
||||
};
|
||||
});
|
||||
|
||||
// Import after mocks
|
||||
import { DiscordPlayer } from "../src/player";
|
||||
|
||||
describe("DiscordPlayer", () => {
|
||||
let player: DiscordPlayer;
|
||||
const dummyStream = new Readable();
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
player = new DiscordPlayer();
|
||||
});
|
||||
|
||||
describe("ownership", () => {
|
||||
it("starts with owner none", () => {
|
||||
expect(player.getOwner()).toBe("none");
|
||||
});
|
||||
|
||||
it("playStream with owner sets owner", () => {
|
||||
player.playStream(dummyStream, "music");
|
||||
expect(player.getOwner()).toBe("music");
|
||||
});
|
||||
|
||||
it("browser bridge cannot override music owner", () => {
|
||||
player.playStream(dummyStream, "music");
|
||||
expect(() => player.playStream(dummyStream, "browser-bridge")).toThrow(
|
||||
"Discord audio player is owned by music",
|
||||
);
|
||||
});
|
||||
|
||||
it("same owner can replace stream without error", () => {
|
||||
player.playStream(dummyStream, "music");
|
||||
expect(() => player.playStream(dummyStream, "music")).not.toThrow();
|
||||
expect(player.getOwner()).toBe("music");
|
||||
});
|
||||
|
||||
it("matching owner stop releases ownership", () => {
|
||||
player.playStream(dummyStream, "music");
|
||||
player.stop("music");
|
||||
expect(player.getOwner()).toBe("none");
|
||||
});
|
||||
|
||||
it("non-owner stop is ignored", () => {
|
||||
player.playStream(dummyStream, "music");
|
||||
player.stop("browser-bridge");
|
||||
expect(player.getOwner()).toBe("music");
|
||||
});
|
||||
|
||||
it("stop without owner releases ownership", () => {
|
||||
player.playStream(dummyStream, "music");
|
||||
player.stop();
|
||||
expect(player.getOwner()).toBe("none");
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user