mirror of
https://github.com/minescope/mineping.git
synced 2025-07-12 17:44:34 +03:00
test: implement tests using vitest framework
This commit is contained in:
117
test/bedrock.test.js
Normal file
117
test/bedrock.test.js
Normal file
@ -0,0 +1,117 @@
|
||||
import dgram from "node:dgram";
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
||||
import { pingBedrock } from "../lib/bedrock.js";
|
||||
|
||||
vi.mock("node:dgram");
|
||||
|
||||
describe("bedrock.js", () => {
|
||||
let mockSocket;
|
||||
|
||||
beforeEach(() => {
|
||||
// A store for event handlers, closed over by the mockSocket.
|
||||
const handlers = {};
|
||||
|
||||
// Create a stateful mock socket to simulate EventEmitter.
|
||||
mockSocket = {
|
||||
send: vi.fn(),
|
||||
close: vi.fn(),
|
||||
on: vi.fn((event, handler) => {
|
||||
handlers[event] = handler;
|
||||
}),
|
||||
emit: vi.fn((event, ...args) => {
|
||||
if (handlers[event]) {
|
||||
handlers[event](...args);
|
||||
}
|
||||
}),
|
||||
};
|
||||
|
||||
dgram.createSocket = vi.fn().mockReturnValue(mockSocket);
|
||||
vi.useFakeTimers();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it("should ping a server and parse MOTD", async () => {
|
||||
const host = "play.example.com";
|
||||
const options = { port: 25565, timeout: 10000 };
|
||||
const pingPromise = pingBedrock(host, options);
|
||||
|
||||
const motd =
|
||||
"MCPE;§l§bOasys§fPE;0;1337;1096;1999;-37530542056358113;oasys-pe.ru;Adventure;1";
|
||||
const mockPongPacket = createMockPongPacket(motd);
|
||||
|
||||
mockSocket.emit("message", mockPongPacket);
|
||||
|
||||
const result = await pingPromise;
|
||||
|
||||
expect(dgram.createSocket).toHaveBeenCalledWith("udp4");
|
||||
expect(mockSocket.send).toHaveBeenCalledWith(
|
||||
expect.any(Buffer),
|
||||
0,
|
||||
33,
|
||||
options.port,
|
||||
host
|
||||
);
|
||||
expect(mockSocket.close).toHaveBeenCalled();
|
||||
expect(result).toEqual({
|
||||
edition: "MCPE",
|
||||
name: "§l§bOasys§fPE",
|
||||
version: { protocolVersion: 0, minecraftVersion: "1337" },
|
||||
players: { online: 1096, max: 1999 },
|
||||
serverId: "-37530542056358113",
|
||||
mapName: "oasys-pe.ru",
|
||||
gameMode: "Adventure",
|
||||
});
|
||||
});
|
||||
|
||||
describe("errors", () => {
|
||||
it("should throw an error if host is not provided", () => {
|
||||
expect(() => pingBedrock(null)).toThrow("Host argument is not provided");
|
||||
});
|
||||
|
||||
it("should reject on socket timeout", async () => {
|
||||
const pingPromise = pingBedrock("play.example.com", { timeout: 1000 });
|
||||
|
||||
vi.advanceTimersByTime(1000);
|
||||
|
||||
await expect(pingPromise).rejects.toThrow("Socket timeout");
|
||||
expect(mockSocket.close).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("should reject on a generic socket error", async () => {
|
||||
const pingPromise = pingBedrock("play.example.com");
|
||||
|
||||
// Simulate a DNS or network error by emitting it.
|
||||
mockSocket.emit("error", new Error("EHOSTUNREACH"));
|
||||
|
||||
await expect(pingPromise).rejects.toThrow("EHOSTUNREACH");
|
||||
});
|
||||
|
||||
it("should only reject once, even if multiple errors occur", async () => {
|
||||
const pingPromise = pingBedrock("play.example.com");
|
||||
|
||||
// Fire a socket error first.
|
||||
mockSocket.emit("error", new Error("First error"));
|
||||
|
||||
// Then, try to trigger another error by sending a bad message.
|
||||
mockSocket.emit("message", Buffer.alloc(0));
|
||||
|
||||
await expect(pingPromise).rejects.toThrow("First error");
|
||||
expect(mockSocket.close).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createMockPongPacket(motd) {
|
||||
const motdBuffer = Buffer.from(motd, "utf-8");
|
||||
const packet = Buffer.alloc(35 + motdBuffer.length);
|
||||
packet.writeUInt8(0x1c, 0);
|
||||
packet.writeBigInt64LE(BigInt(Date.now()), 1);
|
||||
Buffer.from("00ffff00fefefefefdfdfdfd12345678", "hex").copy(packet, 17);
|
||||
packet.writeUInt16BE(motdBuffer.length, 33);
|
||||
motdBuffer.copy(packet, 35);
|
||||
return packet;
|
||||
}
|
Reference in New Issue
Block a user