1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 'use strict'; 6 7 /** 8 * Test API for Chrome OS Image Editor. 9 * 10 * There are two ways to load Image Editor before testing: 11 * - open File Manager, and then click on an image file to open Image Editor; 12 * or 13 * - open tab with URL: 14 * chrome-extension://hhaomjibdihmijegdhdafkllkbggdgoj/gallery.html 15 * and then call |galleryTestAPI.load('/Downloads/path/to/file.jpg')|. 16 * 17 * After Image Editor is loaded, you can call methods from |galleryTestAPI| to 18 * emulate user actions and get feedback. 19 */ 20 var galleryTestAPI = { 21 /** 22 * Open the Photo Editor. 23 * @param {string} path Path to the directory or an image file. 24 */ 25 load: function(path) { 26 Gallery.openStandalone(path, null, function() { 27 galleryTestAPI.waitFor_('loaded'); 28 }); 29 }, 30 31 /** 32 * Responds with the selected file name. 33 */ 34 getSelectedFileName: function() { 35 galleryTestAPI.respond_(document.querySelector('.namebox').value); 36 }, 37 38 /** 39 * Toggles edit mode. 40 */ 41 clickEditToggle: function() { 42 galleryTestAPI.click('.edit'); 43 setTimeout(galleryTestAPI.respond_.bind(null, true), 0); 44 }, 45 46 /** 47 * Clicks arrow to select next image. 48 */ 49 clickNextImageArrow: function() { 50 galleryTestAPI.click('.arrow.right'); 51 galleryTestAPI.waitFor_('image-displayed'); 52 }, 53 54 /** 55 * Clicks arrow to select previous image. 56 */ 57 clickPreviousImageArrow: function() { 58 galleryTestAPI.click('.arrow.left'); 59 galleryTestAPI.waitFor_('image-displayed'); 60 }, 61 62 /** 63 * Clicks last thumbnail in ribbon to select an image. 64 */ 65 clickLastRibbonThumbnail: function() { 66 galleryTestAPI.clickRibbonThumbnail(true); 67 }, 68 69 /** 70 * Clicks first thumbnail in ribbon to select an image. 71 */ 72 clickFirstRibbonThumbnail: function() { 73 galleryTestAPI.clickRibbonThumbnail(false); 74 }, 75 76 /** 77 * Clicks thumbnail in ribbon. 78 * @param {boolean} last Whether to click on last vs first. 79 */ 80 clickRibbonThumbnail: function(last) { 81 // TODO(dgozman): investigate why this timeout is required sometimes. 82 setTimeout(function() { 83 var nodes = document.querySelectorAll('.ribbon > :not([vanishing])'); 84 if (nodes.length == 0) { 85 galleryTestAPI.respond_(false); 86 return; 87 } 88 nodes[last ? nodes.length - 1 : 0].click(); 89 galleryTestAPI.waitFor_('image-displayed'); 90 }, 0); 91 }, 92 93 /** 94 * Clicks 'rotate left' tool. 95 */ 96 clickRotateLeft: function() { 97 galleryTestAPI.editAndRespond_( 98 galleryTestAPI.click.bind(null, '.rotate_left')); 99 }, 100 101 /** 102 * Clicks 'rotate right' tool. 103 */ 104 clickRotateRight: function() { 105 galleryTestAPI.editAndRespond_( 106 galleryTestAPI.click.bind(null, '.rotate_right')); 107 }, 108 109 /** 110 * Clicks 'undo' tool. 111 */ 112 clickUndo: function() { 113 galleryTestAPI.editAndRespond_(galleryTestAPI.click.bind(null, '.undo')); 114 }, 115 116 /** 117 * Clicks 'redo' tool. 118 */ 119 clickRedo: function() { 120 galleryTestAPI.editAndRespond_(galleryTestAPI.click.bind(null, '.redo')); 121 }, 122 123 /** 124 * Clicks 'autofix' tool. 125 */ 126 clickAutofix: function() { 127 galleryTestAPI.editAndRespond_(galleryTestAPI.click.bind(null, '.autofix')); 128 }, 129 130 /** 131 * Responds whether autofix tool is available. 132 */ 133 isAutofixAvailable: function() { 134 galleryTestAPI.respond_( 135 !document.querySelector('.autofix').hasAttribute('disabled')); 136 }, 137 138 /** 139 * Performs a click on the element with specififc selector. 140 * @param {string} selector CSS selector. 141 */ 142 click: function(selector) { 143 document.querySelector(selector).click(); 144 }, 145 146 /** 147 * Waits until editor is ready, performs action and then responds. 148 * @param {function} action The action to perform. 149 * @private 150 */ 151 editAndRespond_: function(action) { 152 // TODO(dgozman): investigate why this is required sometimes. 153 setTimeout(function() { 154 action(); 155 galleryTestAPI.waitFor_('image-saved'); 156 }, 0); 157 }, 158 159 /** 160 * Waits for event fired and then calls a function. 161 * @param {string} event Event name. 162 * @param {function=} opt_callback Callback. If not passed, 163 * |galleryTestAPI.respond_(true)| is called. 164 * @private 165 */ 166 waitFor_: function(event, opt_callback) { 167 var callback = opt_callback || galleryTestAPI.respond_.bind(null, true); 168 var listener = function() { 169 Gallery.instance.removeEventListener(event, listener); 170 callback(); 171 }; 172 Gallery.instance.addEventListener(event, listener); 173 }, 174 175 /** 176 * @param {string|boolean|number} value Value to send back. 177 * @private 178 */ 179 respond_: function(value) { 180 if (window.domAutomationController) { 181 window.domAutomationController.send(value); 182 } else if (galleryTestAPI.respondCallback) { 183 galleryTestAPI.respondCallback(value); 184 } else { 185 console.log('playerTestAPI response: ' + value); 186 } 187 } 188 }; 189 190 /** 191 * Test example. 192 */ 193 galleryTestAPI.testExample = function() { 194 var api = galleryTestAPI; 195 var PATH = '/Downloads/file.jpg'; 196 197 var steps = [ 198 function load() { 199 if (!Gallery.instance) { 200 api.load(PATH); 201 } else { 202 nextStep(); 203 } 204 }, 205 206 function getName() { api.getSelectedFileName(); }, 207 208 function lastRibbon(filename) { 209 console.log(filename); 210 api.clickLastRibbonThumbnail(); 211 }, 212 213 function toggleEdit() { api.clickEditToggle(); }, 214 215 function rightArrow() { api.clickNextImageArrow(); }, 216 217 function rotateLeft() { api.clickRotateLeft(); }, 218 219 function rotateRight() { api.clickRotateRight(); }, 220 221 function undo() { api.clickUndo(); }, 222 223 function queryAutofix() { api.isAutofixAvailable(); }, 224 225 function autofix(available) { 226 if (available) { 227 api.clickAutofix(); 228 } else { 229 nextStep(); 230 } 231 }, 232 233 function done() { console.log('done'); } 234 ]; 235 236 var step = 0; 237 238 function nextStep() { 239 ++step; 240 console.log('nextStep calls: ' + steps[step - 1].name); 241 steps[step - 1].apply(null, arguments); 242 } 243 244 api.respondCallback = nextStep; 245 nextStep(); 246 }; 247