text: from contextlib import contextmanager
  
  from six.moves.urllib.parse import urlencode
  
  from .api_asserts import (
      assert_error_code_is,
      assert_has_keys,
      assert_not_has_keys,
      assert_status_code_is,
  )
  from .api_util import (
      ADMIN_TEST_USER,
      get_master_api_key,
      get_user_api_key,
      OTHER_USER,
      TEST_USER,
  )
  from .interactor import TestCaseGalaxyInteractor as BaseInteractor
  from .testcase import FunctionalTestCase
  
  
  class UsesApiTestCaseMixin:
  
      def _api_url(self, path, params=None, use_key=None, use_admin_key=None):
          if not params:
              params = {}
          url = "%s/api/%s" % (self.url, path)
          if use_key:
              params["key"] = self.galaxy_interactor.api_key
          if use_admin_key:
              params["key"] = self.galaxy_interactor.master_api_key
          query = urlencode(params)
          if query:
              url = "%s?%s" % (url, query)
          return url
  
      def _setup_interactor(self):
          self.user_api_key = get_user_api_key()
          self.master_api_key = get_master_api_key()
          self.galaxy_interactor = ApiTestInteractor(self)
  
      def _setup_user(self, email, password=None):
          self.galaxy_interactor.ensure_user_with_email(email, password=password)
          users = self._get("users", admin=True).json()
          user = [user for user in users if user["email"] == email][0]
          return user
  
      def _setup_user_get_key(self, email):
          self.galaxy_interactor.ensure_user_with_email(email)
          users = self._get("users", admin=True).json()
          user = [user for user in users if user["email"] == email][0]
          return self._post("users/%s/api_key" % user["id"], admin=True).json()
  
      @contextmanager
      def _different_user(self, email=OTHER_USER):
          """ Use in test cases to switch get/post operations to act as new user,
  
              with self._different_user( "other_user@bx.psu.edu" ):
                  self._get( "histories" )  # Gets other_user@bx.psu.edu histories.
          """
          original_api_key = self.user_api_key
          original_interactor_key = self.galaxy_interactor.api_key
          new_key = self._setup_user_get_key(email)
          try:
              self.user_api_key = new_key
              self.galaxy_interactor.api_key = new_key
              yield
          finally:
              self.user_api_key = original_api_key
              self.galaxy_interactor.api_key = original_interactor_key
  
      def _get(self, *args, **kwds):
          return self.galaxy_interactor.get(*args, **kwds)
  
      def _post(self, *args, **kwds):
          return self.galaxy_interactor.post(*args, **kwds)
  
      def _delete(self, *args, **kwds):
          return self.galaxy_interactor.delete(*args, **kwds)
  
      def _put(self, *args, **kwds):
          return self.galaxy_interactor.put(*args, **kwds)
  
      def _patch(self, *args, **kwds):
          return self.galaxy_interactor.patch(*args, **kwds)
  
      def _assert_status_code_is(self, response, expected_status_code):
          assert_status_code_is(response, expected_status_code)
  
      def _assert_has_keys(self, response, *keys):
          assert_has_keys(response, *keys)
  
      def _assert_not_has_keys(self, response, *keys):
          assert_not_has_keys(response, *keys)
  
      def _assert_error_code_is(self, response, error_code):
          assert_error_code_is(response, error_code)
  
      def _random_key(self):  # Used for invalid request testing...
          return "1234567890123456"
  
      _assert_has_key = _assert_has_keys
  
  
  class ApiTestCase(FunctionalTestCase, UsesApiTestCaseMixin):
  
      def setUp(self):
          super(ApiTestCase, self).setUp()
          self._setup_interactor()
  
  
  class ApiTestInteractor(BaseInteractor):
      """ Specialized variant of the API interactor (originally developed for
      tool functional tests) for testing the API generally.
      """
  
      def __init__(self, test_case):
          admin = getattr(test_case, "require_admin_user", False)
          test_user = TEST_USER if not admin else ADMIN_TEST_USER
          super(ApiTestInteractor, self).__init__(test_case, test_user=test_user)
  
      # This variant the lower level get and post methods are meant to be used
      # directly to test API - instead of relying on higher-level constructs for
      # specific pieces of the API (the way it is done with the variant for tool)
      # testing.
      def get(self, *args, **kwds):
          return self._get(*args, **kwds)
  
      def post(self, *args, **kwds):
          return self._post(*args, **kwds)
  
      def delete(self, *args, **kwds):
          return self._delete(*args, **kwds)
  
      def patch(self, *args, **kwds):
          return self._patch(*args, **kwds)
  
      def put(self, *args, **kwds):
          return self._put(*args, **kwds)
  