Skip to content

Commit 3fd007f

Browse files
committed
Fix spell with no cities showing "none" entry instead of empty list.
- Also simplified tests and added more samples and cases
1 parent 8996943 commit 3fd007f

File tree

8 files changed

+3339
-65
lines changed

8 files changed

+3339
-65
lines changed

tests/resources/README.md

Lines changed: 69 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,112 @@
11
# Resources
2+
23
This directory and its subdirectories contain extracts from Tibia.com,
34
trying to cover as many scenarios possible, to be used in unit tests.
45

56
## Character resources
7+
68
- [character.txt](character/character.txt) - A full character response.
79
- [characterTraded.txt](character/characterTraded.txt) - A character that was traded and is also visible.
8-
- [characterWithComplexDeaths.txt](character/characterWithComplexDeaths.txt) - A character with many types of deaths, such as deaths by summons, players, assisted deaths, etcetera.
10+
- [characterWithComplexDeaths.txt](character/characterWithComplexDeaths.txt) - A character with many types of deaths,
11+
such as deaths by summons, players, assisted deaths, etcetera.
912
- [characterDeletionScheduled.txt](character/characterDeletionScheduled.txt) - A character scheduled for deletion.
1013
- [characterFormerNames.txt](character/characterFormerNames.txt) - A character with former names.
1114
- [characterNotFound.txt](character/characterNotFound.txt) - A character not found page.
12-
- [characterWithTitleAndBadges.txt](character/characterWithTitleAndBadges.txt) - A character with unlocked titles and badges.
15+
- [characterWithTitleAndBadges.txt](character/characterWithTitleAndBadges.txt) - A character with unlocked titles and
16+
badges.
1317
- [characterNoBadgesSelected.txt](character/characterNoBadgesSelected.txt) - A character with no selected badges.
1418
- [characterMultipleHouses.txt](character/characterMultipleHouses.txt) - A character with two houses.
15-
- [characterTruncatedDeaths.txt](character/characterTruncatedDeaths.txt) - A character with too many deaths to be displayed.
19+
- [characterTruncatedDeaths.txt](character/characterTruncatedDeaths.txt) - A character with too many deaths to be
20+
displayed.
1621
- [characterSpecialPosition.txt](character/characterSpecialPosition.txt) - A character with a special position.
1722

18-
1923
## Guild resources
24+
2025
- [guild.txt](guild/guild.txt) - The content of a guild's page.
2126
- [guildAtWar.txt](guild/guildAtWar.txt) - The content of a guild's page for a guild with an active war.
2227
- [guildDisbanding.txt](guild/guildDisbanding.txt) - A guild that is set to be disbanded.
2328
- [guildFormation.txt](guild/guildFormation.txt) - A guild still in formation.
24-
- [guildMinimumInfo.txt](guild/guildMinimumInfo.txt) - A guild with the bare minimum (no description, no guildhall, no homepage)
29+
- [guildMinimumInfo.txt](guild/guildMinimumInfo.txt) - A guild with the bare minimum (no description, no guildhall, no
30+
homepage)
2531
- [guildsSection.txt](guild/guildsSection.txt) - The guild list of a world.
2632
- [guildsSectionNotFound.txt](guild/guildsSectionNotFound.txt) - The guild list of a world that doesn't exist.
2733
- [guildNotFound.txt](guild/guildNotFound.txt) - The page shown for a guild that doesn't exist.
28-
34+
2935
### War resources
3036

3137
- [guildWarEmpty.txt](guild/wars/guildWarEmpty.txt) - A guild with no active wars and no war history.
32-
- [guildWarUnactiveAndHistory.txt](guild/wars/guildWarUnactiveAndHistory.txt) - A guild with no active wars and a previous war (enemy disbanded).
33-
- [guildWarActiveAndHistory.txt](guild/wars/guildWarActiveAndHistory.txt) - A guild with an active war and two previous wars.
38+
- [guildWarUnactiveAndHistory.txt](guild/wars/guildWarUnactiveAndHistory.txt) - A guild with no active wars and a
39+
previous war (enemy disbanded).
40+
- [guildWarActiveAndHistory.txt](guild/wars/guildWarActiveAndHistory.txt) - A guild with an active war and two previous
41+
wars.
3442

