Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
449062e
migrated the library to support both py2 and py3
surenderraju Aug 30, 2019
577e585
addressed review comments
surenderraju Sep 3, 2019
5985a9d
Merge pull request #1 from surenderraju/py3-migration
Sep 9, 2019
5daaca2
updated version and readme
surenderraju Sep 10, 2019
e5b7894
Bump version: 0.4.2 → 1.0.0
surenderraju Sep 10, 2019
e4e3f0b
bumpversion
surenderraju Sep 10, 2019
1cc73c5
updated readme with version
surenderraju Sep 10, 2019
4585cf4
Merge pull request #2 from surenderraju/py3-migration
Sep 10, 2019
64e0d7b
[FIX] Added Makefile in to bumpversion files to update
Sep 10, 2019
9fab2db
now get response body returns string
surenderraju Sep 12, 2019
0e90d8d
Bump version: 1.0.0 → 1.0.1
surenderraju Sep 12, 2019
fba1df2
Fixed get response body decode error for py2
surenderraju Oct 8, 2019
7014d2b
Bump version: 1.0.1 → 1.0.2
surenderraju Oct 8, 2019
1be4994
Fix cookie header key issue, add a function to compare dictionaries i…
Oct 21, 2019
0e696d6
Remove redundent code and fix spacing
Oct 29, 2019
b160f4d
Merge pull request #7 from celeraone/fixes
surenderraju Nov 8, 2019
b08e4f8
Add functions to compare query params and fragments
Nov 29, 2019
6449051
Add tests for url comparison functions
Nov 29, 2019
db72789
Change empty string to None to support empty strings as query params
Nov 29, 2019
963894f
Bump version: 1.0.2 → 1.1.0
Nov 29, 2019
1bc398c
fixed set-cookie header issue when multiple values comes
surenderraju Dec 27, 2019
7d0722c
Merge pull request #13 from celeraone/bugfix/set-cookie-header
surenderraju Jan 10, 2020
7ac06f4
Handling set-cookie effectively and removing some un-necessary code
Feb 5, 2020
b933ca1
Merge pull request #14 from celeraone/handling-set-cookies
shafeequ Feb 5, 2020
79e1a81
add new line at the end
shafeequ Feb 5, 2020
c427cd6
fiddle if and only if there is auth_tkt in the Session Cookie
shafeequ Feb 5, 2020
7d7871e
Merge pull request #15 from celeraone/handling-set-cookies
shafeequ Feb 6, 2020
6dae08f
Bump version: 1.1.0 → 1.1.2
Feb 6, 2020
45199f3
Merge pull request #16 from celeraone/handling-set-cookies
shafeequ Feb 6, 2020
20d09dc
code cleanup
shafeequ Feb 7, 2020
c5cd25d
Merge pull request #17 from celeraone/handling-set-cookies
shafeequ Feb 7, 2020
fd550cf
Returning same headers as a list.
Jun 8, 2020
0b5fd6b
Bump version: 1.1.2 → 1.1.3
Jun 8, 2020
1131285
NO-TICKET [FIX] HEAD request parameter fixed
Jun 15, 2020
4a0c447
NO-TICKET [REFAC] Simplified decoding of (none) string values
Jun 15, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[bumpversion]
files = setup.py src/HttpLibrary/__init__.py
files = setup.py src/HttpLibrary/__init__.py Makefile
commit = True
tag = True
current_version = 1.1.3

25 changes: 25 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
VERSION = 1.1.3

.PHONY: tests
tests:
tox

.PHONY: clean
clean:
git clean -dfx

.PHONY: run-robotframework
run-robotframework:
bin/robotframework tests

.PHONY: buildout-development-py2
buildout-development-py2:
virtualenv --no-site-packages .venv27
.venv27/bin/python bootstrap.py
bin/buildout

.PHONY: buildout-development-py3
buildout-development-py3:
virtualenv --no-site-packages --python=python3 .venv36
.venv36/bin/python bootstrap.py
bin/buildout
7 changes: 7 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,13 @@ mostly a wrapper supposed to have a nice API)!
Changelog
---------

**v1.0.0**

- Upgraded dependent robotframework library version to 3.1.2(latest).
- Migrated source code to support both python 2 and python 3.
- Unit tests updated accordingly.
- Integrated tox test automation tool to test on multiple python environments.

**v0.4.2**

