diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/core/document_transition/document_transition_test.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/core/document_transition/document_transition_test.cc | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/core/document_transition/document_transition_test.cc b/chromium/third_party/blink/renderer/core/document_transition/document_transition_test.cc new file mode 100644 index 00000000000..cd5262a4a08 --- /dev/null +++ b/chromium/third_party/blink/renderer/core/document_transition/document_transition_test.cc @@ -0,0 +1,259 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/document_transition/document_transition.h" + +#include "base/test/scoped_feature_list.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_document_transition_init.h" +#include "third_party/blink/renderer/core/document_transition/document_transition_supplement.h" +#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" + +namespace blink { + +class DocumentTransitionTest : public RenderingTest, + private ScopedDocumentTransitionForTest { + public: + DocumentTransitionTest() + : RenderingTest(MakeGarbageCollected<SingleChildLocalFrameClient>()), + ScopedDocumentTransitionForTest(true) {} + + void SetUp() override { + EnableCompositing(); + RenderingTest::SetUp(); + } + + // Testing the compositor interaction is not in scope for these unittests. So, + // instead of setting up a full commit flow, simulate it by calling the commit + // callback directly. + void UpdateAllLifecyclePhasesAndSimulateCommit() { + UpdateAllLifecyclePhasesForTest(); + for (auto& request : GetChromeClient() + .layer_tree_host() + ->TakeDocumentTransitionRequestsForTesting()) { + request->TakeCommitCallback().Run(); + } + } + + using State = DocumentTransition::State; + + State GetState(DocumentTransition* transition) const { + return transition->state_; + } +}; + +TEST_F(DocumentTransitionTest, TransitionObjectPersists) { + auto* first_transition = + DocumentTransitionSupplement::documentTransition(GetDocument()); + auto* second_transition = + DocumentTransitionSupplement::documentTransition(GetDocument()); + + EXPECT_TRUE(first_transition); + EXPECT_EQ(GetState(first_transition), State::kIdle); + EXPECT_TRUE(second_transition); + EXPECT_EQ(first_transition, second_transition); +} + +TEST_F(DocumentTransitionTest, TransitionPreparePromiseResolves) { + DocumentTransitionInit init; + auto* transition = + DocumentTransitionSupplement::documentTransition(GetDocument()); + ASSERT_TRUE(transition); + EXPECT_EQ(GetState(transition), State::kIdle); + + V8TestingScope v8_scope; + ScriptState* script_state = v8_scope.GetScriptState(); + + ScriptPromiseTester promise_tester(script_state, + transition->prepare(script_state, &init)); + + EXPECT_EQ(GetState(transition), State::kPreparing); + UpdateAllLifecyclePhasesAndSimulateCommit(); + promise_tester.WaitUntilSettled(); + + EXPECT_TRUE(promise_tester.IsFulfilled()); + EXPECT_EQ(GetState(transition), State::kPrepared); +} + +TEST_F(DocumentTransitionTest, AdditionalPrepareRejectsPreviousPromise) { + auto* transition = + DocumentTransitionSupplement::documentTransition(GetDocument()); + + V8TestingScope v8_scope; + ScriptState* script_state = v8_scope.GetScriptState(); + + DocumentTransitionInit init; + ScriptPromiseTester first_promise_tester( + script_state, transition->prepare(script_state, &init)); + EXPECT_EQ(GetState(transition), State::kPreparing); + + ScriptPromiseTester second_promise_tester( + script_state, transition->prepare(script_state, &init)); + EXPECT_EQ(GetState(transition), State::kPreparing); + + UpdateAllLifecyclePhasesAndSimulateCommit(); + first_promise_tester.WaitUntilSettled(); + second_promise_tester.WaitUntilSettled(); + + EXPECT_TRUE(first_promise_tester.IsRejected()); + EXPECT_TRUE(second_promise_tester.IsFulfilled()); + EXPECT_EQ(GetState(transition), State::kPrepared); +} + +TEST_F(DocumentTransitionTest, EffectParsing) { + // Test default init. + auto* transition = + DocumentTransitionSupplement::documentTransition(GetDocument()); + + V8TestingScope v8_scope; + ScriptState* script_state = v8_scope.GetScriptState(); + DocumentTransitionInit default_init; + transition->prepare(script_state, &default_init); + + auto request = transition->TakePendingRequest(); + ASSERT_TRUE(request); + + auto directive = request->ConstructDirective(); + EXPECT_EQ(directive.effect(), DocumentTransition::Request::Effect::kNone); + + // Test "explode" effect parsing. + DocumentTransitionInit explode_init; + explode_init.setRootTransition("explode"); + transition->prepare(script_state, &explode_init); + + request = transition->TakePendingRequest(); + ASSERT_TRUE(request); + + directive = request->ConstructDirective(); + EXPECT_EQ(directive.effect(), DocumentTransition::Request::Effect::kExplode); + + // Test invalid effect parsing. + DocumentTransitionInit invalid_init; + invalid_init.setRootTransition("invalid effect"); + transition->prepare(script_state, &invalid_init); + + request = transition->TakePendingRequest(); + ASSERT_TRUE(request); + + directive = request->ConstructDirective(); + EXPECT_EQ(directive.effect(), DocumentTransition::Request::Effect::kNone); +} + +TEST_F(DocumentTransitionTest, AdditionalPrepareAfterPreparedSucceeds) { + auto* transition = + DocumentTransitionSupplement::documentTransition(GetDocument()); + + V8TestingScope v8_scope; + ScriptState* script_state = v8_scope.GetScriptState(); + + DocumentTransitionInit init; + ScriptPromiseTester first_promise_tester( + script_state, transition->prepare(script_state, &init)); + EXPECT_EQ(GetState(transition), State::kPreparing); + + UpdateAllLifecyclePhasesAndSimulateCommit(); + first_promise_tester.WaitUntilSettled(); + EXPECT_TRUE(first_promise_tester.IsFulfilled()); + EXPECT_EQ(GetState(transition), State::kPrepared); + + ScriptPromiseTester second_promise_tester( + script_state, transition->prepare(script_state, &init)); + EXPECT_EQ(GetState(transition), State::kPreparing); + + UpdateAllLifecyclePhasesAndSimulateCommit(); + second_promise_tester.WaitUntilSettled(); + EXPECT_TRUE(second_promise_tester.IsFulfilled()); + EXPECT_EQ(GetState(transition), State::kPrepared); +} + +TEST_F(DocumentTransitionTest, TransitionCleanedUpBeforePromiseResolution) { + V8TestingScope v8_scope; + ScriptState* script_state = v8_scope.GetScriptState(); + + DocumentTransitionInit init; + ScriptPromiseTester tester( + script_state, + DocumentTransitionSupplement::documentTransition(GetDocument()) + ->prepare(script_state, &init)); + + // ActiveScriptWrappable should keep the transition alive. + ThreadState::Current()->CollectAllGarbageForTesting(); + + UpdateAllLifecyclePhasesAndSimulateCommit(); + tester.WaitUntilSettled(); + EXPECT_TRUE(tester.IsFulfilled()); +} + +TEST_F(DocumentTransitionTest, StartHasNoEffectUnlessPrepared) { + auto* transition = + DocumentTransitionSupplement::documentTransition(GetDocument()); + EXPECT_EQ(GetState(transition), State::kIdle); + EXPECT_FALSE(transition->TakePendingRequest()); + + transition->start(); + + EXPECT_EQ(GetState(transition), State::kIdle); + EXPECT_FALSE(transition->TakePendingRequest()); +} + +TEST_F(DocumentTransitionTest, StartAfterPrepare) { + auto* transition = + DocumentTransitionSupplement::documentTransition(GetDocument()); + + V8TestingScope v8_scope; + ScriptState* script_state = v8_scope.GetScriptState(); + + DocumentTransitionInit init; + ScriptPromiseTester prepare_tester(script_state, + transition->prepare(script_state, &init)); + EXPECT_EQ(GetState(transition), State::kPreparing); + + UpdateAllLifecyclePhasesAndSimulateCommit(); + prepare_tester.WaitUntilSettled(); + EXPECT_TRUE(prepare_tester.IsFulfilled()); + EXPECT_EQ(GetState(transition), State::kPrepared); + + transition->start(); + EXPECT_EQ(GetState(transition), State::kStarted); + + // Take the request. + EXPECT_TRUE(transition->TakePendingRequest()); + + // Subsequent starts should not do anything. + transition->start(); + EXPECT_EQ(GetState(transition), State::kStarted); + EXPECT_FALSE(transition->TakePendingRequest()); +} + +TEST_F(DocumentTransitionTest, StartIsPropagated) { + auto* transition = + DocumentTransitionSupplement::documentTransition(GetDocument()); + + V8TestingScope v8_scope; + ScriptState* script_state = v8_scope.GetScriptState(); + + DocumentTransitionInit init; + ScriptPromiseTester prepare_tester(script_state, + transition->prepare(script_state, &init)); + EXPECT_EQ(GetState(transition), State::kPreparing); + + UpdateAllLifecyclePhasesAndSimulateCommit(); + prepare_tester.WaitUntilSettled(); + EXPECT_TRUE(prepare_tester.IsFulfilled()); + EXPECT_EQ(GetState(transition), State::kPrepared); + + transition->start(); + + EXPECT_EQ(GetState(transition), State::kStarted); + UpdateAllLifecyclePhasesAndSimulateCommit(); + + // TODO(vmpstr): This test relies on the fact that the commit callback will + // switch the state to kIdle. Long term, the state should only switch to + // kStarted here, and have a separate callback for when the transition is + // finished. When that happens, the expectations of this test should change. + EXPECT_EQ(GetState(transition), State::kIdle); +} + +} // namespace blink |