jamesshore / quixote

CSS unit and integration testing

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Does frame.scroll() support dynamic updates ?

musclor opened this issue · comments

Hello,

After several tests using frame.scroll() It seems QFrame does not detect any update in the view that have been performed by Javascript code.

For instance, element.RawPosition() is giving me the position of the element as if the Javascript code did not manipulate it.

I am testing with :

  • Karma
  • Chrome
  • Quixote in Integration Test style

The javascript code I am refering to comes from Bootstrap.

<nav class="navbar navbar-inverse" data-spy="affix" data-offset-top="55" id="nav">

My navbar should be affixed if I scroll more than 55px but when I call frame.scroll(0, 100) then element.RawPosition().top gives me the expected new postion not the actual one. Whereas I can see in the browser that the page is correctly loaded and the navbar affixed when I scroll manually.

I asked Quixote to create a frame which is small enough (height : 200) to make sure my page is scrollable.

Could you tell me if I am missing something, please ?

Hi, thanks for asking. The scenario you're describing should work. Can you send me a simplified HTML file that demonstrates the problem?

Have you checked whether the scrolling works properly inside of Karma? You could be experiencing a test setup issue. For example, the Bootstrap code might not be running.

You can check Karma manually as follows:

  1. Run only the test that's failing. If you're using Mocha, you can do this by running the test with it.only(... instead of it(....

  2. Comment out the frame.remove() line in that test file. This will leave the test frame visible in the Karma window after the test completes.

  3. Attach the test browser manually. (Run karma start and then point your browser at the Karma URL.)

  4. Run the test. (karma run)

  5. Look at the Karma page. The Quixote test frame should be visible under the list of attached browsers. Try scrolling the frame and see what happens.

Hi James,

First of all thank you very much for taking care of my case with so much attention. I really do appreciate.

Indeed I got some difficulties to reproduce my scenario with a simplified HTML file inside of Karma. My main mystake was that I did not call frame.reload() instead of frame.reset() leading bootstrap.min.js not to be part of the local files...

I am learning Karma as well so thank you for your advises. I confirm it works correctly inside Karma.

As per your request, please find here after my test files :

nav.html :

<!DOCTYPE html>
<html>
<head>
  <title>Bootstrap Example</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link type="text/css" href="https://github.com/base/assets/styles/bootstrap/bootstrap.min.css" target="_blank" rel="nofollow" rel="stylesheet">
  <style>
  .affix {
      top:0;
      width: 100%;
      z-index: 9999 !important;
  }

  .page {height:1000px;}
  </style>
</head>
<body>

<nav class="navbar navbar-inverse" data-spy="affix" data-offset-top="600">
  <div class="container-fluid">
    <div class="navbar-header">
        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">WebSiteName</a>
    </div>
    <div>
      <div class="collapse navbar-collapse" id="myNavbar">
        <ul class="nav navbar-nav">
          <li><a href="#page1">page 1</a></li>
          <li><a href="#page2">page 2</a></li>
          <li><a href="#page3">page 3</a></li>
        </ul>
      </div>
    </div>
  </div>
</nav>

<div id="page1" class="page">
  <h1>page 1</h1>
</div>
<div id="page2" class="page">
  <h1>page 2</h1>
</div>
<div id="page3" class="page">
  <h1>page 3</h1>
</div>

<script type="text/javascript" src="/base/assets/js/dependencies/jquery/jquery.min.js"></script>
<script type="text/javascript" src="/base/assets/js/dependencies/bootstrap/bootstrap.min.js"></script>
</body>
</html>

myTest.js :

describe("Nav", function() {
  this.timeout(10000);

  var frame;
  var nav;

  before(function(done) {
    frame = quixote.createFrame({
      src: "base/views/nav.html"
    }, done);
  });

  // after(function() {
  //   frame.remove();
  // });

  beforeEach(function(done) {
    frame.reload(function() {
        done();
    });
  });


  it("stays on top if I scroll more than the offset", function() {
    nav = frame.get('nav');

    frame.scroll(0, 1000);

    nav.assert({
      top: frame.viewport().top
    });
    
  });

});

The output :

03 12 2016 21:26:32.364:WARN [karma]: No captured browser, open http://localhost:9876/
03 12 2016 21:26:32.382:INFO [karma]: Karma v1.3.0 server started at http://localhost:9876/
03 12 2016 21:26:32.383:INFO [launcher]: Launching browser Chrome with unlimited concurrency
03 12 2016 21:26:32.430:INFO [launcher]: Starting browser Chrome
03 12 2016 21:26:33.841:INFO [Chrome 54.0.2840 (Windows 10 0.0.0)]: Connected on socket /#u9muALB40ezBaEvDAAAA with id 15636142
Chrome 54.0.2840 (Windows 10 0.0.0) Nav stays on top if I scroll more than the offset FAILED
        Error: Differences found:
        top edge of 'nav' was 1000px higher than expected.
          Expected: 1000px (top edge of viewport)
          But was:  0px

            at QElement.assert (node_modules/quixote/dist/quixote.js:141:25)
            at Context.<anonymous> (test/styles/local.test.js:29:9)
Chrome 54.0.2840 (Windows 10 0.0.0): Executed 1 of 1 (1 FAILED) ERROR (0.217 secs / 0.002 secs)

Thanks, I should have time to take a look at it this weekend.

Hi, @musclor, sorry for the long delay in getting back to you on this.

I've investigated this issue and it's the result of Bootstrap doing its work asynchronously. If you change your example test as follows, the tests will pass:

  it("stays on top if I scroll more than the offset", function(done) {
    nav = frame.get('nav');

    frame.scroll(0, 1000);

    setTimeout(function() {
        nav.assert({
            top: frame.viewport().top
        });
        done();
    }, 5000);

  });

This causes the test to wait five seconds before performing the assertion. That's enough time for Bootstrap to finish moving the navbar, and the test passes.

I don't recommend using this kind of timeout in real test code because it will make your tests run too slowly. However, it does prove that Quixote is working correctly.

The proper way to test this would be to replace the setTimeout with a listener for a Bootstrap event. That way your test runs as quickly as possible. It looks like affixed.bs.affix is the event you need. I haven't tried it myself, though.

Hi @jamesshore ,

Actually I remember I also tested using directly HTML DOM with the same result, I now understand why...
I should have guessed my spec was not correct and my understanding of Bootstrap's functioning not accurate.

Thank you for having taken the time to provide me with a complete explaination and for your advices.