title: Laravel Dusk: Wait for a load mask/overlay to finish
body: <p>I am having difficulty getting some tests to pass because of a load mask I put over the entire screen during AJAX calls (transparent black with a loading gif in the middle).</p>
  
  <p>I can get it to work if I <code>pause(2000)</code> each time, but the amount of AJAX calls in the app make that the slow solution. I am trying to use <code>waitUntilMissing</code> but it's not working.</p>
  
  <ul>
  <li>I have a <code>div</code> with two classes: <code>load-mask</code> and <code>loading</code>. </li>
  <li><code>load-mask</code> is always there</li>
  <li><code>loading</code> class applied to div during all vue.js AJAX calls; this is the load mask</li>
  <li>When AJAX response received, <code>loading</code> class removed</li>
  </ul>
  
  <p>So in my test I am trying to do this:</p>
  
  <pre><code>$browser-&gt;loginAs($this-&gt;user)
      -&gt;visit(new CustomInputPage)
      -&gt;saveNarrative('Lorem ipsum dolor')
      -&gt;visit(new CustomInputPage)
      -&gt;waitUntilMissing('.load-mask')
      -&gt;assertSee('Lorem ipsum dolor');
  </code></pre>
  
  <ul>
  <li>Load a page</li>
  <li>Enter text &amp; hit save</li>
  <li>reload page</li>
  <li>make sure text is still there</li>
  </ul>
  
  <p>I get an error on the <code>assertSee</code> because once the page loads, the <code>loading</code> is applied as it makes it's AJAX call so it hasn't loaded the text yet. </p>
  
  <p>I am assuming <code>waitForMissing('.load-mask')</code> is passing before the load mask even starts, so it tries to <code>assertSee</code> during the loading process, but it's an assumption.</p>
  
  <p>Is there a working solution outside just using <code>pause</code>?</p>
  
  <p><strong>EDIT:</strong> I am currently trying to click around the page to reload the AJAX instead of a full page load. I am still experiencing the same issue. </p>
  
  <p>Now I am trying this instead:</p>
  
  <pre><code>$browser-&gt;loginAs($this-&gt;user)
      -&gt;visit(new CustomInputPage)
      -&gt;saveNarrative('Lorem ipsum dolor')
      -&gt;clickLink('Tab 2')
      -&gt;waitUntilMissing('.load-mask')
      -&gt;assertSee('Lorem ipsum dolor');
  </code></pre>
  
  <p>Clicking a tab will load the AJAX call I'm referring to. I notice in the screenshot it's always showing my <code>.loading</code> animation. </p>
  
  <p>So...<code>Tab 2</code> should be an empty box but the screenshot shows the text hasn't been cleared yet and load mask is still present (happens after response is received).</p>
  
  <p>So I can't get the timing on a completed AJAX call down without using <code>pause</code>. Should I try another way?</p>
  
  <p><strong>EDIT 2</strong></p>
  
  <p>Here is where my load mask is being inserted. The vue.js axios library.</p>
  
  <pre><code>import store from '../store';
  
  let numberOfAjaxCAllPending = 0;
  
  axios.interceptors.request.use(function (config) {
    // Do something before request is sent
    numberOfAjaxCAllPending++;
    store.commit('isLoading', true);
    return config;
  }, function (error) {
    numberOfAjaxCAllPending = 0;
    store.commit('isLoading', false);
    // Do something with request error
    return Promise.reject(error);
  });
  
  // Add a response interceptor
  axios.interceptors.response.use(function (response) {
  
    // Do something with response data
    numberOfAjaxCAllPending--;
    if (numberOfAjaxCAllPending === 0) {
      store.commit('isLoading', false);
    }
    return response;
  }, function (error) {
    numberOfAjaxCAllPending = 0;
    store.commit('isLoading', false);
    // Do something with response error
    return Promise.reject(error);
  });
  </code></pre>
  
  <p>And on each Laravel blade template, I tried this first:</p>
  
  <pre><code>&lt;div :class="{ loading: $store.state.isLoading }" class="load-mask"&gt;&lt;/div&gt;
  </code></pre>
  
  <p>But now I am trying this way, with the loading class always present and just toggling display none/block</p>
  
  <pre><code>&lt;div :style="{display: $store.getters.getLoadingDisplay }" class="loading"&gt;&lt;/div&gt;
  </code></pre>
  
  <p>Same issue occurs this way as well. The load mask is present and I am also noticing the text box isn't being cleared when switching tabs in Laravel Dusk (the tabs clear fine in a regular browser).</p>
  
  <p><strong>EDIT 3</strong></p>
  
  <p>The first assertion passes, then it fails when trying to <code>-&gt;press('Save')</code>. I get this error:</p>
  
  <pre><code>Facebook\WebDriver\Exception\UnknownServerException: unknown error: Element &lt;button type="button" class="btn btn-sm mt-3 btn-primary" style="float: left;"&gt;...&lt;/button&gt; is not clickable at point (440, 912). Other element would receive the click: &lt;div class="loading" style="display: block;"&gt;&lt;/div&gt;
  </code></pre>
  
  <p>This is the test I am trying to run. As you can see, I have a <code>waitUntilMissing</code> and an <code>assertMissing</code> right after each other. Then I press <code>Save</code> and it says there's still a load mask. If I wait 2 seconds before the <code>keys</code> statement, it works fine. </p>
  
  <pre><code>$browser-&gt;loginAs($this-&gt;user)
    -&gt;visit(new CustomInputPage)
    -&gt;waitUntilMissing('.loading')
    -&gt;assertMissing('.loading')
    -&gt;keys('.ql-editor', 'Test Text')
    -&gt;press('Save')
    -&gt;waitUntilMissing('.loading');
  </code></pre>