diff --git a/.dockerignore b/.dockerignore index 48324223d..cdc3406ad 100644 --- a/.dockerignore +++ b/.dockerignore @@ -24,4 +24,7 @@ docker-compose* /*.js .env *pycache* -target \ No newline at end of file +target +data/v2/cries +data/v2/csv +data/v2/sprites \ No newline at end of file diff --git a/Resources/k8s/kustomize/base/deployments/pokeapi-deployment.yaml b/Resources/k8s/kustomize/base/deployments/pokeapi-deployment.yaml index 8c1d9b65d..38cb2d4fc 100644 --- a/Resources/k8s/kustomize/base/deployments/pokeapi-deployment.yaml +++ b/Resources/k8s/kustomize/base/deployments/pokeapi-deployment.yaml @@ -23,6 +23,23 @@ spec: echo waiting for database; sleep 2; done; + - name: data-download + image: alpine:3.21.2 + command: ['sh', '-c'] + args: + - apk add --update git && + git clone --depth=1 --single-branch --branch=master --recurse-submodules --shallow-submodules https://github.com/PokeAPI/pokeapi.git && + mv /code/pokeapi/data/v2/cries/* /tmp/cries/ && + mv /code/pokeapi/data/v2/csv/* /tmp/csv/ && + mv /code/pokeapi/data/v2/sprites/* /tmp/sprites/ + workingDir: /code + volumeMounts: + - mountPath: /tmp/cries + name: cries-data-share + - mountPath: /tmp/csv + name: csv-data-share + - mountPath: /tmp/sprites + name: sprites-data-share containers: - name: pokeapi image: pokeapi/pokeapi:master @@ -51,6 +68,13 @@ spec: envFrom: - configMapRef: name: pokeapi-configmap + volumeMounts: + - mountPath: /code/data/v2/cries + name: cries-data-share + - mountPath: /code/data/v2/csv + name: csv-data-share + - mountPath: /code/data/v2/sprites + name: sprites-data-share resources: {} readinessProbe: periodSeconds: 5 @@ -64,3 +88,10 @@ spec: httpGet: path: /api/v2/ port: 8080 + volumes: + - name: cries-data-share + emptyDir: {} + - name: csv-data-share + emptyDir: {} + - name: sprites-data-share + emptyDir: {} diff --git a/pokemon_v2/api.py b/pokemon_v2/api.py index dac987720..7454badd9 100644 --- a/pokemon_v2/api.py +++ b/pokemon_v2/api.py @@ -39,7 +39,8 @@ class NameOrIdRetrieval: """ idPattern = re.compile(r"^-?[0-9]+$") - namePattern = re.compile(r"^[0-9A-Za-z\-\+]+$") + # Allow alphanumeric, hyphen, plus, and space (Space added for test cases using name for lookup, ex: 'base pkm') + namePattern = re.compile(r"^[0-9A-Za-z\-\+ ]+$") def get_queryset(self): queryset = super().get_queryset() @@ -63,7 +64,7 @@ def get_object(self): resp = get_object_or_404(queryset, pk=lookup) elif self.namePattern.match(lookup): - resp = get_object_or_404(queryset, name=lookup) + resp = get_object_or_404(queryset, name__iexact=lookup) else: raise Http404 diff --git a/pokemon_v2/tests.py b/pokemon_v2/tests.py index 1400e8057..8e8eee0c8 100644 --- a/pokemon_v2/tests.py +++ b/pokemon_v2/tests.py @@ -5690,3 +5690,110 @@ def test_id_range_api(self): response = self.client.get("{}/pokemon/{}/".format(API_V2, 2147483648)) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + + # Test if API endpoints are case-insensitive + def test_case_insensitive_api(self): + # Set up pokemon data + pokemon_species = self.setup_pokemon_species_data( + name="pkmn spcs for base pkmn" + ) + pokemon = self.setup_pokemon_data( + pokemon_species=pokemon_species, name="base pkm" + ) + pokemon_form = self.setup_pokemon_form_data( + pokemon=pokemon, name="pkm form for base pkmn" + ) + generation = self.setup_generation_data(name="base gen") + pokemon_ability = self.setup_pokemon_ability_data(pokemon=pokemon) + pokemon_past_ability = self.setup_pokemon_past_ability_data( + pokemon=pokemon, generation=generation + ) + pokemon_stat = self.setup_pokemon_stat_data(pokemon=pokemon) + pokemon_type = self.setup_pokemon_type_data(pokemon=pokemon) + pokemon_past_type = self.setup_pokemon_past_type_data( + pokemon=pokemon, generation=generation + ) + pokemon_item = self.setup_pokemon_item_data(pokemon=pokemon) + pokemon_sprites = self.setup_pokemon_sprites_data(pokemon=pokemon) + pokemon_cries = self.setup_pokemon_cries_data(pokemon, latest=True, legacy=True) + pokemon_game_index = self.setup_pokemon_game_index_data( + pokemon=pokemon, game_index=10 + ) + # To test issue #85, we will create one move that has multiple + # learn levels in different version groups. Later, we'll + # assert that we only got one move record back. + pokemon_move = self.setup_move_data(name="mv for pkmn") + pokemon_moves = [] + for move in range(0, 4): + version_group = self.setup_version_group_data( + name="ver grp " + str(move) + " for pkmn" + ) + new_move = self.setup_pokemon_move_data( + pokemon=pokemon, + move=pokemon_move, + version_group=version_group, + level=move, + ) + pokemon_moves.append(new_move) + + encounter_method = self.setup_encounter_method_data( + name="encntr mthd for lctn area" + ) + location_area1 = self.setup_location_area_data(name="lctn1 area for base pkmn") + encounter_slot1 = self.setup_encounter_slot_data( + encounter_method, slot=1, rarity=30 + ) + self.setup_encounter_data( + location_area=location_area1, + pokemon=pokemon, + encounter_slot=encounter_slot1, + min_level=30, + max_level=35, + ) + location_area2 = self.setup_location_area_data(name="lctn2 area for base pkmn") + encounter_slot2 = self.setup_encounter_slot_data( + encounter_method, slot=2, rarity=40 + ) + self.setup_encounter_data( + location_area=location_area2, + pokemon=pokemon, + encounter_slot=encounter_slot2, + min_level=32, + max_level=36, + ) + + lowercase_name = pokemon.name.lower() + uppercase_name = pokemon.name.upper() + + # Test lowercase + lowercase_response = self.client.get( + "{}/pokemon/{}/".format(API_V2, lowercase_name), HTTP_HOST="testserver" + ) + self.assertEqual(lowercase_response.status_code, status.HTTP_200_OK) + + # Test uppercase + uppercase_response = self.client.get( + "{}/pokemon/{}/".format(API_V2, uppercase_name), HTTP_HOST="testserver" + ) + self.assertEqual(uppercase_response.status_code, status.HTTP_200_OK) + + self.assertEqual(lowercase_response.data, uppercase_response.data) + + # Same test with /language endpoint + language = self.setup_language_data(name="base-lang") + language_name = self.setup_language_name_data(language, name="base-lang-name") + + lowercase_name = language.name.lower() + uppercase_name = language.name.upper() + + lowercase_response = self.client.get( + "{}/language/{}/".format(API_V2, lowercase_name), HTTP_HOST="testserver" + ) + self.assertEqual(lowercase_response.status_code, status.HTTP_200_OK) + + uppercase_response = self.client.get( + "{}/language/{}/".format(API_V2, uppercase_name), HTTP_HOST="testserver" + ) + self.assertEqual(uppercase_response.status_code, status.HTTP_200_OK) + + self.assertEqual(lowercase_response.data, uppercase_response.data)