Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / internal/modules/recruiting/redact_test.go |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 720d47fae476b0d38477ae4401697d372b1ea2bc |
| Branch | feature/opportunity-to-outcome |
| Path or archive member | internal/modules/recruiting/redact_test.go |
| Original SHA-256 | f6d9ad2749f3593a644c53fef3a65e190555fe6fc2761c1b51930fd5ea4aee59 |
| Git blob SHA | f9fd92e05a9b0b84a52545508d35e013374394b0 |
| Reading-copy SHA-256 | f6d9ad2749f3593a644c53fef3a65e190555fe6fc2761c1b51930fd5ea4aee59 |
Recovered source transcript
Download complete source text ↓223 lines · 9.5 KB
package recruiting
import (
"reflect"
"testing"
"github.com/shopspring/decimal"
"github.com/missionworkforce/missionmatch/internal/platform/orgsettings"
)
func amt(v string) *decimal.Decimal {
d := decimal.RequireFromString(v)
return &d
}
// A recruiter at the shipped defaults: rates are managers and above, margin is the owner alone.
var recruiterPolicy = orgsettings.Policy{CanSeeRates: false, CanSeeMargins: false, CanSeeContacts: true}
var ownerPolicy = orgsettings.Policy{CanSeeRates: true, CanSeeMargins: true, CanSeeContacts: true}
func TestRedactOfferRemovesRatesAndTheCostSide(t *testing.T) {
o := Offer{
BillRate: amt("185.00"), PayRate: amt("120.00"), Salary: amt("210000"),
FeePct: amt("0.22"),
Economics: Economics{
SpreadPerHour: amt("65.00"), SpreadPct: amt("35.1351"),
BurdenPct: amt("0.35"), BurdenSource: BurdenFromOrg,
CostPerHour: amt("162.00"), MarginPerHour: amt("23.00"), MarginPct: amt("12.4324"),
Fee: amt("46200"),
},
}
redactOffer(&o, recruiterPolicy)
// ABSENT, not zero. A bill rate of zero is a statement about the placement and it would be false.
if o.BillRate != nil || o.PayRate != nil || o.Salary != nil {
t.Fatalf("rates survived redaction: bill=%v pay=%v salary=%v", o.BillRate, o.PayRate, o.Salary)
}
if o.FeePct != nil {
t.Fatal("fee percentage survived, it is the margin in another unit")
}
// THE WRAP IS THE FIRM'S OWN COST STRUCTURE and appears nowhere else, so it is the thing the margin
// setting most has to protect.
if o.Economics.BurdenPct != nil || o.Economics.BurdenSource != "" {
t.Fatalf("the wrap survived redaction: %+v", o.Economics)
}
if o.Economics.CostPerHour != nil || o.Economics.MarginPerHour != nil || o.Economics.MarginPct != nil {
t.Fatalf("the cost side survived redaction: %+v", o.Economics)
}
if o.Economics.Fee != nil {
t.Fatal("the fee survived redaction")
}
}
// The SPREAD survives a margin redaction ON PURPOSE, and this pins that rather than leaving it to be read as
// an oversight. Anybody permitted to see the bill and the pay rate can subtract them on paper, so removing
// their difference while showing both inputs would protect nothing and would only make the screen confusing.
// What the margin setting protects is the wrap and what follows from it.
func TestRedactLeavesTheSpreadWhenRatesAreVisible(t *testing.T) {
ratesButNoMargins := orgsettings.Policy{CanSeeRates: true, CanSeeMargins: false}
o := Offer{
BillRate: amt("185.00"), PayRate: amt("120.00"),
Economics: Economics{
SpreadPerHour: amt("65.00"), SpreadPct: amt("35.1351"),
BurdenPct: amt("0.35"), CostPerHour: amt("162.00"), MarginPerHour: amt("23.00"),
},
}
redactOffer(&o, ratesButNoMargins)
if o.Economics.SpreadPerHour == nil || o.Economics.SpreadPct == nil {
t.Fatal("the spread was removed by the margin setting, but it is arithmetic on two visible rates")
}
if o.Economics.BurdenPct != nil || o.Economics.MarginPerHour != nil {
t.Fatal("the cost side survived")
}
}
// Unburdened is cleared as well, because left set it tells somebody who may not see the wrap whether one
// exists. That is a small fact about the firm's finances leaking through a field whose only job is to explain
// a blank to the people who ARE allowed to see it.
func TestRedactDoesNotLeakWhetherAWrapExists(t *testing.T) {
unburdened := Offer{Economics: Economics{SpreadPerHour: amt("65.00"), Unburdened: true}}
redactOffer(&unburdened, recruiterPolicy)
if unburdened.Economics.Unburdened {
t.Fatal("a redacted response still announced that no wrap is set")
}
}
func TestRedactOfferLeavesAnOwnerAlone(t *testing.T) {
o := Offer{BillRate: amt("185.00"), Economics: Economics{MarginPct: amt("12.4324"), BurdenPct: amt("0.35")}}
redactOffer(&o, ownerPolicy)
if o.BillRate == nil || o.Economics.MarginPct == nil || o.Economics.BurdenPct == nil {
t.Fatal("an owner was redacted, the setting narrows and must never blind the top seat")
}
}
// The two settings are SEPARATE, and this is the case that proves it: a manager who may see rates but not
// the margin gets the rates and does not get the spread. If the two were collapsed into one check this test
// fails, which is the point, because collapsing them forces an owner to choose between blinding their desk
// and publishing their economics.
func TestRatesAndMarginAreGovernedSeparately(t *testing.T) {
p := orgsettings.Policy{CanSeeRates: true, CanSeeMargins: false}
o := Offer{BillRate: amt("185.00"), PayRate: amt("120.00"),
Economics: Economics{BurdenPct: amt("0.35"), MarginPerHour: amt("23.00")}}
redactOffer(&o, p)
if o.BillRate == nil || o.PayRate == nil {
t.Fatal("rates were removed by the margin setting")
}
if o.Economics.MarginPerHour != nil || o.Economics.BurdenPct != nil {
t.Fatal("the margin survived the margin setting")
}
}
func TestRedactAssignmentReachesNestedMoney(t *testing.T) {
a := Assignment{
Offers: []Offer{{BillRate: amt("185.00")}, {PayRate: amt("120.00")}},
Placements: []Placement{{BillRate: amt("185.00"), Economics: Economics{MarginPct: amt("12.4324")}}},
}
redactAssignment(&a, recruiterPolicy)
// The defect this guards against is a redaction that covers the top level and publishes every rate in
// the product through the one route that nests them.
if a.Offers[0].BillRate != nil || a.Offers[1].PayRate != nil {
t.Fatal("a nested offer kept its rate")
}
if a.Placements[0].BillRate != nil || a.Placements[0].Economics.MarginPct != nil {
t.Fatal("a nested placement kept its money")
}
}
func TestRedactRequisitionRemovesBothRangesTogether(t *testing.T) {
rq := Requisition{
BillRateMin: amt("170"), BillRateMax: amt("195"),
PayRateMin: amt("110"), PayRateMax: amt("130"),
SalaryMin: amt("180000"), SalaryMax: amt("220000"),
}
redactRequisition(&rq, recruiterPolicy)
// Both ranges move together on purpose. Hiding one and showing the other leaks the same spread with an
// extra subtraction.
if rq.BillRateMin != nil || rq.BillRateMax != nil || rq.PayRateMin != nil || rq.PayRateMax != nil ||
rq.SalaryMin != nil || rq.SalaryMax != nil {
t.Fatalf("a rate range survived: %+v", rq)
}
}
// TestEveryMoneyDTOIsRoutedThroughWriteMoney is the guard that makes the rest of this hold as the package
// grows. The compiler cannot tell that a new DTO carrying a decimal needs a redaction rule, so this does:
// it walks the types the package declares as responses, finds the ones carrying money, and fails when one is
// neither handled by writeMoney nor recorded below as deliberately outside it.
//
// It exists because the original defect was not a wrong line of code, it was an ABSENT one. Nobody wrote a
// redaction and nothing noticed for as long as the feature existed. A test that only exercised the routes
// somebody remembered would have missed it exactly the same way.
func TestEveryMoneyDTOIsRoutedThroughWriteMoney(t *testing.T) {
handled := map[string]bool{}
for _, v := range moneyTypesHandled() {
handled[reflect.TypeOf(v).Name()] = true
}
// Types that carry a decimal and are deliberately NOT written through writeMoney, each with the reason.
// Adding a name here is a decision, which is why it needs a sentence beside it.
exempt := map[string]string{
// Inputs, not responses. A rate ARRIVING from a recruiter is not a disclosure to them, and the
// handlers that take these never echo them back.
"CreateRequisitionInput": "an input, never written to a response",
"UpdateRequisitionInput": "an input, never written to a response",
"CreateOfferInput": "an input, never written to a response",
"CreatePlacementInput": "an input, never written to a response",
// Economics is a field of Offer and Placement rather than a response in its own right, and it is
// redacted through both.
"Economics": "nested inside Offer and Placement, redacted through them",
}
for name, typ := range declaredStructs() {
if !carriesDecimal(typ, 0) || handled[name] || exempt[name] != "" {
continue
}
t.Errorf("%s carries money and is not handled by writeMoney. Add a redaction rule, or record it in "+
"the exempt list with the reason it is not a response.", name)
}
}
// declaredStructs lists the struct types this test knows about. Go offers no reflection over a package's
// declarations, so the list is explicit, and it is the ONE place a new response type has to be added: the
// test above then decides whether it needs a rule.
func declaredStructs() map[string]reflect.Type {
all := []any{
Assignment{}, Offer{}, Placement{}, PlacementList{}, Economics{}, Guarantee{},
Requisition{}, RequisitionDetail{}, RequisitionList{}, RequisitionEvent{},
CreateRequisitionInput{}, UpdateRequisitionInput{}, CreateOfferInput{}, CreatePlacementInput{},
CreateInterviewInput{}, UpdateInterviewInput{}, Interview{},
CreateClientInput{}, UpdateClientInput{}, CreateContactInput{}, UpdateContactInput{},
CreateApplicationInput{}, CreateTaskInput{}, UpdateTaskInput{},
}
out := map[string]reflect.Type{}
for _, v := range all {
typ := reflect.TypeOf(v)
out[typ.Name()] = typ
}
return out
}
// carriesDecimal reports whether a type holds a decimal anywhere inside it, following pointers, slices and
// embedded structs. The depth bound stops a self referential shape turning a test into a hang.
func carriesDecimal(t reflect.Type, depth int) bool {
if depth > 6 {
return false
}
for t.Kind() == reflect.Ptr || t.Kind() == reflect.Slice || t.Kind() == reflect.Array {
t = t.Elem()
}
if t == reflect.TypeOf(decimal.Decimal{}) {
return true
}
if t.Kind() != reflect.Struct {
return false
}
for i := 0; i < t.NumField(); i++ {
if carriesDecimal(t.Field(i).Type, depth+1) {
return true
}
}
return false
}