3543
## House resources
44+
3645
- [houseRented.txt](house/houseRented.txt) - The content of a house's page
3746
- [houseStatusNoBids.txt](house/houseStatusNoBids.txt) - The status string of a auction house with no bids.
3847
- [houseStatusRented.txt](house/houseStatusRented.txt) - The status string of a rented house.
3948
- [houseStatusTransferred.txt](house/houseStatusTransferred.txt) - The status string of a rented house that is set
40-
for transfer.
49+
for transfer.
4150
- [houseStatusWithBids.txt](house/houseAuctionedWithBids.txt) - The status string of a auctioned house with
42-
bids.
43-
- - [houseBeforeMerge.txt](house/houseBeforeMerge.txt) - A house from a world scheduled to be merged.
51+
bids.
52+
-
53+
- [houseBeforeMerge.txt](house/houseBeforeMerge.txt) - A house from a world scheduled to be merged.
4454
- [houseNotFound.txt](house/houseNotFound.txt) - The content of a page for a house not found.
4555
- [housesSection.txt](house/housesSection.txt) - The house list of a world.
4656
- [housesSectionEmpty.txt](house/housesSectionEmpty.txt) - The house list of a world, showing no houses.
47-
- [housesSectionNotFound.txt](house/housesSectionNotFound.txt) - The house list of a world or town that doesn't
48-
exist.
49-
- [housesSectionBeforeMerge.txt](house/housesSectionBeforeMerge.txt) - The houses section of a world that is scheduled to be merged.
57+
- [housesSectionNotFound.txt](house/housesSectionNotFound.txt) - The house list of a world or town that doesn't
58+
exist.
59+
- [housesSectionBeforeMerge.txt](house/housesSectionBeforeMerge.txt) - The houses section of a world that is scheduled
60+
to be merged.
5061

5162
## Highscores resources
63+
5264
- [highscores.txt](highscores/highscores.txt) - The content of a correct highscore's page.
5365
- [highscoresEmpty.txt](highscores/highscoresEmpty.txt) - The content of the highscores page of a nonexistent world.
54-
- [highscoresNoResults.txt](highscores/highscoresNoResults.txt) - The content of the highscores page of a new world (no results shown). _OUTDATED_
66+
- [highscoresNoResults.txt](highscores/highscoresNoResults.txt) - The content of the highscores page of a new world (no
67+
results shown). _OUTDATED_
5568
- [highscoresExperience.txt](highscores/highscoresExperience.txt) - The content of an experience highscores page.
5669
- [highscoresLoyalty.txt](highscores/highscoresLoyalty.txt) - The content of a loyalty highscores page.
57-
- [highscoresBattleEyePvpFilters.txt](highscores/highscoresBattleEyePvpFilters.txt) - The content of the highscores page using BattlEye and PvP filters.
58-
70+
- [highscoresBattleEyePvpFilters.txt](highscores/highscoresBattleEyePvpFilters.txt) - The content of the highscores page
71+
using BattlEye and PvP filters.
5972

6073
## Kill Statistics resources
61-
- [killStatisticsWithResults.txt](killStatistics/killStatisticsWithResults.txt) - The content of a correct kill statistics' page.
62-
- [killStatisticsNotFound.txt](killStatistics/killStatisticsNotFound.txt) - The content of the kill statistics's page of a
63-
nonexistent world or a unselected world.
74+
75+
- [killStatisticsWithResults.txt](killStatistics/killStatisticsWithResults.txt) - The content of a correct kill
76+
statistics' page.
77+
- [killStatisticsNotFound.txt](killStatistics/killStatisticsNotFound.txt) - The content of the kill statistics's page of
78+
a
79+
nonexistent world or a unselected world.
6480

6581
## News resources
66-
- [newsArchiveInitial.txt](news/newsArchiveInitial.txt) - The content of the news search page with results and default filters.
67-
- [newsArchiveWithFilters.txt](news/newsArchiveWithFilters.txt) - The content of the news search page with results using filters.
82+
83+
- [newsArchiveInitial.txt](news/newsArchiveInitial.txt) - The content of the news search page with results and default
84+
filters.
85+
- [newsArchiveWithFilters.txt](news/newsArchiveWithFilters.txt) - The content of the news search page with results using
86+
filters.
6887
- [newsArchiveEmpty.txt](news/newsArchiveEmpty.txt) - The content of the news search page with no results.
6988
- [newsArchiveError.txt](news/newsArchiveError.txt) - The content of the news search page with an error.
7089
- [newsArticle.txt](news/newsArticle.txt) - The content of a news article.
7190
- [newsTicker.txt](news/newsTicker.txt) - The content of a news ticker.
7291

