view test/wsgi_liveserver.py @ 8177:2967f37e73e4

refactor: issue2551289. invalid REST Accept header stops request Sending a POST, PUT (maybe PATCH) with an accept header that is not application/json or xml (if enabled) used to complete the request before throwing a 406 error. This was wrong. Now it reports an error without dispatching/processing the requested transaction. This is the first of a series of refactors of the dispatch method to make it faster and more readable by using return early pattern and extracting methods from the code. changes: The following now return 406 errors not 400 errors invalid version specified with @apiver in URL. invalid version specified with @apiver in payload body invalid version specified in accept headers as application/vnd.roundup.test-vz+json or version property Parsing the accept header returns a 400 when presented with a parameter without an = sign or other parse error. They used to return a 406 which is wrong since the header is malformed rather than having a value I can't respond to. Some error messages were made clearer. Results in the case of an error are proper json error object rather than text/plain strings. New test added for testdetermine_output_formatBadAccept that test the new method using the same test cases as for testDispatchBadAccept. I intend to extend the test coverage for determine_output_format to cover more cases. This should be a faster unit test than for dispatch. Removed .lower() calls for accept_mime_type as the input values are taken from the values in the __accepted_content_type dict which only has lower case values.
author John Rouillard <rouilj@ieee.org>
date Sun, 08 Dec 2024 01:09:34 -0500
parents e9760702bf0c
children f6923d2ba9a5
line wrap: on
line source

# -*- coding: utf-8 -*-
"""
wsgi-liveserver provides a simple LiverServerTestCase class that can be used to
help start a web server in the background to serve a WSGI compliant application
for use with testing. Generally it will be used in conjuction with something
like Selenium to perform a series of functional tests using a browser.

Licensed under the GNU GPL v3

Copyright (c) 2013 John Kristensen (unless explicitly stated otherwise).
"""
import threading
import socket
import unittest
from wsgiref.simple_server import make_server, WSGIRequestHandler

__author__ = 'John Kristensen'
__version__ = '0.3.1'
__license__ = 'GPLv3'


class QuietHandler(WSGIRequestHandler):
    def log_request(*args, **kwargs):
        pass


class LiveServerTestCase(unittest.TestCase):

    port_range = (8080, 8090)

    def create_app(self):
        """Create your wsgi app and return it."""
        raise NotImplementedError

    def __call__(self, result=None):
        """
        Do some custom setup stuff and then hand off to TestCase to do its
        thing.
        """
        try:
            self._pre_setup()
            super(LiveServerTestCase, self).__call__(result)
        finally:
            self._post_teardown()

    def url_base(self):
        """Return the url of the test server."""
        return 'http://{0}:{1}'.format(self.host, self.port)

    def _pre_setup(self):
        """Setup and start the test server in the background."""
        self._server = None

        self.host = 'localhost'
        self.port = self.port_range[0]
        self._thread = None

        # Get the app
        self.app = self.create_app()

        # Cycle through the port range to find a free port
        while self._server is None and self.port <= self.port_range[1]:
            try:
                self._server = make_server(self.host, self.port, self.app,
                                           handler_class=QuietHandler)
            except socket.error:
                self.port += 1

        # No free port, raise an exception
        if self._server is None:
            raise socket.error('Ports {0}-{1} are all already in use'.format(
                *self.port_range))

        # Start the test server in the background
        self._thread = threading.Thread(target=self._server.serve_forever)
        self._thread.start()

    def _post_teardown(self):
        """Stop the test server."""
        if self._thread is not None:
            self._server.shutdown()
            self._server.server_close()
            self._thread.join()
            del self._server

Roundup Issue Tracker: http://roundup-tracker.org/