"""Functional tests around fetching meta languages.""" import json import pytest from product_digital.constants import header as header_constants from python_pdp_sdk import ForwardKwargsGetter, UnauthenticatedException from tests.factories import language as lang_factory from tests.factories import release as release_factory from tests.testutils import db def language_items(languages): """Convert language objects to dicts.""" return [lang.to_dict() for lang in languages] @db.test_schema def test_get_meta_languages_success(client, valid_headers, mock_authorization_backend): """Test successful status and response payload.""" mock_authorization_backend.is_authorized.return_value = True languages = lang_factory.LanguageFactory.build_batch(3) db.seed_models(languages) expected_payload = json.dumps({'items': language_items(languages)}) api_response = client.get('/meta-language', headers=valid_headers) mock_authorization_backend.is_authorized.assert_called_once() call_kwargs = mock_authorization_backend.is_authorized.call_args.kwargs assert call_kwargs['action'] == 'view' assert call_kwargs['resource_id'] == 0 assert call_kwargs['resource_type'] == 'language' assert isinstance(call_kwargs['resource_getter'], ForwardKwargsGetter) assert api_response.status_code == 200 assert api_response.data.decode('utf-8') == expected_payload api_response = client.get('/meta-language', query_string={'include_instrumental': 'true'}, headers=valid_headers) assert api_response.status_code == 200 api_response_items = api_response.json.get('items') assert len(api_response_items) == 4 found_na = list(filter(lambda item: item['code'] == 'N/A', api_response_items)) assert found_na @db.test_schema @pytest.mark.parametrize("error_class", [ RuntimeError, ConnectionError, TimeoutError, ValueError, Exception, UnauthenticatedException, ]) def test_get_meta_languages_sdk_error_falls_through( client, valid_headers, mock_authorization_backend, error_class ): """PP SDK error should not break the endpoint during observability rollout.""" mock_authorization_backend.is_authorized.side_effect = error_class("sdk error") api_response = client.get('/meta-language', headers=valid_headers) assert api_response.status_code == 200 @db.test_schema def test_get_meta_languages_with_product_id(client, valid_headers, mock_authorization_backend): """Test that languages used by the product are included in the response when productId is provided.""" mock_authorization_backend.is_authorized.return_value = True release = release_factory.ReleaseFactory.build(meta_language='eus') # Basque is not apple_compatible, so it won't appear in the baseline query; # it should only be included when the product's language is explicitly requested. basque_language = lang_factory.LanguageFactory.build(language_code='eus', language='Basque', apple_compatible=False) other_language = lang_factory.LanguageFactory.build(language_code='fra', language='French') db.seed_models([release, basque_language, other_language]) response_without_product_id = client.get('/meta-language', headers=valid_headers) assert response_without_product_id.status_code == 200 codes_without = {item['code'] for item in response_without_product_id.json['items']} assert 'eus' not in codes_without api_response = client.get( '/meta-language', query_string={'productId': release.release_id}, headers=valid_headers, ) assert api_response.status_code == 200 response_codes = {item['code'] for item in api_response.json['items']} assert 'eus' in response_codes def test_get_meta_languages_missing_content_type(client): """Test that an error is returned if Content-Type header is missing.""" api_response = client.get('/meta-language') response_body = json.loads(api_response.data.decode('utf-8')) assert api_response.status_code == 400 assert header_constants.CONTENT_TYPE in response_body['message'] @db.test_schema def test_get_meta_languages_unauthorized_jwt_user_falls_through( client, valid_headers, mock_authorization_backend ): """JWT caller unauthorized by PP falls through to legacy (no auth) and gets 200.""" mock_authorization_backend.is_authorized.return_value = False api_response = client.get('/meta-language', headers=valid_headers) assert api_response.status_code == 200