feature/class-wiki-spell-progression (#13)
Reviewed-on: https://gitea.westgate.pw/ShadowsOverWestgate/sow-tools/pulls/13 Co-authored-by: vickydotbat <vickydotbat@tutamail.com> Co-committed-by: vickydotbat <vickydotbat@tutamail.com>
This commit is contained in:
@@ -1478,6 +1478,278 @@ tables:
|
||||
}
|
||||
}
|
||||
|
||||
func TestWikiTemplateRendersConfiguredClassProgressionSpellColumns(t *testing.T) {
|
||||
ctx := testWikiTableContext(t, `
|
||||
tables:
|
||||
ClassProgression:
|
||||
source: class_progression
|
||||
class: "wiki-table wiki-class-progression"
|
||||
rows:
|
||||
levels: 1-2
|
||||
columns:
|
||||
- key: level
|
||||
label: Lvl
|
||||
value: "{{Level}}"
|
||||
- key: per_day
|
||||
label: Base spells per day
|
||||
when: "{{HasSpellsPerDay}}"
|
||||
children:
|
||||
- key: per_day_0
|
||||
label: 0
|
||||
value: "{{SpellsPerDay0}}"
|
||||
empty: "-"
|
||||
- key: per_day_1
|
||||
label: 1
|
||||
value: "{{SpellsPerDay1}}"
|
||||
empty: "-"
|
||||
- key: known
|
||||
label: Known spells
|
||||
when: "{{HasSpellsKnown}}"
|
||||
children:
|
||||
- key: known_0
|
||||
label: 0
|
||||
value: "{{SpellsKnown0}}"
|
||||
empty: "-"
|
||||
- key: known_1
|
||||
label: 1
|
||||
value: "{{SpellsKnown1}}"
|
||||
empty: "-"
|
||||
`)
|
||||
ctx.classSpellGainTables["classes/spellsgained:bard"] = wikiTable{Rows: []map[string]any{
|
||||
{"Level": 1, "SpellLevel0": 2, "SpellLevel1": 1},
|
||||
{"Level": 2, "SpellLevel0": 3, "SpellLevel1": nil},
|
||||
}}
|
||||
ctx.classSpellKnownTables["classes/spellsknown:bard"] = wikiTable{Rows: []map[string]any{
|
||||
{"Level": 1, "SpellLevel0": 4, "SpellLevel1": 2},
|
||||
{"Level": 2, "SpellLevel0": 5, "SpellLevel1": 3},
|
||||
}}
|
||||
page := wikiTemplatePage{
|
||||
PageID: "classes:bard",
|
||||
Category: "classes",
|
||||
Key: "classes:bard",
|
||||
Title: "Bard",
|
||||
Row: map[string]any{
|
||||
"SpellCaster": 1,
|
||||
"SpellGainTable": map[string]any{"table": "classes/spellsgained:bard"},
|
||||
"SpellKnownTable": map[string]any{"table": "classes/spellsknown:bard"},
|
||||
},
|
||||
}
|
||||
|
||||
got, err := ctx.renderWikiTemplateString("classes.html", `{{table:ClassProgression}}`, page)
|
||||
if err != nil {
|
||||
t.Fatalf("render table template: %v", err)
|
||||
}
|
||||
for _, expected := range []string{
|
||||
`<th scope="colgroup" colspan="2">Base spells per day</th>`,
|
||||
`<th scope="colgroup" colspan="2">Known spells</th>`,
|
||||
`<tr><td>1</td><td>2</td><td>1</td><td>4</td><td>2</td></tr>`,
|
||||
`<tr><td>2</td><td>3</td><td>-</td><td>5</td><td>3</td></tr>`,
|
||||
} {
|
||||
if !strings.Contains(got, expected) {
|
||||
t.Fatalf("expected %q in rendered table:\n%s", expected, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWikiTemplateHidesUnusedConfiguredClassSpellColumns(t *testing.T) {
|
||||
ctx := testWikiTableContext(t, `
|
||||
tables:
|
||||
ClassProgression:
|
||||
source: class_progression
|
||||
class: "wiki-table wiki-class-progression"
|
||||
rows:
|
||||
levels: 1-2
|
||||
columns:
|
||||
- key: level
|
||||
label: Lvl
|
||||
value: "{{Level}}"
|
||||
- key: per_day
|
||||
label: Base spells per day
|
||||
when: "{{HasSpellsPerDay}}"
|
||||
children:
|
||||
- key: per_day_0
|
||||
label: 0
|
||||
value: "{{SpellsPerDay0}}"
|
||||
when: "{{SpellsPerDay0}}"
|
||||
- key: per_day_1
|
||||
label: 1
|
||||
value: "{{SpellsPerDay1}}"
|
||||
when: "{{SpellsPerDay1}}"
|
||||
- key: per_day_2
|
||||
label: 2
|
||||
value: "{{SpellsPerDay2}}"
|
||||
when: "{{SpellsPerDay2}}"
|
||||
`)
|
||||
ctx.classSpellGainTables["classes/spellsgained:bard"] = wikiTable{Rows: []map[string]any{
|
||||
{"Level": 1, "SpellLevel0": 2, "SpellLevel1": 1, "SpellLevel2": nil},
|
||||
{"Level": 2, "SpellLevel0": 3, "SpellLevel1": 2, "SpellLevel2": nil},
|
||||
}}
|
||||
page := wikiTemplatePage{
|
||||
PageID: "classes:bard",
|
||||
Category: "classes",
|
||||
Key: "classes:bard",
|
||||
Title: "Bard",
|
||||
Row: map[string]any{
|
||||
"SpellCaster": 1,
|
||||
"SpellGainTable": map[string]any{"table": "classes/spellsgained:bard"},
|
||||
},
|
||||
}
|
||||
|
||||
got, err := ctx.renderWikiTemplateString("classes.html", `{{table:ClassProgression}}`, page)
|
||||
if err != nil {
|
||||
t.Fatalf("render table template: %v", err)
|
||||
}
|
||||
if !strings.Contains(got, `<th scope="colgroup" colspan="2">Base spells per day</th>`) {
|
||||
t.Fatalf("expected only two visible spell columns:\n%s", got)
|
||||
}
|
||||
if strings.Contains(got, `<th scope="col">2</th>`) {
|
||||
t.Fatalf("expected unused spell level 2 column to be hidden:\n%s", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWikiTemplateOmitsSpellColumnsForPreparedAndNonCasterClasses(t *testing.T) {
|
||||
ctx := testWikiTableContext(t, `
|
||||
tables:
|
||||
ClassProgression:
|
||||
source: class_progression
|
||||
rows:
|
||||
levels: 1
|
||||
columns:
|
||||
- key: level
|
||||
label: Lvl
|
||||
value: "{{Level}}"
|
||||
- key: per_day
|
||||
label: Base spells per day
|
||||
when: "{{HasSpellsPerDay}}"
|
||||
children:
|
||||
- key: per_day_0
|
||||
label: 0
|
||||
value: "{{SpellsPerDay0}}"
|
||||
- key: known
|
||||
label: Known spells
|
||||
when: "{{HasSpellsKnown}}"
|
||||
children:
|
||||
- key: known_0
|
||||
label: 0
|
||||
value: "{{SpellsKnown0}}"
|
||||
`)
|
||||
ctx.classSpellGainTables["classes/spellsgained:cleric"] = wikiTable{Rows: []map[string]any{
|
||||
{"Level": 1, "SpellLevel0": 3},
|
||||
}}
|
||||
prepared := wikiTemplatePage{
|
||||
PageID: "classes:cleric",
|
||||
Category: "classes",
|
||||
Key: "classes:cleric",
|
||||
Title: "Cleric",
|
||||
Row: map[string]any{
|
||||
"SpellCaster": 1,
|
||||
"SpellGainTable": map[string]any{"table": "classes/spellsgained:cleric"},
|
||||
},
|
||||
}
|
||||
nonCaster := wikiTemplatePage{
|
||||
PageID: "classes:fighter",
|
||||
Category: "classes",
|
||||
Key: "classes:fighter",
|
||||
Title: "Fighter",
|
||||
Row: map[string]any{"SpellCaster": 0},
|
||||
}
|
||||
|
||||
gotPrepared, err := ctx.renderWikiTemplateString("classes.html", `{{table:ClassProgression}}`, prepared)
|
||||
if err != nil {
|
||||
t.Fatalf("render prepared caster table: %v", err)
|
||||
}
|
||||
if !strings.Contains(gotPrepared, `Base spells per day`) || strings.Contains(gotPrepared, `Known spells`) {
|
||||
t.Fatalf("expected prepared caster to render per-day but not known columns:\n%s", gotPrepared)
|
||||
}
|
||||
gotNonCaster, err := ctx.renderWikiTemplateString("classes.html", `{{table:ClassProgression}}`, nonCaster)
|
||||
if err != nil {
|
||||
t.Fatalf("render non-caster table: %v", err)
|
||||
}
|
||||
if strings.Contains(gotNonCaster, `Base spells per day`) || strings.Contains(gotNonCaster, `Known spells`) {
|
||||
t.Fatalf("expected non-caster to omit spell columns:\n%s", gotNonCaster)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWikiTemplateRendersClassSpellbookProviderBySpellLevel(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
dataPath := filepath.Join(root, "data.yaml")
|
||||
writeFile(t, dataPath, `
|
||||
providers:
|
||||
ClassSpellbook:
|
||||
source: class_spellbook
|
||||
`+"\n")
|
||||
providers, err := loadWikiDataProviders(dataPath)
|
||||
if err != nil {
|
||||
t.Fatalf("load data providers: %v", err)
|
||||
}
|
||||
ctx := testWikiTableContext(t, "")
|
||||
ctx.wikiDataPath = dataPath
|
||||
ctx.wikiDataProviders = providers
|
||||
ctx.spellRows = map[string]map[string]any{
|
||||
"spells:light": {"Name": map[string]any{"tlk": map[string]any{"text": "Light"}}},
|
||||
"spells:cure_light_wounds": {"Name": map[string]any{"tlk": map[string]any{"text": "Cure Light Wounds"}}},
|
||||
"spells:bless": {"Name": map[string]any{"tlk": map[string]any{"text": "Bless"}}},
|
||||
}
|
||||
ctx.classSpellbooks = map[string]classSpellbookSpec{
|
||||
"classes:acolyte": {
|
||||
Class: "classes:acolyte",
|
||||
Levels: map[int][]string{
|
||||
0: {"spells:light"},
|
||||
1: {"spells:cure_light_wounds", "spells:bless"},
|
||||
},
|
||||
},
|
||||
}
|
||||
page := wikiTemplatePage{
|
||||
PageID: "classes:acolyte",
|
||||
Category: "classes",
|
||||
Key: "classes:acolyte",
|
||||
Title: "Acolyte",
|
||||
Row: map[string]any{"SpellCaster": 1},
|
||||
}
|
||||
|
||||
got, err := ctx.renderWikiTemplateString("classes.html", `{{#each ClassSpellbook}}
|
||||
<h4>{{SpellLevelLabel}}</h4>{{Spells|list:"wiki-list wiki-spellbook-list"}}
|
||||
{{/each}}`, page)
|
||||
if err != nil {
|
||||
t.Fatalf("render spellbook provider: %v", err)
|
||||
}
|
||||
for _, expected := range []string{
|
||||
`<h4>0-level spells</h4><ul class="wiki-list wiki-spellbook-list"><li>[[Spells/Light|Light]]</li></ul>`,
|
||||
`<h4>1st-level spells</h4><ul class="wiki-list wiki-spellbook-list"><li>[[Spells/Bless|Bless]]</li>`,
|
||||
`<li>[[Spells/Cure_Light_Wounds|Cure Light Wounds]]</li>`,
|
||||
} {
|
||||
if !strings.Contains(got, expected) {
|
||||
t.Fatalf("expected %q in rendered spellbook:\n%s", expected, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadWikiTablesFromDirsSupportsCanonicalAndLegacyClassTableDirs(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
mkdirAll(t, filepath.Join(root, "bonusfeats"))
|
||||
mkdirAll(t, filepath.Join(root, "bfeat"))
|
||||
writeFile(t, filepath.Join(root, "bonusfeats", "fighter.json"), `{
|
||||
"key": "classes/bonusfeats:fighter",
|
||||
"output": "cls_bfeat_fight.2da",
|
||||
"rows": [{"id": 1, "Bonus": "1"}]
|
||||
}`+"\n")
|
||||
writeFile(t, filepath.Join(root, "bfeat", "commoner.json"), `{
|
||||
"key": "classes/bonusfeats:commoner",
|
||||
"output": "cls_bfeat_comm.2da",
|
||||
"rows": [{"id": 1, "Bonus": "0"}]
|
||||
}`+"\n")
|
||||
|
||||
tables, err := loadWikiTablesFromDirs(filepath.Join(root, "bonusfeats"), filepath.Join(root, "bfeat"))
|
||||
if err != nil {
|
||||
t.Fatalf("load wiki tables from aliases: %v", err)
|
||||
}
|
||||
for _, key := range []string{"classes/bonusfeats:fighter", "cls_bfeat_fight", "classes/bonusfeats:commoner", "cls_bfeat_comm"} {
|
||||
if _, ok := tables[key]; !ok {
|
||||
t.Fatalf("expected table key %q in merged alias tables: %#v", key, tables)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestWikiTableMissingFieldReportsTableAndColumn(t *testing.T) {
|
||||
ctx := testWikiTableContext(t, `
|
||||
tables:
|
||||
@@ -1967,12 +2239,15 @@ datasets:
|
||||
func testWikiTableContext(t *testing.T, yamlSource string) *wikiContext {
|
||||
t.Helper()
|
||||
ctx := &wikiContext{
|
||||
featRows: map[string]map[string]any{},
|
||||
featIDToKey: map[int]string{},
|
||||
classFeatTables: map[string]wikiTable{},
|
||||
classBonusTables: map[string]wikiTable{},
|
||||
classSaveTables: map[string]wikiTable{},
|
||||
wikiTablesPath: "test-tables.yaml",
|
||||
featRows: map[string]map[string]any{},
|
||||
featIDToKey: map[int]string{},
|
||||
classFeatTables: map[string]wikiTable{},
|
||||
classBonusTables: map[string]wikiTable{},
|
||||
classSaveTables: map[string]wikiTable{},
|
||||
classSpellGainTables: map[string]wikiTable{},
|
||||
classSpellKnownTables: map[string]wikiTable{},
|
||||
classSpellbooks: map[string]classSpellbookSpec{},
|
||||
wikiTablesPath: "test-tables.yaml",
|
||||
}
|
||||
ctx.featRows["feat:literate"] = map[string]any{"FEAT": map[string]any{"tlk": map[string]any{"text": "Literate"}}}
|
||||
ctx.featRows["feat:weapon_proficiency_simple"] = map[string]any{"FEAT": map[string]any{"tlk": map[string]any{"text": "Simple Weapon Proficiency"}}}
|
||||
|
||||
Reference in New Issue
Block a user