def test_create_jobs_payload(): jobs = { 'some-unique-id': Job( name='FooBar.js', data={'baz': 1234}, ), 'some-other-unique-id': Job( name='MyComponent.js', data={'title': 'sup'}, ), } expected_result = { 'some-unique-id': { 'name': 'FooBar.js', 'data': { 'baz': 1234, }, }, 'some-other-unique-id': { 'name': 'MyComponent.js', 'data': { 'title': 'sup', }, }, } assert create_jobs_payload(jobs) == expected_result
def test_batch_request_with_component_errors(self, spy_plugin_controller, test_data, batch_request): data = test_data[0] token_1 = batch_request.render('MyComponent1.js', data[0]) token_2 = batch_request.render('MyComponent2.js', data[1]) job_2 = Job(name='MyComponent2.js', data=data[1]) fake_response_json = { 'error': None, 'results': { token_1.identifier: { 'error': None, 'html': '<div>wow such SSR</div>', }, token_2.identifier: { 'error': { 'name': 'SomeError', 'message': 'we goofed', 'stack': ['line 1', 'line 2'] }, 'html': None, } } } with mock.patch('fido.fetch') as mock_fetch: mock_fetch.return_value.wait.return_value.json.return_value = fake_response_json response = batch_request.submit() if batch_request.max_batch_size is None: assert mock_fetch.call_count == 1 else: # Division (rounded-up) up to get total number of calls jobs_count = len(batch_request.jobs) max_batch_size = batch_request.max_batch_size assert mock_fetch.call_count == (jobs_count + (max_batch_size - 1)) // max_batch_size assert response == { token_1.identifier: JobResult( error=None, html='<div>wow such SSR</div>', job=Job(name='MyComponent1.js', data=data[0]) ), token_2.identifier: JobResult( error=HypernovaError( name='SomeError', message='we goofed', stack=['line 1', 'line 2'], ), html=render_blank_markup(token_2.identifier, job_2, True, batch_request.json_encoder), job=job_2, ) }
def test_batch_request_with_unhealthy_service(self, spy_plugin_controller, test_data, batch_request): data = test_data[0] job = Job(name='MyComponent.js', data=data[0]) token = batch_request.render('MyComponent.js', data[0]) with mock.patch('fido.fetch') as mock_fetch: mock_fetch.return_value.wait.return_value.json.side_effect = NetworkError('oh no') response = batch_request.submit() if batch_request.max_batch_size is None: assert mock_fetch.call_count == 1 else: # Division (rounded-up) up to get total number of calls jobs_count = len(batch_request.jobs) max_batch_size = batch_request.max_batch_size assert mock_fetch.call_count == (jobs_count + (max_batch_size - 1)) // max_batch_size assert response == { token.identifier: JobResult( error=HypernovaError( name="<class 'fido.exceptions.NetworkError'>", message='oh no', stack=mock.ANY, ), html=render_blank_markup(token.identifier, job, True, batch_request.json_encoder), job=job, ), }
def test_batch_request_with_application_error(self, spy_plugin_controller, batch_request): job = Job(name='MyComponent.js', data={'foo': 'bar'}) token = batch_request.render('MyComponent.js', {'foo': 'bar'}) fake_response_json = { 'error': { 'name': 'SomeError', 'message': 'yikes', 'stack': ['line 1', 'line 2'] } } with mock.patch('fido.fetch') as mock_fetch: mock_fetch.return_value.wait.return_value.json.return_value = fake_response_json response = batch_request.submit() if batch_request.max_batch_size is None: assert mock_fetch.call_count == 1 else: # Division (rounded-up) up to get total number of calls jobs_count = len(batch_request.jobs) max_batch_size = batch_request.max_batch_size assert mock_fetch.call_count == (jobs_count + (max_batch_size - 1)) // max_batch_size assert response == { token.identifier: JobResult( error=HypernovaError( name='SomeError', message='yikes', stack=['line 1', 'line 2'], ), html=render_blank_markup(token.identifier, job, True), job=job, ), }
def test_render_blank_markup_with_error(): job = Job('MyCoolComponent.js', data={'title': 'sup'}, context={}) markup = render_blank_markup('my-unique-token', job, True, JSONEncoder()) assert markup == dedent(''' <div data-hypernova-key="MyCoolComponentjs" data-hypernova-id="my-unique-token"></div> <script type="application/json" data-hypernova-key="MyCoolComponentjs" data-hypernova-id="my-unique-token" ><!--{"title": "sup"}--></script> <script type="text/javascript"> (function () { function ServerSideRenderingError(component) { this.name = 'ServerSideRenderingError'; this.component = component; } ServerSideRenderingError.prototype = Object.create(ServerSideRenderingError.prototype); ServerSideRenderingError.prototype.constructor = ServerSideRenderingError; throw new ServerSideRenderingError('MyCoolComponentjs failed to render server-side, and fell back to client-side rendering.'); }()); </script> ''') # noqa: ignore=E501
def render(self, name, data): identifier = str(uuid.uuid4()) data = self.plugin_controller.get_view_data(name, data) job = Job(name, data) self.jobs[identifier] = job return RenderToken(identifier)
def render(self, name, data, context=None): if context is None: # pragma: no cover context = {} identifier = str(uuid.uuid4()) data = self.plugin_controller.get_view_data(name, data) job = Job(name, data, context) self.jobs[identifier] = job return RenderToken(identifier)
def test_render_blank_markup(): job = Job('MyCoolComponent.js', data={'title': 'sup'}, context={}) markup = render_blank_markup('my-unique-token', job, False, JSONEncoder()) assert markup == dedent(''' <div data-hypernova-key="MyCoolComponentjs" data-hypernova-id="my-unique-token"></div> <script type="application/json" data-hypernova-key="MyCoolComponentjs" data-hypernova-id="my-unique-token" ><!--{"title": "sup"}--></script> ''')
def test_create_fallback_response(throw_client_error): jobs = { 'some-unique-id': Job( name='FooBar.js', data={'baz': 1234}, ), 'some-other-unique-id': Job( name='MyComponent.js', data={'title': 'sup'}, ), } expected_response = { identifier: JobResult( error=None, html=render_blank_markup(identifier, job, throw_client_error), job=job, ) for identifier, job in jobs.items() } assert create_fallback_response(jobs, throw_client_error) == expected_response
def test_render_blank_markup_with_custom_json_encoder(): job = Job('MyCoolComponent.js', data={'a complex subject': 4.3 + 2.1j}) markup = render_blank_markup('my-unique-token', job, False, ComplexJSONEncoder()) assert markup == dedent(''' <div data-hypernova-key="MyCoolComponentjs" data-hypernova-id="my-unique-token"></div> <script type="application/json" data-hypernova-key="MyCoolComponentjs" data-hypernova-id="my-unique-token" ><!--{"a complex subject": [4.3, 2.1]}--></script> ''')
def test_batch_request_with_application_error( self, spy_plugin_controller, test_data, batch_request, mock_hypernova_query, ): data = test_data[0] job = Job(name='MyComponent.js', data=data[0], context={}) token = batch_request.render('MyComponent.js', data[0]) fake_response_json = { 'error': { 'name': 'SomeError', 'message': 'yikes', 'stack': ['line 1', 'line 2'] } } mock_hypernova_query.return_value.json.return_value = fake_response_json response = batch_request.submit() if batch_request.max_batch_size is None: assert mock_hypernova_query.call_count == 1 else: # Division (rounded-up) up to get total number of calls jobs_count = len(batch_request.jobs) max_batch_size = batch_request.max_batch_size batch_count = (jobs_count + (max_batch_size - 1)) // max_batch_size assert mock_hypernova_query.call_count == batch_count mock_hypernova_query.assert_called_with(mock.ANY, mock.ANY, mock.ANY, batch_count == 1, {}) assert response == { token.identifier: JobResult( error=HypernovaError( name='SomeError', message='yikes', stack=['line 1', 'line 2'], ), html=render_blank_markup(token.identifier, job, True, batch_request.json_encoder), job=job, ), }
def test_batch_request_with_unhealthy_service( self, spy_plugin_controller, test_data, batch_request, mock_hypernova_query, ): data = test_data[0] job = Job(name='MyComponent.js', data=data[0], context={}) token = batch_request.render('MyComponent.js', data[0]) mock_hypernova_query.return_value.json.side_effect = HypernovaQueryError( 'oh no') response = batch_request.submit() if batch_request.max_batch_size is None: assert mock_hypernova_query.call_count == 1 else: # Division (rounded-up) up to get total number of calls jobs_count = len(batch_request.jobs) max_batch_size = batch_request.max_batch_size batch_count = (jobs_count + (max_batch_size - 1)) // max_batch_size assert mock_hypernova_query.call_count == batch_count mock_hypernova_query.assert_called_with(mock.ANY, mock.ANY, mock.ANY, batch_count == 1, {}) assert response == { token.identifier: JobResult( error=HypernovaError( name='HypernovaQueryError', message='oh no', stack=mock.ANY, ), html=render_blank_markup(token.identifier, job, True, batch_request.json_encoder), job=job, ), }
def test_successful_batch_request(self, spy_plugin_controller, test_data, batch_request): data = test_data[0] token_1 = batch_request.render('component-1.js', data[0]) token_2 = batch_request.render('component-2.js', data[1]) token_3 = batch_request.render('component-3.js', data[2]) assert batch_request.jobs == { token_1.identifier: Job( name='component-1.js', data=data[0], ), token_2.identifier: Job( name='component-2.js', data=data[1], ), token_3.identifier: Job( name='component-3.js', data=data[2], ), } fake_response_json = { 'error': None, 'results': { token_1.identifier: { 'error': None, 'html': '<div>component 1</div>', }, token_2.identifier: { 'error': None, 'html': '<div>component 2</div>', }, token_3.identifier: { 'error': None, 'html': '<div>component 3</div>', }, } } with mock.patch('fido.fetch') as mock_fetch: mock_fetch.return_value.wait.return_value.json.return_value = fake_response_json response = batch_request.submit() if batch_request.max_batch_size is None: assert mock_fetch.call_count == 1 else: # Division (rounded-up) up to get total number of calls jobs_count = len(batch_request.jobs) max_batch_size = batch_request.max_batch_size assert mock_fetch.call_count == (jobs_count + (max_batch_size - 1)) // max_batch_size assert response == { token_1.identifier: JobResult( error=None, html='<div>component 1</div>', job=Job(name='component-1.js', data=data[0]) ), token_2.identifier: JobResult( error=None, html='<div>component 2</div>', job=Job(name='component-2.js', data=data[1]) ), token_3.identifier: JobResult( error=None, html='<div>component 3</div>', job=Job(name='component-3.js', data=data[2]) ), }
from fido.exceptions import NetworkError from pyramid_hypernova.batch import BatchRequest from pyramid_hypernova.batch import create_fallback_response from pyramid_hypernova.batch import create_job_groups from pyramid_hypernova.batch import create_jobs_payload from pyramid_hypernova.plugins import PluginController from pyramid_hypernova.rendering import render_blank_markup from pyramid_hypernova.types import HypernovaError from pyramid_hypernova.types import Job from pyramid_hypernova.types import JobResult from testing.json_encoder import ComplexJSONEncoder test_jobs = { 'some-unique-id': Job( name='FooBar.js', data={'baz': 1234}, ), 'some-other-unique-id': Job( name='MyComponent.js', data={'title': 'sup'}, ), } test_jobs_with_complex_numbers_in_data = { 'some-unique-id': Job( name='FooBar.js', data={'baz': 1 + 2j}, ), 'some-other-unique-id': Job( name='MyComponent.js', data={'title': 3 + 4j},
from pyramid_hypernova.batch import BatchRequest from pyramid_hypernova.batch import create_fallback_response from pyramid_hypernova.batch import create_job_groups from pyramid_hypernova.plugins import PluginController from pyramid_hypernova.rendering import render_blank_markup from pyramid_hypernova.request import HypernovaQueryError from pyramid_hypernova.types import HypernovaError from pyramid_hypernova.types import Job from pyramid_hypernova.types import JobResult from testing.json_encoder import ComplexJSONEncoder test_jobs = { 'some-unique-id': Job( name='FooBar.js', data={'baz': 1234}, context={}, ), 'some-other-unique-id': Job( name='MyComponent.js', data={'title': 'sup'}, context={}, ), } test_jobs_with_complex_numbers_in_data = { 'some-unique-id': Job( name='FooBar.js', data={'baz': 1 + 2j},
from json import JSONEncoder import mock import pytest from fido.exceptions import NetworkError from requests.exceptions import HTTPError from pyramid_hypernova.request import create_jobs_payload from pyramid_hypernova.request import HypernovaQuery from pyramid_hypernova.request import HypernovaQueryError from pyramid_hypernova.types import Job TEST_JOB_GROUP = { 'yellow keycard': Job('open the exit door', 'behind the cacodemon', {}), 'red skull key': Job('get the bfg9k', 'rocket jump from the platform', {'foo': 'bar'}), } @pytest.fixture def mock_fido_fetch(): with mock.patch('pyramid_hypernova.request.fido.fetch') as mock_fido_fetch: yield mock_fido_fetch @pytest.fixture def mock_requests_post(): with mock.patch( 'pyramid_hypernova.request.requests.post') as mock_requests_post: