Search code examples
javascriptvue.jselectroncypressvue-cli-4

Cypress test fails for asserting equal to DOM title


Working on a project created with the @vue/cli 4.2.2 and Vue CLI Electron Plugin Builder. Vue CLI uses the HtmlWebpackPlugin that automatically generates the index.html in the public directory. The </title> of the relevant index.html page has the <%= htmlWebpackPlugin.options.title %> syntax that automatically detects the title of the page from the vue.config.js file.

vue.config.js

module.exports = {
  pluginOptions: {
    electronBuilder: {
      chainWebpackRendererProcess: config => {
        config.plugin("html").tap(args => {
          args[0].title = "Stack Overflow";
          return args;
        });
      }
    }
  }
};

The problem is that when the app starts, there's a millisecond flash where the page title changes from stackoverflow to Stack Overflow. To prevent this, I used the Electron page-title-updated hook like the following to make sure the app title loads correctly.

main.js

var win = new BrowserWindow({
  width: 800, 
  height: 600,
  title: 'Stack Overflow'
});

win.on('page-title-updated', (evt) => {
  evt.preventDefault();
});

It works great and there's no window flashing in the </title> now but when running e2e test using the Cypress, it just can't find the correct title Stack Overflow and test fails. test.js

describe("My First Test", () => {
  it("ensures the correct title", () => {
    cy.visit('/').title().should('eq', 'Stack Overflow')
  })
});

The result of Cypress test expected stackoverflow to equal Stack Overflow. So, the million dollar question is, how do I get the Cypress test pass?


Solution

  • If you are testing via Vue's script test:e2e, it looks like the test target is the Vue app in the browser, not the electron app.

    Of course, you can set title in the Vue app as per this question How can I bind the html content in vuejs (as well as your mod to the Electon startup) and your Electron app still looks ok.

    Title.vue

    <script>
      export default {
        name: 'vue-title',
        props: ['title'],
        watch: {
          title: {
            immediate: true,
            handler() {
              document.title = this.title;
            }
          }
        },
        render () {
          return null;
        },
      }
    </script>
    

    App.vue

    <template>
      <div id="app">
        <Title title="Stack Overflow"></Title>
        ...
      </div>
    </template>
    
    <script>
    import Title from './components/Title.vue'
    
    export default {
      name: 'App',
      components: {
        Title
      },
    }
    </script>
    

    Now the test passes, but you are still just testing Vue code, not as running in Electron.

    See Testing Electron.js applications using Cypress - alpha release for some info that may help you.