- Don't enforce ASCII when converting to JSON (so chinese characters are
Expand Down
14 changes: 3 additions & 11 deletions bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
$Id: bootstrap.py 102545 2009-08-06 14:49:47Z chrisw $
"""

import os, shutil, sys, tempfile, urllib2
import os, shutil, sys, tempfile
from optparse import OptionParser

tmpeggs = tempfile.mkdtemp()
Expand All @@ -32,7 +32,7 @@
parser.add_option("-v", "--version", dest="version",
help="use a specific zc.buildout version")
parser.add_option("-d", "--distribute",
action="store_true", dest="distribute", default=True,
action="store_true", dest="distribute", default=False,
help="Use Disribute rather than Setuptools.")

options, args = parser.parse_args()
Expand All @@ -49,18 +49,10 @@
try:
import pkg_resources
if not hasattr(pkg_resources, '_distribute'):
to_reload = True
to_reload = False
raise ImportError
except ImportError:
ez = {}
if USE_DISTRIBUTE:
exec urllib2.urlopen('http://python-distribute.org/distribute_setup.py'
).read() in ez
ez['use_setuptools'](to_dir=tmpeggs, download_delay=0, no_fake=True)
else:
exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
).read() in ez
ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)

if to_reload:
reload(pkg_resources)
Expand Down
20 changes: 3 additions & 17 deletions buildout.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,23 @@ show-picked-versions = true

develop = .

parts = develop-eggs robotframework pylint
parts = develop-eggs robotframework

[develop-eggs]
recipe = zc.recipe.egg
eggs = robotframework-httplibrary

[versions]
robotframework = 2.7.5
robotframework = 3.1.2

[robotframework]
recipe = zc.recipe.egg
eggs =
robotframework == ${versions:robotframework}
future
robotframework-httplibrary
entry-points =
robotframework=rf_httplib_dev_helper:run_cli
libdoc=robot.libdoc:libdoc_cli

arguments = sys.argv[1:]

[pylint]
recipe = zc.recipe.egg
eggs =
pylint
entry-points = pylint=pylint.lint:Run
extra-paths = src/
arguments = [
'--output-format=colorized',
'--reports=n',
'--include-ids=y',
'--disable=E0611,F0401,W0232,E1101,C0103,C0111,I0011',
'HttpLibrary',
] + sys.argv[1:]

4 changes: 3 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

CLASSIFIERS = """
Programming Language :: Python
Programming Language :: Python 2.7
Programming Language :: Python 3.6
Topic :: Software Development :: Testing
"""[1:-1]

Expand All @@ -12,7 +14,7 @@

setup(
name='robotframework-httplibrary',
version="0.4.2",
version="1.1.3",
description='Robot Framework keywords for HTTP requests',
long_description=long_description,
author='Filip Noetzel',
Expand Down
110 changes: 93 additions & 17 deletions src/HttpLibrary/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
from __future__ import absolute_import
from future import standard_library
standard_library.install_aliases()
from builtins import object, str
from robot.api import logger

from base64 import b64encode
from functools import wraps
from urlparse import urlparse
from urllib.parse import urlparse, parse_qs

import livetest
import sys
from . import livetest
import json
import jsonpointer
import jsonpatch
Expand All @@ -13,7 +18,7 @@
def load_json(json_string):
try:
return json.loads(json_string)
except ValueError, e:
except ValueError as e:
raise ValueError("Could not parse '%s' as JSON: %s" % (json_string, e))


Expand All @@ -25,7 +30,7 @@ def wrapper(self, json_string, *args, **kwargs):
return wrapper


class HTTP:
class HTTP(object):
"""
HttpLibrary for Robot Framework

Expand All @@ -35,7 +40,7 @@ class HTTP:
Pointer, go to http://tools.ietf.org/html/draft-pbryan-zyp-json-pointer-00.
"""

ROBOT_LIBRARY_VERSION = "0.4.2"
ROBOT_LIBRARY_VERSION = "1.1.3"

class Context(object):
def __init__(self, http, host=None, scheme='http'):
Expand Down Expand Up @@ -64,7 +69,7 @@ def __init__(self, http, host=None, scheme='http'):
self.post_process_request(None)

def pre_process_request(self):
if len(self.request_headers.items()) > 0:
if len(list(self.request_headers.items())) > 0:
logger.debug("Request headers:")
for name, value in self.request_headers.items():
logger.debug("%s: %s" % (name, value))
Expand Down Expand Up @@ -212,7 +217,7 @@ def HEAD(self, url):
logger.debug("Performing HEAD request on %s://%s%s" % (
self.context._scheme, self.app.host, path,))
self.context.post_process_request(
self.app.head(path, self.context.request_headers)
self.app.head(path, {}, self.context.request_headers)
)

def GET(self, url):
Expand Down Expand Up @@ -243,10 +248,10 @@ def POST(self, url):
logger.debug("Performing POST request on %s://%s%s" % (
self.context._scheme, self.app.host, url))
self.context.pre_process_request()
self.context.post_process_request(
self.app.post(path, self.context.request_body or {},
self.context.request_headers, **kwargs)
)
response = self.app.post(path, self.context.request_body or {}, self.context.request_headers, **kwargs)
if path == '/kill' and response.status_int == 200:
return
self.context.post_process_request(response)

def PUT(self, url):
"""
Expand Down Expand Up @@ -323,7 +328,48 @@ def next_request_should_have_status_code(self, status_code=None):
"""
self.context.next_request_should = status_code

# status code
def should_contain_url_params(self, url, expected):
"""
Compares query parameters of the url.
Note: Each value of the key in expected to be a list because its valid param to pass list in query params
if some query params are dynamic, just add the key in 'expected' with null value to check their existence
Example:
| Should Contain Url Params | 'url' | {"status":[200],'code':null}
"""
self.__url_qs_fragment_helper(url, expected, False)

def should_contain_url_fragments(self, url, expected):
"""
Compares fragments of the url.
Note: Each value of the key in expected to be a list because its valid param to pass list in fragments
if some fragments are dynamic, just add the key in 'expected' with null value to check their existence

