Programação JavaScript, contratos e debugging
Você vai construir uma cotação que pode ser chamada por uma interface ou por uma ferramenta de agente. Comece com um arquivo cotacao.cjs e Node.js 24 disponível. Os dados são sintéticos; a função não altera estoque e não envia cobrança. A entrega inclui código, testes e uma pequena investigação do defeito do limiar. Faça as previsões do exercício antes de abrir a solução.
O laboratório exige justificar cada caso, não apenas executar um bloco pronto. Ao terminar, outra pessoa deve conseguir reconhecer o contrato pelas entradas aceitas, recusas e resultados. Separe a avaliação do algoritmo da avaliação de experiência do usuário: esta etapa oferece o núcleo de cálculo; uma interface futura ainda precisará traduzir erros e manter rótulos e valores compreensíveis.
JavaScriptProgramaçãoAo terminar esta aula
- Transforme requisitos em previsões antes da execução.
- Use erros controlados para verificar o verificador.
- Explique os limites de autoridade do cálculo.
Antes de continuar: Leitura: Programação JavaScript, contratos e debugging
Escreva a política como exemplos verificáveis
FundamentosAbra uma tabela de casos no seu caderno: um item de 9999 centavos, um item de 10000 e um de 10001. Preveja o frete sem olhar o código. Acrescente duas linhas distintas cuja soma alcance 10000; esse caso verifica acumulação, não apenas comparação. Agora liste entradas recusadas: quantidade zero, negativa, fracionária, texto, NaN e Infinity. O caso de lista vazia exige uma escolha: esta cotação a recusa porque uma compra sem itens não tem significado no fluxo proposto.
Escreva o contrato do preço: inteiro positivo em centavos por unidade. Não use o nome genérico valor quando ele puder significar preço da linha ou da unidade. Defina também o retorno: dois campos numéricos, sem texto monetário formatado. A apresentação pode gerar R$ 100,00 depois, mas a função não deve misturar cálculo e mensagem. Essa separação evita um teste frágil que compara uma frase inteira para descobrir se o frete foi calculado corretamente.
Implemente uma passagem e conserve a entrada
FundamentosCrie inteiroPositivo para centralizar a decisão sobre números. Em seguida, cotar verifica a coleção, percorre seus itens e acrescenta cada parcial. A helper não substitui todas as verificações: sku tem contrato textual, enquanto o resultado da multiplicação exige outra checagem de intervalo. Não normalize o sku alterando o objeto recebido; somente verificar que o texto não é vazio basta neste exemplo. Uma normalização comercial precisaria de política própria sobre maiúsculas e caracteres permitidos.
Antes da execução, descreva o valor de total após cada linha do caso com dois itens. Compare sua previsão com o resultado. Se você colocou o acumulador dentro do laço, verá que o primeiro subtotal desaparece. Corrija a posição e explique a invariante: total soma somente os itens já validados. O cálculo termina devolvendo um novo objeto; isso permite testar preservação da entrada com um snapshot JSON simples. Neste domínio só há campos básicos serializáveis; não extrapole esse snapshot como verificador universal de objetos.
Provoque um defeito e investigue sua causa
FundamentosExecute a solução e confirme que as asserções terminam sem erro. Faça então uma alteração deliberada: troque >= por >. O caso de 10000 deve falhar. Leia a diferença exibida e identifique qual valor esperado veio da política. Restaure o operador. Não capture o erro para imprimir sucesso, pois isso eliminaria justamente a evidência de que o teste protege o requisito. A documentação de assert distingue os métodos de comparação e de exigência de exceção.
Amplie o caso sem transformar teste em espelho
AvaliaçãoAcrescente um teste com duas linhas cujo total é 10000, outro com sku vazio e outro com um preço tão grande que a multiplicação perde segurança. Para cada um, escreva o defeito que ele detectaria. Se você adicionar uma condição somente porque o código atual a contém, talvez esteja testando a implementação em vez do contrato. Um requisito justificável, como não apresentar valor monetário inexato, dá razão independente ao teste de overflow.
Investigue também o que a cotação não garante. Um preço validado pode estar desatualizado; um sku não vazio pode não existir no catálogo; o cliente pode tentar modificar o preço recebido. Em uma aplicação real, o servidor consulta valores autorizados e associa a identidade à operação. Aqui queremos dominar a função e seus limites, não fabricar uma autorização implícita. Entregue o contrato, os casos anotados e uma explicação do erro provocado. A rubrica considera forte uma solução que detecta fronteira, tipo, acumulação e mutação; somente o caso nominal é evidência insuficiente.
Exercício aplicado
Uma cotação anuncia frete grátis a partir de R$ 100,00. O código antigo usa total > 10000 e soma quantidades sem validar. Uma compra de exatamente R$ 100,00 recebe frete e uma quantidade "2" chega do formulário. Defina o contrato e corrija o comportamento sem alterar a entrada.
- Antes da resolução, escreva resultados esperados para 9999, 10000 e 10001 centavos.
- Liste tipos e valores recusados; decida se o domínio aceita quantidade fracionária.
- Implemente cálculo separado de leitura de formulário e apresentação.
- Execute asserções nominais, de limite, erro, overflow e preservação da entrada.
Abrir resolução comentada
O requisito inclui o limiar: a comparação correta é >=. Quantidade é inteiro positivo seguro; a string do formulário deve ser convertida numa fronteira explícita e validada, não aceita silenciosamente pelo núcleo. Cada multiplicação e soma precisa permanecer no intervalo de inteiros seguros.
A função não envia pagamento nem altera estoque. Ela devolve fatos para uma camada de apresentação. As asserções de 9999 e 10000 detectam a troca de operador; os casos NaN, Infinity e string detectam um contrato insuficiente. O snapshot da entrada confirma que os objetos recebidos não foram modificados.
const assert=require('node:assert/strict');
function inteiroPositivo(x,nome) {
if(!Number.isSafeInteger(x)||x<=0)throw new Error(nome+' invalido');
return x;
}
function cotar(itens) {
if(!Array.isArray(itens)||itens.length===0)throw new Error('lista invalida');
let total=0;
for(const item of itens) {
if(!item||typeof item.sku!=='string'||!item.sku.trim())throw new Error('sku invalido');
const q=inteiroPositivo(item.quantidade,'quantidade');
const p=inteiroPositivo(item.precoCentavos,'preco');
const parcial=q*p;
if(!Number.isSafeInteger(parcial)||!Number.isSafeInteger(total+parcial))throw new Error('overflow');
total+=parcial;
}
return {totalCentavos:total,freteCentavos:total>=10000?0:1500};
}
const entrada=[{sku:'I2',quantidade:2,precoCentavos:5000}];
const antes=JSON.stringify(entrada);
assert.deepEqual(cotar(entrada),{totalCentavos:10000,freteCentavos:0});
assert.equal(JSON.stringify(entrada),antes);
assert.equal(cotar([{sku:'I2',quantidade:1,precoCentavos:9999}]).freteCentavos,1500);
for(const x of [0,-1,1.5,NaN,Infinity,'2'])assert.throws(()=>cotar([{sku:'I2',quantidade:x,precoCentavos:5000}]),/quantidade/);
assert.throws(()=>cotar([{sku:'I2',quantidade:2,precoCentavos:Number.MAX_SAFE_INTEGER}]),/overflow/);
assert.throws(()=>cotar([]),/lista/);
console.log('contrato, limiar, imutabilidade e entradas adversariais verificados');Como conferir seu resultado
- O contrato declara tipos, unidade monetária e limites numéricos.
- O caso de exatamente 10000 centavos recebe frete zero.
- Todas as entradas adversariais são recusadas sem efeito externo.
- A entrada permanece igual e a falha do teste não é engolida.
Teste sua compreensão
Responda com suas palavras antes de abrir o comentário. Saber explicar uma decisão é parte do domínio.
1. Qual teste detecta reinicializar total a cada iteração?
Uma coleção com pelo menos dois subtotais diferentes.
Um único item pode produzir o resultado certo apesar da posição errada do acumulador.
2. Por que manter o teste deliberadamente vermelho antes da correção?
Para confirmar que observa a regra quebrada.
Se o operador muda e o teste continua passando, ele não protege essa fronteira.
3. Um preço inteiro correto é necessariamente autorizado?
Não. A origem do preço é outro contrato.
Validade numérica e autoridade comercial são verificações diferentes.
Seu progresso fica salvo neste navegador. Concluir a leitura não substitui demonstrar o domínio nos exercícios.
Referências e aprofundamento
Documentação oficial e trabalhos originais. As referências registram o escopo e as limitações para você conferir o que sustentam.
- JavaScript Guide: Functions
MDN • consulta: 2026-10-06
JavaScriptFunções, argumentos, retorno e efeitos de mutação em objetos.
Limites: Referencia de linguagem; não define contratos comerciais.
- JavaScript Guide: Control flow and error handling
MDN • consulta: 2026-10-06
JavaScriptCondicionais, laços e exceções.
Limites: Controle sintático não demonstra correção do requisito.
- Node.js24: Assert
Node.js • consulta: 2026-10-06
FundamentosAsserções estritas de valores, estruturas e exceções.
Limites: Exemplos usam APIs estáveis e foram executados com Node24.19.0; documento versionado24.15.0.