Beispiel #1
0
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
Beispiel #2
0
    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,
            )
        }
Beispiel #3
0
    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,
            ),
        }
Beispiel #5
0
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
Beispiel #6
0
    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)
Beispiel #7
0
    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)
Beispiel #8
0
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
Beispiel #10
0
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,
            ),
        }
Beispiel #13
0
    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])
            ),
        }
Beispiel #14
0
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},
Beispiel #16
0
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: