Skip to content

Commit 9923154

Browse files
authored
Merge pull request #1190 from FallenDeity/feat/case-insensitive-query
feat: Make name lookups in api endpoints case insensitive
2 parents 72398af + 63f0e26 commit 9923154

File tree

2 files changed

+110
-2
lines changed

2 files changed

+110
-2
lines changed

pokemon_v2/api.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ class NameOrIdRetrieval:
3939
"""
4040

4141
idPattern = re.compile(r"^-?[0-9]+$")
42-
namePattern = re.compile(r"^[0-9A-Za-z\-\+]+$")
42+
# Allow alphanumeric, hyphen, plus, and space (Space added for test cases using name for lookup, ex: 'base pkm')
43+
namePattern = re.compile(r"^[0-9A-Za-z\-\+ ]+$")
4344

4445
def get_queryset(self):
4546
queryset = super().get_queryset()
@@ -63,7 +64,7 @@ def get_object(self):
6364
resp = get_object_or_404(queryset, pk=lookup)
6465

6566
elif self.namePattern.match(lookup):
66-
resp = get_object_or_404(queryset, name=lookup)
67+
resp = get_object_or_404(queryset, name__iexact=lookup)
6768

6869
else:
6970
raise Http404

pokemon_v2/tests.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5690,3 +5690,110 @@ def test_id_range_api(self):
56905690
response = self.client.get("{}/pokemon/{}/".format(API_V2, 2147483648))
56915691

56925692
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
5693+
5694+
# Test if API endpoints are case-insensitive
5695+
def test_case_insensitive_api(self):
5696+
# Set up pokemon data
5697+
pokemon_species = self.setup_pokemon_species_data(
5698+
name="pkmn spcs for base pkmn"
5699+
)
5700+
pokemon = self.setup_pokemon_data(
5701+
pokemon_species=pokemon_species, name="base pkm"
5702+
)
5703+
pokemon_form = self.setup_pokemon_form_data(
5704+
pokemon=pokemon, name="pkm form for base pkmn"
5705+
)
5706+
generation = self.setup_generation_data(name="base gen")
5707+
pokemon_ability = self.setup_pokemon_ability_data(pokemon=pokemon)
5708+
pokemon_past_ability = self.setup_pokemon_past_ability_data(
5709+
pokemon=pokemon, generation=generation
5710+
)
5711+
pokemon_stat = self.setup_pokemon_stat_data(pokemon=pokemon)
5712+
pokemon_type = self.setup_pokemon_type_data(pokemon=pokemon)
5713+
pokemon_past_type = self.setup_pokemon_past_type_data(
5714+
pokemon=pokemon, generation=generation
5715+
)
5716+
pokemon_item = self.setup_pokemon_item_data(pokemon=pokemon)
5717+
pokemon_sprites = self.setup_pokemon_sprites_data(pokemon=pokemon)
5718+
pokemon_cries = self.setup_pokemon_cries_data(pokemon, latest=True, legacy=True)
5719+
pokemon_game_index = self.setup_pokemon_game_index_data(
5720+
pokemon=pokemon, game_index=10
5721+
)
5722+
# To test issue #85, we will create one move that has multiple
5723+
# learn levels in different version groups. Later, we'll
5724+
# assert that we only got one move record back.
5725+
pokemon_move = self.setup_move_data(name="mv for pkmn")
5726+
pokemon_moves = []
5727+
for move in range(0, 4):
5728+
version_group = self.setup_version_group_data(
5729+
name="ver grp " + str(move) + " for pkmn"
5730+
)
5731+
new_move = self.setup_pokemon_move_data(
5732+
pokemon=pokemon,
5733+
move=pokemon_move,
5734+
version_group=version_group,
5735+
level=move,
5736+
)
5737+
pokemon_moves.append(new_move)
5738+
5739+
encounter_method = self.setup_encounter_method_data(
5740+
name="encntr mthd for lctn area"
5741+
)
5742+
location_area1 = self.setup_location_area_data(name="lctn1 area for base pkmn")
5743+
encounter_slot1 = self.setup_encounter_slot_data(
5744+
encounter_method, slot=1, rarity=30
5745+
)
5746+
self.setup_encounter_data(
5747+
location_area=location_area1,
5748+
pokemon=pokemon,
5749+
encounter_slot=encounter_slot1,
5750+
min_level=30,
5751+
max_level=35,
5752+
)
5753+
location_area2 = self.setup_location_area_data(name="lctn2 area for base pkmn")
5754+
encounter_slot2 = self.setup_encounter_slot_data(
5755+
encounter_method, slot=2, rarity=40
5756+
)
5757+
self.setup_encounter_data(
5758+
location_area=location_area2,
5759+
pokemon=pokemon,
5760+
encounter_slot=encounter_slot2,
5761+
min_level=32,
5762+
max_level=36,
5763+
)
5764+
5765+
lowercase_name = pokemon.name.lower()
5766+
uppercase_name = pokemon.name.upper()
5767+
5768+
# Test lowercase
5769+
lowercase_response = self.client.get(
5770+
"{}/pokemon/{}/".format(API_V2, lowercase_name), HTTP_HOST="testserver"
5771+
)
5772+
self.assertEqual(lowercase_response.status_code, status.HTTP_200_OK)
5773+
5774+
# Test uppercase
5775+
uppercase_response = self.client.get(
5776+
"{}/pokemon/{}/".format(API_V2, uppercase_name), HTTP_HOST="testserver"
5777+
)
5778+
self.assertEqual(uppercase_response.status_code, status.HTTP_200_OK)
5779+
5780+
self.assertEqual(lowercase_response.data, uppercase_response.data)
5781+
5782+
# Same test with /language endpoint
5783+
language = self.setup_language_data(name="base-lang")
5784+
language_name = self.setup_language_name_data(language, name="base-lang-name")
5785+
5786+
lowercase_name = language.name.lower()
5787+
uppercase_name = language.name.upper()
5788+
5789+
lowercase_response = self.client.get(
5790+
"{}/language/{}/".format(API_V2, lowercase_name), HTTP_HOST="testserver"
5791+
)
5792+
self.assertEqual(lowercase_response.status_code, status.HTTP_200_OK)
5793+
5794+
uppercase_response = self.client.get(
5795+
"{}/language/{}/".format(API_V2, uppercase_name), HTTP_HOST="testserver"
5796+
)
5797+
self.assertEqual(uppercase_response.status_code, status.HTTP_200_OK)
5798+
5799+
self.assertEqual(lowercase_response.data, uppercase_response.data)

0 commit comments

Comments
 (0)