Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(321)

Side by Side Diff: third_party/WebKit/Source/core/dom/ElementTest.cpp

Issue 2647533002: Force compositing inputs to be clean for getBoundingClientRect (Closed)
Patch Set: Finish new ElementTest test, address reviewer comments Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "core/dom/Element.h" 5 #include "core/dom/Element.h"
6 6
7 #include "core/dom/Document.h" 7 #include "core/dom/Document.h"
8 #include "core/frame/FrameView.h" 8 #include "core/frame/FrameView.h"
9 #include "core/html/HTMLHtmlElement.h" 9 #include "core/html/HTMLHtmlElement.h"
10 #include "core/layout/LayoutBoxModelObject.h"
11 #include "core/paint/PaintLayer.h"
10 #include "core/testing/DummyPageHolder.h" 12 #include "core/testing/DummyPageHolder.h"
11 #include "testing/gtest/include/gtest/gtest.h" 13 #include "testing/gtest/include/gtest/gtest.h"
12 #include <memory> 14 #include <memory>
13 15
14 namespace blink { 16 namespace blink {
15 17
16 TEST(ElementTest, SupportsFocus) { 18 TEST(ElementTest, SupportsFocus) {
17 std::unique_ptr<DummyPageHolder> pageHolder = DummyPageHolder::create(); 19 std::unique_ptr<DummyPageHolder> pageHolder = DummyPageHolder::create();
18 Document& document = pageHolder->document(); 20 Document& document = pageHolder->document();
19 DCHECK(isHTMLHtmlElement(document.documentElement())); 21 DCHECK(isHTMLHtmlElement(document.documentElement()));
20 document.setDesignMode("on"); 22 document.setDesignMode("on");
21 document.view()->updateAllLifecyclePhases(); 23 document.view()->updateAllLifecyclePhases();
22 EXPECT_TRUE(document.documentElement()->supportsFocus()) 24 EXPECT_TRUE(document.documentElement()->supportsFocus())
23 << "<html> with designMode=on should be focusable."; 25 << "<html> with designMode=on should be focusable.";
24 } 26 }
25 27
28 // Verifies that calling getBoundingClientRect cleans compositor inputs.
29 // Cleaning the compositor inputs is required so that position:sticky elements
30 // and their descendants have the correct location.
31 TEST(ElementTest, GetBoundingClientRectUpdatesCompositorInputs) {
32 std::unique_ptr<DummyPageHolder> pageHolder = DummyPageHolder::create();
33 Document& document = pageHolder->document();
34
35 document.view()->updateAllLifecyclePhases();
36 EXPECT_EQ(DocumentLifecycle::PaintClean, document.lifecycle().state());
37
38 document.body()->setInnerHTML("<div id='test'></div>");
39 EXPECT_EQ(DocumentLifecycle::VisualUpdatePending,
40 document.lifecycle().state());
41
42 document.body()->getBoundingClientRect();
43 EXPECT_EQ(DocumentLifecycle::CompositingClean, document.lifecycle().state());
44 }
45
46 // Verifies that calling scrollIntoView* cleans compositor inputs. Cleaning the
47 // compositor inputs is required so that position:sticky elements and their
48 // descendants have the correct location.
49 TEST(ElementTest, ScrollIntoViewUpdatesCompositorInputs) {
50 std::unique_ptr<DummyPageHolder> pageHolder = DummyPageHolder::create();
51 Document& document = pageHolder->document();
52
53 document.view()->updateAllLifecyclePhases();
54 EXPECT_EQ(DocumentLifecycle::PaintClean, document.lifecycle().state());
55
56 document.body()->setInnerHTML("<div id='test'></div>");
57 EXPECT_EQ(DocumentLifecycle::VisualUpdatePending,
58 document.lifecycle().state());
59
60 document.body()->scrollIntoView();
61 EXPECT_EQ(DocumentLifecycle::CompositingClean, document.lifecycle().state());
62
63 document.body()->setInnerHTML("<div id='test2'></div>");
64 EXPECT_EQ(DocumentLifecycle::VisualUpdatePending,
65 document.lifecycle().state());
66
67 document.body()->scrollIntoViewIfNeeded();
68 EXPECT_EQ(DocumentLifecycle::CompositingClean, document.lifecycle().state());
69 }
70
71 // Verifies that calling offsetTop/offsetLeft cleans compositor inputs.
72 // Cleaning the compositor inputs is required so that position:sticky elements
73 // and their descendants have the correct location.
74 TEST(ElementTest, OffsetTopAndLeftUpdateCompositorInputs) {
75 std::unique_ptr<DummyPageHolder> pageHolder = DummyPageHolder::create();
76 Document& document = pageHolder->document();
77
78 document.view()->updateAllLifecyclePhases();
79 EXPECT_EQ(DocumentLifecycle::PaintClean, document.lifecycle().state());
80
81 document.body()->setInnerHTML("<div id='test'></div>");
82 EXPECT_EQ(DocumentLifecycle::VisualUpdatePending,
83 document.lifecycle().state());
84
85 document.body()->offsetTop();
86 EXPECT_EQ(DocumentLifecycle::CompositingClean, document.lifecycle().state());
87
88 document.body()->setInnerHTML("<div id='test2'></div>");
89 EXPECT_EQ(DocumentLifecycle::VisualUpdatePending,
90 document.lifecycle().state());
91
92 document.body()->offsetLeft();
93 EXPECT_EQ(DocumentLifecycle::CompositingClean, document.lifecycle().state());
94 }
95
96 TEST(ElementTest, OffsetTopAndLeftCorrectForStickyElementsAfterInsertion) {
97 std::unique_ptr<DummyPageHolder> pageHolder = DummyPageHolder::create();
98 Document& document = pageHolder->document();
99
100 document.body()->setInnerHTML(
101 "<style>body { margin: 0 }"
102 "#scroller { overflow: scroll; height: 100px; width: 100px; }"
103 "#sticky { height: 25px; position: sticky; top: 0; left: 25px }"
flackr 2017/01/24 22:47:16 nit: semicolon after 25px
smcgruer 2017/01/25 20:51:57 Done.
104 "#padding { height: 500px; width: 300px; }</style>"
105 "<div id='scroller'><div id='writer'></div><div id='sticky'></div>"
106 "<div id='padding'></div></div>");
107 document.view()->updateAllLifecyclePhases();
108
109 Element* scroller = document.getElementById("scroller");
110 Element* writer = document.getElementById("writer");
111 Element* sticky = document.getElementById("sticky");
112
113 ASSERT_TRUE(scroller);
114 ASSERT_TRUE(writer);
115 ASSERT_TRUE(sticky);
116
117 scroller->scrollTo(0, 200.0);
118
119 // After scrolling, the position:sticky element should be offset to stay at
120 // the top of the viewport.
121 EXPECT_EQ(scroller->scrollTop(), sticky->offsetTop());
122
123 // Insert a new <div> above the sticky. This will dirty layout.
124 writer->setInnerHTML("<div style='height: 100px;'></div>");
125 EXPECT_EQ(DocumentLifecycle::VisualUpdatePending,
126 document.lifecycle().state());
127
128 // Querying the new position of the sticky should now cause both layout and
129 // compositing inputs to be clean and should return the correct position.
130 // Additionally, repeated calls to offsetTop should give the same value.
131 int offsetTop = sticky->offsetTop();
132 EXPECT_EQ(DocumentLifecycle::CompositingClean, document.lifecycle().state());
133 EXPECT_FALSE(
134 sticky->layoutBoxModelObject()->layer()->needsCompositingInputsUpdate());
135 EXPECT_EQ(scroller->scrollTop(), sticky->offsetTop());
136 EXPECT_EQ(offsetTop, sticky->offsetTop());
flackr 2017/01/24 22:47:16 Hm, I'm not sure what case I was worried about wit
smcgruer 2017/01/25 20:51:57 Ok, removed.
137
138 scroller->scrollTo(50.0, 0);
139
140 // After scrolling, the position:sticky element should be offset to stay 25
141 // pixels from the left of the viewport.
142 EXPECT_EQ(scroller->scrollLeft() + 25, sticky->offsetLeft());
143
144 // Insert a new <div> above the sticky. This will dirty layout.
145 writer->setInnerHTML("<div style='width: 700px;'></div>");
146 EXPECT_EQ(DocumentLifecycle::VisualUpdatePending,
147 document.lifecycle().state());
148
149 // Again, querying the position should cause layout and compositing clean, and
150 // should return the correct position repeatedly.
151 int offsetLeft = sticky->offsetLeft();
152 EXPECT_EQ(DocumentLifecycle::CompositingClean, document.lifecycle().state());
153 EXPECT_FALSE(
154 sticky->layoutBoxModelObject()->layer()->needsCompositingInputsUpdate());
155 EXPECT_EQ(scroller->scrollLeft() + 25, sticky->offsetLeft());
156 EXPECT_EQ(offsetLeft, sticky->offsetLeft());
157 }
158
26 } // namespace blink 159 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698