Giter Site home page Giter Site logo

cypress-daywalker's Introduction

Cypress Daywalker

Gitter

Use Cypress Daywalker to test your web components (Polymer, lit-html, ...) app.

Please star this repo if you use this plugin. This helps me to understand how many people it is useful for and motivates me to continue improving it.

This plugin does not randomly query through trees of nodes but rather creates an index of all registered custom elements.

Installation

1. Install the dependency

Add the plugin to your devDependencies

npm install -D cypress-daywalker

2. Add daywalker commands

At the top of cypress/support/commands.js:

import 'cypress-daywalker/commands'

3. Add the Daywalker script

You need to inject cypress-daywalker.js into your application's entrypoint. This can happen by manually or dynamically adding a script tag to your entrypoint file. (If you test a built app, don't forget to add 'node_modules/cypress-daywalker/cypress-daywalker.js' as an extra dependency.)

Via a static script tag

This is the easiest way: At the top of your entrypoint file e.g. index.html add the following script tag.

  <!-- Eventually adjust the path to your node modules -->
  <script src="./node_modules/cypress-daywalker/cypress-daywalker.js"></script>

Via a dynamic script tag

You might want to avoid that the script tag ends up in a production environment. Therefore, you can inject the script tag into your document before any other javascript gets executed by listening to the window:before:load event.

context('Default', () => {
  before(() => {

    // INJECT THE SCRIPT LIKE THIS:
    cy.on('window:before:load', (w) => {
      const script = w.document.createElement('script');
      
      // Eventually adjust the path to your node modules
      script.src = '/node_modules/cypress-daywalker/cypress-daywalker.js';
      
      // // If you cannot reach your node_modules folder easily (e.g. in a Java application), try to load it via a cdn.
      // script.src = 'https://cdn.jsdelivr.net/gh/jaysunsyn/[email protected]/cypress-daywalker.js';
      
      
      w.document.querySelector('head').appendChild(script);
    });

    cy.visit('http://localhost:3000/');
  });
  it('input gets filled', () => {
    // Test stuff
  });
});

Usage

Find an example here.

Not all CSS selectors are supported yet, so do not use it as you would use jQuery or the usual querySelector command. Please create issues of use cases where you would like better querying functionalities. For the apps this plugin was developed for, the current functionalities worked pretty well.

Query

By default, cy.dwGet returns the first found node. If you want it to return any other one, there are two options:

nth

  1. cy.dwGet('my-element', {nth: 2})
  2. cy.dwGet(paper-input:nth(3) input')

If you want to retrieve all results, add the all flag like this cy.dwGet('my-element', {all: true}).

By Tag

This works very well.

cy.dwGet('paper-button')

By ID

This works very well.

cy.dwGet('#submit')
cy.dwGet('paper-button#submit')

By Class

Find custom elements everywhere in the app or native elements at root level.

cy.dwGet('.foo')
cy.dwGet('.foo.moo')

By Direct Parent

<div class="find-me">
  <paper-button></paper-button>
</div>
<paper-button></paper-button>
cy.dwGet('.find-me > paper-button')

By path

Starting from the root level:

cy.dwGet('div my-element paper-input#important')

or starting from any custom element:

cy.dwGet('my-element div#jay')

Starting a path with a native element which is inside a shadow root is not supported.

Lazy loaded components

If you lazy load some components, you can, for example, add a .wait(500) to your .visit() command to wait for them to get available.

Commands

Not all cypress commands can be used yet. For some, there are replacements below.

Click

Instead of .click() use:

cy.dwGet('paper-button').dwDispatch('click') // Results in Event('click')
cy.dwGet('paper-button').dwDispatch(new MouseEvent('click')) // Or pass in any other event

Type

Instead of .type('Hello world') use:

cy.dwGet('paper-input').dwSetProp('moto moto') // Results in the value property gets set
cy.dwGet('paper-input').dwSetProp('Question', 'label') // Or specify the property name

Invoke

Instead of .invoke() use:

cy.dwGet('my-el').dwCall('close')

Should

Before using .should() you need to attach the node.

When a node gets attached, it gets cloned and appended to the body. When detatching, this clone gets removed.

Be aware that after attaching, you interact with a cloned node and not with the original one.

cy.dwGet('div > paper-button span').dwAttach().should('have.text', 'Click').dwDetach();

Contributors

CI

See the latest tests of the example https://travis-ci.com/JaySunSyn/cypress-daywalker/builds/

cypress-daywalker's People

Contributors

jaysunsyn avatar dependabot[bot] avatar ilaborie avatar

Stargazers

frankfanslc avatar Dan Bowling avatar Robin Jonker (Kalbuir) avatar Henry Ruhs avatar Alex Rodriguez avatar Dawid Loranc avatar Alex Strand avatar Jesse Clark avatar Brett Jankord avatar Sébastien Roch avatar Nico König avatar steflen avatar  avatar Kyle Mott avatar Egon Meijers avatar Gary Großgarten avatar  avatar Nazar avatar Chris Beech avatar Kuka Radovan avatar Jeremy W. Sherman avatar Adam Larsen avatar  avatar Michał Pietraszko avatar Aidan Sawyer avatar Matarr Jobe avatar Serhii Kulykov avatar  avatar  avatar Scott Warren avatar Thomas Caserta avatar Kristof Jannes avatar Tom Gijselinck avatar Marc avatar Kuba avatar Dan Lemon avatar Cody Sand avatar Alexander Tkachev avatar Pierre-Yves avatar Chris Clarke avatar Kevin Massicotte avatar Jon Wiedmann avatar Phillipe Bojorquez avatar Leonardo Favre avatar  avatar Jan Pfajfr avatar Tom Wagner avatar morbidick avatar Leonard avatar Haritha Hari avatar Arthur BRady avatar cambiph avatar Thomas Kratz avatar Patrick Valer avatar  avatar Zach Bloomquist avatar  avatar Kyle Warneck avatar Ron avatar André Furchner avatar Daan Haitsma avatar Cristian Necula avatar Gleb Bahmutov avatar Kevin Krefting avatar Andreas Mehlsen avatar

Watchers

James Cloos avatar Kevin Krefting avatar  avatar Haritha Hari avatar Nazar avatar Karin Touchie avatar  avatar

cypress-daywalker's Issues

.focus(), .click(), etc fail on custom elements

First of all, thank you for starting this project!
Doing acceptance tests for apps with custom elements is a real pain.

I took your plugin for a spin and quickly run into this issue:
2019-04-12-100239_837x685_scrot

I am fully aware that this error is to be expected at this stage. I just want to know if you think it's possible to make this work?

Slotted content support

I can't seem to be able to get an element that was rendered as slotted content.

Here is an example of trying to get the label of a paper-input:

cy.get('paper-input paper-input-container label');

I can successfully get the paper-input-container, but not the label element.

cannot find element in shadow dom

I just try to get started with daywalker.

I have a vaadin-text-field with an id. Inside of that custom element I need to type into a textfield of the shadow dom. When I try

cy.get('#nameField input').type("TEST")

it does not find the input. I guess I am getting something completely wrong and really would appreciate a little help :)

