Etapa 1 inteira (logica com 100% de cobertura, cena 3D, toque, sons, bancada de desempenho, e2e) e a base da etapa 2 (mapa novo no Tiled, texturas, imagens dos itens, sons conferidos, golpe recortado e medido). Pagina /jogo fora do menu e do sitemap ate a medicao no celular.
244 lines
7.2 KiB
TypeScript
244 lines
7.2 KiB
TypeScript
import { fireEvent } from "@testing-library/react";
|
|
import { criarControle } from "./controle";
|
|
|
|
let alvo: HTMLDivElement;
|
|
let travaDo: Element | null;
|
|
|
|
beforeEach(() => {
|
|
alvo = document.createElement("div");
|
|
document.body.append(alvo);
|
|
travaDo = null;
|
|
Object.defineProperty(document, "pointerLockElement", {
|
|
configurable: true,
|
|
get: () => travaDo,
|
|
});
|
|
});
|
|
|
|
afterEach(() => {
|
|
alvo.remove();
|
|
});
|
|
|
|
function travar() {
|
|
travaDo = alvo;
|
|
document.dispatchEvent(new Event("pointerlockchange"));
|
|
}
|
|
|
|
function mover(movementX: number, movementY: number) {
|
|
const e = new MouseEvent("mousemove");
|
|
Object.defineProperty(e, "movementX", { value: movementX });
|
|
Object.defineProperty(e, "movementY", { value: movementY });
|
|
document.dispatchEvent(e);
|
|
}
|
|
|
|
describe("criarControle: teclado", () => {
|
|
it("W e as setas movem; teclas opostas se anulam", () => {
|
|
const c = criarControle(alvo);
|
|
fireEvent.keyDown(window, { code: "KeyW" });
|
|
fireEvent.keyDown(window, { code: "ArrowRight" });
|
|
expect(c.ler().mover).toEqual([1, 1]);
|
|
fireEvent.keyDown(window, { code: "KeyS" });
|
|
fireEvent.keyDown(window, { code: "KeyA" });
|
|
expect(c.ler().mover).toEqual([0, 0]);
|
|
fireEvent.keyUp(window, { code: "KeyS" });
|
|
fireEvent.keyUp(window, { code: "KeyA" });
|
|
expect(c.ler().mover).toEqual([1, 1]);
|
|
c.descartar();
|
|
});
|
|
|
|
it("soma o direcional de toque ao teclado", () => {
|
|
const c = criarControle(alvo);
|
|
c.definirMover(-1, 0.5);
|
|
fireEvent.keyDown(window, { code: "KeyD" });
|
|
expect(c.ler().mover).toEqual([0, 0.5]);
|
|
c.descartar();
|
|
});
|
|
|
|
it("1, 2 e 3 escolhem a arma", () => {
|
|
const c = criarControle(alvo);
|
|
expect(c.ler().arma).toBe(0);
|
|
fireEvent.keyDown(window, { code: "Digit3" });
|
|
expect(c.ler().arma).toBe(2);
|
|
fireEvent.keyDown(window, { code: "Digit2" });
|
|
expect(c.ler().arma).toBe(1);
|
|
fireEvent.keyDown(window, { code: "Digit1" });
|
|
expect(c.ler().arma).toBe(0);
|
|
c.descartar();
|
|
});
|
|
|
|
it("a roda troca para a próxima e para a anterior, em volta", () => {
|
|
const c = criarControle(alvo);
|
|
fireEvent.wheel(window, { deltaY: 100 });
|
|
expect(c.ler().arma).toBe(1);
|
|
fireEvent.wheel(window, { deltaY: -100 });
|
|
fireEvent.wheel(window, { deltaY: -100 });
|
|
expect(c.ler().arma).toBe(2);
|
|
fireEvent.wheel(window, { deltaY: 100 });
|
|
expect(c.ler().arma).toBe(0);
|
|
c.descartar();
|
|
});
|
|
|
|
it("perder o foco da janela solta as teclas", () => {
|
|
const c = criarControle(alvo);
|
|
fireEvent.keyDown(window, { code: "KeyW" });
|
|
fireEvent.blur(window);
|
|
expect(c.ler().mover).toEqual([0, 0]);
|
|
c.descartar();
|
|
});
|
|
|
|
it("ignora tecla com o foco num campo de texto ou botão", () => {
|
|
const c = criarControle(alvo);
|
|
const campo = document.createElement("input");
|
|
const botao = document.createElement("button");
|
|
document.body.append(campo, botao);
|
|
fireEvent.keyDown(campo, { code: "KeyW" });
|
|
fireEvent.keyDown(botao, { code: "Digit3" });
|
|
const entrada = c.ler();
|
|
expect(entrada.mover).toEqual([0, 0]);
|
|
expect(entrada.arma).toBe(0);
|
|
campo.remove();
|
|
botao.remove();
|
|
c.descartar();
|
|
});
|
|
});
|
|
|
|
describe("criarControle: mouse", () => {
|
|
it("clicar no alvo pede a trava do ponteiro", () => {
|
|
alvo.requestPointerLock = jest.fn();
|
|
const c = criarControle(alvo);
|
|
fireEvent.click(alvo);
|
|
expect(alvo.requestPointerLock).toHaveBeenCalledTimes(1);
|
|
c.descartar();
|
|
});
|
|
|
|
it("clicar não falha onde não há trava do ponteiro", () => {
|
|
const c = criarControle(alvo);
|
|
expect(() => fireEvent.click(alvo)).not.toThrow();
|
|
c.descartar();
|
|
});
|
|
|
|
it("avisa quando a trava muda", () => {
|
|
const aoMudarTrava = jest.fn();
|
|
const c = criarControle(alvo, { aoMudarTrava });
|
|
travar();
|
|
travaDo = null;
|
|
document.dispatchEvent(new Event("pointerlockchange"));
|
|
expect(aoMudarTrava.mock.calls).toEqual([[true], [false]]);
|
|
c.descartar();
|
|
});
|
|
|
|
it("sem a trava, o mouse não gira nem atira", () => {
|
|
const c = criarControle(alvo);
|
|
mover(100, 100);
|
|
fireEvent.mouseDown(document, { button: 0 });
|
|
const entrada = c.ler();
|
|
expect(entrada.olhar).toEqual([0, 0]);
|
|
expect(entrada.atirar).toBe(false);
|
|
c.descartar();
|
|
});
|
|
|
|
it("com a trava, soma o giro e o ler o zera", () => {
|
|
const c = criarControle(alvo);
|
|
travar();
|
|
mover(100, -50);
|
|
mover(100, 0);
|
|
const [rumo, inclinacao] = c.ler().olhar;
|
|
expect(rumo).toBeCloseTo(-200 * 0.0022);
|
|
expect(inclinacao).toBeCloseTo(50 * 0.0022);
|
|
expect(c.ler().olhar).toEqual([0, 0]);
|
|
c.descartar();
|
|
});
|
|
|
|
it("botão esquerdo pressionado atira; outro botão e soltar não", () => {
|
|
const c = criarControle(alvo);
|
|
travar();
|
|
fireEvent.mouseDown(document, { button: 2 });
|
|
expect(c.ler().atirar).toBe(false);
|
|
fireEvent.mouseDown(document, { button: 0 });
|
|
expect(c.ler().atirar).toBe(true);
|
|
fireEvent.mouseUp(document, { button: 2 });
|
|
expect(c.ler().atirar).toBe(true);
|
|
fireEvent.mouseUp(document, { button: 0 });
|
|
expect(c.ler().atirar).toBe(false);
|
|
c.descartar();
|
|
});
|
|
|
|
it("clique inteiro entre duas leituras ainda dá um tiro, e só um", () => {
|
|
const c = criarControle(alvo);
|
|
travar();
|
|
fireEvent.mouseDown(document, { button: 0 });
|
|
fireEvent.mouseUp(document, { button: 0 });
|
|
expect(c.ler().atirar).toBe(true);
|
|
expect(c.ler().atirar).toBe(false);
|
|
c.descartar();
|
|
});
|
|
});
|
|
|
|
describe("criarControle: toque, soltar e descartar", () => {
|
|
it("junta o giro, o tiro e a arma vindos do toque", () => {
|
|
const c = criarControle(alvo);
|
|
c.somarOlhar(0.1, 0.2);
|
|
c.somarOlhar(0.1, 0);
|
|
c.definirAtirar(true);
|
|
c.definirArma(2);
|
|
expect(c.ler()).toEqual({
|
|
mover: [0, 0],
|
|
olhar: [0.2, 0.2],
|
|
atirar: true,
|
|
arma: 2,
|
|
});
|
|
c.descartar();
|
|
});
|
|
|
|
it("toque no botão de tiro entre duas leituras ainda dá um tiro, e só um", () => {
|
|
const c = criarControle(alvo);
|
|
c.definirAtirar(true);
|
|
c.definirAtirar(false);
|
|
expect(c.ler().atirar).toBe(true);
|
|
expect(c.ler().atirar).toBe(false);
|
|
c.descartar();
|
|
});
|
|
|
|
it("soltar zera movimento, tiro e giro, e mantém a arma", () => {
|
|
const c = criarControle(alvo);
|
|
travar();
|
|
fireEvent.keyDown(window, { code: "KeyW" });
|
|
fireEvent.mouseDown(document, { button: 0 });
|
|
c.definirMover(1, 1);
|
|
c.definirAtirar(true);
|
|
c.somarOlhar(1, 1);
|
|
c.definirArma(1);
|
|
c.soltar();
|
|
expect(c.ler()).toEqual({
|
|
mover: [0, 0],
|
|
olhar: [0, 0],
|
|
atirar: false,
|
|
arma: 1,
|
|
});
|
|
c.descartar();
|
|
});
|
|
|
|
it("descartar remove todos os ouvintes", () => {
|
|
alvo.requestPointerLock = jest.fn();
|
|
const aoMudarTrava = jest.fn();
|
|
const c = criarControle(alvo, { aoMudarTrava });
|
|
travar();
|
|
aoMudarTrava.mockClear();
|
|
c.descartar();
|
|
fireEvent.keyDown(window, { code: "KeyW" });
|
|
fireEvent.keyDown(window, { code: "Digit3" });
|
|
fireEvent.wheel(window, { deltaY: 100 });
|
|
fireEvent.mouseDown(document, { button: 0 });
|
|
mover(100, 100);
|
|
fireEvent.click(alvo);
|
|
document.dispatchEvent(new Event("pointerlockchange"));
|
|
expect(c.ler()).toEqual({
|
|
mover: [0, 0],
|
|
olhar: [0, 0],
|
|
atirar: false,
|
|
arma: 0,
|
|
});
|
|
expect(alvo.requestPointerLock).not.toHaveBeenCalled();
|
|
expect(aoMudarTrava).not.toHaveBeenCalled();
|
|
});
|
|
});
|