7392
## Leaderboard resources
74-
- [leaderboardCurrentRotation.txt](leaderboards/leaderboardCurrentRotation.txt) - The leaderboard page for the current rotation of a world.
75-
- [leaderboardDeletedCharacter.txt](leaderboards/leaderboardDeletedCharacter.txt) - A leaderboad containing a deleted character.
93+
94+
- [leaderboardCurrentRotation.txt](leaderboards/leaderboardCurrentRotation.txt) - The leaderboard page for the current
95+
rotation of a world.
96+
- [leaderboardDeletedCharacter.txt](leaderboards/leaderboardDeletedCharacter.txt) - A leaderboad containing a deleted
97+
character.
7698
- [leaderboardEmpty.txt](leaderboards/leaderboardEmpty.txt) - The leaderboard page for a world with no entries.
7799
- [leaderboardNotFound.txt](leaderboards/leaderboardNotFound.txt) - The leaderboard page for a world that doesn't exist.
78100

79101
## World resources
80-
- [worldOnline.txt](world/worldOnline.txt) - An online world on Tibia.com.
81-
- [worldUnprotected.txt](world/worldUnprotected.txt) - A world with no BattlEye protection.
82-
- [worldYellowBattlEye.txt](world/worldYellowBattlEye.txt) - A world that was not initially protected by BattlEye.
83-
- [worldNoTitles.txt](world/worldNoTitles.txt) - A world without titles.
84-
- [worldNotFound.txt](world/worldNotFound.txt) - The page shown for a world that doesn't exist.
85-
- [worldOverviewOnline.txt](world/worldOverviewOnline.txt) - The world list with all worlds online.
86-
- [worldOverviewOffline.txt](world/worldOverviewOffline.txt) - The world list with all worlds offline.
102+
103+
- [worldOnline.txt](world/worldOnline.txt) - An online world on Tibia.com.
104+
- [worldUnprotected.txt](world/worldUnprotected.txt) - A world with no BattlEye protection.
105+
- [worldYellowBattlEye.txt](world/worldYellowBattlEye.txt) - A world that was not initially protected by BattlEye.
106+
- [worldNoTitles.txt](world/worldNoTitles.txt) - A world without titles.
107+
- [worldNotFound.txt](world/worldNotFound.txt) - The page shown for a world that doesn't exist.
108+
- [worldOverviewOnline.txt](world/worldOverviewOnline.txt) - The world list with all worlds online.
109+
- [worldOverviewOffline.txt](world/worldOverviewOffline.txt) - The world list with all worlds offline.
87110

88111
## Forum resources
89112

@@ -109,23 +132,31 @@ nonexistent world or a unselected world.
109132
- [cmPostArchivePages.txt](forums/cmPostArchivePages.txt) - The CM Post Archive with multiple pages.
110133

111134
## Events resources
135+
112136
- [tibiacom_calendar.txt](events/event_schedule.txt) - The content of the event's calendar.
113137

114138
## Bazaar resources
139+
115140
- [auctionFinished.txt](bazaar/auctionFinished.txt) - The content of a finished auction.
116141
- [auctionNotFound.txt](bazaar/auctionNotFound.txt) - The content of an auction that doesn't exist.
117142
- [bazaarCurrentAuctions.txt](bazaar/bazaarCurrentAuctions.txt) - The content of the current auctions page.
118-
- [bazaarCurrentAuctionsWithFilters.txt](bazaar/bazaarCurrentAuctionsWithFilters.txt) - The content of the current auctions page with all filters selected.
143+
- [bazaarCurrentAuctionsWithFilters.txt](bazaar/bazaarCurrentAuctionsWithFilters.txt) - The content of the current
144+
auctions page with all filters selected.
119145
- [bazaarHistory.txt](bazaar/bazaarHistory.txt) - The content of the auction history page.
120146
- [bazaarHistoryEmpty.txt](bazaar/bazaarHistoryEmpty.txt) - The content of the auction history page with no entries.
121147

