| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/memory/ptr_util.h" | 5 #include "base/memory/ptr_util.h" |
| 6 #include "base/strings/string_number_conversions.h" | 6 #include "base/strings/string_number_conversions.h" |
| 7 #include "base/strings/sys_string_conversions.h" | 7 #include "base/strings/sys_string_conversions.h" |
| 8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
| 9 #include "base/test/ios/wait_util.h" | 9 #import "ios/testing/wait_util.h" |
| 10 #import "ios/web/navigation/navigation_item_impl.h" | 10 #import "ios/web/navigation/navigation_item_impl.h" |
| 11 #import "ios/web/public/navigation_item.h" | 11 #import "ios/web/public/navigation_item.h" |
| 12 #import "ios/web/public/navigation_manager.h" | 12 #import "ios/web/public/navigation_manager.h" |
| 13 #import "ios/web/public/test/http_server.h" | 13 #import "ios/web/public/test/http_server.h" |
| 14 #include "ios/web/public/test/http_server_util.h" | 14 #include "ios/web/public/test/http_server_util.h" |
| 15 #import "ios/web/public/test/web_view_interaction_test_util.h" | 15 #import "ios/web/public/test/web_view_interaction_test_util.h" |
| 16 #import "ios/web/public/web_state/web_state.h" | 16 #import "ios/web/public/web_state/web_state.h" |
| 17 #import "ios/web/test/web_int_test.h" | 17 #import "ios/web/test/web_int_test.h" |
| 18 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
| 19 #include "testing/gtest_mac.h" | 19 #include "testing/gtest_mac.h" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 41 // Button IDs used in the window.location test page. | 41 // Button IDs used in the window.location test page. |
| 42 const char kPushStateId[] = "push-state"; | 42 const char kPushStateId[] = "push-state"; |
| 43 const char kReplaceStateId[] = "replace-state"; | 43 const char kReplaceStateId[] = "replace-state"; |
| 44 | 44 |
| 45 // JavaScript functions on the history state test page. | 45 // JavaScript functions on the history state test page. |
| 46 NSString* const kUpdateStateParamsScriptFormat = | 46 NSString* const kUpdateStateParamsScriptFormat = |
| 47 @"updateStateParams('%s', '%s', '%s')"; | 47 @"updateStateParams('%s', '%s', '%s')"; |
| 48 NSString* const kOnLoadCheckScript = @"isOnLoadPlaceholderTextVisible()"; | 48 NSString* const kOnLoadCheckScript = @"isOnLoadPlaceholderTextVisible()"; |
| 49 NSString* const kNoOpCheckScript = @"isNoOpPlaceholderTextVisible()"; | 49 NSString* const kNoOpCheckScript = @"isNoOpPlaceholderTextVisible()"; |
| 50 | 50 |
| 51 // Wait timeout for state updates. |
| 52 const NSTimeInterval kWaitForStateUpdateTimeout = 2.0; |
| 53 |
| 51 } // namespace | 54 } // namespace |
| 52 | 55 |
| 53 // Test fixture for integration tests involving html5 window.history state | 56 // Test fixture for integration tests involving html5 window.history state |
| 54 // operations. | 57 // operations. |
| 55 class HistoryStateOperationsTest : public web::WebIntTest { | 58 class HistoryStateOperationsTest : public web::WebIntTest { |
| 56 protected: | 59 protected: |
| 57 void SetUp() override { | 60 void SetUp() override { |
| 58 web::WebIntTest::SetUp(); | 61 web::WebIntTest::SetUp(); |
| 59 | 62 |
| 60 // History state tests use file-based test pages. | 63 // History state tests use file-based test pages. |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 103 return [ExecuteJavaScript(kOnLoadCheckScript) boolValue]; | 106 return [ExecuteJavaScript(kOnLoadCheckScript) boolValue]; |
| 104 } | 107 } |
| 105 | 108 |
| 106 // Executes JavaScript to check whether the no-op text is visible. | 109 // Executes JavaScript to check whether the no-op text is visible. |
| 107 bool IsNoOpTextVisible() { | 110 bool IsNoOpTextVisible() { |
| 108 return [ExecuteJavaScript(kNoOpCheckScript) boolValue]; | 111 return [ExecuteJavaScript(kNoOpCheckScript) boolValue]; |
| 109 } | 112 } |
| 110 | 113 |
| 111 // Waits for the NoOp text to be visible. | 114 // Waits for the NoOp text to be visible. |
| 112 void WaitForNoOpText() { | 115 void WaitForNoOpText() { |
| 113 base::test::ios::WaitUntilCondition(^bool { | 116 BOOL completed = testing::WaitUntilConditionOrTimeout( |
| 114 return IsNoOpTextVisible(); | 117 testing::kWaitForJSCompletionTimeout, ^{ |
| 115 }); | 118 return IsNoOpTextVisible(); |
| 119 }); |
| 120 EXPECT_TRUE(completed) << "NoOp text failed to be visible."; |
| 116 } | 121 } |
| 117 | 122 |
| 118 private: | 123 private: |
| 119 GURL state_operations_url_; | 124 GURL state_operations_url_; |
| 120 }; | 125 }; |
| 121 | 126 |
| 122 // Tests that calling window.history.pushState() is a no-op for unresolvable | 127 // Tests that calling window.history.pushState() is a no-op for unresolvable |
| 123 // URLs. | 128 // URLs. |
| 124 TEST_F(HistoryStateOperationsTest, NoOpPushUnresolvable) { | 129 TEST_F(HistoryStateOperationsTest, NoOpPushUnresolvable) { |
| 125 // Perform a window.history.pushState() with an unresolvable URL. This will | 130 // Perform a window.history.pushState() with an unresolvable URL. This will |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 navigation_manager()->GoBack(); | 245 navigation_manager()->GoBack(); |
| 241 }); | 246 }); |
| 242 EXPECT_EQ(state_operations_url(), GetLastCommittedItem()->GetURL()); | 247 EXPECT_EQ(state_operations_url(), GetLastCommittedItem()->GetURL()); |
| 243 // Set up the state parameters and tap the replace state button. | 248 // Set up the state parameters and tap the replace state button. |
| 244 std::string empty_state; | 249 std::string empty_state; |
| 245 std::string new_title("NEW TITLE"); | 250 std::string new_title("NEW TITLE"); |
| 246 GURL empty_url; | 251 GURL empty_url; |
| 247 SetStateParams(empty_state, new_title, empty_url); | 252 SetStateParams(empty_state, new_title, empty_url); |
| 248 ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kReplaceStateId)); | 253 ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kReplaceStateId)); |
| 249 // Wait for the title to be reflected in the NavigationItem. | 254 // Wait for the title to be reflected in the NavigationItem. |
| 250 base::test::ios::WaitUntilCondition(^bool { | 255 BOOL completed = |
| 251 return GetLastCommittedItem()->GetTitle() == ASCIIToUTF16(new_title); | 256 testing::WaitUntilConditionOrTimeout(kWaitForStateUpdateTimeout, ^{ |
| 252 }); | 257 return GetLastCommittedItem()->GetTitle() == ASCIIToUTF16(new_title); |
| 258 }); |
| 259 EXPECT_TRUE(completed) << "Failed to validate NavigationItem title."; |
| 253 // Verify that the forward navigation was not pruned. | 260 // Verify that the forward navigation was not pruned. |
| 254 EXPECT_EQ(GetIndexOfNavigationItem(GetLastCommittedItem()) + 1, | 261 EXPECT_EQ(GetIndexOfNavigationItem(GetLastCommittedItem()) + 1, |
| 255 GetIndexOfNavigationItem(about_blank_item)); | 262 GetIndexOfNavigationItem(about_blank_item)); |
| 256 } | 263 } |
| 257 | 264 |
| 258 // Tests that calling window.history.replaceState() with a new state object | 265 // Tests that calling window.history.replaceState() with a new state object |
| 259 // replaces the state object for the current NavigationItem. | 266 // replaces the state object for the current NavigationItem. |
| 260 TEST_F(HistoryStateOperationsTest, StateReplacement) { | 267 TEST_F(HistoryStateOperationsTest, StateReplacement) { |
| 261 // Navigate to about:blank then navigate back to the test page. The created | 268 // Navigate to about:blank then navigate back to the test page. The created |
| 262 // NavigationItem can be used later to verify that the state is replaced | 269 // NavigationItem can be used later to verify that the state is replaced |
| 263 // rather than pushed. | 270 // rather than pushed. |
| 264 GURL about_blank("about:blank"); | 271 GURL about_blank("about:blank"); |
| 265 LoadUrl(about_blank); | 272 LoadUrl(about_blank); |
| 266 web::NavigationItem* about_blank_item = GetLastCommittedItem(); | 273 web::NavigationItem* about_blank_item = GetLastCommittedItem(); |
| 267 ExecuteBlockAndWaitForLoad(state_operations_url(), ^{ | 274 ExecuteBlockAndWaitForLoad(state_operations_url(), ^{ |
| 268 navigation_manager()->GoBack(); | 275 navigation_manager()->GoBack(); |
| 269 }); | 276 }); |
| 270 ASSERT_EQ(state_operations_url(), GetLastCommittedItem()->GetURL()); | 277 ASSERT_EQ(state_operations_url(), GetLastCommittedItem()->GetURL()); |
| 271 // Set up the state parameters and tap the replace state button. | 278 // Set up the state parameters and tap the replace state button. |
| 272 std::string new_state("STATE OBJECT"); | 279 std::string new_state("STATE OBJECT"); |
| 273 std::string empty_title; | 280 std::string empty_title; |
| 274 GURL empty_url; | 281 GURL empty_url; |
| 275 SetStateParams(new_state, empty_title, empty_url); | 282 SetStateParams(new_state, empty_title, empty_url); |
| 276 ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kReplaceStateId)); | 283 ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kReplaceStateId)); |
| 277 // Verify that the state is reflected in the JavaScript context. | 284 // Verify that the state is reflected in the JavaScript context. |
| 278 base::test::ios::WaitUntilCondition(^bool { | 285 BOOL verify_java_script_context_completed = |
| 279 return GetJavaScriptState() == new_state; | 286 testing::WaitUntilConditionOrTimeout( |
| 280 }); | 287 testing::kWaitForJSCompletionTimeout, ^{ |
| 288 return GetJavaScriptState() == new_state; |
| 289 }); |
| 290 EXPECT_TRUE(verify_java_script_context_completed) |
| 291 << "Failed to validate JavaScript state."; |
| 281 // Verify that the state is reflected in the latest NavigationItem. | 292 // Verify that the state is reflected in the latest NavigationItem. |
| 282 std::string serialized_state("\"STATE OBJECT\""); | 293 std::string serialized_state("\"STATE OBJECT\""); |
| 283 base::test::ios::WaitUntilCondition(^bool { | 294 BOOL verify_navigation_item_completed = |
| 284 web::NavigationItemImpl* item = | 295 testing::WaitUntilConditionOrTimeout(kWaitForStateUpdateTimeout, ^{ |
| 285 static_cast<web::NavigationItemImpl*>(GetLastCommittedItem()); | 296 web::NavigationItemImpl* item = |
| 286 std::string item_state = | 297 static_cast<web::NavigationItemImpl*>(GetLastCommittedItem()); |
| 287 base::SysNSStringToUTF8(item->GetSerializedStateObject()); | 298 std::string item_state = |
| 288 return item_state == serialized_state; | 299 base::SysNSStringToUTF8(item->GetSerializedStateObject()); |
| 289 }); | 300 return item_state == serialized_state; |
| 301 }); |
| 302 EXPECT_TRUE(verify_navigation_item_completed) |
| 303 << "Failed to validate NavigationItem state."; |
| 290 // Verify that the forward navigation was not pruned. | 304 // Verify that the forward navigation was not pruned. |
| 291 EXPECT_EQ(GetIndexOfNavigationItem(GetLastCommittedItem()) + 1, | 305 EXPECT_EQ(GetIndexOfNavigationItem(GetLastCommittedItem()) + 1, |
| 292 GetIndexOfNavigationItem(about_blank_item)); | 306 GetIndexOfNavigationItem(about_blank_item)); |
| 293 } | 307 } |
| 294 | 308 |
| 295 // Tests that the state object is reset to the correct value after reloading a | 309 // Tests that the state object is reset to the correct value after reloading a |
| 296 // page whose state has been replaced. | 310 // page whose state has been replaced. |
| 297 TEST_F(HistoryStateOperationsTest, StateReplacementReload) { | 311 TEST_F(HistoryStateOperationsTest, StateReplacementReload) { |
| 298 // Set up the state parameters and tap the replace state button. | 312 // Set up the state parameters and tap the replace state button. |
| 299 std::string new_state("STATE OBJECT"); | 313 std::string new_state("STATE OBJECT"); |
| 300 std::string empty_title; | 314 std::string empty_title; |
| 301 GURL empty_url; | 315 GURL empty_url; |
| 302 SetStateParams(new_state, empty_title, empty_url); | 316 SetStateParams(new_state, empty_title, empty_url); |
| 303 ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kReplaceStateId)); | 317 ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kReplaceStateId)); |
| 304 // Reload the page and check that the state object is present. | 318 // Reload the page and check that the state object is present. |
| 305 Reload(); | 319 Reload(); |
| 306 ASSERT_TRUE(IsOnLoadTextVisible()); | 320 ASSERT_TRUE(IsOnLoadTextVisible()); |
| 307 base::test::ios::WaitUntilCondition(^bool { | 321 BOOL completed = testing::WaitUntilConditionOrTimeout( |
| 308 return GetJavaScriptState() == new_state; | 322 testing::kWaitForJSCompletionTimeout, ^{ |
| 309 }); | 323 return GetJavaScriptState() == new_state; |
| 324 }); |
| 325 EXPECT_TRUE(completed) << "Failed to validate JavaScript state."; |
| 310 } | 326 } |
| 311 | 327 |
| 312 // Tests that the state object is correctly set for a page after a back/forward | 328 // Tests that the state object is correctly set for a page after a back/forward |
| 313 // navigation. | 329 // navigation. |
| 314 TEST_F(HistoryStateOperationsTest, StateReplacementBackForward) { | 330 TEST_F(HistoryStateOperationsTest, StateReplacementBackForward) { |
| 315 // Navigate to about:blank then navigate back to the test page. The created | 331 // Navigate to about:blank then navigate back to the test page. The created |
| 316 // NavigationItem can be used later to verify that the state is replaced | 332 // NavigationItem can be used later to verify that the state is replaced |
| 317 // rather than pushed. | 333 // rather than pushed. |
| 318 GURL about_blank("about:blank"); | 334 GURL about_blank("about:blank"); |
| 319 LoadUrl(about_blank); | 335 LoadUrl(about_blank); |
| 320 ExecuteBlockAndWaitForLoad(state_operations_url(), ^{ | 336 ExecuteBlockAndWaitForLoad(state_operations_url(), ^{ |
| 321 navigation_manager()->GoBack(); | 337 navigation_manager()->GoBack(); |
| 322 }); | 338 }); |
| 323 ASSERT_EQ(state_operations_url(), GetLastCommittedItem()->GetURL()); | 339 ASSERT_EQ(state_operations_url(), GetLastCommittedItem()->GetURL()); |
| 324 // Set up the state parameters and tap the replace state button. | 340 // Set up the state parameters and tap the replace state button. |
| 325 std::string new_state("STATE OBJECT"); | 341 std::string new_state("STATE OBJECT"); |
| 326 std::string empty_title(""); | 342 std::string empty_title(""); |
| 327 GURL empty_url(""); | 343 GURL empty_url(""); |
| 328 SetStateParams(new_state, empty_title, empty_url); | 344 SetStateParams(new_state, empty_title, empty_url); |
| 329 ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kReplaceStateId)); | 345 ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kReplaceStateId)); |
| 330 // Go forward and back, then check that the state object is present. | 346 // Go forward and back, then check that the state object is present. |
| 331 ExecuteBlockAndWaitForLoad(about_blank, ^{ | 347 ExecuteBlockAndWaitForLoad(about_blank, ^{ |
| 332 navigation_manager()->GoForward(); | 348 navigation_manager()->GoForward(); |
| 333 }); | 349 }); |
| 334 ExecuteBlockAndWaitForLoad(state_operations_url(), ^{ | 350 ExecuteBlockAndWaitForLoad(state_operations_url(), ^{ |
| 335 navigation_manager()->GoBack(); | 351 navigation_manager()->GoBack(); |
| 336 }); | 352 }); |
| 337 ASSERT_TRUE(IsOnLoadTextVisible()); | 353 ASSERT_TRUE(IsOnLoadTextVisible()); |
| 338 base::test::ios::WaitUntilCondition(^bool { | 354 BOOL completed = testing::WaitUntilConditionOrTimeout( |
| 339 return GetJavaScriptState() == new_state; | 355 testing::kWaitForJSCompletionTimeout, ^{ |
| 340 }); | 356 return GetJavaScriptState() == new_state; |
| 357 }); |
| 358 EXPECT_TRUE(completed) << "Failed to validate JavaScript state."; |
| 341 } | 359 } |
| 342 | 360 |
| 343 // Tests that calling window.history.pushState() creates a new NavigationItem | 361 // Tests that calling window.history.pushState() creates a new NavigationItem |
| 344 // and prunes trailing items. | 362 // and prunes trailing items. |
| 345 TEST_F(HistoryStateOperationsTest, PushState) { | 363 TEST_F(HistoryStateOperationsTest, PushState) { |
| 346 // Navigate to about:blank then navigate back to the test page. The created | 364 // Navigate to about:blank then navigate back to the test page. The created |
| 347 // NavigationItem can be used later to verify that the state is replaced | 365 // NavigationItem can be used later to verify that the state is replaced |
| 348 // rather than pushed. | 366 // rather than pushed. |
| 349 GURL about_blank("about:blank"); | 367 GURL about_blank("about:blank"); |
| 350 LoadUrl(about_blank); | 368 LoadUrl(about_blank); |
| 351 web::NavigationItem* about_blank_item = GetLastCommittedItem(); | 369 web::NavigationItem* about_blank_item = GetLastCommittedItem(); |
| 352 ExecuteBlockAndWaitForLoad(state_operations_url(), ^{ | 370 ExecuteBlockAndWaitForLoad(state_operations_url(), ^{ |
| 353 navigation_manager()->GoBack(); | 371 navigation_manager()->GoBack(); |
| 354 }); | 372 }); |
| 355 ASSERT_EQ(state_operations_url(), GetLastCommittedItem()->GetURL()); | 373 ASSERT_EQ(state_operations_url(), GetLastCommittedItem()->GetURL()); |
| 356 web::NavigationItem* non_pushed_item = GetLastCommittedItem(); | 374 web::NavigationItem* non_pushed_item = GetLastCommittedItem(); |
| 357 // Set up the state parameters and tap the replace state button. | 375 // Set up the state parameters and tap the replace state button. |
| 358 std::string empty_state; | 376 std::string empty_state; |
| 359 std::string empty_title; | 377 std::string empty_title; |
| 360 GURL new_url = state_operations_url().Resolve("path"); | 378 GURL new_url = state_operations_url().Resolve("path"); |
| 361 SetStateParams(empty_state, empty_title, new_url); | 379 SetStateParams(empty_state, empty_title, new_url); |
| 362 ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kPushStateId)); | 380 ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kPushStateId)); |
| 363 // Verify that the url with the path is pushed. | 381 // Verify that the url with the path is pushed. |
| 364 base::test::ios::WaitUntilCondition(^bool { | 382 BOOL completed = |
| 365 return GetLastCommittedItem()->GetURL() == new_url; | 383 testing::WaitUntilConditionOrTimeout(kWaitForStateUpdateTimeout, ^{ |
| 366 }); | 384 return GetLastCommittedItem()->GetURL() == new_url; |
| 385 }); |
| 386 EXPECT_TRUE(completed) << "Failed to validate current url."; |
| 367 // Verify that a new NavigationItem was created and that the forward item was | 387 // Verify that a new NavigationItem was created and that the forward item was |
| 368 // pruned. | 388 // pruned. |
| 369 EXPECT_EQ(GetIndexOfNavigationItem(non_pushed_item) + 1, | 389 EXPECT_EQ(GetIndexOfNavigationItem(non_pushed_item) + 1, |
| 370 GetIndexOfNavigationItem(GetLastCommittedItem())); | 390 GetIndexOfNavigationItem(GetLastCommittedItem())); |
| 371 EXPECT_EQ(NSNotFound, GetIndexOfNavigationItem(about_blank_item)); | 391 EXPECT_EQ(NSNotFound, GetIndexOfNavigationItem(about_blank_item)); |
| 372 } | 392 } |
| 373 | 393 |
| 374 // Tests that performing a replaceState() on a page created with a POST request | 394 // Tests that performing a replaceState() on a page created with a POST request |
| 375 // resets the page to a GET request. | 395 // resets the page to a GET request. |
| 376 TEST_F(HistoryStateOperationsTest, ReplaceStatePostRequest) { | 396 TEST_F(HistoryStateOperationsTest, ReplaceStatePostRequest) { |
| 377 // Add POST data to the current NavigationItem. | 397 // Add POST data to the current NavigationItem. |
| 378 base::scoped_nsobject<NSData> post_data([NSData data]); | 398 base::scoped_nsobject<NSData> post_data([NSData data]); |
| 379 static_cast<web::NavigationItemImpl*>(GetLastCommittedItem()) | 399 static_cast<web::NavigationItemImpl*>(GetLastCommittedItem()) |
| 380 ->SetPostData(post_data); | 400 ->SetPostData(post_data); |
| 381 ASSERT_TRUE(GetLastCommittedItem()->HasPostData()); | 401 ASSERT_TRUE(GetLastCommittedItem()->HasPostData()); |
| 382 // Set up the state parameters and tap the replace state button. | 402 // Set up the state parameters and tap the replace state button. |
| 383 std::string new_state("STATE OBJECT"); | 403 std::string new_state("STATE OBJECT"); |
| 384 std::string empty_title; | 404 std::string empty_title; |
| 385 GURL new_url = state_operations_url().Resolve("path"); | 405 GURL new_url = state_operations_url().Resolve("path"); |
| 386 SetStateParams(new_state, empty_title, new_url); | 406 SetStateParams(new_state, empty_title, new_url); |
| 387 ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kReplaceStateId)); | 407 ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kReplaceStateId)); |
| 388 // Verify that url has been replaced. | 408 // Verify that url has been replaced. |
| 389 base::test::ios::WaitUntilCondition(^bool { | 409 BOOL completed = |
| 390 return GetLastCommittedItem()->GetURL() == new_url; | 410 testing::WaitUntilConditionOrTimeout(kWaitForStateUpdateTimeout, ^{ |
| 391 }); | 411 return GetLastCommittedItem()->GetURL() == new_url; |
| 412 }); |
| 413 EXPECT_TRUE(completed) << "Failed to validate current url."; |
| 392 // Verify that the NavigationItem no longer has POST data. | 414 // Verify that the NavigationItem no longer has POST data. |
| 393 EXPECT_FALSE(GetLastCommittedItem()->HasPostData()); | 415 EXPECT_FALSE(GetLastCommittedItem()->HasPostData()); |
| 394 } | 416 } |
| 395 | 417 |
| 396 // Tests that performing a replaceState() on a page where only the URL fragment | 418 // Tests that performing a replaceState() on a page where only the URL fragment |
| 397 // is updated does not trigger a hashchange event. | 419 // is updated does not trigger a hashchange event. |
| 398 TEST_F(HistoryStateOperationsTest, ReplaceStateNoHashChangeEvent) { | 420 TEST_F(HistoryStateOperationsTest, ReplaceStateNoHashChangeEvent) { |
| 399 // Set up the state parameters and tap the replace state button. | 421 // Set up the state parameters and tap the replace state button. |
| 400 std::string empty_state; | 422 std::string empty_state; |
| 401 std::string empty_title; | 423 std::string empty_title; |
| 402 GURL new_url = state_operations_url().Resolve("#hash"); | 424 GURL new_url = state_operations_url().Resolve("#hash"); |
| 403 SetStateParams(empty_state, empty_title, new_url); | 425 SetStateParams(empty_state, empty_title, new_url); |
| 404 ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kReplaceStateId)); | 426 ASSERT_TRUE(web::test::TapWebViewElementWithId(web_state(), kReplaceStateId)); |
| 405 // Verify that url has been replaced. | 427 // Verify that url has been replaced. |
| 406 base::test::ios::WaitUntilCondition(^bool { | 428 BOOL completed = |
| 407 return GetLastCommittedItem()->GetURL() == new_url; | 429 testing::WaitUntilConditionOrTimeout(kWaitForStateUpdateTimeout, ^{ |
| 408 }); | 430 return GetLastCommittedItem()->GetURL() == new_url; |
| 431 }); |
| 432 EXPECT_TRUE(completed) << "Failed to validate current url."; |
| 409 // Verify that the hashchange event was not fired. | 433 // Verify that the hashchange event was not fired. |
| 410 EXPECT_FALSE(static_cast<web::NavigationItemImpl*>(GetLastCommittedItem()) | 434 EXPECT_FALSE(static_cast<web::NavigationItemImpl*>(GetLastCommittedItem()) |
| 411 ->IsCreatedFromHashChange()); | 435 ->IsCreatedFromHashChange()); |
| 412 } | 436 } |
| OLD | NEW |