Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Download assets method #24

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
funcsigs==1.0.2
mock==2.0.0
pbr==5.1.3
six==1.12.0
37 changes: 36 additions & 1 deletion sauceclient.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ def __init__(self, *args, **kwargs):
super(SauceException, self).__init__(*args)
self.response = kwargs.get('response')

class PathException(Exception):
"""SauceClient exception."""

class SauceClient(object):
"""SauceClient class."""
Expand Down Expand Up @@ -86,6 +88,32 @@ def request(self, method, url, body=None, content_type='application/json'):
response.status, response.reason), response=response)
return json.loads(data.decode('utf-8'))

def request_content(self, url, filename, dirpath=None,content_type=''):
"""Send http request for asset content"""
headers = self.make_auth_headers(content_type)
connection = http_client.HTTPSConnection(self.apibase)
full_url = url + filename
connection.request('GET', full_url, headers=headers)
response = connection.getresponse()
data = response.read()

if dirpath:
if os.path.exists(dirpath):
full_path = os.path.join(dirpath, filename)
with open(full_path, 'wb') as file_handle:
file_handle.write(data)
else:
raise PathException("Path does not exist")
else:
with open(filename, 'wb') as file_handle:
file_handle.write(data)

connection.close()
if response.status not in [200, 201]:
raise SauceException('{}: {}.\nSauce Status NOT OK'.format(
response.status, response.reason), response=response)
return True


class Account(object):
"""Account Methods
Expand Down Expand Up @@ -474,9 +502,16 @@ def get_job_assets(self, job_id):

def get_job_asset_url(self, job_id, filename):
"""Get details about the static assets collected for a specific job."""
return 'https://saucelabs.com/rest/v1/{}/jobs/{}/assets/{}'.format(
return 'https://{}/rest/v1/{}/jobs/{}/assets/{}'.format(self.client.apibase,
self.client.sauce_username, job_id, filename)

def get_job_asset_content(self, job_id, filename, dirpath=None):
"""Get content collected for a specific asset on a specific job."""
endpoint = '/rest/v1/{}/jobs/{}/assets/'.format(
self.client.sauce_username, job_id)

return self.client.request_content(endpoint,filename,dirpath)

def delete_job_assets(self, job_id):
"""Delete all the assets captured during a test run."""
method = 'DELETE'
Expand Down
35 changes: 35 additions & 0 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,41 @@ def test_jobs_get_job_assets(self, mocked):
def test_jobs_get_job_asset_url(self, mocked):
resp = self.sc.jobs.get_job_asset_url('job-id', '0000screenshot.jpg')
self.assertIsInstance(resp, str)
self.assertEqual(resp,"https://saucelabs.com/rest/v1/sauce-username/jobs/job-id/assets/0000screenshot.jpg")

@patch('sauceclient.os.path')
@patch('sauceclient.open', create=True)
def test_jobs_get_job_asset_content(self, mocked_open, mocked_path, mocked):

mocked.return_value.status = 200
mocked.return_value.reason = 'OK'
mocked.return_value.read.return_value = b''

mocked_path.path.exists.return_value = True

mocked_open.read_data(b'aaa')

resp = self.sc.jobs.get_job_asset_content('job-id',"0000screenshot.jpg")
self.assertTrue(resp)

@patch('sauceclient.os.path')
@patch('sauceclient.open', create=True)
def test_jobs_get_job_asset_content_specific_dir(self, mocked_open, mocked_path, mocked):
mocked.return_value.status = 200
mocked.return_value.reason = 'OK'
mocked.return_value.read.return_value = b''

mocked_path.path.exists.return_value = True

mocked_open.read_data(b'aaa')

resp = self.sc.jobs.get_job_asset_content('job-id',"0000screenshot.jpg","/path/to/somewhere")
self.assertTrue(resp)

def test_jobs_get_job_asset_content_nonexistent_dir(self, mocked):

with self.assertRaises(sauceclient.PathException):
self.sc.jobs.get_job_asset_content('job-id',"0000screenshot.jpg","/path/nowhere/")

def test_jobs_delete_job_assets(self, mocked):
mocked.return_value.status = 200
Expand Down