package topdata import ( "reflect" "testing" "git.westgate.pw/ShadowsOverWestgate/sow-tools/internal/project" ) func raceFeatDataset(output string, rows ...map[string]any) nativeCollectedDataset { return nativeCollectedDataset{ Dataset: nativeDataset{OutputName: output}, Rows: rows, } } func usableRow(featID string, usable any) map[string]any { row := map[string]any{"FeatIndex": map[string]any{"id": featID}} if usable != nil { row["UsableFeat"] = usable } return row } func TestRacialUsableFeatRules(t *testing.T) { collected := []nativeCollectedDataset{ raceFeatDataset("race_feat_ddrw.2da", usableRow("feat:keen_sense", nil), // passive, no UsableFeat -> skipped usableRow("feat:darkvision", 1), // usable usableRow("feat:use_poison", 0), // explicitly not usable -> skipped usableRow("feat:drow/faerie_fire", "1"),// usable, string form ), raceFeatDataset("race_feat_tief.2da", usableRow("feat:darkvision", 1), // duplicate across races -> collapses to one usableRow("feat:tiefling/darkness", 1), ), raceFeatDataset("feat.2da", // not a race feats table -> ignored entirely usableRow("feat:power_attack", 1), ), } got := racialUsableFeatRules(collected) want := []project.TopDataClassFeatGlobalRule{ {Feat: "feat:darkvision", List: "3", GrantedOnLevel: "99", OnMenu: "1"}, {Feat: "feat:drow/faerie_fire", List: "3", GrantedOnLevel: "99", OnMenu: "1"}, {Feat: "feat:tiefling/darkness", List: "3", GrantedOnLevel: "99", OnMenu: "1"}, } if len(got) != len(want) { t.Fatalf("rule count: got %d, want %d (%+v)", len(got), len(want), got) } for i := range want { if !reflect.DeepEqual(got[i], want[i]) { // slice is sorted by Feat, so order is deterministic t.Fatalf("rule %d: got %+v, want %+v", i, got[i], want[i]) } } }