Codebase list python-webargs / bcd95e2 tests / test_webapp2parser.py
bcd95e2

Tree @bcd95e2 (Download .tar.gz)

test_webapp2parser.py @bcd95e2raw · history · blame

# -*- coding: utf-8 -*-
"""Tests for the webapp2 parser"""
try:
    from urllib.parse import urlencode
except ImportError:  # PY2
    from urllib import urlencode  # type: ignore
from webargs.core import json

import pytest
from marshmallow import fields, ValidationError

import webtest
import webapp2
from webargs.webapp2parser import parser

hello_args = {"name": fields.Str(missing="World")}

hello_multiple = {"name": fields.List(fields.Str())}

hello_validate = {
    "num": fields.Int(
        validate=lambda n: n != 3,
        error_messages={"validator_failed": "Houston, we've had a problem."},
    )
}


def test_parse_querystring_args():
    request = webapp2.Request.blank("/echo?name=Fred")
    assert parser.parse(hello_args, req=request) == {"name": "Fred"}


def test_parse_querystring_multiple():
    expected = {"name": ["steve", "Loria"]}
    request = webapp2.Request.blank("/echomulti?name=steve&name=Loria")
    assert parser.parse(hello_multiple, req=request) == expected


def test_parse_form():
    expected = {"name": "Joe"}
    request = webapp2.Request.blank("/echo", POST=expected)
    assert parser.parse(hello_args, req=request) == expected


def test_parse_form_multiple():
    expected = {"name": ["steve", "Loria"]}
    request = webapp2.Request.blank("/echo", POST=urlencode(expected, doseq=True))
    assert parser.parse(hello_multiple, req=request) == expected


def test_parsing_form_default():
    request = webapp2.Request.blank("/echo", POST="")
    assert parser.parse(hello_args, req=request) == {"name": "World"}


def test_parse_json():
    expected = {"name": "Fred"}
    request = webapp2.Request.blank(
        "/echo", POST=json.dumps(expected), headers={"content-type": "application/json"}
    )
    assert parser.parse(hello_args, req=request) == expected


def test_parse_json_content_type_mismatch():
    request = webapp2.Request.blank(
        "/echo_json",
        POST=json.dumps({"name": "foo"}),
        headers={"content-type": "application/x-www-form-urlencoded"},
    )
    assert parser.parse(hello_args, req=request) == {"name": "World"}


def test_parse_invalid_json():
    request = webapp2.Request.blank(
        "/echo", POST='{"foo": "bar", }', headers={"content-type": "application/json"}
    )
    with pytest.raises(json.JSONDecodeError):
        parser.parse(hello_args, req=request)


def test_parse_json_with_vendor_media_type():
    expected = {"name": "Fred"}
    request = webapp2.Request.blank(
        "/echo",
        POST=json.dumps(expected),
        headers={"content-type": "application/vnd.api+json"},
    )
    assert parser.parse(hello_args, req=request) == expected


def test_parse_json_default():
    request = webapp2.Request.blank(
        "/echo", POST="", headers={"content-type": "application/json"}
    )
    assert parser.parse(hello_args, req=request) == {"name": "World"}


def test_parsing_cookies():
    # whitespace is not valid in a cookie name or value per RFC 6265
    # http://tools.ietf.org/html/rfc6265#section-4.1.1
    expected = {"name": "Jean-LucPicard"}
    response = webapp2.Response()
    response.set_cookie("name", expected["name"])
    request = webapp2.Request.blank(
        "/", headers={"Cookie": response.headers["Set-Cookie"]}
    )
    assert parser.parse(hello_args, req=request, locations=("cookies",)) == expected


def test_parsing_headers():
    expected = {"name": "Fred"}
    request = webapp2.Request.blank("/", headers=expected)
    assert parser.parse(hello_args, req=request, locations=("headers",)) == expected


def test_parse_files():
    """Test parsing file upload using WebTest since I don't know how to mock
    that using a webob.Request
    """

    class Handler(webapp2.RequestHandler):
        @parser.use_args({"myfile": fields.List(fields.Field())}, locations=("files",))
        def post(self, args):
            self.response.content_type = "application/json"

            def _value(f):
                return f.getvalue().decode("utf-8")

            data = dict((i.filename, _value(i.file)) for i in args["myfile"])
            self.response.write(json.dumps(data))

    app = webapp2.WSGIApplication([("/", Handler)])
    testapp = webtest.TestApp(app)
    payload = [("myfile", "baz.txt", b"bar"), ("myfile", "moo.txt", b"zoo")]
    res = testapp.post("/", upload_files=payload)
    assert res.json == {"baz.txt": "bar", "moo.txt": "zoo"}


def test_exception_on_validation_error():
    request = webapp2.Request.blank("/", POST={"num": "3"})
    with pytest.raises(ValidationError):
        parser.parse(hello_validate, req=request)


def test_validation_error_with_message():
    request = webapp2.Request.blank("/", POST={"num": "3"})
    with pytest.raises(ValidationError) as exc:
        parser.parse(hello_validate, req=request)
        assert "Houston, we've had a problem." in exc.value


def test_default_app_request():
    """Test that parser.parse uses the request from webapp2.get_request() if no
    request is passed
    """
    expected = {"name": "Joe"}
    request = webapp2.Request.blank("/echo", POST=expected)
    app = webapp2.WSGIApplication([])
    app.set_globals(app, request)
    assert parser.parse(hello_args) == expected