closes #150 - added Casper.captureBase64()
Showing
5 changed files
with
122 additions
and
12 deletions
... | @@ -17,6 +17,7 @@ XXXX-XX-XX, v1.0 | ... | @@ -17,6 +17,7 @@ XXXX-XX-XX, v1.0 |
17 | - added [`Casper.userAgent()`](http://casperjs.org/api.html#casper.userAgent) to ease a more dynamic setting of user-agent string | 17 | - added [`Casper.userAgent()`](http://casperjs.org/api.html#casper.userAgent) to ease a more dynamic setting of user-agent string |
18 | - added [`Tester.assertTitleMatch()`](http://casperjs.org/api.html#tester.assertTitleMatch) method | 18 | - added [`Tester.assertTitleMatch()`](http://casperjs.org/api.html#tester.assertTitleMatch) method |
19 | - added [`utils.getPropertyPath()`](http://casperjs.org/api.html#utils.getPropertyPath) | 19 | - added [`utils.getPropertyPath()`](http://casperjs.org/api.html#utils.getPropertyPath) |
20 | - added [`Casper.captureBase64()`](http://casperjs.org/api.html#casper.captureBase64) for rendering screen captures as base64 strings - closes [#150](https://github.com/n1k0/casperjs/issues/150) | ||
20 | - added [`Casper.reload()`](http://casperjs.org/api.html#casper.reload) | 21 | - added [`Casper.reload()`](http://casperjs.org/api.html#casper.reload) |
21 | - added experimental support of custom headers sending in outgoing request (refs [#137](https://github.com/n1k0/casperjs/issues/137) - PhantomJS 1.6 required) | 22 | - added experimental support of custom headers sending in outgoing request (refs [#137](https://github.com/n1k0/casperjs/issues/137) - PhantomJS 1.6 required) |
22 | - switched to more standard `.textContent` property to get a node text; this allows a better compatibility of the clientutils bookmarklet with non-webkit browsers | 23 | - switched to more standard `.textContent` property to get a node text; this allows a better compatibility of the clientutils bookmarklet with non-webkit browsers | ... | ... |
... | @@ -246,7 +246,47 @@ Casper.prototype.capture = function capture(targetFile, clipRect) { | ... | @@ -246,7 +246,47 @@ Casper.prototype.capture = function capture(targetFile, clipRect) { |
246 | }; | 246 | }; |
247 | 247 | ||
248 | /** | 248 | /** |
249 | * Captures the page area containing the provided selector. | 249 | * Returns a Base64 representation of a binary image capture of the current |
250 | * page, or an area within the page, in a given format. | ||
251 | * | ||
252 | * Supported image formats are `bmp`, `jpg`, `jpeg`, `png`, `ppm`, `tiff`, | ||
253 | * `xbm` and `xpm`. | ||
254 | * | ||
255 | * @param String format The image format | ||
256 | * @param String|Object|undefined selector CSS3 selector or clipRect object (optional) | ||
257 | * @return Casper | ||
258 | */ | ||
259 | Casper.prototype.captureBase64 = function captureBase64(format, area) { | ||
260 | "use strict"; | ||
261 | var base64; | ||
262 | var previousClipRect; | ||
263 | var formats = ['bmp', 'jpg', 'jpeg', 'png', 'ppm', 'tiff', 'xbm', 'xpm']; | ||
264 | if (formats.indexOf(format.toLowerCase()) === -1) { | ||
265 | throw new CasperError(f('Unsupported format "%s"', format)); | ||
266 | } | ||
267 | if (utils.isClipRect(area)) { | ||
268 | // if area is a clipRect object | ||
269 | this.log(f("Capturing base64 %s representation of %s", format, utils.serialize(area)), "debug"); | ||
270 | previousClipRect = this.page.clipRect; | ||
271 | this.page.clipRect = area; | ||
272 | base64 = this.page.renderBase64(format); | ||
273 | } else if (utils.isValidSelector(area)) { | ||
274 | // if area is a selector string or object | ||
275 | this.log(f("Capturing base64 %s representation of %s", format, area), "debug"); | ||
276 | base64 = this.captureBase64(format, this.getElementBounds(area)); | ||
277 | } else { | ||
278 | // whole page capture | ||
279 | this.log(f("Capturing base64 %s representation of page", format), "debug"); | ||
280 | base64 = this.page.renderBase64(format); | ||
281 | } | ||
282 | if (previousClipRect) { | ||
283 | this.page.clipRect = previousClipRect; | ||
284 | } | ||
285 | return base64; | ||
286 | }; | ||
287 | |||
288 | /** | ||
289 | * Captures the page area matching the provided selector. | ||
250 | * | 290 | * |
251 | * @param String targetFile Target destination file path. | 291 | * @param String targetFile Target destination file path. |
252 | * @param String selector CSS3 selector | 292 | * @param String selector CSS3 selector | ... | ... |
... | @@ -57,7 +57,7 @@ | ... | @@ -57,7 +57,7 @@ |
57 | * @param Mixed value | 57 | * @param Mixed value |
58 | */ | 58 | */ |
59 | function dump(value) { | 59 | function dump(value) { |
60 | console.log(serialize(value)); | 60 | console.log(serialize(value, 4)); |
61 | } | 61 | } |
62 | exports.dump = dump; | 62 | exports.dump = dump; |
63 | 63 | ||
... | @@ -304,6 +304,39 @@ | ... | @@ -304,6 +304,39 @@ |
304 | exports.isUndefined = isUndefined; | 304 | exports.isUndefined = isUndefined; |
305 | 305 | ||
306 | /** | 306 | /** |
307 | * Checks if value is a valid selector Object. | ||
308 | * | ||
309 | * @param mixed value | ||
310 | * @return Boolean | ||
311 | */ | ||
312 | function isValidSelector(value) { | ||
313 | if (isString(value)) { | ||
314 | try { | ||
315 | // phantomjs env has a working document object, let's use it | ||
316 | document.querySelector(value); | ||
317 | } catch(e) { | ||
318 | if ('name' in e && e.name === 'SYNTAX_ERR') { | ||
319 | return false; | ||
320 | } | ||
321 | } | ||
322 | return true; | ||
323 | } else if (isObject(value)) { | ||
324 | if (!value.hasOwnProperty('type')) { | ||
325 | return false; | ||
326 | } | ||
327 | if (!value.hasOwnProperty('path')) { | ||
328 | return false; | ||
329 | } | ||
330 | if (['css', 'xpath'].indexOf(value.type) === -1) { | ||
331 | return false; | ||
332 | } | ||
333 | return true; | ||
334 | } | ||
335 | return false; | ||
336 | } | ||
337 | exports.isValidSelector = isValidSelector; | ||
338 | |||
339 | /** | ||
307 | * Checks if the provided var is a WebPage instance | 340 | * Checks if the provided var is a WebPage instance |
308 | * | 341 | * |
309 | * @param mixed what | 342 | * @param mixed what |
... | @@ -362,13 +395,13 @@ | ... | @@ -362,13 +395,13 @@ |
362 | * @param Mixed value | 395 | * @param Mixed value |
363 | * @return String | 396 | * @return String |
364 | */ | 397 | */ |
365 | function serialize(value) { | 398 | function serialize(value, indent) { |
366 | if (isArray(value)) { | 399 | if (isArray(value)) { |
367 | value = value.map(function _map(prop) { | 400 | value = value.map(function _map(prop) { |
368 | return isFunction(prop) ? prop.toString().replace(/\s{2,}/, '') : prop; | 401 | return isFunction(prop) ? prop.toString().replace(/\s{2,}/, '') : prop; |
369 | }); | 402 | }); |
370 | } | 403 | } |
371 | return JSON.stringify(value, null, 4); | 404 | return JSON.stringify(value, null, indent); |
372 | } | 405 | } |
373 | exports.serialize = serialize; | 406 | exports.serialize = serialize; |
374 | 407 | ... | ... |
... | @@ -4,17 +4,26 @@ if (fs.exists(testFile) && fs.isFile(testFile)) { | ... | @@ -4,17 +4,26 @@ if (fs.exists(testFile) && fs.isFile(testFile)) { |
4 | fs.remove(testFile); | 4 | fs.remove(testFile); |
5 | } | 5 | } |
6 | 6 | ||
7 | casper.start('tests/site/index.html', function(self) { | 7 | casper.start('tests/site/index.html', function() { |
8 | self.viewport(300, 200); | 8 | this.viewport(300, 200); |
9 | this.test.comment('Casper.capture()'); | 9 | this.test.comment('Casper.capture()'); |
10 | self.capture(testFile); | 10 | this.capture(testFile); |
11 | this.test.assert(fs.isFile(testFile), 'Casper.capture() captured a screenshot'); | 11 | this.test.assert(fs.isFile(testFile), 'Casper.capture() captured a screenshot'); |
12 | }); | 12 | }); |
13 | 13 | ||
14 | try { | 14 | casper.thenOpen('tests/site/index.html', function() { |
15 | fs.remove(testFile); | 15 | this.test.comment('Casper.captureBase64()'); |
16 | } catch(e) {} | 16 | this.test.assert(this.captureBase64('png').length > 0, |
17 | 'Casper.captureBase64() rendered a page capture as base64'); | ||
18 | this.test.assert(this.captureBase64('png', 'ul').length > 0, | ||
19 | 'Casper.captureBase64() rendered a capture from a selector as base64'); | ||
20 | this.test.assert(this.captureBase64('png', {top: 0, left: 0, width: 30, height: 30}).length > 0, | ||
21 | 'Casper.captureBase64() rendered a capture from a clipRect as base64'); | ||
22 | }); | ||
17 | 23 | ||
18 | casper.run(function(self) { | 24 | casper.run(function() { |
25 | try { | ||
26 | fs.remove(testFile); | ||
27 | } catch(e) {} | ||
19 | this.test.done(); | 28 | this.test.done(); |
20 | }); | 29 | }); | ... | ... |
1 | var utils = require('utils'), t = casper.test; | 1 | var utils = require('utils'), t = casper.test, x = require('casper').selectXPath; |
2 | 2 | ||
3 | t.comment('fileExt()'); | 3 | t.comment('fileExt()'); |
4 | (function() { | 4 | (function() { |
... | @@ -100,6 +100,33 @@ t.comment('isObject()'); | ... | @@ -100,6 +100,33 @@ t.comment('isObject()'); |
100 | t.assertEquals(utils.isObject(null), false, 'isObject() checks for an Object'); | 100 | t.assertEquals(utils.isObject(null), false, 'isObject() checks for an Object'); |
101 | })(); | 101 | })(); |
102 | 102 | ||
103 | t.comment('isValidSelector()'); | ||
104 | (function() { | ||
105 | t.assertEquals(utils.isValidSelector({}), false, 'isValidSelector() checks for a valid selector'); | ||
106 | t.assertEquals(utils.isValidSelector(""), false, 'isValidSelector() checks for a valid selector'); | ||
107 | t.assertEquals(utils.isValidSelector("a"), true, 'isValidSelector() checks for a valid selector'); | ||
108 | t.assertEquals(utils.isValidSelector('div#plop form[name="form"] input[type="submit"]'), true, 'isValidSelector() checks for a valid selector'); | ||
109 | t.assertEquals(utils.isValidSelector(x('//a')), true, 'isValidSelector() checks for a valid selector'); | ||
110 | t.assertEquals(utils.isValidSelector({ | ||
111 | type: "css", | ||
112 | path: 'div#plop form[name="form"] input[type="submit"]' | ||
113 | }), true, 'isValidSelector() checks for a valid selector'); | ||
114 | t.assertEquals(utils.isValidSelector({ | ||
115 | type: "xpath", | ||
116 | path: '//a' | ||
117 | }), true, 'isValidSelector() checks for a valid selector'); | ||
118 | t.assertEquals(utils.isValidSelector({ | ||
119 | type: "css" | ||
120 | }), false, 'isValidSelector() checks for a valid selector'); | ||
121 | t.assertEquals(utils.isValidSelector({ | ||
122 | type: "xpath" | ||
123 | }), false, 'isValidSelector() checks for a valid selector'); | ||
124 | t.assertEquals(utils.isValidSelector({ | ||
125 | type: "css3", | ||
126 | path: "a" | ||
127 | }), false, 'isValidSelector() checks for a valid selector'); | ||
128 | })(); | ||
129 | |||
103 | t.comment('isWebPage()'); | 130 | t.comment('isWebPage()'); |
104 | (function() { | 131 | (function() { |
105 | var pageModule = require('webpage'); | 132 | var pageModule = require('webpage'); | ... | ... |
-
Please register or sign in to post a comment