# -*- coding: utf-8 -*-
#
# REST Unit Tests
#
# To run this script use:
# python web2py.py -S eden -M -R applications/eden/modules/unit_tests/s3/s3rest.py
#
import unittest
from gluon import *
from gluon.storage import Storage
from s3.s3rest import S3Request
try:
    from cStringIO import StringIO
except ImportError:
    from StringIO import StringIO

# =============================================================================
class POSTFilterTests(unittest.TestCase):
    """ Tests for POST filter queries """

    # -------------------------------------------------------------------------
    def setUp(self):

        request = current.request
        self.request_body = request._body
        self.content_type = request.env.content_type

    # -------------------------------------------------------------------------
    def tearDown(self):

        request = current.request
        request._body = self.request_body
        request.env.content_type = self.content_type

    # -------------------------------------------------------------------------
    def testPOSTFilter(self):
        """ Test POST filter interpretation with multipart request body """

        assertEqual = self.assertEqual
        assertNotIn = self.assertNotIn
        assertIn = self.assertIn

        request = current.request
        request.env.content_type = "multipart/form-data"

        # Test with valid filter expression JSON
        r = S3Request(prefix = "org",
                      name = "organisation",
                      http = "POST",
                      get_vars = {"$search": "form", "test": "retained"},
                      post_vars = {"~.name|~.comments__like": '''["first","second"]''',
                                   "~.other_field__lt": '''"1"''',
                                   "multi.nonstr__belongs": '''[1,2,3]''',
                                   "service_organisation.service_id__belongs": "1",
                                   "other": "testing",
                                   },
                      )

        # Method changed to GET:
        assertEqual(r.http, "GET")
        get_vars = r.get_vars
        post_vars = r.post_vars

        # $search removed from GET vars:
        assertNotIn("$search", get_vars)

        # Filter queries from POST vars JSON-decoded and added to GET vars:
        assertEqual(get_vars.get("~.name|~.comments__like"), ["first","second"])
        assertEqual(get_vars.get("~.other_field__lt"), "1")

        # Edge-cases (non-str values) properly converted:
        assertEqual(get_vars.get("multi.nonstr__belongs"), ["1", "2", "3"])
        assertEqual(get_vars.get("service_organisation.service_id__belongs"), "1")

        # Filter queries removed from POST vars:
        assertNotIn("~.name|~.comments__like", post_vars)
        assertNotIn("~.other_field__lt", post_vars)
        assertNotIn("service_organisation.service_id__belongs", post_vars)

        # Non-queries retained in POST vars:
        assertIn("other", post_vars)

        # Must retain other GET vars:
        assertEqual(get_vars.get("test"), "retained")

        # Test without $search
        r = S3Request(prefix = "org",
                      name = "organisation",
                      http = "POST",
                      get_vars = {"test": "retained"},
                      post_vars = {"service_organisation.service_id__belongs": "1",
                                   "other": "testing",
                                   },
                      )

        # Method should still be POST:
        assertEqual(r.http, "POST")
        get_vars = r.get_vars
        post_vars = r.post_vars

        # $search never was in GET vars - confirm this to exclude test regression
        assertNotIn("$search", get_vars)

        # Filter queries from POST vars not added to GET vars:
        assertNotIn("service_organisation.service_id__belongs", get_vars)

        # Filter queries still in POST vars:
        assertIn("service_organisation.service_id__belongs", post_vars)

        # Must retain other GET vars:
        assertEqual(get_vars.get("test"), "retained")

    # -------------------------------------------------------------------------
    def testPOSTFilterAjax(self):
        """ Test POST filter interpretation with JSON request body """

        assertEqual = self.assertEqual
        assertNotIn = self.assertNotIn

        request = current.request

        # Test with valid filter expression JSON
        jsonstr = '''{"service_organisation.service_id__belongs":"1","~.example__lt":1,"~.other__like":[1,2]}'''
        request._body = StringIO(jsonstr)