CypressError: Timed out retrying: Expected to find element: '#nameField input', but never found it.

I added daywalker like suggested in support/commands.js

Running example results in incostenties with timeouts and infinite loops

Since our back-and-forth yesterday in the Cypress repo, I'm now trying get the example specs to run properly. I hadn't updated Node.js yet yesterday, I've now done that as well. So I'm now running on the latest Node.js, Cypress and your plugin. This is what's happening for me when I run the example specs twice:

Me running the example specs twice

Timeouts, errors and the second run resulted in an infinite loop where the first run didn't. These are the exact steps I've taken:

git clone https://github.com/JaySunSyn/cypress-daywalker.git
cd cypress-daywalker\example
npm i
npm test
Click on example_spec js in Cypress window
(wait for tests to complete)
Click the reload button in the browser

Also, I noticed in your screen gif is that all tests take just under 15 seconds to complete, while one run for me takes over 90 seconds. I'm running on a high-end business laptop, it's a three month old Dell Latitude 5591 with 16GB RAM, 2.60GHz i7, SSD, all great specs. I don't understand the massive difference.

Failed to construct 'HTMLElement': Please use the 'new' operator

Injecting script from CDN using Angular 8 (Ionic 4 webcomponents).

Appears to be an issue with angular/custom elements (angular/angular#24556).

Solution suggests ensure tsconfig set to target es2015, however I found I also needed to inject custom-elements-es5-adapter script after injecting daywalker. i.e.

      const script1 = w.document.createElement("script");
      script1.src =
        "https://cdn.jsdelivr.net/gh/jaysunsyn/[email protected]/cypress-daywalker.js";
      const script2 = w.document.createElement("script");
      script2.src =
        "https://unpkg.com/@webcomponents/[email protected]/custom-elements-es5-adapter.js";
      w.document.querySelector("head").appendChild(script1);
      w.document.querySelector("head").appendChild(script2);

So likely not a bug in daywalker, but might be of use to others

TypeError: Cannot read property 'store' of undefined

Hey there,

Nice work on the plugin!
I have a question about handling the Spring Security login screen.
In my before function, I have to log in to the application but your plugin throws an exception:

This is the code I use:

before(function() {
    cy.visit('http://localhost:8080');
    cy.get('[name=username]').type('user');
    cy.get('[name=submit]').click();
})

Cypress throws:

TypeError: Cannot read property 'store' of undefined

Do I need to disable your plugin on the login page?

Thanks in advance.
Regards

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.