From a6a7b3a8c7f15e0bbeed969ff7c03e7cdd322826 Mon Sep 17 00:00:00 2001 From: Willem van den Ende Date: Tue, 27 Oct 2026 21:28:37 +0000 Subject: [PATCH] yak(pin-user-inspect-output-exactly-both-redacted-fields-shape-l0mg): pin User inspect output exactly (both redacted fields + shape) --- app/test/firehose/accounts_test.exs | 53 +++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/app/test/firehose/accounts_test.exs b/app/test/firehose/accounts_test.exs index abb569e..41b598c 100644 --- a/app/test/firehose/accounts_test.exs +++ b/app/test/firehose/accounts_test.exs @@ -390,8 +390,57 @@ defmodule Firehose.AccountsTest do end describe "inspect/2 for the User module" do - test "does not include password" do - refute inspect(%User{password: "123456"}) =~ "password: \"123456\"" + # Rendering is `#Firehose.Accounts.User<__meta__: ..., id: 42, ...>`: a + # single line that ends with `, ...>`. The tests below pin the stable parts + # (module name, one line, redaction, field names and values) rather than + # the full string, so a toolchain bump that changes formatting does not + # fail them. + test "redacts every field the schema marks redacted, by name and by value" do + user = %User{ + id: 42, + email: "shape-pin@example.com", + password: "plaintext-secret-value", + hashed_password: "hashed-secret-value" + } + + output = inspect(user) + redacted = User.__schema__(:redact_fields) + + # Guard against a vacuous loop if the schema key ever changes meaning. + # (`match?` rather than a comparison against `[]`: the type checker + # proves this schema's literal list non-empty and warns on the compare.) + assert match?([_ | _], redacted) + # The two secrets this schema declares; ties the loop to real fields. + assert :password in redacted + assert :hashed_password in redacted + + for field <- redacted do + refute output =~ Atom.to_string(field) + refute output =~ Map.fetch!(user, field) + end + end + + test "renders a single struct line with non-redacted fields and values" do + user = %User{ + id: 42, + email: "shape-pin@example.com", + password: "plaintext-secret-value", + hashed_password: "hashed-secret-value" + } + + output = inspect(user) + redacted = User.__schema__(:redact_fields) + + assert String.starts_with?(output, "#Firehose.Accounts.User<") + assert String.ends_with?(output, ">") + refute output =~ "\n" + + assert output =~ "id: 42" + assert output =~ ~s(email: "shape-pin@example.com") + + for %{field: field} <- User.__info__(:struct), field not in redacted do + assert output =~ Atom.to_string(field) + end end end end