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"}, } // Slice is sorted by Feat, so order is deterministic. if !reflect.DeepEqual(got, want) { t.Fatalf("rules: got %+v, want %+v", got, want) } }