122-
123148
## Spells resources
149+
124150
- [spellsSectionDefault.txt](spells/spellsSectionDefault.txt) - The spells section with all results (no filters used).
125-
- [spellsSectionEmpty.txt](spells/spellsSectionEmpty.txt) - The spells section with empty results (due to filter combination).
126-
- [spellWithSecondaryGroup.txt](spells/spellWithSecondaryGroup.txt) - A spell with a secondary cooldown group.
151+
- [spellsSectionEmpty.txt](spells/spellsSectionEmpty.txt) - The spells section with empty results (due to filter
152+
combination).
153+
- [spell.txt](spells/spell.txt) - A regular spell.
154+
- [spellMultilneDescription.txt](spells/spellMultilneDescription.txt) - A spell with a description of multiple lines.
155+
- [spellVariableMana.txt](spells/spellVariableMana.txt) - A spell with variable mana usage.
156+
- [spellRevelationPerk.txt](spells/spellRevelationPerk.txt) - A spell obtained from a revelation perk.
127157
- [spellWithRune.txt](spells/spellWithRune.txt) - A spell that produces a rune.
128158

129-
## Other resources
130-
- [tibiacom_about.txt](tibiacom_about.txt) - The 'About Tibia' section on Tibia.com, used to provide invalid content
131-
for tests.
159+
## Other resources
160+
161+
- [tibiacom_about.txt](tibiacom_about.txt) - The 'About Tibia' section on Tibia.com, used to provide invalid content
162+
for tests.

tests/resources/spells/spell.txt

Lines changed: 804 additions & 0 deletions
Large diffs are not rendered by default.

tests/resources/spells/spellMultilneDescription.txt

Lines changed: 804 additions & 0 deletions
Large diffs are not rendered by default.

tests/resources/spells/spellRevelationPerk.txt

Lines changed: 806 additions & 0 deletions
Large diffs are not rendered by default.

tests/resources/spells/spellVariableMana.txt

Lines changed: 804 additions & 0 deletions
Large diffs are not rendered by default.

tests/tests_spell.py

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44

55
FILE_SPELLS_SECTION = "spells/spellsSectionDefault.txt"
66
FILE_SPELLS_SECTION_EMPTY = "spells/spellsSectionEmpty.txt"
7+
FILE_SPELL = "spells/spell.txt"
78
FILE_SPELL_RUNE = "spells/spellWithRune.txt"
9+
FILE_SPELL_REVELATION_PERK = "spells/spellRevelationPerk.txt"
10+
FILE_SPELL_VARIABLE_MANA = "spells/spellVariableMana.txt"
11+
FILE_SPELL_MULTILINE_DESC = "spells/spellMultilneDescription.txt"
812
FILE_SPELL_SECONDARY_GROUP = "spells/spellWithSecondaryGroup.txt"
913

1014

@@ -41,30 +45,52 @@ def test_spells_section_parser_from_content_unrelated_section(self):
4145

4246
# region Spells Tests
4347

44-
def test_spell_parser_from_content_rune(self):
45-
"""Testing parsing a rune spell."""
46-
content = self.load_resource(FILE_SPELL_RUNE)
48+
def test_spell_parser_from_content(self):
49+
content = self.load_resource(FILE_SPELL)
4750

4851
spell = SpellParser.from_content(content)
4952

