Pular para o conteúdo

Painel de dados

Um dashboard com filtro, métricas e tabela — testado com a sonda, sem navegador.

A Vitrine roda o programa inteiro de novo a cada interação, e o estado da sessão sobrevive. É o modelo que dispensa callback — e por isso o painel é um programa de cima para baixo que se testa como qualquer outro: a sonda digita, clica e pergunta o que apareceu.

PeçaO que ela exercita
V.titulo / V.metricao topo do painel
V.escolhao filtro que reexecuta a página
V.tabelaas linhas filtradas
V.testarclicar e digitar sem navegador

Estrutura#

text
painel-vendas/
  src/
    dados.df       carregar (com V.cache em producao)
    painel.df      a pagina
  main.df          V.rodar(painel)
  tests/
forge.toml
[project]
name = "painel-vendas"
version = "0.1.0"
description = "Painel de vendas"
entry = "src/main.df"
dataforge = ">=1.1"

[dependencies]

[scripts]
start = "run src/main.df"
test = "test tests/"

O núcleo#

Este bloco roda sozinho — copie para um arquivo e rode dataforge run. Ele termina com assert, e é assim que esta página é conferida a cada build.

src/painel.df
adopt Arcane.Vitrine as V

VENDAS := [
    {"loja": "centro", "mes": "jul", "valor": 1200},
    {"loja": "centro", "mes": "ago", "valor": 1500},
    {"loja": "norte", "mes": "jul", "valor": 800},
    {"loja": "norte", "mes": "ago", "valor": 950}
]

action painel():
    V.titulo("Vendas por loja")
    loja := V.escolha("Loja", ["todas", "centro", "norte"])
    linhas := VENDAS given loja is "todas" otherwise (VENDAS >> sift v: v["loja"] is loja)
    total := sum(linhas >> morph v: v["valor"])
    V.metrica("Total", $"R$ {total}")
    V.metrica("Lançamentos", str(len(linhas)))
    V.tabela(linhas)

t := V.testar(painel)
assert not t.falhou()
assert "R$ 4450" in t.texto()

t.selecionar("Loja", "norte")
assert "R$ 1750" in t.texto()
assert t.existe("tabela")
out "painel verde"

O teste#

No projeto, a regra mora em src/ e o teste a importa pelo caminho relativo — dataforge test tests/ descobre o arquivo sozinho.

tests/nucleo_test.df
adopt Arcane.Vitrine as V
adopt ../src/painel as P

crucible "painel":
    trial "o filtro muda o total":
        t := V.testar(P.painel)
        t.selecionar("Loja", "centro")
        expect "R$ 2700" in t.texto()

As decisões#

DecisãoSem ela
o painel é uma ação sem argumentonão há como testá-lo sem subir o servidor
o filtro é um valor, não um callbacko estado se espalha por funções que ninguém chama em ordem
V.cache na leitura dos dados (em produção)cada clique relê o banco inteiro
a sonda pergunta o textoo teste quebra a cada mudança de CSS

Para ir além#

Volte para todos os tipos de projeto.