Example:
| Should Contain Url Fragments | 'url' | {"status":[200],'code':null}
"""
self.__url_qs_fragment_helper(url, expected, True)

def __url_qs_fragment_helper(self, url, expected_params, check_fragments):
expected_params = json.loads(expected_params)
parsed_url = urlparse(url, allow_fragments=check_fragments)
query = parsed_url.query
if check_fragments:
query = parsed_url.fragment

if sys.version_info[0] == 2:
query = unicode(query)
parsed_arguments = parse_qs(query, keep_blank_values=True)

assert set(parsed_arguments.keys()) == set(expected_params.keys())

# We remove the dynamic params because we don't know the expected value
# 'None' value in expected indicates its dynamic, so we remove it from both expected and actual
for p in list(expected_params):
if expected_params[p] is None:
del expected_params[p]
del parsed_arguments[p]

assert parsed_arguments == expected_params

def get_response_status(self):
"""
Expand Down Expand Up @@ -385,6 +431,7 @@ def get_response_header(self, header_name):
keyword is a list containing both values.
"""
self.response_should_have_header(header_name)

return self.response.headers.getall(header_name)

def response_header_should_equal(self, header_name, expected):
Expand Down Expand Up @@ -445,6 +492,8 @@ def set_basic_auth(self, username, password):
"""
credentials = "%s:%s" % (username, password)
logger.info('Set basic auth to "%s"' % credentials)
if isinstance(credentials, str):
credentials = credentials.encode()
self.set_request_header(
"Authorization", "Basic %s" % b64encode(credentials))

Expand All @@ -471,7 +520,12 @@ def get_response_body(self):
| ${body}= | Get Response Body | |
| Should Start With | ${body} | <?xml version="1.0" encoding="UTF-8" |
"""
return self.response.body
response_body = self.response.body

if not isinstance(response_body, str):
response_body = response_body.decode('utf-8')

return response_body

def response_body_should_contain(self, should_contain):
"""
Expand All @@ -482,10 +536,14 @@ def response_body_should_contain(self, should_contain):
| Response Body Should Contain | version="1.0" |
| Response Body Should Contain | encoding="UTF-8" |
"""
logger.debug('Testing whether "%s" contains "%s".' % (
self.response.body, should_contain))

assert should_contain in self.response.body, \
response = self.response.body
if not isinstance(response, str):
response = response.decode("utf-8")

logger.debug('Testing whether "%s" contains "%s".' % (response, should_contain))

assert should_contain in response, \
'"%s" should have contained "%s", but did not.' % (
self.response.body, should_contain)

Expand Down Expand Up @@ -548,7 +606,7 @@ def stringify_json(self, data):

try:
return json.dumps(data, ensure_ascii=False)
except ValueError, e:
except ValueError as e:
raise ValueError(
"Could not stringify '%r' to JSON: %s" % (data, e))

Expand Down Expand Up @@ -630,3 +688,21 @@ def show_response_body_in_browser(self):
This is meant for debugging response body's with complex media types.
"""
self.context.response.showbrowser()

def get_major_python_version(self):
"""
returns the current python version
"""
return sys.version_info[0]

def log_message(self, message, log_level='INFO'):
"""
Logs the message.

Specify `log_level` (default: "INFO") to set the log level.
"""
if message:
logger.write("Message :", log_level)
logger.write(message, log_level)
else:
logger.debug("No message received", log_level)
Loading