Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / internal/modules/opportunities/teaming_test.go |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 720d47fae476b0d38477ae4401697d372b1ea2bc |
| Branch | feature/opportunity-to-outcome |
| Path or archive member | internal/modules/opportunities/teaming_test.go |
| Original SHA-256 | 2ff152aa7d6926a6f2a47f8c30b2b3dd24acfb271b54a2c3acb152c858dc12b9 |
| Git blob SHA | 768e3e3f85df2f4e441f7a65b56bfb21c139c07e |
| Reading-copy SHA-256 | 2ff152aa7d6926a6f2a47f8c30b2b3dd24acfb271b54a2c3acb152c858dc12b9 |
Recovered source transcript
Download complete source text ↓52 lines · 2.4 KB
package opportunities
import (
"errors"
"testing"
)
// THE DATABASE'S REFUSALS MUST ARRIVE AS SENTENCES, not as raw constraint violations.
//
// Every CHECK in migration 0102 encodes a rule somebody thought about: a signed agreement carries its date, a
// commitment names exactly one person, an expiry cannot precede a signature. Surfacing them as
// "ERROR: new row violates check constraint ck_kpc_names_somebody" wastes the fact that the rule was written
// down, and leaves a capture manager guessing at something they could fix in seconds.
func TestConstraintViolationsBecomeActionableSentences(t *testing.T) {
for _, c := range []struct {
name, raw string
want error
}{
{"duplicate partner", `ERROR: duplicate key value violates unique constraint "uq_teaming_partner_per_pursuit"`, ErrPartnerExists},
{"commitment names nobody", `ERROR: new row for relation "key_personnel_commitments" violates check constraint "ck_kpc_names_somebody"`, ErrCommitmentNeedsPerson},
{"signed with no date", `ERROR: violates check constraint "ck_teaming_signed_dated"`, ErrSignedNeedsDate},
{"committed with no date", `ERROR: violates check constraint "ck_kpc_committed_dated"`, ErrSignedNeedsDate},
} {
got := translateTeaming(errors.New(c.raw))
if !errors.Is(got, c.want) {
t.Errorf("%s: got %v, want %v", c.name, got, c.want)
}
}
}
// An error the module does not recognise passes through UNCHANGED rather than being flattened into one of the
// known sentences. A wrong explanation is worse than no explanation: it sends somebody to fix a rule they did
// not break.
func TestAnUnknownDatabaseErrorIsNotGuessedAt(t *testing.T) {
raw := errors.New("ERROR: connection reset by peer")
if got := translateTeaming(raw); got != raw {
t.Fatalf("an unrelated error was translated into %v, which would send somebody to the wrong fix", got)
}
}
// The expiry rule reads as a sentence too, and it is the one a capture manager trips most: entering the
// signature and expiry the wrong way round.
func TestExpiryBeforeSigningExplainsItself(t *testing.T) {
got := translateTeaming(errors.New(`violates check constraint "ck_kpc_expiry_after_signing"`))
if !errors.Is(got, ErrInvalidInput) {
t.Fatalf("got %v, want an invalid input error", got)
}
if got.Error() == ErrInvalidInput.Error() {
t.Error("the message says nothing beyond invalid input, so it does not say what to change")
}
}