1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 package org.mozilla.gecko.tests.components; 6 7 import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertEquals; 8 import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertFalse; 9 import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertNotNull; 10 import static org.mozilla.gecko.tests.helpers.AssertionHelper.fAssertTrue; 11 12 import org.mozilla.gecko.R; 13 import org.mozilla.gecko.tests.UITestContext; 14 import org.mozilla.gecko.tests.helpers.DeviceHelper; 15 import org.mozilla.gecko.tests.helpers.NavigationHelper; 16 import org.mozilla.gecko.tests.helpers.WaitHelper; 17 import org.mozilla.gecko.toolbar.PageActionLayout; 18 19 import android.view.View; 20 import android.widget.EditText; 21 import android.widget.ImageButton; 22 import android.widget.TextView; 23 24 import com.robotium.solo.Condition; 25 import com.robotium.solo.Solo; 26 27 /** 28 * A class representing any interactions that take place on the Toolbar. 29 */ 30 public class ToolbarComponent extends BaseComponent { 31 32 private static final String URL_HTTP_PREFIX = "http://"; 33 34 // We are waiting up to 30 seconds instead of the default waiting time because reader mode 35 // parsing can take quite some time on slower devices (Bug 1142699) 36 private static final int READER_MODE_WAIT_MS = 30000; 37 ToolbarComponent(final UITestContext testContext)38 public ToolbarComponent(final UITestContext testContext) { 39 super(testContext); 40 } 41 assertIsEditing()42 public ToolbarComponent assertIsEditing() { 43 fAssertTrue("The toolbar is in the editing state", isEditing()); 44 return this; 45 } 46 assertIsNotEditing()47 public ToolbarComponent assertIsNotEditing() { 48 fAssertFalse("The toolbar is not in the editing state", isEditing()); 49 return this; 50 } 51 assertTitle(final String url)52 public ToolbarComponent assertTitle(final String url) { 53 fAssertNotNull("The url argument is not null", url); 54 55 final String expected; 56 final String absoluteURL = NavigationHelper.adjustUrl(url); 57 58 if (mStringHelper.ABOUT_HOME_URL.equals(absoluteURL)) { 59 expected = mStringHelper.ABOUT_HOME_TITLE; 60 } else if (absoluteURL.startsWith(URL_HTTP_PREFIX)) { 61 expected = absoluteURL.substring(URL_HTTP_PREFIX.length()); 62 } else { 63 expected = absoluteURL; 64 } 65 66 // Since we only display a shortened "base domain" (See bug 1236431) we use the content 67 // description to obtain the full URL. 68 fAssertEquals("The Toolbar title is " + expected, expected, getUrlFromContentDescription()); 69 return this; 70 } 71 assertUrl(final String expected)72 public ToolbarComponent assertUrl(final String expected) { 73 assertIsEditing(); 74 fAssertEquals("The Toolbar url is " + expected, expected, getUrlEditText().getText()); 75 return this; 76 } 77 assertIsUrlEditTextSelected()78 public ToolbarComponent assertIsUrlEditTextSelected() { 79 fAssertTrue("The edit text is selected", isUrlEditTextSelected()); 80 return this; 81 } 82 assertIsUrlEditTextNotSelected()83 public ToolbarComponent assertIsUrlEditTextNotSelected() { 84 fAssertFalse("The edit text is not selected", isUrlEditTextSelected()); 85 return this; 86 } 87 assertBackButtonIsNotEnabled()88 public ToolbarComponent assertBackButtonIsNotEnabled() { 89 fAssertFalse("The back button is not enabled", isBackButtonEnabled()); 90 return this; 91 } 92 93 /** 94 * Returns the root View for the browser toolbar. 95 */ getToolbarView()96 private View getToolbarView() { 97 mSolo.waitForView(R.id.browser_toolbar); 98 return mSolo.getView(R.id.browser_toolbar); 99 } 100 getUrlEditText()101 private EditText getUrlEditText() { 102 return (EditText) getToolbarView().findViewById(R.id.url_edit_text); 103 } 104 getUrlDisplayLayout()105 private View getUrlDisplayLayout() { 106 return getToolbarView().findViewById(R.id.display_layout); 107 } 108 getUrlTitleText()109 private TextView getUrlTitleText() { 110 return (TextView) getToolbarView().findViewById(R.id.url_bar_title); 111 } 112 getBackButton()113 private ImageButton getBackButton() { 114 DeviceHelper.assertIsTablet(); 115 return (ImageButton) getToolbarView().findViewById(R.id.back); 116 } 117 getForwardButton()118 private ImageButton getForwardButton() { 119 DeviceHelper.assertIsTablet(); 120 return (ImageButton) getToolbarView().findViewById(R.id.forward); 121 } 122 getReloadButton()123 private ImageButton getReloadButton() { 124 DeviceHelper.assertIsTablet(); 125 return (ImageButton) getToolbarView().findViewById(R.id.reload); 126 } 127 getPageActionLayout()128 private PageActionLayout getPageActionLayout() { 129 return (PageActionLayout) getToolbarView().findViewById(R.id.page_action_layout); 130 } 131 getReaderModeButton()132 private ImageButton getReaderModeButton() { 133 final PageActionLayout pageActionLayout = getPageActionLayout(); 134 final int count = pageActionLayout.getChildCount(); 135 136 for (int i = 0; i < count; i++) { 137 final View view = pageActionLayout.getChildAt(i); 138 if (mStringHelper.CONTENT_DESCRIPTION_READER_MODE_BUTTON.equals(view.getContentDescription())) { 139 return (ImageButton) view; 140 } 141 } 142 143 return null; 144 } 145 146 /** 147 * Returns the View for the edit cancel button in the browser toolbar. 148 */ getEditCancelButton()149 private View getEditCancelButton() { 150 return getToolbarView().findViewById(R.id.edit_cancel); 151 } 152 getUrlFromContentDescription()153 private String getUrlFromContentDescription() { 154 assertIsNotEditing(); 155 156 final CharSequence contentDescription = getUrlDisplayLayout().getContentDescription(); 157 if (contentDescription == null) { 158 return ""; 159 } else { 160 return contentDescription.toString(); 161 } 162 } 163 164 /** 165 * Returns the title of the page. Note that this makes no assertions to Toolbar state and 166 * may return a value that may never be visible to the user. Callers likely want to use 167 * {@link assertTitle} instead. 168 */ getPotentiallyInconsistentTitle()169 public String getPotentiallyInconsistentTitle() { 170 return getTitleHelper(false); 171 } 172 getTitleHelper(final boolean shouldAssertNotEditing)173 private String getTitleHelper(final boolean shouldAssertNotEditing) { 174 if (shouldAssertNotEditing) { 175 assertIsNotEditing(); 176 } 177 178 return getUrlTitleText().getText().toString(); 179 } 180 isEditing()181 private boolean isEditing() { 182 return getUrlDisplayLayout().getVisibility() != View.VISIBLE && 183 getUrlEditText().getVisibility() == View.VISIBLE; 184 } 185 enterEditingMode()186 public ToolbarComponent enterEditingMode() { 187 assertIsNotEditing(); 188 189 mSolo.clickOnView(getUrlTitleText(), true); 190 191 waitForEditing(); 192 WaitHelper.waitFor("UrlEditText to be input method target", new Condition() { 193 @Override 194 public boolean isSatisfied() { 195 return getUrlEditText().isInputMethodTarget(); 196 } 197 }); 198 199 return this; 200 } 201 commitEditingMode()202 public ToolbarComponent commitEditingMode() { 203 assertIsEditing(); 204 205 WaitHelper.waitForPageLoad(new Runnable() { 206 @Override 207 public void run() { 208 mSolo.sendKey(Solo.ENTER); 209 } 210 }); 211 waitForNotEditing(); 212 213 return this; 214 } 215 dismissEditingMode()216 public ToolbarComponent dismissEditingMode() { 217 assertIsEditing(); 218 219 if (DeviceHelper.isTablet()) { 220 final EditText urlEditText = getUrlEditText(); 221 if (urlEditText.isFocused()) { 222 mSolo.goBack(); 223 } 224 mSolo.goBack(); 225 } else { 226 mSolo.clickOnView(getEditCancelButton()); 227 } 228 229 waitForNotEditing(); 230 231 return this; 232 } 233 enterUrl(final String url)234 public ToolbarComponent enterUrl(final String url) { 235 fAssertNotNull("url is not null", url); 236 237 assertIsEditing(); 238 239 final EditText urlEditText = getUrlEditText(); 240 fAssertTrue("The UrlEditText is the input method target", 241 urlEditText.isInputMethodTarget()); 242 243 mSolo.clearEditText(urlEditText); 244 mSolo.typeText(urlEditText, url); 245 246 return this; 247 } 248 pressBackButton()249 public ToolbarComponent pressBackButton() { 250 final ImageButton backButton = getBackButton(); 251 return pressButton(backButton, "back"); 252 } 253 pressForwardButton()254 public ToolbarComponent pressForwardButton() { 255 final ImageButton forwardButton = getForwardButton(); 256 return pressButton(forwardButton, "forward"); 257 } 258 pressReloadButton()259 public ToolbarComponent pressReloadButton() { 260 final ImageButton reloadButton = getReloadButton(); 261 return pressButton(reloadButton, "reload"); 262 } 263 pressReaderModeButton()264 public ToolbarComponent pressReaderModeButton() { 265 final ImageButton readerModeButton = waitForReaderModeButton(); 266 pressButton(readerModeButton, "reader mode"); 267 268 return this; 269 } 270 pressButton(final View view, final String buttonName)271 private ToolbarComponent pressButton(final View view, final String buttonName) { 272 fAssertNotNull("The " + buttonName + " button View is not null", view); 273 fAssertTrue("The " + buttonName + " button is enabled", view.isEnabled()); 274 fAssertEquals("The " + buttonName + " button is visible", 275 View.VISIBLE, view.getVisibility()); 276 assertIsNotEditing(); 277 278 WaitHelper.waitForPageLoad(new Runnable() { 279 @Override 280 public void run() { 281 mSolo.clickOnView(view); 282 } 283 }); 284 285 return this; 286 } 287 waitForEditing()288 private void waitForEditing() { 289 WaitHelper.waitFor("Toolbar to enter editing mode", new Condition() { 290 @Override 291 public boolean isSatisfied() { 292 return isEditing(); 293 } 294 }); 295 } 296 waitForNotEditing()297 private void waitForNotEditing() { 298 WaitHelper.waitFor("Toolbar to exit editing mode", new Condition() { 299 @Override 300 public boolean isSatisfied() { 301 return !isEditing(); 302 } 303 }); 304 } 305 waitForReaderModeButton()306 private ImageButton waitForReaderModeButton() { 307 final ImageButton[] readerModeButton = new ImageButton[1]; 308 309 WaitHelper.waitFor("the Reader mode button to be visible", new Condition() { 310 @Override 311 public boolean isSatisfied() { 312 return (readerModeButton[0] = getReaderModeButton()) != null; 313 } 314 }, READER_MODE_WAIT_MS); 315 316 return readerModeButton[0]; 317 } 318 isUrlEditTextSelected()319 private boolean isUrlEditTextSelected() { 320 return getUrlEditText().isSelected(); 321 } 322 isBackButtonEnabled()323 private boolean isBackButtonEnabled() { 324 return getBackButton().isEnabled(); 325 } 326 } 327