robotframework-appiumwindows 0.1.0__py3-none-any.whl → 0.1.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,74 +1,74 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- from robot.libraries import BuiltIn
4
-
5
- from .keywordgroup import KeywordGroup
6
-
7
- BUILTIN = BuiltIn.BuiltIn()
8
-
9
-
10
- class _RunOnFailureKeywords(KeywordGroup):
11
-
12
- def __init__(self):
13
- self._run_on_failure_keyword = None
14
- self._running_on_failure_routine = False
15
-
16
- # Public
17
-
18
- def register_keyword_to_run_on_failure(self, keyword):
19
- """Sets the keyword to execute when a AppiumLibrary keyword fails.
20
-
21
- `keyword_name` is the name of a keyword (from any available
22
- libraries) that will be executed if a AppiumLibrary keyword fails.
23
- It is not possible to use a keyword that requires arguments.
24
- Using the value "Nothing" will disable this feature altogether.
25
-
26
- The initial keyword to use is set in `importing`, and the
27
- keyword that is used by default is `Capture Page Screenshot`.
28
- Taking a screenshot when something failed is a very useful
29
- feature, but notice that it can slow down the execution.
30
-
31
- This keyword returns the name of the previously registered
32
- failure keyword. It can be used to restore the original
33
- value later.
34
-
35
- Example:
36
- | Register Keyword To Run On Failure | Log Source | # Run `Log Source` on failure. |
37
- | ${previous kw}= | Register Keyword To Run On Failure | Nothing | # Disables run-on-failure functionality and stores the previous kw name in a variable. |
38
- | Register Keyword To Run On Failure | ${previous kw} | # Restore to the previous keyword. |
39
-
40
- This run-on-failure functionality only works when running tests on Python/Jython 2.4
41
- or newer and it does not work on IronPython at all.
42
- """
43
- old_keyword = self._run_on_failure_keyword
44
- old_keyword_text = old_keyword if old_keyword is not None else "Nothing"
45
-
46
- new_keyword = keyword if keyword.strip().lower() != "nothing" else None
47
- new_keyword_text = new_keyword if new_keyword is not None else "Nothing"
48
-
49
- self._run_on_failure_keyword = new_keyword
50
- self._info('%s will be run on failure.' % new_keyword_text)
51
-
52
- return old_keyword_text
53
-
54
- # Private
55
-
56
- def _run_on_failure(self):
57
- if self._run_on_failure_keyword is None:
58
- return
59
- if self._running_on_failure_routine:
60
- return
61
- self._running_on_failure_routine = True
62
- try:
63
- BUILTIN.run_keyword(self._run_on_failure_keyword)
64
- except Exception as err:
65
- self._run_on_failure_error(err)
66
- finally:
67
- self._running_on_failure_routine = False
68
-
69
- def _run_on_failure_error(self, err):
70
- err = "Keyword '%s' could not be run on failure: %s" % (self._run_on_failure_keyword, err)
71
- if hasattr(self, '_warn'):
72
- self._warn(err)
73
- return
74
- raise Exception(err)
1
+ # -*- coding: utf-8 -*-
2
+
3
+ from robot.libraries import BuiltIn
4
+
5
+ from .keywordgroup import KeywordGroup
6
+
7
+ BUILTIN = BuiltIn.BuiltIn()
8
+
9
+
10
+ class _RunOnFailureKeywords(KeywordGroup):
11
+
12
+ def __init__(self):
13
+ self._run_on_failure_keyword = None
14
+ self._running_on_failure_routine = False
15
+
16
+ # Public
17
+
18
+ def register_keyword_to_run_on_failure(self, keyword):
19
+ """Sets the keyword to execute when a AppiumLibrary keyword fails.
20
+
21
+ `keyword_name` is the name of a keyword (from any available
22
+ libraries) that will be executed if a AppiumLibrary keyword fails.
23
+ It is not possible to use a keyword that requires arguments.
24
+ Using the value "Nothing" will disable this feature altogether.
25
+
26
+ The initial keyword to use is set in `importing`, and the
27
+ keyword that is used by default is `Capture Page Screenshot`.
28
+ Taking a screenshot when something failed is a very useful
29
+ feature, but notice that it can slow down the execution.
30
+
31
+ This keyword returns the name of the previously registered
32
+ failure keyword. It can be used to restore the original
33
+ value later.
34
+
35
+ Example:
36
+ | Register Keyword To Run On Failure | Log Source | # Run `Log Source` on failure. |
37
+ | ${previous kw}= | Register Keyword To Run On Failure | Nothing | # Disables run-on-failure functionality and stores the previous kw name in a variable. |
38
+ | Register Keyword To Run On Failure | ${previous kw} | # Restore to the previous keyword. |
39
+
40
+ This run-on-failure functionality only works when running tests on Python/Jython 2.4
41
+ or newer and it does not work on IronPython at all.
42
+ """
43
+ old_keyword = self._run_on_failure_keyword
44
+ old_keyword_text = old_keyword if old_keyword is not None else "Nothing"
45
+
46
+ new_keyword = keyword if keyword.strip().lower() != "nothing" else None
47
+ new_keyword_text = new_keyword if new_keyword is not None else "Nothing"
48
+
49
+ self._run_on_failure_keyword = new_keyword
50
+ self._info('%s will be run on failure.' % new_keyword_text)
51
+
52
+ return old_keyword_text
53
+
54
+ # Private
55
+
56
+ def _run_on_failure(self):
57
+ if self._run_on_failure_keyword is None:
58
+ return
59
+ if self._running_on_failure_routine:
60
+ return
61
+ self._running_on_failure_routine = True
62
+ try:
63
+ BUILTIN.run_keyword(self._run_on_failure_keyword)
64
+ except Exception as err:
65
+ self._run_on_failure_error(err)
66
+ finally:
67
+ self._running_on_failure_routine = False
68
+
69
+ def _run_on_failure_error(self, err):
70
+ err = "Keyword '%s' could not be run on failure: %s" % (self._run_on_failure_keyword, err)
71
+ if hasattr(self, '_warn'):
72
+ self._warn(err)
73
+ return
74
+ raise Exception(err)
@@ -1,138 +1,138 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- import base64
4
- import os
5
-
6
- import robot
7
-
8
- from .keywordgroup import KeywordGroup
9
-
10
-
11
- class _ScreenrecordKeywords(KeywordGroup):
12
-
13
- def __init__(self):
14
- self._screenrecord_index = 0
15
- self._recording = None
16
- self._output_format = None
17
-
18
- def start_screen_recording(self,
19
- timeLimit='180s',
20
- **options):
21
- """Starts an asynchronous Screen Recording for the current open application.
22
-
23
- ``timeLimit`` sets the actual time limit of the recorded video.
24
- - The default value for both iOS and Android is 180 seconds (3 minutes).
25
- - The maximum value for Android is 3 minutes.
26
- - The maximum value for iOS is 10 minutes.
27
-
28
- === Optional Args ===
29
-
30
- - ``bitRate`` (Android Only) The video bit rate for the video, in megabits per second.
31
- 4 Mbp/s(4000000) is by default for Android API level below 27. \
32
- 20 Mb/s(20000000) for API level 27 and above.
33
-
34
- - ``videoSize`` (Android Only) The format is widthxheight. The default value is the \
35
- device's native display resolution (if supported), 1280x720 if not. For best \
36
- results, use a size supported by your device's Advanced Video Coding (AVC) \
37
- encoder. For example, "1280x720"
38
-
39
- - ``bugReport`` (Android Only) Set it to true in order to display additional \
40
- information on the video overlay, such as a timestamp, that is helpful in \
41
- videos captured to illustrate bugs. This option is only supported since \
42
- API level 27 (Android O).
43
-
44
- - ``videoQuality`` (iOS Only) The video encoding quality (low, medium, high, \
45
- photo - defaults to medium).
46
-
47
- - ``videoFps`` (iOS Only) The Frames Per Second rate of the recorded video. \
48
- Change this value if the resulting video is too slow or too fast. Defaults to 10. \
49
- This can decrease the resulting file size.
50
-
51
- - ``videoScale`` (iOS Only) The scaling value to apply. Read \
52
- https://trac.ffmpeg.org/wiki/Scaling for possible values. Example value of 720p \
53
- scaling is '1280:720'. This can decrease/increase the resulting file size. \
54
- No scale is applied by default.
55
-
56
- `Start Screen Recording` is used hand in hand with `Stop Screen Recording`.
57
- See `Stop Screen Recording` for more details.
58
- Example:
59
- | `Start Screen Recording` | | # starts a screen record session |
60
- | .... keyword actions | | |
61
- | `Stop Screen Recording` | filename=output | # saves the recorded session |
62
- """
63
- timeLimit = robot.utils.timestr_to_secs(timeLimit)
64
- options['timeLimit'] = timeLimit
65
- self._output_format = self._set_output_format() \
66
- if self._output_format is None else self._output_format
67
- if self._recording is None:
68
- self._recording = self._current_application().start_recording_screen(**options)
69
-
70
- def stop_screen_recording(self, filename=None, **options):
71
- """Gathers the output from the previously started screen recording \
72
- to a media file, then embeds it to the log.html(Android Only).
73
-
74
- Requires an active or exhausted Screen Recording Session.
75
- See `Start Screen Recording` for more details.
76
-
77
- === Optional Args ===
78
-
79
- - ``remotePath`` The path to the remote location, where the resulting video should be \
80
- uploaded. The following protocols are supported _http/https_, ftp. Null or empty \
81
- string value (the default setting) means the content of resulting file should \
82
- be encoded as Base64 and passed as the endpoint response value. An \
83
- exception will be thrown if the generated media file is too big to fit \
84
- into the available process memory.
85
-
86
- - ``username`` The name of the user for the remote authentication.
87
-
88
- - ``password`` The password for the remote authentication.
89
-
90
- - ``method`` The http multipart upload method name. The _PUT_ one is used by default.
91
-
92
- Example:
93
- | `Start Screen Recording` | | # starts a screen record session |
94
- | .... keyword actions | | |
95
- | `Stop Screen Recording` | filename=output | # saves the recorded session |
96
- """
97
- if self._recording is not None:
98
- self._recording = self._current_application().stop_recording_screen(**options)
99
- return self._save_recording(filename, options)
100
- else:
101
- raise RuntimeError("There is no Active Screen Record Session.")
102
-
103
- def _save_recording(self, filename, options):
104
- path, link = self._get_screenrecord_paths(options, filename)
105
- decoded = base64.b64decode(self._recording)
106
- with open(path, 'wb') as screenrecording:
107
- screenrecording.write(decoded)
108
- # Embed the Screen Recording to the log file
109
- # if the current platform is Android and no remotePath is set.
110
- if self._is_android() and not self._is_remotepath_set(options):
111
- self._html('</td></tr><tr><td colspan="3"><a href="{vid}">'
112
- '<video width="800px" controls>'
113
- '<source src="{vid}" type="video/mp4">'
114
- '</video></a>'.format(vid=link)
115
- )
116
- # Empty Screen Record Variable
117
- self._recording = None
118
- return path
119
-
120
- def _set_output_format(self):
121
- return '.ffmpeg' if self._is_ios() else '.mp4'
122
-
123
- def _get_screenrecord_paths(self, options, filename=None):
124
- if filename is None:
125
- self._screenrecord_index += 1
126
- filename = 'appium-screenrecord-{index}{ext}'.format(index=self._screenrecord_index,
127
- ext=self._output_format
128
- )
129
- else:
130
- filename = (filename.replace('/', os.sep)) + self._output_format
131
- logdir = options['remotePath'] if self._is_remotepath_set(options) \
132
- else self._get_log_dir()
133
- path = os.path.join(logdir, filename)
134
- link = robot.utils.get_link_path(path, logdir)
135
- return path, link
136
-
137
- def _is_remotepath_set(self, options):
138
- return True if 'remotePath' in options else False
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import base64
4
+ import os
5
+
6
+ import robot
7
+
8
+ from .keywordgroup import KeywordGroup
9
+
10
+
11
+ class _ScreenrecordKeywords(KeywordGroup):
12
+
13
+ def __init__(self):
14
+ self._screenrecord_index = 0
15
+ self._recording = None
16
+ self._output_format = None
17
+
18
+ def start_screen_recording(self,
19
+ timeLimit='180s',
20
+ **options):
21
+ """Starts an asynchronous Screen Recording for the current open application.
22
+
23
+ ``timeLimit`` sets the actual time limit of the recorded video.
24
+ - The default value for both iOS and Android is 180 seconds (3 minutes).
25
+ - The maximum value for Android is 3 minutes.
26
+ - The maximum value for iOS is 10 minutes.
27
+
28
+ === Optional Args ===
29
+
30
+ - ``bitRate`` (Android Only) The video bit rate for the video, in megabits per second.
31
+ 4 Mbp/s(4000000) is by default for Android API level below 27. \
32
+ 20 Mb/s(20000000) for API level 27 and above.
33
+
34
+ - ``videoSize`` (Android Only) The format is widthxheight. The default value is the \
35
+ device's native display resolution (if supported), 1280x720 if not. For best \
36
+ results, use a size supported by your device's Advanced Video Coding (AVC) \
37
+ encoder. For example, "1280x720"
38
+
39
+ - ``bugReport`` (Android Only) Set it to true in order to display additional \
40
+ information on the video overlay, such as a timestamp, that is helpful in \
41
+ videos captured to illustrate bugs. This option is only supported since \
42
+ API level 27 (Android O).
43
+
44
+ - ``videoQuality`` (iOS Only) The video encoding quality (low, medium, high, \
45
+ photo - defaults to medium).
46
+
47
+ - ``videoFps`` (iOS Only) The Frames Per Second rate of the recorded video. \
48
+ Change this value if the resulting video is too slow or too fast. Defaults to 10. \
49
+ This can decrease the resulting file size.
50
+
51
+ - ``videoScale`` (iOS Only) The scaling value to apply. Read \
52
+ https://trac.ffmpeg.org/wiki/Scaling for possible values. Example value of 720p \
53
+ scaling is '1280:720'. This can decrease/increase the resulting file size. \
54
+ No scale is applied by default.
55
+
56
+ `Start Screen Recording` is used hand in hand with `Stop Screen Recording`.
57
+ See `Stop Screen Recording` for more details.
58
+ Example:
59
+ | `Start Screen Recording` | | # starts a screen record session |
60
+ | .... keyword actions | | |
61
+ | `Stop Screen Recording` | filename=output | # saves the recorded session |
62
+ """
63
+ timeLimit = robot.utils.timestr_to_secs(timeLimit)
64
+ options['timeLimit'] = timeLimit
65
+ self._output_format = self._set_output_format() \
66
+ if self._output_format is None else self._output_format
67
+ if self._recording is None:
68
+ self._recording = self._current_application().start_recording_screen(**options)
69
+
70
+ def stop_screen_recording(self, filename=None, **options):
71
+ """Gathers the output from the previously started screen recording \
72
+ to a media file, then embeds it to the log.html(Android Only).
73
+
74
+ Requires an active or exhausted Screen Recording Session.
75
+ See `Start Screen Recording` for more details.
76
+
77
+ === Optional Args ===
78
+
79
+ - ``remotePath`` The path to the remote location, where the resulting video should be \
80
+ uploaded. The following protocols are supported _http/https_, ftp. Null or empty \
81
+ string value (the default setting) means the content of resulting file should \
82
+ be encoded as Base64 and passed as the endpoint response value. An \
83
+ exception will be thrown if the generated media file is too big to fit \
84
+ into the available process memory.
85
+
86
+ - ``username`` The name of the user for the remote authentication.
87
+
88
+ - ``password`` The password for the remote authentication.
89
+
90
+ - ``method`` The http multipart upload method name. The _PUT_ one is used by default.
91
+
92
+ Example:
93
+ | `Start Screen Recording` | | # starts a screen record session |
94
+ | .... keyword actions | | |
95
+ | `Stop Screen Recording` | filename=output | # saves the recorded session |
96
+ """
97
+ if self._recording is not None:
98
+ self._recording = self._current_application().stop_recording_screen(**options)
99
+ return self._save_recording(filename, options)
100
+ else:
101
+ raise RuntimeError("There is no Active Screen Record Session.")
102
+
103
+ def _save_recording(self, filename, options):
104
+ path, link = self._get_screenrecord_paths(options, filename)
105
+ decoded = base64.b64decode(self._recording)
106
+ with open(path, 'wb') as screenrecording:
107
+ screenrecording.write(decoded)
108
+ # Embed the Screen Recording to the log file
109
+ # if the current platform is Android and no remotePath is set.
110
+ if self._is_android() and not self._is_remotepath_set(options):
111
+ self._html('</td></tr><tr><td colspan="3"><a href="{vid}">'
112
+ '<video width="800px" controls>'
113
+ '<source src="{vid}" type="video/mp4">'
114
+ '</video></a>'.format(vid=link)
115
+ )
116
+ # Empty Screen Record Variable
117
+ self._recording = None
118
+ return path
119
+
120
+ def _set_output_format(self):
121
+ return '.ffmpeg' if self._is_ios() else '.mp4'
122
+
123
+ def _get_screenrecord_paths(self, options, filename=None):
124
+ if filename is None:
125
+ self._screenrecord_index += 1
126
+ filename = 'appium-screenrecord-{index}{ext}'.format(index=self._screenrecord_index,
127
+ ext=self._output_format
128
+ )
129
+ else:
130
+ filename = (filename.replace('/', os.sep)) + self._output_format
131
+ logdir = options['remotePath'] if self._is_remotepath_set(options) \
132
+ else self._get_log_dir()
133
+ path = os.path.join(logdir, filename)
134
+ link = robot.utils.get_link_path(path, logdir)
135
+ return path, link
136
+
137
+ def _is_remotepath_set(self, options):
138
+ return True if 'remotePath' in options else False
@@ -1,109 +1,105 @@
1
- # -*- coding: utf-8 -*-
2
-
3
- import os
4
- from base64 import b64decode
5
-
6
- import robot
7
-
8
- from .keywordgroup import KeywordGroup, ignore_on_fail
9
-
10
-
11
- class _ScreenshotKeywords(KeywordGroup):
12
-
13
- # Public
14
-
15
- def appium_get_element_screenshot(self, locator, timeout=20, filename=None):
16
- """
17
- Get a screenshot of element to base64
18
- If provide filename, saves a screenshot to a PNG image file.
19
-
20
- Parameters:
21
- -----------
22
- locator: Element locator
23
- timeout: timeout in second to find element
24
- filename : str
25
- - The full path you wish to save your screenshot to. This
26
- - should end with a `.png` extension.
27
-
28
- Example:
29
- --------
30
- >>> driver.get_screenshot_as_file("/Screenshots/foo.png")
31
- """
32
-
33
- element = self._invoke_original("appium_get_element", locator, timeout, False)
34
-
35
- if not element:
36
- self._info(f'Not found {locator}, return None')
37
- return None
38
-
39
- base64data = element.screenshot_as_base64
40
-
41
- if filename:
42
- if not str(filename).lower().endswith(".png"):
43
- self._info(
44
- "name used for saved screenshot does not match file type. It should end with a `.png` extension")
45
-
46
- png = b64decode(base64data.encode("ascii"))
47
- try:
48
- with open(filename, "wb") as f:
49
- f.write(png)
50
- except OSError:
51
- self._info(f'Fail to write screenshot file {filename}, return False')
52
- return False
53
- finally:
54
- del png
55
- return True
56
-
57
- return base64data
58
-
59
- @ignore_on_fail
60
- def appium_get_screenshot(self):
61
- return self._invoke_original("appium_capture_page_screenshot", None, False)
62
-
63
- def appium_capture_page_screenshot(self, filename=None, embed=True):
64
- try:
65
- return self._invoke_original("capture_page_screenshot", filename, embed)
66
- except Exception as err:
67
- self._info(err)
68
- return None
69
-
70
- def capture_page_screenshot(self, filename=None, embed=True):
71
- """Takes a screenshot of the current page and embeds it into the log.
72
-
73
- `filename` argument specifies the name of the file to write the
74
- screenshot into. If no `filename` is given, the screenshot will be
75
- embedded as Base64 image to the log.html. In this case no file is created in the filesystem.
76
-
77
- `embed` is True: the screenshot will be embedded to the log.html
78
-
79
- Warning: this behavior is new in 1.7. Previously if no filename was given
80
- the screenshots where stored as separate files named `appium-screenshot-<counter>.png`
81
- """
82
- if filename:
83
- path, link = self._get_screenshot_paths(filename)
84
-
85
- if hasattr(self._current_application(), 'get_screenshot_as_file'):
86
- self._current_application().get_screenshot_as_file(path)
87
- else:
88
- self._current_application().save_screenshot(path)
89
-
90
- # Image is shown on its own row and thus prev row is closed on purpose
91
- if embed:
92
- self._html('</td></tr><tr><td colspan="3"><a href="%s">'
93
- '<img src="%s" width="800px"></a>' % (link, link))
94
- return path
95
- else:
96
- base64_screenshot = self._current_application().get_screenshot_as_base64()
97
- if embed:
98
- self._html('</td></tr><tr><td colspan="3">'
99
- '<img src="data:image/png;base64, %s" width="800px">' % base64_screenshot)
100
- return None
101
-
102
- # Private
103
-
104
- def _get_screenshot_paths(self, filename):
105
- filename = filename.replace('/', os.sep)
106
- logdir = self._get_log_dir()
107
- path = os.path.join(logdir, filename)
108
- link = robot.utils.get_link_path(path, logdir)
109
- return path, link
1
+ # -*- coding: utf-8 -*-
2
+
3
+ import os
4
+ from base64 import b64decode
5
+
6
+ import robot
7
+
8
+ from .keywordgroup import KeywordGroup, ignore_on_fail
9
+
10
+
11
+ class _ScreenshotKeywords(KeywordGroup):
12
+
13
+ # Public
14
+
15
+ def appium_get_element_screenshot(self, locator, timeout=20, filename=None):
16
+ """
17
+ Get a screenshot of element to base64
18
+ If provide filename, saves a screenshot to a PNG image file.
19
+
20
+ Parameters:
21
+ -----------
22
+ locator: Element locator
23
+ timeout: timeout in second to find element
24
+ filename : str
25
+ - The full path you wish to save your screenshot to. This
26
+ - should end with a `.png` extension.
27
+
28
+ Example:
29
+ --------
30
+ >>> driver.get_screenshot_as_file("/Screenshots/foo.png")
31
+ """
32
+
33
+ element = self.appium_get_element(locator, timeout, False)
34
+
35
+ if not element:
36
+ self._info(f'Not found {locator}, return None')
37
+ return None
38
+
39
+ base64data = element.screenshot_as_base64
40
+
41
+ if filename:
42
+ if not str(filename).lower().endswith(".png"):
43
+ self._info("name used for saved screenshot does not match file type. It should end with a `.png` extension")
44
+
45
+ png = b64decode(base64data.encode("ascii"))
46
+ try:
47
+ with open(filename, "wb") as f:
48
+ f.write(png)
49
+ except OSError:
50
+ self._info(f'Fail to write screenshot file {filename}, return False')
51
+ return False
52
+ finally:
53
+ del png
54
+ return True
55
+
56
+ return base64data
57
+
58
+ @ignore_on_fail
59
+ def appium_get_screenshot(self):
60
+ return self.appium_capture_page_screenshot(None, False)
61
+
62
+ def appium_capture_page_screenshot(self, filename=None, embed=True):
63
+ try:
64
+ return self.capture_page_screenshot(filename, embed)
65
+ except Exception as err:
66
+ self._info(err)
67
+ return None
68
+
69
+ def capture_page_screenshot(self, filename=None, embed=True):
70
+ """Takes a screenshot of the current page and embeds it into the log.
71
+
72
+ `filename` argument specifies the name of the file to write the
73
+ screenshot into. If no `filename` is given, the screenshot will be
74
+ embedded as Base64 image to the log.html. In this case no file is created in the filesystem.
75
+
76
+ `embed` is True: the screenshot will be embedded to the log.html
77
+
78
+ Warning: this behavior is new in 1.7. Previously if no filename was given
79
+ the screenshots where stored as separate files named `appium-screenshot-<counter>.png`
80
+ """
81
+ if filename:
82
+ path, link = self._get_screenshot_paths(filename)
83
+
84
+ if hasattr(self._current_application(), 'get_screenshot_as_file'):
85
+ self._current_application().get_screenshot_as_file(path)
86
+ else:
87
+ self._current_application().save_screenshot(path)
88
+
89
+ # Image is shown on its own row and thus prev row is closed on purpose
90
+ if embed:
91
+ self._html('</td></tr><tr><td colspan="3"><a href="%s"><img src="%s" width="800px"></a>' % (link, link))
92
+ return path
93
+ else:
94
+ base64_screenshot = self._current_application().get_screenshot_as_base64()
95
+ if embed:
96
+ self._html('</td></tr><tr><td colspan="3"><img src="data:image/png;base64, %s" width="800px">' % base64_screenshot)
97
+ return None
98
+
99
+ # Private
100
+ def _get_screenshot_paths(self, filename):
101
+ filename = filename.replace('/', os.sep)
102
+ logdir = self._get_log_dir()
103
+ path = os.path.join(logdir, filename)
104
+ link = robot.utils.get_link_path(path, logdir)
105
+ return path, link