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

Side by Side Diff: third_party/WebKit/Source/core/layout/ScrollAnchorTest.cpp

Issue 2250523003: Implement SANACLAP (http://bit.ly/sanaclap). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: improve comment Created 4 years, 4 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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/layout/ScrollAnchor.h" 5 #include "core/layout/ScrollAnchor.h"
6 6
7 #include "core/dom/ClientRect.h" 7 #include "core/dom/ClientRect.h"
8 #include "core/frame/VisualViewport.h" 8 #include "core/frame/VisualViewport.h"
9 #include "core/layout/LayoutBox.h" 9 #include "core/layout/LayoutBox.h"
10 #include "core/layout/LayoutTestHelper.h" 10 #include "core/layout/LayoutTestHelper.h"
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
302 " body { height: 3500px }" 302 " body { height: 3500px }"
303 " #div {" 303 " #div {"
304 " position: relative; background-color: pink;" 304 " position: relative; background-color: pink;"
305 " top: 5px; left: 5px; width: 100px; height: 3500px;" 305 " top: 5px; left: 5px; width: 100px; height: 3500px;"
306 " }" 306 " }"
307 " #inline { padding-left: 10px }" 307 " #inline { padding-left: 10px }"
308 "</style>" 308 "</style>"
309 "<div id='div'>" 309 "<div id='div'>"
310 " <a id='inline'>text</a>" 310 " <a id='inline'>text</a>"
311 " <p id='block'>Some text</p>" 311 " <p id='block'>Some text</p>"
312 "</div>"); 312 "</div>"
313 "<div id=a>after</div>");
313 314
314 ScrollableArea* viewport = layoutViewport(); 315 ScrollableArea* viewport = layoutViewport();
315 Element* inlineElem = document().getElementById("inline"); 316 Element* inlineElem = document().getElementById("inline");
316 EXPECT_TRUE(inlineElem->layoutObject()->parent()->isAnonymous()); 317 EXPECT_TRUE(inlineElem->layoutObject()->parent()->isAnonymous());
317 318
318 // Scroll #div into view, making anonymous block a viable candidate. 319 // Scroll #div into view, making anonymous block a viable candidate.
319 document().getElementById("div")->scrollIntoView(); 320 document().getElementById("div")->scrollIntoView();
320 321
321 // Trigger layout and verify that we don't anchor to the anonymous block. 322 // Trigger layout and verify that we don't anchor to the anonymous block.
322 document().getElementById("div")->setAttribute(HTMLNames::styleAttr, 323 setHeight(document().getElementById("a"), 100);
323 AtomicString("top: 6px"));
324 update(); 324 update();
325 EXPECT_EQ(inlineElem->layoutObject()->slowFirstChild(), 325 EXPECT_EQ(inlineElem->layoutObject()->slowFirstChild(),
326 scrollAnchor(viewport).anchorObject()); 326 scrollAnchor(viewport).anchorObject());
327 } 327 }
328 328
329 TEST_F(ScrollAnchorTest, FullyContainedInlineBlock) 329 TEST_F(ScrollAnchorTest, FullyContainedInlineBlock)
330 { 330 {
331 // Exercises every WalkStatus value: 331 // Exercises every WalkStatus value:
332 // html, body -> Constrain 332 // html, body -> Constrain
333 // #outer -> Continue 333 // #outer -> Continue
334 // #ib1, br -> Skip 334 // #ib1, br -> Skip
335 // #ib2 -> Return 335 // #ib2 -> Return
336 setBodyInnerHTML( 336 setBodyInnerHTML(
337 "<style>" 337 "<style>"
338 " body { height: 1000px }" 338 " body { height: 1000px }"
339 " #outer { line-height: 100px }" 339 " #outer { line-height: 100px }"
340 " #ib1, #ib2 { display: inline-block }" 340 " #ib1, #ib2 { display: inline-block }"
341 "</style>" 341 "</style>"
342 "<span id=outer>" 342 "<span id=outer>"
343 " <span id=ib1>abc</span>" 343 " <span id=ib1>abc</span>"
344 " <br><br>" 344 " <br><br>"
345 " <span id=ib2>def</span>" 345 " <span id=ib2>def</span>"
346 "</span>"); 346 "</span>");
347 347
348 scrollLayoutViewport(DoubleSize(0, 150)); 348 scrollLayoutViewport(DoubleSize(0, 150));
349 349
350 Element* ib2 = document().getElementById("ib2"); 350 Element* ib1 = document().getElementById("ib1");
351 ib2->setAttribute(HTMLNames::styleAttr, "line-height: 150px"); 351 ib1->setAttribute(HTMLNames::styleAttr, "line-height: 150px");
352 update(); 352 update();
353 EXPECT_EQ(ib2->layoutObject(), scrollAnchor(layoutViewport()).anchorObject() ); 353 EXPECT_EQ(document().getElementById("ib2")->layoutObject(),
354 scrollAnchor(layoutViewport()).anchorObject());
354 } 355 }
355 356
356 TEST_F(ScrollAnchorTest, TextBounds) 357 TEST_F(ScrollAnchorTest, TextBounds)
357 { 358 {
358 setBodyInnerHTML( 359 setBodyInnerHTML(
359 "<style>" 360 "<style>"
360 " body {" 361 " body {"
361 " position: absolute;" 362 " position: absolute;"
362 " font-size: 100px;" 363 " font-size: 100px;"
363 " width: 200px;" 364 " width: 200px;"
364 " height: 1000px;" 365 " height: 1000px;"
365 " line-height: 100px;" 366 " line-height: 100px;"
366 " }" 367 " }"
367 "</style>" 368 "</style>"
368 "abc <b id=b>def</b> ghi"); 369 "abc <b id=b>def</b> ghi"
370 "<div id=a>after</div>");
369 371
370 scrollLayoutViewport(DoubleSize(0, 150)); 372 scrollLayoutViewport(DoubleSize(0, 150));
371 373
372 setHeight(document().body(), 1100); 374 setHeight(document().getElementById("a"), 100);
373 EXPECT_EQ(document().getElementById("b")->layoutObject()->slowFirstChild(), 375 EXPECT_EQ(document().getElementById("b")->layoutObject()->slowFirstChild(),
374 scrollAnchor(layoutViewport()).anchorObject()); 376 scrollAnchor(layoutViewport()).anchorObject());
375 } 377 }
376 378
377 TEST_F(ScrollAnchorTest, ExcludeFixedPosition) 379 TEST_F(ScrollAnchorTest, ExcludeFixedPosition)
378 { 380 {
379 setBodyInnerHTML( 381 setBodyInnerHTML(
380 "<style>" 382 "<style>"
381 " body { height: 1000px; padding: 20px; }" 383 " body { height: 1000px; padding: 20px; }"
382 " div { position: relative; top: 100px; }" 384 " div { position: relative; top: 100px; }"
383 " #f { position: fixed }" 385 " #f { position: fixed }"
384 "</style>" 386 "</style>"
385 "<div id=f>fixed</div>" 387 "<div id=f>fixed</div>"
386 "<div id=c>content</div>"); 388 "<div id=c>content</div>"
389 "<div id=a>after</div>");
387 390
388 scrollLayoutViewport(DoubleSize(0, 50)); 391 scrollLayoutViewport(DoubleSize(0, 50));
389 392
390 setHeight(document().body(), 1100); 393 setHeight(document().getElementById("a"), 100);
391 EXPECT_EQ(document().getElementById("c")->layoutObject(), 394 EXPECT_EQ(document().getElementById("c")->layoutObject(),
392 scrollAnchor(layoutViewport()).anchorObject()); 395 scrollAnchor(layoutViewport()).anchorObject());
393 } 396 }
394 397
395 // This test verifies that position:absolute elements that stick to the viewport 398 // This test verifies that position:absolute elements that stick to the viewport
396 // are not selected as anchors. 399 // are not selected as anchors.
397 TEST_F(ScrollAnchorTest, ExcludeAbsolutePositionThatSticksToViewport) 400 TEST_F(ScrollAnchorTest, ExcludeAbsolutePositionThatSticksToViewport)
398 { 401 {
399 setBodyInnerHTML( 402 setBodyInnerHTML(
400 "<style>" 403 "<style>"
401 " body { margin: 0; }" 404 " body { margin: 0; }"
402 " #scroller { overflow: scroll; width: 500px; height: 400px; }" 405 " #scroller { overflow: scroll; width: 500px; height: 400px; }"
403 " #space { height: 1000px; }" 406 " #space { height: 1000px; }"
404 " #abs {" 407 " #abs {"
405 " position: absolute; background-color: red;" 408 " position: absolute; background-color: red;"
406 " width: 100px; height: 100px;" 409 " width: 100px; height: 100px;"
407 " }" 410 " }"
408 " #rel {" 411 " #rel {"
409 " position: relative; background-color: green;" 412 " position: relative; background-color: green;"
410 " left: 50px; top: 100px; width: 100px; height: 75px;" 413 " left: 50px; top: 100px; width: 100px; height: 75px;"
411 " }" 414 " }"
412 "</style>" 415 "</style>"
413 "<div id='scroller'><div id='space'>" 416 "<div id='scroller'><div id='space'>"
414 " <div id='abs'></div>" 417 " <div id='abs'></div>"
415 " <div id='rel'></div>" 418 " <div id='rel'></div>"
419 " <div id=a>after</div>"
416 "</div></div>"); 420 "</div></div>");
417 421
418 Element* scrollerElement = document().getElementById("scroller"); 422 Element* scrollerElement = document().getElementById("scroller");
419 ScrollableArea* scroller = scrollerForElement(scrollerElement); 423 ScrollableArea* scroller = scrollerForElement(scrollerElement);
420 Element* absPos = document().getElementById("abs"); 424 Element* absPos = document().getElementById("abs");
421 Element* relPos = document().getElementById("rel"); 425 Element* relPos = document().getElementById("rel");
422 426
423 scroller->scrollBy(DoubleSize(0, 25), UserScroll); 427 scroller->scrollBy(DoubleSize(0, 25), UserScroll);
424 setHeight(relPos, 100); 428 setHeight(document().getElementById("a"), 100);
425 429
426 // When the scroller is position:static, the anchor cannot be position:absol ute. 430 // When the scroller is position:static, the anchor cannot be position:absol ute.
427 EXPECT_EQ(relPos->layoutObject(), scrollAnchor(scroller).anchorObject()); 431 EXPECT_EQ(relPos->layoutObject(), scrollAnchor(scroller).anchorObject());
428 432
429 scrollerElement->setAttribute(HTMLNames::styleAttr, "position: relative"); 433 scrollerElement->setAttribute(HTMLNames::styleAttr, "position: relative");
434 update();
430 scroller->scrollBy(DoubleSize(0, 25), UserScroll); 435 scroller->scrollBy(DoubleSize(0, 25), UserScroll);
431 setHeight(relPos, 125); 436 setHeight(document().getElementById("a"), 125);
432 437
433 // When the scroller is position:relative, the anchor may be position:absolu te. 438 // When the scroller is position:relative, the anchor may be position:absolu te.
434 EXPECT_EQ(absPos->layoutObject(), scrollAnchor(scroller).anchorObject()); 439 EXPECT_EQ(absPos->layoutObject(), scrollAnchor(scroller).anchorObject());
435 } 440 }
436 441
437 // This test verifies that position:absolute elements with top/right/bottom/left
438 // set are not selected as anchors.
439 TEST_F(ScrollAnchorTest, ExcludeOffsettedAbsolutePosition)
440 {
441 setBodyInnerHTML(
442 "<style>"
443 " body { margin: 0; }"
444 " #scroller { overflow: scroll; width: 500px; height: 400px; position :relative; }"
445 " #space { height: 1000px; }"
446 " #abs {"
447 " position: absolute; background-color: red;"
448 " width: 100px; height: 100px;"
449 " }"
450 " #rel {"
451 " position: relative; background-color: green;"
452 " left: 50px; top: 100px; width: 100px; height: 75px;"
453 " }"
454 " .top { top: 10px }"
455 " .left { left: 10px }"
456 " .right { right: 10px }"
457 " .bottom { bottom: 10px }"
458 "</style>"
459 "<div id='scroller'><div id='space'>"
460 " <div id='abs'></div>"
461 " <div id='rel'></div>"
462 "</div></div>");
463
464 Element* scrollerElement = document().getElementById("scroller");
465 ScrollableArea* scroller = scrollerForElement(scrollerElement);
466 Element* relPos = document().getElementById("rel");
467 Element* absPos = document().getElementById("abs");
468
469 scroller->scrollBy(DoubleSize(0, 25), UserScroll);
470 setHeight(relPos, 100);
471 // Pick absolute anchor.
472 EXPECT_EQ(absPos->layoutObject(), scrollAnchor(scroller).anchorObject());
473
474 absPos->setAttribute(HTMLNames::classAttr, "top");
475 scroller->scrollBy(DoubleSize(0, 25), UserScroll);
476 setHeight(relPos, 125);
477 // Don't pick absolute anchor since top is set.
478 EXPECT_EQ(relPos->layoutObject(), scrollAnchor(scroller).anchorObject());
479
480 absPos->removeAttribute(HTMLNames::classAttr);
481 absPos->setAttribute(HTMLNames::classAttr, "right");
482 scroller->scrollBy(DoubleSize(0, 25), UserScroll);
483 setHeight(relPos, 150);
484 // Don't pick absolute anchor since right is set.
485 EXPECT_EQ(relPos->layoutObject(), scrollAnchor(scroller).anchorObject());
486
487 absPos->removeAttribute(HTMLNames::classAttr);
488 absPos->setAttribute(HTMLNames::classAttr, "bottom");
489 scroller->scrollBy(DoubleSize(0, 25), UserScroll);
490 setHeight(relPos, 175);
491 // Don't pick absolute anchor since bottom is set.
492 EXPECT_EQ(relPos->layoutObject(), scrollAnchor(scroller).anchorObject());
493
494 absPos->removeAttribute(HTMLNames::classAttr);
495 absPos->setAttribute(HTMLNames::classAttr, "left");
496 scroller->scrollBy(DoubleSize(0, 25), UserScroll);
497 setHeight(relPos, 200);
498 // Don't pick absolute anchor since left is set.
499 EXPECT_EQ(relPos->layoutObject(), scrollAnchor(scroller).anchorObject());
500 }
501
502 // Test that we descend into zero-height containers that have overflowing conten t. 442 // Test that we descend into zero-height containers that have overflowing conten t.
503 TEST_F(ScrollAnchorTest, DescendsIntoContainerWithOverflow) 443 TEST_F(ScrollAnchorTest, DescendsIntoContainerWithOverflow)
504 { 444 {
505 setBodyInnerHTML( 445 setBodyInnerHTML(
506 "<style>" 446 "<style>"
507 " body { height: 1000; }" 447 " body { height: 1000; }"
508 " #outer { width: 300px; }" 448 " #outer { width: 300px; }"
509 " #zeroheight { height: 0px; }" 449 " #zeroheight { height: 0px; }"
510 " #changer { height: 100px; background-color: red; }" 450 " #changer { height: 100px; background-color: red; }"
511 " #bottom { margin-top: 600px; }" 451 " #bottom { margin-top: 600px; }"
(...skipping 28 matching lines...) Expand all
540 " height: 500px; width: 100%;" 480 " height: 500px; width: 100%;"
541 " }" 481 " }"
542 " #inner { height: 21px; background-color:#7f0; }" 482 " #inner { height: 21px; background-color:#7f0; }"
543 "</style>" 483 "</style>"
544 "<div id='outer'>" 484 "<div id='outer'>"
545 " <div id='zeroheight'>" 485 " <div id='zeroheight'>"
546 " <div id='float'>" 486 " <div id='float'>"
547 " <div id='inner'></div>" 487 " <div id='inner'></div>"
548 " </div>" 488 " </div>"
549 " </div>" 489 " </div>"
550 "</div>"); 490 "</div>"
491 "<div id=a>after</div>");
551 492
552 EXPECT_EQ(0, toLayoutBox(document().getElementById("zeroheight")->layoutObje ct())->size().height()); 493 EXPECT_EQ(0, toLayoutBox(document().getElementById("zeroheight")->layoutObje ct())->size().height());
553 494
554 ScrollableArea* viewport = layoutViewport(); 495 ScrollableArea* viewport = layoutViewport();
555 496
556 scrollLayoutViewport(DoubleSize(0, 200)); 497 scrollLayoutViewport(DoubleSize(0, 200));
557 setHeight(document().getElementById("float"), 600); 498 setHeight(document().getElementById("a"), 100);
558 499
559 EXPECT_EQ(200, viewport->scrollPosition().y()); 500 EXPECT_EQ(200, viewport->scrollPosition().y());
560 EXPECT_EQ(document().getElementById("float")->layoutObject(), 501 EXPECT_EQ(document().getElementById("float")->layoutObject(),
561 scrollAnchor(viewport).anchorObject()); 502 scrollAnchor(viewport).anchorObject());
562 } 503 }
563 504
564 TEST_F(ScrollAnchorTest, FlexboxDelayedClampingAlsoDelaysAdjustment) 505 TEST_F(ScrollAnchorTest, FlexboxDelayedClampingAlsoDelaysAdjustment)
565 { 506 {
566 setBodyInnerHTML( 507 setBodyInnerHTML(
567 "<style>" 508 "<style>"
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
627 AtomicString("overflow-anchor: none")); 568 AtomicString("overflow-anchor: none"));
628 update(); 569 update();
629 570
630 // Opted out element and it's children skipped. 571 // Opted out element and it's children skipped.
631 setHeight(document().getElementById("changer"), 200); 572 setHeight(document().getElementById("changer"), 200);
632 EXPECT_EQ(260, viewport->scrollPosition().y()); 573 EXPECT_EQ(260, viewport->scrollPosition().y());
633 EXPECT_EQ(document().getElementById("secondDiv")->layoutObject(), 574 EXPECT_EQ(document().getElementById("secondDiv")->layoutObject(),
634 scrollAnchor(viewport).anchorObject()); 575 scrollAnchor(viewport).anchorObject());
635 } 576 }
636 577
578 TEST_F(ScrollAnchorTest, SuppressAnchorNodeAncestorChangingLayoutAffectingProper ty)
579 {
580 setBodyInnerHTML(
581 "<style> body { height: 1000px } div { height: 100px } </style>"
582 "<div id='block1'>abc</div>");
583
584 ScrollableArea* viewport = layoutViewport();
585
586 scrollLayoutViewport(DoubleSize(0, 50));
587 document().body()->setAttribute(HTMLNames::styleAttr, "padding-top: 20px");
588 update();
589
590 EXPECT_EQ(50, viewport->scrollPosition().y());
591 EXPECT_EQ(nullptr, scrollAnchor(viewport).anchorObject());
592 }
593
594 TEST_F(ScrollAnchorTest, AnchorNodeAncestorChangingNonLayoutAffectingProperty)
595 {
596 setBodyInnerHTML(
597 "<style> body { height: 1000px } div { height: 100px } </style>"
598 "<div id='block1'>abc</div>"
599 "<div id='block2'>def</div>");
600
601 ScrollableArea* viewport = layoutViewport();
602 scrollLayoutViewport(DoubleSize(0, 150));
603
604 document().body()->setAttribute(HTMLNames::styleAttr, "color: red");
605 setHeight(document().getElementById("block1"), 200);
606
607 EXPECT_EQ(250, viewport->scrollPosition().y());
608 EXPECT_EQ(document().getElementById("block2")->layoutObject(),
609 scrollAnchor(viewport).anchorObject());
610 }
611
612 TEST_F(ScrollAnchorTest, TransformIsLayoutAffecting)
613 {
614 setBodyInnerHTML(
615 "<style>"
616 " body { height: 1000px }"
617 " #block1 { height: 100px }"
618 "</style>"
619 "<div id='block1'>abc</div>"
620 "<div id=a>after</div>");
621
622 ScrollableArea* viewport = layoutViewport();
623
624 scrollLayoutViewport(DoubleSize(0, 50));
625 document().getElementById("block1")->setAttribute(
626 HTMLNames::styleAttr, "transform: matrix(1, 0, 0, 1, 25, 25);");
627 update();
628
629 document().getElementById("block1")->setAttribute(
630 HTMLNames::styleAttr, "transform: matrix(1, 0, 0, 1, 50, 50);");
631 setHeight(document().getElementById("a"), 100);
632 update();
633
634 EXPECT_EQ(50, viewport->scrollPosition().y());
635 EXPECT_EQ(nullptr, scrollAnchor(viewport).anchorObject());
636 }
637
637 TEST_F(ScrollAnchorTest, OptOutBody) 638 TEST_F(ScrollAnchorTest, OptOutBody)
638 { 639 {
639 setBodyInnerHTML( 640 setBodyInnerHTML(
640 "<style>" 641 "<style>"
641 " body { height: 2000px; overflow-anchor: none; }" 642 " body { height: 2000px; overflow-anchor: none; }"
642 " #scroller { overflow: scroll; width: 500px; height: 300px; }" 643 " #scroller { overflow: scroll; width: 500px; height: 300px; }"
643 " .anchor {" 644 " .anchor {"
644 " position:relative; height: 100px; width: 150px;" 645 " position:relative; height: 100px; width: 150px;"
645 " background-color: #afa; border: 1px solid gray;" 646 " background-color: #afa; border: 1px solid gray;"
646 " }" 647 " }"
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 " #a { width: 400px; height: 300px; }" 797 " #a { width: 400px; height: 300px; }"
797 " .change { width: 100px; }" 798 " .change { width: 100px; }"
798 "</style>" 799 "</style>"
799 "<div id='changer'></div>" 800 "<div id='changer'></div>"
800 "<div id='a'></div>"); 801 "<div id='a'></div>");
801 802
802 checkCorner(Corner::TopRight, DoublePoint(-20, 20), DoubleSize(-100, 0)); 803 checkCorner(Corner::TopRight, DoublePoint(-20, 20), DoubleSize(-100, 0));
803 } 804 }
804 805
805 } 806 }
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/layout/ScrollAnchor.cpp ('k') | third_party/WebKit/Source/core/style/ComputedStyle.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698