5053
self.assertIsNotNone(spell)
5154
self.assertIsNotNone(spell.url)
5255
self.assertIsNotNone(spell.image_url)
56+
57+
self.assertEqual("Light Healing", spell.name)
58+
self.assertEqual("exura", spell.words)
59+
self.assertIn("Druid", spell.vocations)
60+
self.assertEqual("Healing", spell.group.value)
61+
self.assertEqual("Instant", spell.spell_type.value)
62+
self.assertEqual(1, spell.cooldown)
63+
self.assertEqual(1, spell.cooldown_group)
64+
self.assertEqual(8, spell.exp_level)
65+
self.assertEqual(20, spell.mana)
66+
self.assertEqual(0, spell.price)
67+
self.assertIn("Carlin", spell.cities)
68+
self.assertFalse(spell.is_premium)
69+
70+
def test_spell_parser_from_content_variable_mana(self):
71+
content = self.load_resource(FILE_SPELL_VARIABLE_MANA)
72+
73+
spell = SpellParser.from_content(content)
74+
75+
self.assertIsNone(spell.mana)
76+
77+
def test_spell_parser_from_content_multiline_description(self):
78+
content = self.load_resource(FILE_SPELL_MULTILINE_DESC)
79+
80+
spell = SpellParser.from_content(content)
81+
82+
self.assertEqual(2, spell.description.count("\n"))
83+
84+
def test_spell_parser_from_content_rune(self):
85+
"""Testing parsing a rune spell."""
86+
content = self.load_resource(FILE_SPELL_RUNE)
87+
88+
spell = SpellParser.from_content(content)
89+
5390
self.assertEqual("Sudden Death Rune", spell.name)
54-
self.assertEqual("adori gran mort", spell.words)
55-
self.assertIn("Sorcerer", spell.vocations)
5691
self.assertEqual("Support", spell.group.value)
5792
self.assertEqual("Rune", spell.spell_type.value)
58-
self.assertEqual(2, spell.cooldown)
59-
self.assertEqual(2, spell.cooldown_group)
6093
self.assertEqual(5, spell.soul_points)
61-
self.assertEqual(3, spell.amount)
62-
self.assertEqual(45, spell.exp_level)
63-
self.assertEqual(985, spell.mana)
64-
self.assertEqual(3000, spell.price)
65-
self.assertIn("Yalahar", spell.cities)
66-
self.assertIn("Edron", spell.cities)
67-
self.assertFalse(spell.is_premium)
6894
self.assertEqual("Sudden Death Rune", spell.rune.name)
6995
self.assertIn("Knight", spell.rune.vocations)
7096
self.assertEqual("Attack", spell.rune.group.value)
@@ -78,22 +104,21 @@ def test_spell_parser_from_content_secondary_group(self):
78104
spell = SpellParser.from_content(content)
79105

80106
self.assertIsNotNone(spell)
81-
self.assertEqual("Protector", spell.name)
82-
self.assertEqual("utamo tempo", spell.words)
83-
self.assertIn("Knight", spell.vocations)
84107
self.assertEqual("Support", spell.group.value)
85108
self.assertEqual("Focus", spell.group_secondary)
86-
self.assertEqual("Instant", spell.spell_type.value)
87109
self.assertEqual(2, spell.cooldown)
88110
self.assertEqual(2, spell.cooldown_group)
89111
self.assertEqual(2, spell.cooldown_group_secondary)
90-
self.assertIsNone(spell.soul_points)
91-
self.assertIsNone(spell.amount)
92-
self.assertEqual(55, spell.exp_level)
93-
self.assertEqual(200, spell.mana)
94-
self.assertEqual(6000, spell.price)
95-
self.assertIn("Edron", spell.cities)
96-
self.assertTrue(spell.is_premium)
112+
113+
def test_spell_parser_from_content_revelation_perk(self):
114+
"""Testing parsing a spell with a secondary group."""
115+
content = self.load_resource(FILE_SPELL_REVELATION_PERK)
116+
spell = SpellParser.from_content(content)
117+
118+
self.assertIsNotNone(spell)
119+
self.assertIsNone(spell.exp_level)
120+
self.assertEqual(0, spell.price)
121+
self.assertIsEmpty(spell.cities)
97122

98123
def test_spells_from_content_unknown_spell(self):
99124
"""Testing parsing an unknown spell

tibiapy/models/spell.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class SpellEntry(BaseModel):
5050
spell_type: SpellType
5151
"""The type of the spell"""
5252
exp_level: Optional[int] = None
53-
"""The required level to cast the spell."""
53+
"""The required level to cast the spell. If obj:`None`, the spell is obtained through a Revelation Perk."""
5454
mana: Optional[int] = None
5555
"""The mana required to use the spell. If :obj:`None`, the mana cost is variable."""
5656
price: int

tibiapy/parsers/spell.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ def _parse_spells_table(cls, builder: SpellBuilder, spell_table: bs4.Tag):
202202
builder.is_premium("yes" in attrs["premium"])
203203
builder.exp_level(parse_integer(attrs["exp_lvl"], None))
204204
builder.vocations([s.strip() for s in attrs["vocation"].split(",")])
205-
builder.cities([s.strip() for s in attrs["city"].split(",")])
205+
builder.cities([s.strip() for s in attrs["city"].split(",")] if "none" not in attrs["city"] else [])
206206
m = group_pattern.match(attrs["group"])
207207
groups = m.groupdict()
208208
builder.group(try_enum(SpellGroup, groups.get("group")))

0 commit comments

Comments
 (0)