Skip to content

Commit

Permalink
Merge pull request #4170 from vltansky/cypress
Browse files Browse the repository at this point in the history
feat: cypress
  • Loading branch information
nolimits4web committed Feb 22, 2021
2 parents 5f0fa3d + 3ea6260 commit ccd5a45
Show file tree
Hide file tree
Showing 13 changed files with 1,634 additions and 201 deletions.
8 changes: 8 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ module.exports = {
plugins: ['react'],
rules,
},
{
files: ['cypress/**/*.jsx', 'cypress/**/*.js'],
plugins: ['cypress'],
extends: ['plugin:cypress/recommended'],
env: {
'cypress/globals': true,
},
},
{
files: ['**/*.svelte'],
plugins: ['svelte3'],
Expand Down
24 changes: 24 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: E2E
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout the repository
uses: actions/checkout@v2
- name: Install Node.js
uses: actions/setup-node@v2
with:
node-version: 14
- name: Install dependencies
uses: bahmutov/npm-install@v1
- name: Run build dev
run: npm run build:dev
- name: Run build prod
run: npm run build:prod
- name: Run test
run: npm run test:e2e
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ package/*.scss
package/*.svelte
!package/postinstall.js
dist/demo


cypress/screenshots
3 changes: 3 additions & 0 deletions cypress.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"video": false
}
5 changes: 5 additions & 0 deletions cypress/fixtures/example.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}
39 changes: 39 additions & 0 deletions cypress/integration/modules/a11y.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/// <reference types="cypress" />

context('Core', () => {
describe('a11y', () => {
beforeEach(() => {
cy.swiperPage();
cy.initSwiper();
});
it('should add aria-live="polite" to swiper-wrapper', () => {
cy.getSliderWrapper().should('have.attr', 'aria-live', 'polite');
});

it('should add aria-role-description="slide" to swiper-slide', () => {
cy.initSwiper({
a11y: { itemRoleDescriptionMessage: 'test' },
});
cy.getSlides().should('have.attr', 'aria-role-description', 'test');
});

it('should add aria-role-description="slide" to swiper-container', () => {
cy.initSwiper({
a11y: { containerRoleDescriptionMessage: 'test' },
});
cy.getSliderContainer().should('have.attr', 'aria-role-description', 'test');
});

it('should add role="group" to swiper-slide', () => {
cy.getSlides().should('have.attr', 'role', 'group');
});

it('should add aria-lalbel to swiper-slide', () => {
const count = Cypress.$('.swiper-slide').length;
cy.getSlide(0).should('have.attr', 'aria-label', `1 / ${count}`);
cy.getSlide(2).should('have.attr', 'aria-label', `3 / ${count}`);
cy.getSlide(4).should('have.attr', 'aria-label', `5 / ${count}`);
cy.getSlide(9).should('have.attr', 'aria-label', `10 / ${count}`);
});
});
});
124 changes: 124 additions & 0 deletions cypress/integration/modules/core.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/// <reference types="cypress" />

context('Core', () => {
describe('centeredSlides & slidesPerView', () => {
beforeEach(() => {
cy.swiperPage();
cy.initSwiper({
centeredSlides: true,
slidesPerView: 3,
speed: 0,
spaceBetween: 10,
navigation: true,
});
});
it('should have slide with active class', () => {
cy.getSlide(0).should('have.class', 'swiper-slide-active').and('be.visible');
});

it('should position slides center', () => {
cy.getActiveSlide().should(($el) => {
expect($el[0].getBoundingClientRect().x).to.be.greaterThan(100);
});
});

it('should not has slide with prev class', () => {
cy.getSlides().should('not.have.class', 'swiper-slide-prev');
});

it('should have slide with next class', () => {
cy.getSlide(1).should('have.class', 'swiper-slide-next').and('be.visible');
});
describe('visible slides', () => {
it('should have 2 visible slides', () => {
cy.getSlides().filter(':visible').its('length').should('be.eq', 2);
});
it('should have 3 visible slides after navigation', () => {
cy.swipeLeft();
cy.getSlides().filter(':visible').its('length').should('be.eq', 3);
});
});

it('should have 10px margin on slides', () => {
cy.getSlides()
.should('have.attr', 'style')
.and('match', /margin-right:\s+10px/);
});
});

describe('methods', () => {
beforeEach(() => {
cy.swiperPage();
cy.initSwiper().as('swiper');
});
it('should slide next', function () {
this.swiper.slideNext();
cy.getSlideContains('Slide 2').should('have.class', 'swiper-slide-active');
});
it('should slide prev', function () {
this.swiper.slideNext();
this.swiper.slidePrev();
cy.getSlideContains('Slide 1').should('have.class', 'swiper-slide-active');
});
it('should slide to slide 3', function () {
this.swiper.slideTo(2);
cy.getSlideContains('Slide 3').should('have.class', 'swiper-slide-active');
});
// it('should slide to first slide when slideTo called with number bigger then slides amount', function () {
// this.swiper.slideTo(14);
// cy.getSlideContains('Slide 1').should('have.class', 'swiper-slide-active');
// });
it('Add slide at index', function () {
this.swiper.addSlide(1, '<div class="swiper-slide">Add slide</div>');
cy.getSlide(1).should('contain', 'Add slide');
this.swiper.addSlide(4, '<div class="swiper-slide">Add slide 4</div>');
cy.getSlide(4).should('contain', 'Add slide 4');
});

// it('Add multiple slides at index', function () {
// this.swiper.addSlide(0, [
// '<div class="swiper-slide">Add slide 0</div>',
// '<div class="swiper-slide">Add slide 1</div>',
// '<div class="swiper-slide">Add slide 2</div>',
// ]);
// // cy.getSlide(2).should('contain', 'Add slide 0');
// // cy.getSlide(1).should('contain', 'Add slide 1');
// cy.getSlide(0).should('contain', 'Add slide 2');
// });

it('Add slide to the end', function () {
this.swiper.appendSlide('<div class="swiper-slide">Add slide at the end</div>');
cy.getSlide(10).should('contain', 'Add slide at the end');
this.swiper.appendSlide([
'<div class="swiper-slide">END 1</div>',
'<div class="swiper-slide">END 2</div>',
]);
cy.getSlide(11).should('contain', 'END 1');
cy.getSlide(12).should('contain', 'END 2');
});
});

// TODO: swipe
describe('Slide', () => {
before(() => {
cy.swiperPage();
cy.initSwiper({
speed: 0,
});
});
it('should slide next with swiping the left', () => {
cy.swipeLeft();
cy.getSlide(1).should('have.class', 'swiper-slide-active');
cy.swipeLeft();
cy.swipeLeft();
cy.getSlide(3).should('have.class', 'swiper-slide-active');
});
it('should slide prev with swiping the right', () => {
cy.swipeRight();
cy.getSlide(2).should('have.class', 'swiper-slide-active');
cy.swipeRight();
cy.swipeRight();
cy.getSlide(0).should('have.class', 'swiper-slide-active');
});
});
});
22 changes: 22 additions & 0 deletions cypress/plugins/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins
//
// You can change the location of this file or turn off loading
// the plugins file with the 'pluginsFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/plugins-guide
// ***********************************************************

// This function is called when a project is opened or re-opened (e.g. due to
// the project's config changing)

/**
* @type {Cypress.PluginConfig}
*/
/* eslint-disable no-unused-vars */
module.exports = (on, config) => {
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
};
113 changes: 113 additions & 0 deletions cypress/support/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************

Cypress.Commands.add('navigationNextSlide', { prevSubject: 'optional' }, () => {
cy.get('.swiper-button-next').click();
});
Cypress.Commands.add('navigationPrevSlide', { prevSubject: 'optional' }, () => {
cy.get('.swiper-button-prev').click();
});
// subject, options
Cypress.Commands.add('getActiveSlide', { prevSubject: 'optional' }, () => {
return cy.get('.swiper-slide-active');
});

Cypress.Commands.add('getSliderWrapper', { prevSubject: 'optional' }, () => {
return cy.get('.swiper-wrapper');
});

Cypress.Commands.add('getSliderContainer', { prevSubject: 'optional' }, () => {
return cy.get('.swiper-container');
});

Cypress.Commands.add('getSlide', { prevSubject: 'optional' }, (subject, slideIndex) => {
return cy.get(`.swiper-slide:nth-child(${slideIndex + 1})`);
});
Cypress.Commands.add('getSlideContains', { prevSubject: 'optional' }, (subject, content) => {
cy.get('.swiper-container').contains(content);
});
Cypress.Commands.add('getSlides', { prevSubject: 'optional' }, () => {
return cy.get(`.swiper-slide`);
});
Cypress.Commands.add('swiperPage', { prevSubject: 'optional' }, () => {
return cy.visit('cypress/test.html');
});

Cypress.Commands.add(
'initSwiper',
{ prevSubject: 'optional' },
(subject, config = {}, el = '.swiper-container') => {
return cy.window().then((_window) => {
_window.document.body.innerHTML = `
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide">Slide 1</div>
<div class="swiper-slide">Slide 2</div>
<div class="swiper-slide">Slide 3</div>
<div class="swiper-slide">Slide 4</div>
<div class="swiper-slide">Slide 5</div>
<div class="swiper-slide">Slide 6</div>
<div class="swiper-slide">Slide 7</div>
<div class="swiper-slide">Slide 8</div>
<div class="swiper-slide">Slide 9</div>
<div class="swiper-slide">Slide 10</div>
</div>
${
config.navigation
? `
<div class="swiper-button-next"></div>
<div class="swiper-button-prev"></div>
`
: ''
}
${
config.pagination
? `
<div class="swiper-pagination"></div>`
: ''
}
</div>
`;
// eslint-disable-next-line dot-notation
_window.swiper = new _window['SwiperClass'](el, config);
return _window.swiper;
});
},
);

Cypress.Commands.add(
'reinitSwiper',
{ prevSubject: 'optional' },
(subject, config = {}, options) => {
return cy.window().then((_window) => {
_window.swiper.destroy();
cy.initSwiper(config, options);
});
},
);

Cypress.Commands.add('swipeLeft', () => {
cy.getSliderContainer()
.trigger('pointerdown', { which: 1, pageX: 100, pageY: 100, force: true })
.trigger('pointermove', { pageX: 50, pageY: 100, force: true })
.trigger('pointerup', { force: true });
});

Cypress.Commands.add('swipeRight', () => {
cy.getSliderContainer()
.trigger('pointerdown', { which: 1, pageX: -100, pageY: 100, force: true })
.trigger('pointermove', { pageX: 50, pageY: 100, force: true })
.trigger('pointerup', { force: true });
});

Cypress.Commands.add('waitSwipe', (subject, time = 300) => {
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wait(time);
});
20 changes: 20 additions & 0 deletions cypress/support/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************

// Import commands.js using ES2015 syntax:
import './commands';

// Alternatively you can use CommonJS syntax:
// require('./commands')

0 comments on commit ccd5a45

Please sign in to comment.