236 lines
6.9 KiB
TypeScript
236 lines
6.9 KiB
TypeScript
import { describe, expect, it } from "bun:test"
|
|
import z from "zod"
|
|
import {
|
|
codigosResposta,
|
|
respostaComuns,
|
|
zCodigosRespostaErro,
|
|
zResposta,
|
|
zRespostaErro,
|
|
zRespostaSucesso,
|
|
zRespostas,
|
|
type tipoZResposta,
|
|
} from "../src/respostas"
|
|
|
|
describe("zRespostas - Sucesso", () => {
|
|
it("deve validar resposta de sucesso com schema específico (string)", () => {
|
|
const schema = zRespostas(z.string())
|
|
const res = respostaComuns.valor("Operação realizada com sucesso")
|
|
|
|
const parsed = schema.parse(res)
|
|
expect(parsed.cod).toBe(codigosResposta.sucesso)
|
|
expect(parsed.eCerto).toBe(true)
|
|
expect(parsed.eErro).toBe(false)
|
|
if (parsed.eCerto) {
|
|
expect(parsed.valor).toBe("Operação realizada com sucesso")
|
|
}
|
|
})
|
|
|
|
it("deve validar resposta de sucesso com schema de objeto complexo", () => {
|
|
const zUsuario = z.object({
|
|
id: z.number(),
|
|
nome: z.string(),
|
|
ativo: z.boolean(),
|
|
})
|
|
const schema = zRespostas(zUsuario)
|
|
const res = respostaComuns.valor({ id: 10, nome: "Maria", ativo: true }, [
|
|
"detalhe 1",
|
|
])
|
|
|
|
const parsed = schema.parse(res)
|
|
expect(parsed.eCerto).toBe(true)
|
|
if (parsed.eCerto) {
|
|
expect(parsed.valor.id).toBe(10)
|
|
expect(parsed.valor.nome).toBe("Maria")
|
|
expect(parsed.valor.ativo).toBe(true)
|
|
expect(parsed.detalhes).toEqual(["detalhe 1"])
|
|
}
|
|
})
|
|
|
|
it("deve aceitar qualquer valor quando invocado sem parâmetros (default z.any())", () => {
|
|
const schema = zRespostas()
|
|
const resString = respostaComuns.valor("qualquer texto")
|
|
const resNumero = respostaComuns.valor(12345)
|
|
const resBool = respostaComuns.valorTrue()
|
|
|
|
expect(schema.parse(resString).eCerto).toBe(true)
|
|
expect(schema.parse(resNumero).eCerto).toBe(true)
|
|
expect(schema.parse(resBool).eCerto).toBe(true)
|
|
})
|
|
|
|
it("deve funcionar com zRespostaSucesso isoladamente", () => {
|
|
const schema = zRespostaSucesso(z.number())
|
|
const res = respostaComuns.valor(99)
|
|
|
|
const parsed = schema.parse(res)
|
|
expect(parsed.cod).toBe(200)
|
|
expect(parsed.valor).toBe(99)
|
|
})
|
|
|
|
it("deve rejeitar sucesso quando o tipo de valor for incompatível", () => {
|
|
const schema = zRespostas(z.string())
|
|
const resInvalido = {
|
|
cod: codigosResposta.sucesso,
|
|
eCerto: true,
|
|
eErro: false,
|
|
valor: 12345, // número em vez de string
|
|
}
|
|
|
|
expect(() => schema.parse(resInvalido)).toThrow()
|
|
})
|
|
|
|
it("deve aceitar detalhes nullish (null, undefined ou ausente)", () => {
|
|
const schema = zRespostas(z.string())
|
|
|
|
const resComNull = {
|
|
cod: codigosResposta.sucesso,
|
|
eCerto: true,
|
|
eErro: false,
|
|
valor: "ok",
|
|
detalhes: null,
|
|
}
|
|
const resSemDetalhes = {
|
|
cod: codigosResposta.sucesso,
|
|
eCerto: true,
|
|
eErro: false,
|
|
valor: "ok",
|
|
}
|
|
|
|
expect(schema.parse(resComNull).detalhes).toBeNull()
|
|
expect(schema.parse(resSemDetalhes).detalhes).toBeUndefined()
|
|
})
|
|
})
|
|
|
|
describe("zRespostas - Erro", () => {
|
|
const schema = zRespostas(z.string())
|
|
|
|
it("deve validar erroConhecido (400)", () => {
|
|
const res = respostaComuns.erro("Dados inválidos", ["campo X obrigatório"])
|
|
const parsed = schema.parse(res)
|
|
|
|
expect(parsed.cod).toBe(codigosResposta.erroConhecido)
|
|
expect(parsed.eCerto).toBe(false)
|
|
expect(parsed.eErro).toBe(true)
|
|
if (parsed.eErro) {
|
|
expect(parsed.mensagem).toBe("Dados inválidos")
|
|
expect(parsed.detalhes).toEqual(["campo X obrigatório"])
|
|
}
|
|
})
|
|
|
|
it("deve validar erroPermissao (401)", () => {
|
|
const res = respostaComuns.erroPermissao("Acesso negado")
|
|
const parsed = schema.parse(res)
|
|
|
|
expect(parsed.cod).toBe(codigosResposta.erroPermissao)
|
|
expect(parsed.eErro).toBe(true)
|
|
if (parsed.eErro) {
|
|
expect(parsed.mensagem).toBe("Acesso negado")
|
|
}
|
|
})
|
|
|
|
it("deve validar erroNaoEncontrado (404)", () => {
|
|
const res = respostaComuns.naoEncontrado("Usuário não encontrado")
|
|
const parsed = schema.parse(res)
|
|
|
|
expect(parsed.cod).toBe(codigosResposta.erroNaoEncontrado)
|
|
expect(parsed.eErro).toBe(true)
|
|
if (parsed.eErro) {
|
|
expect(parsed.mensagem).toBe("Usuário não encontrado")
|
|
}
|
|
})
|
|
|
|
it("deve validar erroDesconhecido (500)", () => {
|
|
const res = respostaComuns.erroInterno({
|
|
erro: new Error("Falha no banco"),
|
|
local: "usuario.service",
|
|
mensagem: "Erro inesperado",
|
|
})
|
|
const parsed = schema.parse(res)
|
|
|
|
expect(parsed.cod).toBe(codigosResposta.erroDesconhecido)
|
|
expect(parsed.eErro).toBe(true)
|
|
if (parsed.eErro) {
|
|
expect(parsed.mensagem).toBe("Erro inesperado")
|
|
}
|
|
})
|
|
|
|
it("deve validar tempoEsgotado (504)", () => {
|
|
const res = respostaComuns.tempoEsgotado("Gateway Timeout")
|
|
const parsed = schema.parse(res)
|
|
|
|
expect(parsed.cod).toBe(codigosResposta.tempoEsgotado)
|
|
expect(parsed.eErro).toBe(true)
|
|
if (parsed.eErro) {
|
|
expect(parsed.mensagem).toBe("Gateway Timeout")
|
|
}
|
|
})
|
|
|
|
it("deve funcionar com zRespostaErro isoladamente", () => {
|
|
const res = respostaComuns.erro("Falha simples")
|
|
const parsed = zRespostaErro.parse(res)
|
|
|
|
expect(parsed.cod).toBe(400)
|
|
expect(parsed.mensagem).toBe("Falha simples")
|
|
})
|
|
|
|
it("deve rejeitar códigos de erro não pertencentes a codigosResposta", () => {
|
|
const resInvalido = {
|
|
cod: 403, // 403 não é código do enum codigosResposta (p-respostas usa 401)
|
|
eCerto: false,
|
|
eErro: true,
|
|
mensagem: "Proibido",
|
|
}
|
|
|
|
expect(() => schema.parse(resInvalido)).toThrow()
|
|
})
|
|
|
|
it("deve rejeitar erro sem mensagem", () => {
|
|
const resSemMsg = {
|
|
cod: codigosResposta.erroConhecido,
|
|
eCerto: false,
|
|
eErro: true,
|
|
}
|
|
|
|
expect(() => schema.parse(resSemMsg)).toThrow()
|
|
})
|
|
})
|
|
|
|
describe("zRespostas - Consistência e Aliases", () => {
|
|
it("zResposta deve ser idêntico a zRespostas", () => {
|
|
expect(zResposta).toBe(zRespostas)
|
|
})
|
|
|
|
it("zCodigosRespostaErro deve aceitar apenas os 5 códigos de erro", () => {
|
|
expect(zCodigosRespostaErro.parse(400)).toBe(400)
|
|
expect(zCodigosRespostaErro.parse(401)).toBe(401)
|
|
expect(zCodigosRespostaErro.parse(404)).toBe(404)
|
|
expect(zCodigosRespostaErro.parse(500)).toBe(500)
|
|
expect(zCodigosRespostaErro.parse(504)).toBe(504)
|
|
|
|
expect(() => zCodigosRespostaErro.parse(200)).toThrow()
|
|
expect(() => zCodigosRespostaErro.parse(403)).toThrow()
|
|
expect(() => zCodigosRespostaErro.parse(502)).toThrow()
|
|
})
|
|
|
|
it("deve permitir narrowing estático em TypeScript", () => {
|
|
const schema = zRespostas(z.string())
|
|
const res: tipoZResposta<z.ZodString> = schema.parse(
|
|
respostaComuns.valor("dados"),
|
|
)
|
|
|
|
if (res.eCerto) {
|
|
const v: string = res.valor
|
|
expect(v).toBe("dados")
|
|
} else {
|
|
const m: string = res.mensagem
|
|
expect(m).toBeDefined()
|
|
}
|
|
|
|
if (res.cod === codigosResposta.sucesso) {
|
|
const v: string = res.valor
|
|
expect(v).toBe("dados")
|
|
} else {
|
|
const m: string = res.mensagem
|
|
expect(m).toBeDefined()
|
|
}
|
|
})
|
|
})
|