mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-15 17:42:15 +08:00
test(cypress): migrate Angular tests to Cypress (#23083)
This commit is contained in:
@ -458,7 +458,7 @@ jobs:
|
|||||||
command: npm install --legacy-peer-deps
|
command: npm install --legacy-peer-deps
|
||||||
working_directory: /tmp/workspace/angular/test/test-app
|
working_directory: /tmp/workspace/angular/test/test-app
|
||||||
- run:
|
- run:
|
||||||
command: npm run test -- --protractor-config=e2e/protractor-ci.conf.js
|
command: npm run test
|
||||||
working_directory: /tmp/workspace/angular/test/test-app
|
working_directory: /tmp/workspace/angular/test/test-app
|
||||||
|
|
||||||
install-vue-test-app:
|
install-vue-test-app:
|
||||||
|
@ -85,33 +85,6 @@
|
|||||||
"browserTarget": "test-app:build"
|
"browserTarget": "test-app:build"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"test": {
|
|
||||||
"builder": "@angular-devkit/build-angular:karma",
|
|
||||||
"options": {
|
|
||||||
"main": "src/test.ts",
|
|
||||||
"polyfills": "src/polyfills.ts",
|
|
||||||
"tsConfig": "tsconfig.spec.json",
|
|
||||||
"karmaConfig": "karma.conf.js",
|
|
||||||
"styles": ["src/styles.css"],
|
|
||||||
"scripts": [],
|
|
||||||
"assets": ["src/favicon.ico", "src/assets"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"e2e": {
|
|
||||||
"builder": "@angular-devkit/build-angular:protractor",
|
|
||||||
"options": {
|
|
||||||
"protractorConfig": "e2e/protractor.conf.js",
|
|
||||||
"devServerTarget": "test-app:serve"
|
|
||||||
},
|
|
||||||
"configurations": {
|
|
||||||
"production": {
|
|
||||||
"devServerTarget": "test-app:serve:production"
|
|
||||||
},
|
|
||||||
"ci": {
|
|
||||||
"devServerTarget": "test-app:serve:ci"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"lint": {
|
"lint": {
|
||||||
"builder": "@angular-devkit/build-angular:tslint",
|
"builder": "@angular-devkit/build-angular:tslint",
|
||||||
"options": {
|
"options": {
|
||||||
|
8
angular/test/test-app/cypress.json
Normal file
8
angular/test/test-app/cypress.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"integrationFolder": "./e2e",
|
||||||
|
"testFiles": "**/*.spec.ts",
|
||||||
|
"baseUrl": "http://localhost:4200/",
|
||||||
|
"ignoreTestFiles": "**/examples/*",
|
||||||
|
"video": false,
|
||||||
|
"screenshotOnRunFailure": false
|
||||||
|
}
|
22
angular/test/test-app/cypress/plugins/index.js
vendored
Normal file
22
angular/test/test-app/cypress/plugins/index.js
vendored
Normal file
@ -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-next-line no-unused-vars
|
||||||
|
module.exports = (on, config) => {
|
||||||
|
// `on` is used to hook into various events Cypress emits
|
||||||
|
// `config` is the resolved Cypress config
|
||||||
|
}
|
79
angular/test/test-app/cypress/support/commands.js
vendored
Normal file
79
angular/test/test-app/cypress/support/commands.js
vendored
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// ***********************************************
|
||||||
|
// 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
|
||||||
|
// ***********************************************
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This is a parent command --
|
||||||
|
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This is a child command --
|
||||||
|
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This is a dual command --
|
||||||
|
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// -- This will overwrite an existing command --
|
||||||
|
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||||
|
|
||||||
|
Cypress.Commands.add('ionSwipeToGoBack', (complete = false, selector = 'ion-router-outlet') => {
|
||||||
|
const increment = (complete) ? 60 : 25;
|
||||||
|
cy.get(selector)
|
||||||
|
.first()
|
||||||
|
.trigger('mousedown', 0, 275, { which: 1, force: true })
|
||||||
|
.trigger('mousemove', increment * 1, 275, { which: 1, force: true })
|
||||||
|
.wait(50)
|
||||||
|
.trigger('mousemove', increment * 2, 275, { which: 1, force: true })
|
||||||
|
.wait(50)
|
||||||
|
.trigger('mousemove', increment * 3, 275, { which: 1, force: true })
|
||||||
|
.wait(50)
|
||||||
|
.trigger('mousemove', increment * 4, 275, { which: 1, force: true })
|
||||||
|
.wait(50)
|
||||||
|
.trigger('mouseup', increment * 4, 275, { which: 1, force: true })
|
||||||
|
cy.wait(150);
|
||||||
|
})
|
||||||
|
|
||||||
|
Cypress.Commands.add('testStack', (selector, expected) => {
|
||||||
|
cy.document().then((doc) => {
|
||||||
|
const children = Array.from(
|
||||||
|
doc.querySelector(selector).children
|
||||||
|
).map(el => el.tagName.toLowerCase());
|
||||||
|
expect(children).to.deep.equal(expected);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Cypress.Commands.add('testLifeCycle', (selector, expected) => {
|
||||||
|
cy.get(`${selector} #ngOnInit`).invoke('text').should('equal', '1');
|
||||||
|
cy.get(`${selector} #ionViewWillEnter`).invoke('text').should('equal', expected.ionViewWillEnter.toString());
|
||||||
|
cy.get(`${selector} #ionViewDidEnter`).invoke('text').should('equal', expected.ionViewDidEnter.toString());
|
||||||
|
cy.get(`${selector} #ionViewWillLeave`).invoke('text').should('equal', expected.ionViewWillLeave.toString());
|
||||||
|
cy.get(`${selector} #ionViewDidLeave`).invoke('text').should('equal', expected.ionViewDidLeave.toString());
|
||||||
|
})
|
||||||
|
|
||||||
|
Cypress.Commands.add('ionPageVisible', (selector) => {
|
||||||
|
cy.get(selector)
|
||||||
|
.should('have.class', 'ion-page')
|
||||||
|
.should('not.have.class', 'ion-page-hidden')
|
||||||
|
.should('not.have.class', 'ion-page-invisible')
|
||||||
|
.should('have.length', 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
Cypress.Commands.add('ionPageHidden', (selector) => {
|
||||||
|
cy.get(selector)
|
||||||
|
.should('have.class', 'ion-page')
|
||||||
|
.should('have.class', 'ion-page-hidden')
|
||||||
|
.should('have.length', 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
Cypress.Commands.add('ionPageDoesNotExist', (selector) => {
|
||||||
|
cy.get(selector)
|
||||||
|
.should('not.exist')
|
||||||
|
});
|
69
angular/test/test-app/cypress/support/index.d.ts
vendored
Normal file
69
angular/test/test-app/cypress/support/index.d.ts
vendored
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/// <reference types="cypress" />
|
||||||
|
|
||||||
|
declare namespace Cypress {
|
||||||
|
interface Chainable<Subject> {
|
||||||
|
/**
|
||||||
|
* Swipe to go back on the current selector or router outlet
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* cy.ionSwipeToGoBack();
|
||||||
|
* cy.ionSwipeToGoBack(true);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
ionSwipeToGoBack(complete: boolean, selector: string): Chainable<any>
|
||||||
|
/**
|
||||||
|
* Test that the proper pages are in the navigation stack
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* cy.testStack('ion-router-outlet', ['app-navigation-page2', 'app-navigation-page1']);
|
||||||
|
* cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab1-nested', 'app-tabs-tab2']);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
testStack(selector: string, expected: string[]): Chainable<any>
|
||||||
|
/**
|
||||||
|
* Test whether or not the lifecycle events fired
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* cy.testLifeCycle('app-router-link-page', {
|
||||||
|
* ionViewWillEnter: 1,
|
||||||
|
* ionViewDidEnter: 1,
|
||||||
|
* ionViewWillLeave: 0,
|
||||||
|
* ionViewDidLeave: 0,
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
testLifeCycle(selector: string, expected: any): Chainable<any>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether or not an .ion-page element is visible.
|
||||||
|
* Use this to test a page after navigating to it.
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* cy.ionPageVisible('app-my-page');
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
ionPageVisible(selector: string): Chainable<any>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether or not an .ion-page element is hidden
|
||||||
|
* Use this to test a page after navigating away from it.
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* cy.ionPageHidden('app-my-page');
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
ionPageHidden(selector: string): Chainable<any>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether or not an .ion-page element exists.
|
||||||
|
* Use this to test a page after popping it off the stack.
|
||||||
|
* @example
|
||||||
|
* ```
|
||||||
|
* cy.ionPageDoesNotExist('app-my-page');
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
ionPageDoesNotExist(selector: string): Chainable<any>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
angular/test/test-app/cypress/support/index.js
vendored
Normal file
20
angular/test/test-app/cypress/support/index.js
vendored
Normal file
@ -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')
|
@ -1,14 +0,0 @@
|
|||||||
|
|
||||||
// Protractor CI configuration file, see link for more information
|
|
||||||
// https://angular.io/guide/testing#configure-cli-for-ci-testing-in-chrome
|
|
||||||
|
|
||||||
const config = require('./protractor.conf').config;
|
|
||||||
|
|
||||||
config.capabilities = {
|
|
||||||
browserName: 'chrome',
|
|
||||||
chromeOptions: {
|
|
||||||
args: ['--headless', '--no-sandbox', '--window-size=1920,1080']
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.config = config;
|
|
@ -1,35 +0,0 @@
|
|||||||
// @ts-check
|
|
||||||
// Protractor configuration file, see link for more information
|
|
||||||
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
|
||||||
|
|
||||||
const { SpecReporter } = require('jasmine-spec-reporter');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @type { import("protractor").Config }
|
|
||||||
*/
|
|
||||||
exports.config = {
|
|
||||||
allScriptsTimeout: 11000,
|
|
||||||
specs: [
|
|
||||||
'./src/**/*.e2e-spec.ts'
|
|
||||||
],
|
|
||||||
capabilities: {
|
|
||||||
'browserName': 'chrome'
|
|
||||||
},
|
|
||||||
chromeOptions: {
|
|
||||||
args: [ "--headless", "--disable-gpu", "--window-size=400,1000", "--start-maximized" ]
|
|
||||||
},
|
|
||||||
directConnect: true,
|
|
||||||
baseUrl: 'http://localhost:4200/',
|
|
||||||
framework: 'jasmine',
|
|
||||||
jasmineNodeOpts: {
|
|
||||||
showColors: true,
|
|
||||||
defaultTimeoutInterval: 100000,
|
|
||||||
print: function() {}
|
|
||||||
},
|
|
||||||
onPrepare() {
|
|
||||||
require('ts-node').register({
|
|
||||||
project: require('path').join(__dirname, './tsconfig.json')
|
|
||||||
});
|
|
||||||
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,133 +0,0 @@
|
|||||||
import { browser, element, by } from 'protractor';
|
|
||||||
import { handleErrorMessages, getProperty, setProperty, getText, waitTime } from './utils';
|
|
||||||
|
|
||||||
describe('form', () => {
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
return handleErrorMessages();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('status updates', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await browser.get('/form');
|
|
||||||
await waitTime(30);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should update Ionic form classes when calling form methods programatically', async () => {
|
|
||||||
await element(by.css('form #input-touched')).click();
|
|
||||||
await waitTime(100);
|
|
||||||
const classList = (await getProperty('#touched-input-test', 'classList')) as string[];
|
|
||||||
expect(classList.includes('ion-touched')).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('change', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await browser.get('/form');
|
|
||||||
await waitTime(30);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have default values', async () => {
|
|
||||||
await testStatus('INVALID');
|
|
||||||
expect(await getText('#submit')).toEqual('false');
|
|
||||||
await testData({
|
|
||||||
datetime: '2010-08-20',
|
|
||||||
select: null,
|
|
||||||
toggle: false,
|
|
||||||
input: '',
|
|
||||||
input2: 'Default Value',
|
|
||||||
checkbox: false,
|
|
||||||
range: 5
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should become valid', async () => {
|
|
||||||
await setProperty('ion-input.required', 'value', 'Some value');
|
|
||||||
await testStatus('INVALID');
|
|
||||||
await setProperty('ion-select', 'value', 'nes');
|
|
||||||
await testStatus('INVALID');
|
|
||||||
await setProperty('ion-range', 'value', 40);
|
|
||||||
await testStatus('VALID');
|
|
||||||
await testData({
|
|
||||||
datetime: '2010-08-20',
|
|
||||||
select: 'nes',
|
|
||||||
toggle: false,
|
|
||||||
input: 'Some value',
|
|
||||||
input2: 'Default Value',
|
|
||||||
checkbox: false,
|
|
||||||
range: 40
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('ion-toggle should change', async () => {
|
|
||||||
await element(by.css('form ion-toggle')).click();
|
|
||||||
await testData({
|
|
||||||
datetime: '2010-08-20',
|
|
||||||
select: null,
|
|
||||||
toggle: true,
|
|
||||||
input: '',
|
|
||||||
input2: 'Default Value',
|
|
||||||
checkbox: false,
|
|
||||||
range: 5
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('ion-checkbox should change', async () => {
|
|
||||||
await element(by.css('ion-checkbox')).click();
|
|
||||||
await testData({
|
|
||||||
datetime: '2010-08-20',
|
|
||||||
select: null,
|
|
||||||
toggle: false,
|
|
||||||
input: '',
|
|
||||||
input2: 'Default Value',
|
|
||||||
checkbox: true,
|
|
||||||
range: 5
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should submit', async () => {
|
|
||||||
await element(by.css('#set-values')).click();
|
|
||||||
await waitTime(100);
|
|
||||||
await element(by.css('#submit-button')).click();
|
|
||||||
expect(await getText('#submit')).toEqual('true');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('blur', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await browser.get('/form#blur');
|
|
||||||
await waitTime(30);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('ion-toggle should change only after blur', async () => {
|
|
||||||
await element(by.css('form ion-toggle')).click();
|
|
||||||
await testData({
|
|
||||||
datetime: '2010-08-20',
|
|
||||||
select: null,
|
|
||||||
toggle: false,
|
|
||||||
input: '',
|
|
||||||
input2: 'Default Value',
|
|
||||||
checkbox: false,
|
|
||||||
range: 5
|
|
||||||
});
|
|
||||||
await element(by.css('ion-checkbox')).click();
|
|
||||||
await testData({
|
|
||||||
datetime: '2010-08-20',
|
|
||||||
select: null,
|
|
||||||
toggle: true,
|
|
||||||
input: '',
|
|
||||||
input2: 'Default Value',
|
|
||||||
checkbox: false,
|
|
||||||
range: 5
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
async function testStatus(status: string) {
|
|
||||||
expect(await element(by.css('#status')).getText()).toEqual(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function testData(data: any) {
|
|
||||||
expect(JSON.parse(await element(by.css('#data')).getText())).toEqual(data);
|
|
||||||
}
|
|
118
angular/test/test-app/e2e/src/form.spec.ts
Normal file
118
angular/test/test-app/e2e/src/form.spec.ts
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
describe('Form', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit('/form');
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('status updates', () => {
|
||||||
|
it('should update Ionic form classes when calling form methods programmatically', async () => {
|
||||||
|
cy.get('#input-touched').click();
|
||||||
|
cy.get('#touched-input-test').should('have.class', 'ion-touched');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('change', () => {
|
||||||
|
it('should have default values', () => {
|
||||||
|
testStatus('INVALID');
|
||||||
|
cy.get('#submit').should('have.text', 'false');
|
||||||
|
testData({
|
||||||
|
datetime: '2010-08-20',
|
||||||
|
select: null,
|
||||||
|
toggle: false,
|
||||||
|
input: '',
|
||||||
|
input2: 'Default Value',
|
||||||
|
checkbox: false,
|
||||||
|
range: 5
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should become valid', () => {
|
||||||
|
cy.get('ion-input.required').invoke('prop', 'value', 'Some value');
|
||||||
|
testStatus('INVALID');
|
||||||
|
|
||||||
|
cy.get('ion-select').invoke('prop', 'value', 'nes');
|
||||||
|
testStatus('INVALID');
|
||||||
|
|
||||||
|
cy.get('ion-range').invoke('prop', 'value', 40);
|
||||||
|
testStatus('VALID');
|
||||||
|
|
||||||
|
testData({
|
||||||
|
datetime: '2010-08-20',
|
||||||
|
select: 'nes',
|
||||||
|
toggle: false,
|
||||||
|
input: 'Some value',
|
||||||
|
input2: 'Default Value',
|
||||||
|
checkbox: false,
|
||||||
|
range: 40
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('ion-toggle should change', () => {
|
||||||
|
cy.get('form ion-toggle').click();
|
||||||
|
testData({
|
||||||
|
datetime: '2010-08-20',
|
||||||
|
select: null,
|
||||||
|
toggle: true,
|
||||||
|
input: '',
|
||||||
|
input2: 'Default Value',
|
||||||
|
checkbox: false,
|
||||||
|
range: 5
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('ion-checkbox should change', () => {
|
||||||
|
cy.get('ion-checkbox').click();
|
||||||
|
testData({
|
||||||
|
datetime: '2010-08-20',
|
||||||
|
select: null,
|
||||||
|
toggle: false,
|
||||||
|
input: '',
|
||||||
|
input2: 'Default Value',
|
||||||
|
checkbox: true,
|
||||||
|
range: 5
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should submit', () => {
|
||||||
|
cy.get('#set-values').click();
|
||||||
|
cy.get('#submit-button').click();
|
||||||
|
cy.get('#submit').should('have.text', 'true');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('blur', () => {
|
||||||
|
it('ion-toggle should change only after blur', () => {
|
||||||
|
cy.get('form ion-toggle').click();
|
||||||
|
testData({
|
||||||
|
datetime: '2010-08-20',
|
||||||
|
select: null,
|
||||||
|
toggle: true,
|
||||||
|
input: '',
|
||||||
|
input2: 'Default Value',
|
||||||
|
checkbox: false,
|
||||||
|
range: 5
|
||||||
|
});
|
||||||
|
cy.get('ion-checkbox').click();
|
||||||
|
testData({
|
||||||
|
datetime: '2010-08-20',
|
||||||
|
select: null,
|
||||||
|
toggle: true,
|
||||||
|
input: '',
|
||||||
|
input2: 'Default Value',
|
||||||
|
checkbox: true,
|
||||||
|
range: 5
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function testStatus(status) {
|
||||||
|
cy.get('#status').should('have.text', status);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testData(data) {
|
||||||
|
cy.get('#data').invoke('text').then(text => {
|
||||||
|
const value = JSON.parse(text);
|
||||||
|
console.log(value, data);
|
||||||
|
expect(value).to.deep.equal(data);
|
||||||
|
})
|
||||||
|
}
|
@ -1,69 +0,0 @@
|
|||||||
import { browser, element, by } from 'protractor';
|
|
||||||
import { getProperty, setProperty, handleErrorMessages, waitTime } from './utils';
|
|
||||||
|
|
||||||
describe('inputs', () => {
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await browser.get('/inputs');
|
|
||||||
await waitTime(30);
|
|
||||||
});
|
|
||||||
afterEach(() => {
|
|
||||||
return handleErrorMessages();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have default value', async () => {
|
|
||||||
expect(await getProperty('ion-checkbox', 'checked')).toEqual(true);
|
|
||||||
expect(await getProperty('ion-toggle', 'checked')).toEqual(true);
|
|
||||||
expect(await getProperty('ion-input', 'value')).toEqual('some text');
|
|
||||||
expect(await getProperty('ion-datetime', 'value')).toEqual('1994-03-15');
|
|
||||||
expect(await getProperty('ion-select', 'value')).toEqual('nes');
|
|
||||||
expect(await getProperty('ion-range', 'value')).toEqual(10);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should have reset value', async () => {
|
|
||||||
await element(by.css('#reset-button')).click();
|
|
||||||
|
|
||||||
expect(await getProperty('ion-checkbox', 'checked')).toEqual(false);
|
|
||||||
expect(await getProperty('ion-toggle', 'checked')).toEqual(false);
|
|
||||||
expect(await getProperty('ion-input', 'value')).toEqual('');
|
|
||||||
expect(await getProperty('ion-datetime', 'value')).toEqual('');
|
|
||||||
expect(await getProperty('ion-select', 'value')).toEqual('');
|
|
||||||
expect(await getProperty('ion-range', 'value')).toEqual(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should get some value', async () => {
|
|
||||||
await element(by.css('#reset-button')).click();
|
|
||||||
await element(by.css('#set-button')).click();
|
|
||||||
|
|
||||||
expect(await getProperty('ion-checkbox', 'checked')).toEqual(true);
|
|
||||||
expect(await getProperty('ion-toggle', 'checked')).toEqual(true);
|
|
||||||
expect(await getProperty('ion-input', 'value')).toEqual('some text');
|
|
||||||
expect(await getProperty('ion-datetime', 'value')).toEqual('1994-03-15');
|
|
||||||
expect(await getProperty('ion-select', 'value')).toEqual('nes');
|
|
||||||
expect(await getProperty('ion-range', 'value')).toEqual(10);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('change values should update angular', async () => {
|
|
||||||
await element(by.css('#reset-button')).click();
|
|
||||||
|
|
||||||
await setProperty('ion-checkbox', 'checked', true);
|
|
||||||
await setProperty('ion-toggle', 'checked', true);
|
|
||||||
await setProperty('ion-input', 'value', 'hola');
|
|
||||||
await setProperty('ion-datetime', 'value', '1996-03-15');
|
|
||||||
await setProperty('ion-select', 'value', 'playstation');
|
|
||||||
await setProperty('ion-range', 'value', 20);
|
|
||||||
|
|
||||||
expect(await element(by.css('#checkbox-note')).getText()).toEqual('true');
|
|
||||||
expect(await element(by.css('#toggle-note')).getText()).toEqual('true');
|
|
||||||
expect(await element(by.css('#input-note')).getText()).toEqual('hola');
|
|
||||||
expect(await element(by.css('#datetime-note')).getText()).toEqual('1996-03-15');
|
|
||||||
expect(await element(by.css('#select-note')).getText()).toEqual('playstation');
|
|
||||||
expect(await element(by.css('#range-note')).getText()).toEqual('20');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('nested components should not interfere with NgModel', async () => {
|
|
||||||
expect(await element(by.css('#range-note')).getText()).toEqual('10');
|
|
||||||
await element(by.css('#nested-toggle')).click();
|
|
||||||
expect(await element(by.css('#range-note')).getText()).toEqual('10');
|
|
||||||
});
|
|
||||||
});
|
|
61
angular/test/test-app/e2e/src/inputs.spec.ts
Normal file
61
angular/test/test-app/e2e/src/inputs.spec.ts
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
describe('Inputs', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit('/inputs');
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should have default value', () => {
|
||||||
|
cy.get('ion-checkbox').should('have.prop', 'checked').and('equal', true);
|
||||||
|
cy.get('ion-toggle').should('have.prop', 'checked').and('equal', true);
|
||||||
|
cy.get('ion-input').should('have.prop', 'value').and('equal', 'some text');
|
||||||
|
cy.get('ion-datetime').should('have.prop', 'value').and('equal', '1994-03-15');
|
||||||
|
cy.get('ion-select').should('have.prop', 'value').and('equal', 'nes');
|
||||||
|
cy.get('ion-range').should('have.prop', 'value').and('equal', 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have reset value', () => {
|
||||||
|
cy.get('#reset-button').click();
|
||||||
|
|
||||||
|
cy.get('ion-checkbox').should('have.prop', 'checked').and('equal', false);
|
||||||
|
cy.get('ion-toggle').should('have.prop', 'checked').and('equal', false);
|
||||||
|
cy.get('ion-input').should('have.prop', 'value').and('equal', '');
|
||||||
|
cy.get('ion-datetime').should('have.prop', 'value').and('equal', '');
|
||||||
|
cy.get('ion-select').should('have.prop', 'value').and('equal', '');
|
||||||
|
cy.get('ion-range').should('have.prop', 'value').and('be.NaN');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get some value', () => {
|
||||||
|
cy.get('#reset-button').click();
|
||||||
|
cy.get('#set-button').click();
|
||||||
|
|
||||||
|
cy.get('ion-checkbox').should('have.prop', 'checked').and('equal', true);
|
||||||
|
cy.get('ion-toggle').should('have.prop', 'checked').and('equal', true);
|
||||||
|
cy.get('ion-input').should('have.prop', 'value').and('equal', 'some text');
|
||||||
|
cy.get('ion-datetime').should('have.prop', 'value').and('equal', '1994-03-15');
|
||||||
|
cy.get('ion-select').should('have.prop', 'value').and('equal', 'nes');
|
||||||
|
cy.get('ion-range').should('have.prop', 'value').and('equal', 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('change values should update angular', () => {
|
||||||
|
cy.get('#reset-button').click();
|
||||||
|
|
||||||
|
cy.get('ion-checkbox').invoke('prop', 'checked', true);
|
||||||
|
cy.get('ion-toggle').invoke('prop', 'checked', true);
|
||||||
|
cy.get('ion-input').invoke('prop', 'value', 'hola');
|
||||||
|
cy.get('ion-datetime').invoke('prop', 'value', '1996-03-15');
|
||||||
|
cy.get('ion-select').invoke('prop', 'value', 'playstation');
|
||||||
|
cy.get('ion-range').invoke('prop', 'value', 20);
|
||||||
|
|
||||||
|
cy.get('#checkbox-note').should('have.text', 'true');
|
||||||
|
cy.get('#toggle-note').should('have.text', 'true');
|
||||||
|
cy.get('#input-note').should('have.text', 'hola');
|
||||||
|
cy.get('#datetime-note').should('have.text', '1996-03-15');
|
||||||
|
cy.get('#select-note').should('have.text', 'playstation');
|
||||||
|
cy.get('#range-note').should('have.text', '20');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('nested components should not interfere with NgModel', () => {
|
||||||
|
cy.get('#range-note').should('have.text', '10');
|
||||||
|
cy.get('#nested-toggle').click();
|
||||||
|
cy.get('#range-note').should('have.text', '10');
|
||||||
|
});
|
||||||
|
})
|
@ -1,55 +0,0 @@
|
|||||||
import { browser, element, by } from 'protractor';
|
|
||||||
import { waitTime, getText, handleErrorMessages } from './utils';
|
|
||||||
|
|
||||||
describe('modals', () => {
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await browser.get('/modals');
|
|
||||||
await waitTime(30);
|
|
||||||
});
|
|
||||||
afterEach(() => {
|
|
||||||
return handleErrorMessages();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should open standalone modal and close', async () => {
|
|
||||||
await element(by.css('#action-button')).click();
|
|
||||||
|
|
||||||
await waitTime(800);
|
|
||||||
|
|
||||||
const modal = element(by.css('app-modal-example'));
|
|
||||||
expect(await modal.$('h2').getText()).toEqual('123');
|
|
||||||
expect(await modal.$('h3').getText()).toEqual('321');
|
|
||||||
|
|
||||||
expect(await getText('#onWillDismiss')).toEqual('false');
|
|
||||||
expect(await getText('#onDidDismiss')).toEqual('false');
|
|
||||||
|
|
||||||
await modal.$('#close-modal').click();
|
|
||||||
await waitTime(800);
|
|
||||||
|
|
||||||
expect(await getText('#onWillDismiss')).toEqual('true');
|
|
||||||
expect(await getText('#onDidDismiss')).toEqual('true');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should open nav modal and close', async () => {
|
|
||||||
await element(by.css('#action-button-2')).click();
|
|
||||||
|
|
||||||
await waitTime(800);
|
|
||||||
|
|
||||||
let page = element(by.css('ion-nav > *:last-child'));
|
|
||||||
expect(await page.$('h2').getText()).toEqual('123');
|
|
||||||
expect(await page.$('h3').getText()).toEqual('321');
|
|
||||||
|
|
||||||
await page.$('.push-page').click();
|
|
||||||
await waitTime(800);
|
|
||||||
|
|
||||||
page = element(by.css('ion-nav > *:last-child'));
|
|
||||||
expect(await page.$('h2').getText()).toEqual('pushed!');
|
|
||||||
expect(await page.$('h3').getText()).toEqual('');
|
|
||||||
|
|
||||||
await page.$('.pop-page').click();
|
|
||||||
await waitTime(800);
|
|
||||||
|
|
||||||
page = element(by.css('ion-nav > *:last-child'));
|
|
||||||
expect(await page.$('h2').getText()).toEqual('123');
|
|
||||||
});
|
|
||||||
});
|
|
43
angular/test/test-app/e2e/src/modal.spec.ts
Normal file
43
angular/test/test-app/e2e/src/modal.spec.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
describe('Modals', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit('/modals');
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should open standalone modal and close', () => {
|
||||||
|
cy.get('#action-button').click();
|
||||||
|
|
||||||
|
cy.get('ion-modal').should('exist').should('be.visible');
|
||||||
|
|
||||||
|
cy.get('app-modal-example h2').should('have.text', '123');
|
||||||
|
cy.get('app-modal-example h3').should('have.text', '321');
|
||||||
|
|
||||||
|
cy.get('#onWillDismiss').should('have.text', 'false');
|
||||||
|
cy.get('#onDidDismiss').should('have.text', 'false');
|
||||||
|
|
||||||
|
cy.get('#close-modal').click();
|
||||||
|
|
||||||
|
cy.get('ion-modal').should('not.exist');
|
||||||
|
|
||||||
|
cy.get('#onWillDismiss').should('have.text', 'true');
|
||||||
|
cy.get('#onDidDismiss').should('have.text', 'true');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should open nav modal and close', () => {
|
||||||
|
cy.get('#action-button-2').click();
|
||||||
|
|
||||||
|
cy.get('ion-modal').should('exist').should('be.visible');
|
||||||
|
|
||||||
|
cy.get('ion-nav > *:last-child h2').should('have.text', '123');
|
||||||
|
cy.get('ion-nav > *:last-child h3').should('have.text', '321');
|
||||||
|
|
||||||
|
cy.get('ion-nav > *:last-child .push-page').click();
|
||||||
|
|
||||||
|
cy.get('ion-nav > *:last-child h2').should('have.text', 'pushed!');
|
||||||
|
cy.get('ion-nav > *:last-child h3').should('have.text', '');
|
||||||
|
|
||||||
|
cy.get('ion-nav > *:last-child .pop-page').click();
|
||||||
|
|
||||||
|
cy.get('ion-nav > *:last-child h2').should('have.text', '123');
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -1,73 +0,0 @@
|
|||||||
import { browser, element, by } from 'protractor';
|
|
||||||
import { handleErrorMessages, waitTime, testStack } from './utils';
|
|
||||||
|
|
||||||
describe('navigation', () => {
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
return handleErrorMessages();
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: Fix flaky tests
|
|
||||||
xit ('should swipe and abort', async () => {
|
|
||||||
await browser.get('/router-link?ionic:mode=ios');
|
|
||||||
await waitTime(500);
|
|
||||||
await element(by.css('#routerLink')).click();
|
|
||||||
await waitTime(500);
|
|
||||||
await swipeLeft(5);
|
|
||||||
await waitTime(500);
|
|
||||||
|
|
||||||
const pageHidden = element(by.css('app-router-link'));
|
|
||||||
expect(await pageHidden.getAttribute('aria-hidden')).toEqual('true');
|
|
||||||
expect(await pageHidden.getAttribute('class')).toEqual('ion-page ion-page-hidden');
|
|
||||||
|
|
||||||
const pageVisible = element(by.css('app-router-link-page'));
|
|
||||||
expect(await pageVisible.getAttribute('aria-hidden')).toEqual(null);
|
|
||||||
expect(await pageVisible.getAttribute('class')).toEqual('ion-page can-go-back');
|
|
||||||
});
|
|
||||||
|
|
||||||
xit ('should swipe and go back', async () => {
|
|
||||||
await browser.get('/router-link?ionic:mode=ios');
|
|
||||||
await waitTime(500);
|
|
||||||
await element(by.css('#routerLink')).click();
|
|
||||||
await waitTime(500);
|
|
||||||
await testStack('ion-router-outlet', ['app-router-link', 'app-router-link-page']);
|
|
||||||
|
|
||||||
await swipeLeft(300);
|
|
||||||
|
|
||||||
await waitTime(1000);
|
|
||||||
await testStack('ion-router-outlet', ['app-router-link']);
|
|
||||||
|
|
||||||
const page = element(by.css('app-router-link'));
|
|
||||||
expect(await page.getAttribute('aria-hidden')).toEqual(null);
|
|
||||||
expect(await page.getAttribute('class')).toEqual('ion-page');
|
|
||||||
})
|
|
||||||
|
|
||||||
it('should navigate correctly', async () => {
|
|
||||||
await browser.get('/navigation/page1');
|
|
||||||
await waitTime(2000);
|
|
||||||
await testStack('ion-router-outlet', ['app-navigation-page2', 'app-navigation-page1']);
|
|
||||||
|
|
||||||
const pageHidden = element(by.css('app-navigation-page2'));
|
|
||||||
expect(await pageHidden.getAttribute('aria-hidden')).toEqual('true');
|
|
||||||
expect(await pageHidden.getAttribute('class')).toEqual('ion-page ion-page-hidden');
|
|
||||||
|
|
||||||
const pageVisible = element(by.css('app-navigation-page1'));
|
|
||||||
expect(await pageVisible.getAttribute('aria-hidden')).toEqual(null);
|
|
||||||
expect(await pageVisible.getAttribute('class')).toEqual('ion-page can-go-back');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
function swipeLeft(end: number) {
|
|
||||||
return browser.driver.touchActions()
|
|
||||||
.tapAndHold({x: 5, y: 1})
|
|
||||||
.move({x: 6, y: 1})
|
|
||||||
.move({x: 7, y: 1})
|
|
||||||
.move({x: 8, y: 1})
|
|
||||||
.move({x: 30, y: 1})
|
|
||||||
.move({x: 300, y: 1})
|
|
||||||
.move({x: end, y: 1})
|
|
||||||
.move({x: end, y: 1})
|
|
||||||
.release({x: end, y: 1})
|
|
||||||
.perform();
|
|
||||||
}
|
|
18
angular/test/test-app/e2e/src/navigation.spec.ts
Normal file
18
angular/test/test-app/e2e/src/navigation.spec.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
describe('Navigation', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit('/navigation');
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should navigate correctly', () => {
|
||||||
|
cy.visit('/navigation/page1');
|
||||||
|
cy.wait(2000);
|
||||||
|
cy.testStack('ion-router-outlet', ['app-navigation-page2', 'app-navigation-page1']);
|
||||||
|
|
||||||
|
cy.get('app-navigation-page2').should('have.attr', 'aria-hidden').and('equal', 'true');
|
||||||
|
cy.get('app-navigation-page2').should('have.attr', 'class').and('equal', 'ion-page ion-page-hidden');
|
||||||
|
|
||||||
|
cy.get('app-navigation-page1').should('not.have.attr', 'aria-hidden');
|
||||||
|
cy.get('app-navigation-page1').should('have.attr', 'class').and('equal', 'ion-page can-go-back');
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
@ -1,23 +0,0 @@
|
|||||||
import { browser, element, by } from 'protractor';
|
|
||||||
import { waitTime, handleErrorMessages, goBack } from './utils';
|
|
||||||
|
|
||||||
describe('nested-outlet', () => {
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
return handleErrorMessages();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should navigate correctly', async () => {
|
|
||||||
await browser.get('/nested-outlet/page');
|
|
||||||
expect(await element(by.css('ion-router-outlet ion-router-outlet app-nested-outlet-page h1')).getText()).toEqual('Nested page 1');
|
|
||||||
|
|
||||||
await element(by.css('#goto-tabs')).click();
|
|
||||||
await waitTime(500);
|
|
||||||
await element(by.css('#goto-nested-page1')).click();
|
|
||||||
await waitTime(500);
|
|
||||||
await element(by.css('#goto-nested-page2')).click();
|
|
||||||
await waitTime(500);
|
|
||||||
expect(await element(by.css('ion-router-outlet ion-router-outlet app-nested-outlet-page2 h1')).getText()).toEqual('Nested page 2');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
25
angular/test/test-app/e2e/src/nested-outlet.spec.ts
Normal file
25
angular/test/test-app/e2e/src/nested-outlet.spec.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
describe('Nested Outlet', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit('/nested-outlet/page');
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should navigate correctly', () => {
|
||||||
|
cy.get('ion-router-outlet ion-router-outlet app-nested-outlet-page h1').should('have.text', 'Nested page 1');
|
||||||
|
|
||||||
|
cy.get('#goto-tabs').click();
|
||||||
|
|
||||||
|
cy.ionPageVisible('app-tabs');
|
||||||
|
cy.ionPageVisible('app-tabs-tab1');
|
||||||
|
|
||||||
|
cy.get('#goto-nested-page1').click();
|
||||||
|
|
||||||
|
cy.ionPageVisible('app-nested-outlet-page');
|
||||||
|
cy.ionPageDoesNotExist('app-tabs');
|
||||||
|
|
||||||
|
cy.get('#goto-nested-page2').click();
|
||||||
|
cy.ionPageVisible('app-nested-outlet-page2');
|
||||||
|
|
||||||
|
cy.get('ion-router-outlet ion-router-outlet app-nested-outlet-page2 h1').should('have.text', 'Nested page 2');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -1,29 +0,0 @@
|
|||||||
import { browser, element, by } from 'protractor';
|
|
||||||
import { handleErrorMessages, waitTime } from './utils';
|
|
||||||
|
|
||||||
describe('providers', () => {
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
return handleErrorMessages();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should load all providers', async () => {
|
|
||||||
await browser.get('/providers');
|
|
||||||
|
|
||||||
expect(await element(by.css('#is-loaded')).getText()).toEqual('true');
|
|
||||||
expect(await element(by.css('#is-ready')).getText()).toEqual('true');
|
|
||||||
expect(await element(by.css('#is-paused')).getText()).toEqual('true');
|
|
||||||
expect(await element(by.css('#is-resumed')).getText()).toEqual('true');
|
|
||||||
expect(await element(by.css('#is-resized')).getText()).toEqual('true');
|
|
||||||
expect(await element(by.css('#is-testing')).getText()).toEqual('false');
|
|
||||||
expect(await element(by.css('#is-desktop')).getText()).toEqual('true');
|
|
||||||
expect(await element(by.css('#is-mobile')).getText()).toEqual('false');
|
|
||||||
expect(await element(by.css('#keyboard-height')).getText()).toEqual('12345');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should detect testing mode', async () => {
|
|
||||||
await browser.get('/providers?ionic:_testing=true');
|
|
||||||
|
|
||||||
expect(await element(by.css('#is-testing')).getText()).toEqual('true');
|
|
||||||
});
|
|
||||||
});
|
|
24
angular/test/test-app/e2e/src/providers.spec.ts
Normal file
24
angular/test/test-app/e2e/src/providers.spec.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
describe('Providers', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit('/providers');
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should load all providers', () => {
|
||||||
|
cy.get('#is-loaded').should('have.text', 'true');
|
||||||
|
cy.get('#is-ready').should('have.text', 'true');
|
||||||
|
cy.get('#is-paused').should('have.text', 'true');
|
||||||
|
cy.get('#is-resumed').should('have.text', 'true');
|
||||||
|
cy.get('#is-resized').should('have.text', 'true');
|
||||||
|
cy.get('#is-testing').should('have.text', 'false');
|
||||||
|
cy.get('#is-desktop').should('have.text', 'true');
|
||||||
|
cy.get('#is-mobile').should('have.text', 'false');
|
||||||
|
cy.get('#keyboard-height').should('have.text', '12345');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should detect testing mode', () => {
|
||||||
|
cy.visit('/providers?ionic:_testing=true');
|
||||||
|
|
||||||
|
cy.get('#is-testing').should('have.text', 'true');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -1,194 +0,0 @@
|
|||||||
import { browser, element, by, protractor } from 'protractor';
|
|
||||||
import { waitTime, testStack, testLifeCycle, handleErrorMessages, getText } from './utils';
|
|
||||||
|
|
||||||
const EC = protractor.ExpectedConditions;
|
|
||||||
|
|
||||||
describe('router-link params and fragments', () => {
|
|
||||||
const queryParam = 'A&=#Y';
|
|
||||||
const fragment = 'myDiv1';
|
|
||||||
const id = 'MyPageID==';
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
return handleErrorMessages();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should go to a page with properly encoded values', async () => {
|
|
||||||
await browser.get('/router-link?ionic:_testing=true');
|
|
||||||
await element(by.css('#queryParamsFragment')).click();
|
|
||||||
|
|
||||||
const expectedRoute = `${encodeURIComponent(id)}?token=${encodeURIComponent(queryParam)}#${encodeURIComponent(fragment)}`;
|
|
||||||
|
|
||||||
browser.wait(EC.urlContains(expectedRoute), 5000);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return to a page with preserved query param and fragment', async () => {
|
|
||||||
await browser.get('/router-link?ionic:_testing=true');
|
|
||||||
await waitTime(30);
|
|
||||||
await element(by.css('#queryParamsFragment')).click();
|
|
||||||
await waitTime(400);
|
|
||||||
await element(by.css('#goToPage3')).click();
|
|
||||||
|
|
||||||
browser.wait(EC.urlContains('router-link-page3'), 5000);
|
|
||||||
await waitTime(400);
|
|
||||||
|
|
||||||
await element(by.css('#goBackFromPage3')).click();
|
|
||||||
|
|
||||||
const expectedRoute = `${encodeURIComponent(id)}?token=${encodeURIComponent(queryParam)}#${encodeURIComponent(fragment)}`;
|
|
||||||
browser.wait(EC.urlContains(expectedRoute), 5000);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should preserve query param and fragment with defaultHref string', async () => {
|
|
||||||
await browser.get('/router-link-page3?ionic:_testing=true');
|
|
||||||
await waitTime(30);
|
|
||||||
|
|
||||||
await element(by.css('#goBackFromPage3')).click();
|
|
||||||
|
|
||||||
const expectedRoute = '?token=ABC#fragment';
|
|
||||||
browser.wait(EC.urlContains(expectedRoute), 5000);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('router-link', () => {
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await browser.get('/router-link');
|
|
||||||
await waitTime(30);
|
|
||||||
});
|
|
||||||
afterEach(() => {
|
|
||||||
return handleErrorMessages();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it('should have correct lifecycle counts', async () => {
|
|
||||||
await testLifeCycle('app-router-link', {
|
|
||||||
ionViewWillEnter: 1,
|
|
||||||
ionViewDidEnter: 1,
|
|
||||||
ionViewWillLeave: 0,
|
|
||||||
ionViewDidLeave: 0,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('forward', () => {
|
|
||||||
|
|
||||||
it('should go forward with ion-button[routerLink]', async () => {
|
|
||||||
await element(by.css('#routerLink')).click();
|
|
||||||
await testForward();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should go forward with a[routerLink]', async () => {
|
|
||||||
await element(by.css('#a')).click();
|
|
||||||
await testForward();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should go forward with button + navigateByUrl()', async () => {
|
|
||||||
await element(by.css('#button')).click();
|
|
||||||
await testForward();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should go forward with button + navigateForward()', async () => {
|
|
||||||
await element(by.css('#button-forward')).click();
|
|
||||||
await testForward();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('root', () => {
|
|
||||||
|
|
||||||
it('should go root with ion-button[routerLink][routerDirection=root]', async () => {
|
|
||||||
await element(by.css('#routerLink-root')).click();
|
|
||||||
await testRoot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should go root with a[routerLink][routerDirection=root]', async () => {
|
|
||||||
await element(by.css('#a-root')).click();
|
|
||||||
await testRoot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should go root with button + navigateRoot', async () => {
|
|
||||||
await element(by.css('#button-root')).click();
|
|
||||||
await testRoot();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('back', () => {
|
|
||||||
|
|
||||||
it('should go back with ion-button[routerLink][routerDirection=back]', async () => {
|
|
||||||
await element(by.css('#routerLink-back')).click();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should go back with a[routerLink][routerDirection=back]', async () => {
|
|
||||||
await element(by.css('#a-back')).click();
|
|
||||||
await testBack();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should go back with button + navigateBack', async () => {
|
|
||||||
await element(by.css('#button-back')).click();
|
|
||||||
await testBack();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
async function testForward() {
|
|
||||||
await waitTime(2500);
|
|
||||||
await testStack('ion-router-outlet', ['app-router-link', 'app-router-link-page']);
|
|
||||||
await testLifeCycle('app-router-link-page', {
|
|
||||||
ionViewWillEnter: 1,
|
|
||||||
ionViewDidEnter: 1,
|
|
||||||
ionViewWillLeave: 0,
|
|
||||||
ionViewDidLeave: 0,
|
|
||||||
});
|
|
||||||
expect(await getText(`app-router-link-page #canGoBack`)).toEqual('true');
|
|
||||||
|
|
||||||
await browser.navigate().back();
|
|
||||||
await waitTime(100);
|
|
||||||
await testStack('ion-router-outlet', ['app-router-link']);
|
|
||||||
await testLifeCycle('app-router-link', {
|
|
||||||
ionViewWillEnter: 2,
|
|
||||||
ionViewDidEnter: 2,
|
|
||||||
ionViewWillLeave: 1,
|
|
||||||
ionViewDidLeave: 1,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function testRoot() {
|
|
||||||
await waitTime(200);
|
|
||||||
await testStack('ion-router-outlet', ['app-router-link-page']);
|
|
||||||
await testLifeCycle('app-router-link-page', {
|
|
||||||
ionViewWillEnter: 1,
|
|
||||||
ionViewDidEnter: 1,
|
|
||||||
ionViewWillLeave: 0,
|
|
||||||
ionViewDidLeave: 0,
|
|
||||||
});
|
|
||||||
expect(await getText(`app-router-link-page #canGoBack`)).toEqual('false');
|
|
||||||
|
|
||||||
await browser.navigate().back();
|
|
||||||
await waitTime(100);
|
|
||||||
await testStack('ion-router-outlet', ['app-router-link']);
|
|
||||||
await testLifeCycle('app-router-link', {
|
|
||||||
ionViewWillEnter: 1,
|
|
||||||
ionViewDidEnter: 1,
|
|
||||||
ionViewWillLeave: 0,
|
|
||||||
ionViewDidLeave: 0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function testBack() {
|
|
||||||
await waitTime(500);
|
|
||||||
await testStack('ion-router-outlet', ['app-router-link-page']);
|
|
||||||
await testLifeCycle('app-router-link-page', {
|
|
||||||
ionViewWillEnter: 1,
|
|
||||||
ionViewDidEnter: 1,
|
|
||||||
ionViewWillLeave: 0,
|
|
||||||
ionViewDidLeave: 0,
|
|
||||||
});
|
|
||||||
expect(await getText(`app-router-link-page #canGoBack`)).toEqual('false');
|
|
||||||
|
|
||||||
await browser.navigate().back();
|
|
||||||
await waitTime(100);
|
|
||||||
await testStack('ion-router-outlet', ['app-router-link']);
|
|
||||||
await testLifeCycle('app-router-link', {
|
|
||||||
ionViewWillEnter: 1,
|
|
||||||
ionViewDidEnter: 1,
|
|
||||||
ionViewWillLeave: 0,
|
|
||||||
ionViewDidLeave: 0,
|
|
||||||
});
|
|
||||||
}
|
|
192
angular/test/test-app/e2e/src/router-link.spec.ts
Normal file
192
angular/test/test-app/e2e/src/router-link.spec.ts
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
describe('Router Link', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit('/router-link');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('router-link params and fragments', () => {
|
||||||
|
const queryParam = 'A&=#Y';
|
||||||
|
const fragment = 'myDiv1';
|
||||||
|
const id = 'MyPageID==';
|
||||||
|
|
||||||
|
it('should go to a page with properly encoded values', () => {
|
||||||
|
cy.visit('/router-link?ionic:_testing=true');
|
||||||
|
cy.get('#queryParamsFragment').click();
|
||||||
|
|
||||||
|
const expectedPath = `${encodeURIComponent(id)}`;
|
||||||
|
const expectedSearch = `?token=${encodeURIComponent(queryParam)}`;
|
||||||
|
const expectedHash = `#${encodeURIComponent(fragment)}`;
|
||||||
|
|
||||||
|
cy.location().should((location) => {
|
||||||
|
expect(location.pathname).to.contain(expectedPath);
|
||||||
|
expect(location.search).to.eq(expectedSearch);
|
||||||
|
expect(location.hash).to.eq(expectedHash);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return to a page with preserved query param and fragment', () => {
|
||||||
|
cy.visit('/router-link?ionic:_testing=true');
|
||||||
|
cy.get('#queryParamsFragment').click();
|
||||||
|
cy.get('#goToPage3').click();
|
||||||
|
|
||||||
|
cy.location().should((location) => {
|
||||||
|
expect(location.pathname).to.contain('router-link-page3');
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.get('#goBackFromPage3').click();
|
||||||
|
|
||||||
|
const expectedPath = `${encodeURIComponent(id)}`;
|
||||||
|
const expectedSearch = `?token=${encodeURIComponent(queryParam)}`;
|
||||||
|
const expectedHash = `#${encodeURIComponent(fragment)}`;
|
||||||
|
|
||||||
|
cy.location().should((location) => {
|
||||||
|
expect(location.pathname).to.contain(expectedPath);
|
||||||
|
expect(location.search).to.eq(expectedSearch);
|
||||||
|
expect(location.hash).to.eq(expectedHash);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should preserve query param and fragment with defaultHref string', () => {
|
||||||
|
cy.visit('/router-link-page3?ionic:_testing=true');
|
||||||
|
|
||||||
|
cy.get('#goBackFromPage3').click();
|
||||||
|
|
||||||
|
const expectedSearch = '?token=ABC';
|
||||||
|
const expectedHash = '#fragment';
|
||||||
|
|
||||||
|
cy.location().should((location) => {
|
||||||
|
expect(location.search).to.eq(expectedSearch);
|
||||||
|
expect(location.hash).to.eq(expectedHash);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('router-link', () => {
|
||||||
|
it('should have correct lifecycle counts', () => {
|
||||||
|
cy.testLifeCycle('app-router-link', {
|
||||||
|
ionViewWillEnter: 1,
|
||||||
|
ionViewDidEnter: 1,
|
||||||
|
ionViewWillLeave: 0,
|
||||||
|
ionViewDidLeave: 0,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('forward', () => {
|
||||||
|
it('should go forward with ion-button[routerLink]', () => {
|
||||||
|
cy.get('#routerLink').click();
|
||||||
|
testForward();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should go forward with a[routerLink]', () => {
|
||||||
|
cy.get('#a').click();
|
||||||
|
testForward();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should go forward with button + navigateByUrl()', () => {
|
||||||
|
cy.get('#button').click();
|
||||||
|
testForward();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should go forward with button + navigateForward()', () => {
|
||||||
|
cy.get('#button-forward').click();
|
||||||
|
testForward();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('root', () => {
|
||||||
|
it('should go root with ion-button[routerLink][routerDirection=root]', () => {
|
||||||
|
cy.get('#routerLink-root').click();
|
||||||
|
testRoot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should go root with a[routerLink][routerDirection=root]', () => {
|
||||||
|
cy.get('#a-root').click();
|
||||||
|
testRoot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should go root with button + navigateRoot', () => {
|
||||||
|
cy.get('#button-root').click();
|
||||||
|
testRoot();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('back', () => {
|
||||||
|
it('should go back with ion-button[routerLink][routerDirection=back]', () => {
|
||||||
|
cy.get('#routerLink-back').click();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should go back with a[routerLink][routerDirection=back]', () => {
|
||||||
|
cy.get('#a-back').click();
|
||||||
|
testBack();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should go back with button + navigateBack', () => {
|
||||||
|
cy.get('#button-back').click();
|
||||||
|
testBack();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function testForward() {
|
||||||
|
cy.testStack('ion-router-outlet', ['app-router-link', 'app-router-link-page']);
|
||||||
|
cy.testLifeCycle('app-router-link-page', {
|
||||||
|
ionViewWillEnter: 1,
|
||||||
|
ionViewDidEnter: 1,
|
||||||
|
ionViewWillLeave: 0,
|
||||||
|
ionViewDidLeave: 0,
|
||||||
|
});
|
||||||
|
cy.get('app-router-link-page #canGoBack').should('have.text', 'true');
|
||||||
|
|
||||||
|
cy.go('back');
|
||||||
|
cy.testStack('ion-router-outlet', ['app-router-link']);
|
||||||
|
cy.testLifeCycle('app-router-link', {
|
||||||
|
ionViewWillEnter: 2,
|
||||||
|
ionViewDidEnter: 2,
|
||||||
|
ionViewWillLeave: 1,
|
||||||
|
ionViewDidLeave: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function testRoot() {
|
||||||
|
cy.wait(200);
|
||||||
|
cy.testStack('ion-router-outlet', ['app-router-link-page']);
|
||||||
|
cy.testLifeCycle('app-router-link-page', {
|
||||||
|
ionViewWillEnter: 1,
|
||||||
|
ionViewDidEnter: 1,
|
||||||
|
ionViewWillLeave: 0,
|
||||||
|
ionViewDidLeave: 0,
|
||||||
|
});
|
||||||
|
cy.get('app-router-link-page #canGoBack').should('have.text', 'false');
|
||||||
|
|
||||||
|
cy.go('back');
|
||||||
|
cy.wait(100);
|
||||||
|
cy.testStack('ion-router-outlet', ['app-router-link']);
|
||||||
|
cy.testLifeCycle('app-router-link', {
|
||||||
|
ionViewWillEnter: 1,
|
||||||
|
ionViewDidEnter: 1,
|
||||||
|
ionViewWillLeave: 0,
|
||||||
|
ionViewDidLeave: 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function testBack() {
|
||||||
|
cy.wait(500);
|
||||||
|
cy.testStack('ion-router-outlet', ['app-router-link-page']);
|
||||||
|
cy.testLifeCycle('app-router-link-page', {
|
||||||
|
ionViewWillEnter: 1,
|
||||||
|
ionViewDidEnter: 1,
|
||||||
|
ionViewWillLeave: 0,
|
||||||
|
ionViewDidLeave: 0,
|
||||||
|
});
|
||||||
|
cy.get('app-router-link-page #canGoBack').should('have.text', 'false');
|
||||||
|
|
||||||
|
cy.go('back');
|
||||||
|
cy.wait(100);
|
||||||
|
cy.testStack('ion-router-outlet', ['app-router-link']);
|
||||||
|
cy.testLifeCycle('app-router-link', {
|
||||||
|
ionViewWillEnter: 1,
|
||||||
|
ionViewDidEnter: 1,
|
||||||
|
ionViewWillLeave: 0,
|
||||||
|
ionViewDidLeave: 0,
|
||||||
|
});
|
||||||
|
}
|
36
angular/test/test-app/e2e/src/routing.spec.ts
Normal file
36
angular/test/test-app/e2e/src/routing.spec.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
describe('Routing', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit('/router-link?ionic:mode=ios');
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should swipe and abort', () => {
|
||||||
|
cy.get('#routerLink').click();
|
||||||
|
|
||||||
|
cy.ionSwipeToGoBack();
|
||||||
|
|
||||||
|
cy.get('app-router-link').should('have.attr', 'aria-hidden').and('equal', 'true');
|
||||||
|
cy.get('app-router-link').should('have.attr', 'class').and('equal', 'ion-page ion-page-hidden');
|
||||||
|
|
||||||
|
cy.get('app-router-link-page').should('not.have.attr', 'aria-hidden');
|
||||||
|
cy.get('app-router-link-page').should('have.attr', 'class').and('equal', 'ion-page can-go-back');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should swipe and go back', () => {
|
||||||
|
cy.get('#routerLink').click();
|
||||||
|
|
||||||
|
cy.ionPageHidden('app-router-link');
|
||||||
|
cy.ionPageVisible('app-router-link-page');
|
||||||
|
|
||||||
|
cy.testStack('ion-router-outlet', ['app-router-link', 'app-router-link-page']);
|
||||||
|
|
||||||
|
cy.ionSwipeToGoBack(true);
|
||||||
|
|
||||||
|
cy.ionPageVisible('app-router-link');
|
||||||
|
cy.ionPageDoesNotExist('app-router-link-page');
|
||||||
|
|
||||||
|
cy.testStack('ion-router-outlet', ['app-router-link']);
|
||||||
|
|
||||||
|
cy.get('app-router-link').should('not.have.attr', 'aria-hidden');
|
||||||
|
cy.get('app-router-link').should('have.attr', 'class').and('equal', 'ion-page');
|
||||||
|
});
|
||||||
|
})
|
@ -1,51 +0,0 @@
|
|||||||
import { browser, element, by } from 'protractor';
|
|
||||||
import { handleErrorMessages, waitTime } from './utils';
|
|
||||||
|
|
||||||
describe('slides', () => {
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await browser.get('/slides');
|
|
||||||
await waitTime(30);
|
|
||||||
});
|
|
||||||
afterEach(() => {
|
|
||||||
return handleErrorMessages();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should change index on slide change', async () => {
|
|
||||||
expect(await element.all(by.css('ion-slide')).count()).toEqual(0);
|
|
||||||
await addSlides();
|
|
||||||
expect(await element.all(by.css('ion-slide')).count()).toEqual(3);
|
|
||||||
|
|
||||||
await checkIndex('0');
|
|
||||||
|
|
||||||
await nextSlide();
|
|
||||||
await checkIndex('1');
|
|
||||||
|
|
||||||
await nextSlide();
|
|
||||||
await checkIndex('2');
|
|
||||||
|
|
||||||
await prevSlide();
|
|
||||||
await checkIndex('1');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
async function checkIndex(index: string) {
|
|
||||||
expect(await element(by.css('#slide-index')).getText()).toEqual(index);
|
|
||||||
expect(await element(by.css('#slide-index-2')).getText()).toEqual(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function addSlides() {
|
|
||||||
await element(by.css('#add-slides')).click();
|
|
||||||
await waitTime(800);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async function nextSlide() {
|
|
||||||
await element(by.css('#btn-next')).click();
|
|
||||||
await waitTime(800);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function prevSlide() {
|
|
||||||
await element(by.css('#btn-prev')).click();
|
|
||||||
await waitTime(800);
|
|
||||||
}
|
|
44
angular/test/test-app/e2e/src/slides.spec.ts
Normal file
44
angular/test/test-app/e2e/src/slides.spec.ts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
describe('Slides', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit('/slides');
|
||||||
|
cy.wait(30);
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should change index on slide change', () => {
|
||||||
|
cy.get('ion-slide').should('have.length', 0);
|
||||||
|
|
||||||
|
cy.get('#add-slides').click();
|
||||||
|
|
||||||
|
cy.get('ion-slide').should('have.length', 3);
|
||||||
|
|
||||||
|
// Should be on the first slide
|
||||||
|
checkIndex('0');
|
||||||
|
|
||||||
|
// Swipe to the second slide
|
||||||
|
nextSlide();
|
||||||
|
checkIndex('1');
|
||||||
|
|
||||||
|
// Swipe to the third slide
|
||||||
|
nextSlide();
|
||||||
|
checkIndex('2');
|
||||||
|
|
||||||
|
// Go back to the second slide
|
||||||
|
prevSlide();
|
||||||
|
checkIndex('1');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function checkIndex(index) {
|
||||||
|
cy.get('#slide-index').should('have.text', index);
|
||||||
|
cy.get('#slide-index-2').should('have.text', index);
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextSlide() {
|
||||||
|
cy.get('#btn-next').click();
|
||||||
|
cy.wait(800);
|
||||||
|
}
|
||||||
|
|
||||||
|
function prevSlide() {
|
||||||
|
cy.get('#btn-prev').click();
|
||||||
|
cy.wait(800);
|
||||||
|
}
|
@ -1,334 +0,0 @@
|
|||||||
import { browser, by, element, ElementFinder, ExpectedConditions } from 'protractor';
|
|
||||||
import { handleErrorMessages, testStack, waitTime } from './utils';
|
|
||||||
|
|
||||||
describe('tabs', () => {
|
|
||||||
afterEach(() => {
|
|
||||||
return handleErrorMessages();
|
|
||||||
});
|
|
||||||
describe('entry url - /tabs', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await browser.get('/tabs');
|
|
||||||
await waitTime(30);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should redirect and load tab-account', async () => {
|
|
||||||
await testTabTitle('Tab 1 - Page 1');
|
|
||||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1']);
|
|
||||||
await testState(1, 'account');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should navigate between tabs and ionChange events should be dispatched ', async () => {
|
|
||||||
let tab = await testTabTitle('Tab 1 - Page 1');
|
|
||||||
expect(await tab.$('.segment-changed').getText()).toEqual('false');
|
|
||||||
|
|
||||||
await element(by.css('#tab-button-contact')).click();
|
|
||||||
tab = await testTabTitle('Tab 2 - Page 1');
|
|
||||||
expect(await tab.$('.segment-changed').getText()).toEqual('false');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should simulate stack + double tab click', async () => {
|
|
||||||
let tab = await getSelectedTab() as ElementFinder;
|
|
||||||
await tab.$('#goto-tab1-page2').click();
|
|
||||||
await testTabTitle('Tab 1 - Page 2 (1)');
|
|
||||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab1-nested']);
|
|
||||||
await testState(1, 'account');
|
|
||||||
expect(await tab.$('ion-back-button').isDisplayed()).toBe(true);
|
|
||||||
|
|
||||||
await element(by.css('#tab-button-contact')).click();
|
|
||||||
await testTabTitle('Tab 2 - Page 1');
|
|
||||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab1-nested', 'app-tabs-tab2']);
|
|
||||||
await testState(2, 'contact');
|
|
||||||
|
|
||||||
await element(by.css('#tab-button-account')).click();
|
|
||||||
tab = await testTabTitle('Tab 1 - Page 2 (1)');
|
|
||||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab1-nested', 'app-tabs-tab2']);
|
|
||||||
await testState(3, 'account');
|
|
||||||
expect(await tab.$('ion-back-button').isDisplayed()).toBe(true);
|
|
||||||
|
|
||||||
await element(by.css('#tab-button-account')).click();
|
|
||||||
await testTabTitle('Tab 1 - Page 1');
|
|
||||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab2']);
|
|
||||||
await testState(3, 'account');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should simulate stack + back button click', async () => {
|
|
||||||
const tab = await getSelectedTab();
|
|
||||||
await tab.$('#goto-tab1-page2').click();
|
|
||||||
await testTabTitle('Tab 1 - Page 2 (1)');
|
|
||||||
await testState(1, 'account');
|
|
||||||
|
|
||||||
await element(by.css('#tab-button-contact')).click();
|
|
||||||
await testTabTitle('Tab 2 - Page 1');
|
|
||||||
await testState(2, 'contact');
|
|
||||||
|
|
||||||
await element(by.css('#tab-button-account')).click();
|
|
||||||
await testTabTitle('Tab 1 - Page 2 (1)');
|
|
||||||
await testState(3, 'account');
|
|
||||||
|
|
||||||
await element(by.css('ion-back-button')).click();
|
|
||||||
await testTabTitle('Tab 1 - Page 1');
|
|
||||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab2']);
|
|
||||||
await testState(3, 'account');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should navigate deep then go home', async () => {
|
|
||||||
let tab = await getSelectedTab();
|
|
||||||
await tab.$('#goto-tab1-page2').click();
|
|
||||||
tab = await testTabTitle('Tab 1 - Page 2 (1)');
|
|
||||||
|
|
||||||
await tab.$('#goto-next').click();
|
|
||||||
tab = await testTabTitle('Tab 1 - Page 2 (2)');
|
|
||||||
|
|
||||||
await element(by.css('#tab-button-contact')).click();
|
|
||||||
tab = await testTabTitle('Tab 2 - Page 1');
|
|
||||||
|
|
||||||
await element(by.css('#tab-button-account')).click();
|
|
||||||
await testTabTitle('Tab 1 - Page 2 (2)');
|
|
||||||
await testStack('ion-tabs ion-router-outlet', [
|
|
||||||
'app-tabs-tab1',
|
|
||||||
'app-tabs-tab1-nested',
|
|
||||||
'app-tabs-tab1-nested',
|
|
||||||
'app-tabs-tab2'
|
|
||||||
]);
|
|
||||||
await element(by.css('#tab-button-account')).click();
|
|
||||||
await testTabTitle('Tab 1 - Page 1');
|
|
||||||
await testStack('ion-tabs ion-router-outlet', [
|
|
||||||
'app-tabs-tab1',
|
|
||||||
'app-tabs-tab2'
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should switch tabs and go back', async () => {
|
|
||||||
await element(by.css('#tab-button-contact')).click();
|
|
||||||
const tab = await testTabTitle('Tab 2 - Page 1');
|
|
||||||
|
|
||||||
await tab.$('#goto-tab1-page1').click();
|
|
||||||
await testTabTitle('Tab 1 - Page 1');
|
|
||||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab2']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should switch tabs and go to nested', async () => {
|
|
||||||
await element(by.css('#tab-button-contact')).click();
|
|
||||||
const tab = await testTabTitle('Tab 2 - Page 1');
|
|
||||||
|
|
||||||
await tab.$('#goto-tab1-page2').click();
|
|
||||||
await testTabTitle('Tab 1 - Page 2 (1)');
|
|
||||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab2', 'app-tabs-tab1-nested']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should load lazy loaded tab', async () => {
|
|
||||||
await element(by.css('#tab-button-lazy')).click();
|
|
||||||
await testTabTitle('Tab 3 - Page 1');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should use ion-back-button defaultHref', async () => {
|
|
||||||
let tab = await getSelectedTab() as ElementFinder;
|
|
||||||
await tab.$('#goto-tab3-page2').click();
|
|
||||||
tab = await testTabTitle('Tab 3 - Page 2');
|
|
||||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab3-nested']);
|
|
||||||
|
|
||||||
await tab.$('ion-back-button').click();
|
|
||||||
await testTabTitle('Tab 3 - Page 1');
|
|
||||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab3']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should preserve navigation extras when switching tabs', async () => {
|
|
||||||
const expectUrlToContain = 'search=hello#fragment';
|
|
||||||
let tab = await getSelectedTab() as ElementFinder;
|
|
||||||
await tab.$('#goto-nested-page1-with-query-params').click();
|
|
||||||
await testTabTitle('Tab 1 - Page 2 (1)');
|
|
||||||
await testUrlContains(expectUrlToContain);
|
|
||||||
|
|
||||||
await element(by.css('#tab-button-contact')).click();
|
|
||||||
await testTabTitle('Tab 2 - Page 1');
|
|
||||||
|
|
||||||
await element(by.css('#tab-button-account')).click();
|
|
||||||
tab = await testTabTitle('Tab 1 - Page 2 (1)');
|
|
||||||
await testUrlContains(expectUrlToContain);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should set root when clicking on an active tab to navigate to the root', async () => {
|
|
||||||
const expectNestedTabUrlToContain = 'search=hello#fragment';
|
|
||||||
const tab = await getSelectedTab() as ElementFinder;
|
|
||||||
const initialUrl = await browser.getCurrentUrl();
|
|
||||||
await tab.$('#goto-nested-page1-with-query-params').click();
|
|
||||||
await testTabTitle('Tab 1 - Page 2 (1)');
|
|
||||||
await testUrlContains(expectNestedTabUrlToContain);
|
|
||||||
|
|
||||||
await element(by.css('#tab-button-account')).click();
|
|
||||||
await testTabTitle('Tab 1 - Page 1');
|
|
||||||
|
|
||||||
await testUrlEquals(initialUrl);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('entry tab contains navigation extras', () => {
|
|
||||||
const expectNestedTabUrlToContain = 'search=hello#fragment';
|
|
||||||
const rootUrlParams = 'test=123#rootFragment';
|
|
||||||
const rootUrl = `/tabs/account?${rootUrlParams}`;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await browser.get(rootUrl);
|
|
||||||
await waitTime(30);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should preserve root url navigation extras when clicking on an active tab to navigate to the root', async () => {
|
|
||||||
await browser.get(rootUrl);
|
|
||||||
|
|
||||||
const tab = await getSelectedTab() as ElementFinder;
|
|
||||||
await tab.$('#goto-nested-page1-with-query-params').click();
|
|
||||||
await testTabTitle('Tab 1 - Page 2 (1)');
|
|
||||||
await testUrlContains(expectNestedTabUrlToContain);
|
|
||||||
|
|
||||||
await element(by.css('#tab-button-account')).click();
|
|
||||||
await testTabTitle('Tab 1 - Page 1');
|
|
||||||
|
|
||||||
await testUrlContains(rootUrl);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should preserve root url navigation extras when changing tabs', async () => {
|
|
||||||
await browser.get(rootUrl);
|
|
||||||
|
|
||||||
let tab = await getSelectedTab() as ElementFinder;
|
|
||||||
await element(by.css('#tab-button-contact')).click();
|
|
||||||
tab = await testTabTitle('Tab 2 - Page 1');
|
|
||||||
|
|
||||||
await element(by.css('#tab-button-account')).click();
|
|
||||||
await testTabTitle('Tab 1 - Page 1');
|
|
||||||
|
|
||||||
await testUrlContains(rootUrl);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should navigate deep then go home and preserve navigation extras', async () => {
|
|
||||||
let tab = await getSelectedTab();
|
|
||||||
await tab.$('#goto-tab1-page2').click();
|
|
||||||
tab = await testTabTitle('Tab 1 - Page 2 (1)');
|
|
||||||
|
|
||||||
await tab.$('#goto-next').click();
|
|
||||||
tab = await testTabTitle('Tab 1 - Page 2 (2)');
|
|
||||||
|
|
||||||
await element(by.css('#tab-button-contact')).click();
|
|
||||||
tab = await testTabTitle('Tab 2 - Page 1');
|
|
||||||
|
|
||||||
await element(by.css('#tab-button-account')).click();
|
|
||||||
await testTabTitle('Tab 1 - Page 2 (2)');
|
|
||||||
|
|
||||||
await element(by.css('#tab-button-account')).click();
|
|
||||||
await testTabTitle('Tab 1 - Page 1');
|
|
||||||
|
|
||||||
await testUrlContains(rootUrl);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('entry url - /tabs/account/nested/1', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await browser.get('/tabs/account/nested/1');
|
|
||||||
await waitTime(30);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should only display the back-button when there is a page in the stack', async () => {
|
|
||||||
let tab = await testTabTitle('Tab 1 - Page 2 (1)') as ElementFinder;
|
|
||||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1-nested']);
|
|
||||||
expect(await tab.$('ion-back-button').isDisplayed()).toBe(false);
|
|
||||||
|
|
||||||
await element(by.css('#tab-button-account')).click();
|
|
||||||
tab = await testTabTitle('Tab 1 - Page 1');
|
|
||||||
|
|
||||||
await tab.$('#goto-tab1-page2').click();
|
|
||||||
tab = await testTabTitle('Tab 1 - Page 2 (1)');
|
|
||||||
expect(await tab.$('ion-back-button').isDisplayed()).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not reuse the same page', async () => {
|
|
||||||
let tab = await testTabTitle('Tab 1 - Page 2 (1)') as ElementFinder;
|
|
||||||
await tab.$('#goto-next').click();
|
|
||||||
tab = await testTabTitle('Tab 1 - Page 2 (2)');
|
|
||||||
await tab.$('#goto-next').click();
|
|
||||||
tab = await testTabTitle('Tab 1 - Page 2 (3)');
|
|
||||||
|
|
||||||
await testStack('ion-tabs ion-router-outlet', [
|
|
||||||
'app-tabs-tab1-nested',
|
|
||||||
'app-tabs-tab1-nested',
|
|
||||||
'app-tabs-tab1-nested'
|
|
||||||
]);
|
|
||||||
|
|
||||||
await tab.$('ion-back-button').click();
|
|
||||||
tab = await testTabTitle('Tab 1 - Page 2 (2)');
|
|
||||||
await tab.$('ion-back-button').click();
|
|
||||||
tab = await testTabTitle('Tab 1 - Page 2 (1)');
|
|
||||||
|
|
||||||
expect(await tab.$('ion-back-button').isDisplayed()).toBe(false);
|
|
||||||
|
|
||||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1-nested']);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('entry url - /tabs/lazy', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await browser.get('/tabs/lazy');
|
|
||||||
await waitTime(30);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not display the back-button if coming from a different stack', async () => {
|
|
||||||
let tab = await testTabTitle('Tab 3 - Page 1') as ElementFinder;
|
|
||||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab3']);
|
|
||||||
|
|
||||||
await tab.$('#goto-tab1-page2').click();
|
|
||||||
tab = await testTabTitle('Tab 1 - Page 2 (1)');
|
|
||||||
await testStack('ion-tabs ion-router-outlet', ['app-tabs-tab3', 'app-tabs-tab1-nested']);
|
|
||||||
expect(await tab.$('ion-back-button').isDisplayed()).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('enter url - /tabs/contact/one', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await browser.get('/tabs/contact/one');
|
|
||||||
await waitTime(30);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return to correct tab after going to page in different outlet', async () => {
|
|
||||||
const tab = await getSelectedTab();
|
|
||||||
await tab.$('#goto-nested-page1').click();
|
|
||||||
|
|
||||||
await waitTime(600);
|
|
||||||
await testStack('app-nested-outlet ion-router-outlet', ['app-nested-outlet-page']);
|
|
||||||
|
|
||||||
const nestedOutlet = await element(by.css('app-nested-outlet'));
|
|
||||||
const backButton = await nestedOutlet.$('ion-back-button');
|
|
||||||
await backButton.click();
|
|
||||||
|
|
||||||
await testTabTitle('Tab 2 - Page 1');
|
|
||||||
});
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
async function testState(count: number, tab: string) {
|
|
||||||
expect(await element(by.css('#tabs-state')).getText()).toEqual(`${count}.${tab}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function testTabTitle(title: string) {
|
|
||||||
await waitTime(1000);
|
|
||||||
const tab = await getSelectedTab();
|
|
||||||
expect(await tab.$('ion-title').getText()).toEqual(title);
|
|
||||||
return tab;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function testUrlContains(urlFragment: string) {
|
|
||||||
await browser.wait(ExpectedConditions.urlContains(urlFragment),
|
|
||||||
5000,
|
|
||||||
`expected ${browser.getCurrentUrl()} to contain ${urlFragment}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function testUrlEquals(url: string) {
|
|
||||||
await browser.wait(ExpectedConditions.urlIs(url),
|
|
||||||
5000,
|
|
||||||
`expected ${browser.getCurrentUrl()} to equal ${url}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getSelectedTab(): Promise<ElementFinder> {
|
|
||||||
const tabs = element.all(by.css('ion-tabs ion-router-outlet > *:not(.ion-page-hidden)'));
|
|
||||||
expect(await tabs.count()).toEqual(1);
|
|
||||||
const tab = tabs.first();
|
|
||||||
return tab;
|
|
||||||
}
|
|
329
angular/test/test-app/e2e/src/tabs.spec.ts
Normal file
329
angular/test/test-app/e2e/src/tabs.spec.ts
Normal file
@ -0,0 +1,329 @@
|
|||||||
|
describe('Tabs', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit('/tabs');
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('entry url - /tabs', () => {
|
||||||
|
it('should redirect and load tab-account', () => {
|
||||||
|
testTabTitle('Tab 1 - Page 1');
|
||||||
|
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1']);
|
||||||
|
testState(1, 'account');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should navigate between tabs and ionChange events should be dispatched', () => {
|
||||||
|
let tab = testTabTitle('Tab 1 - Page 1');
|
||||||
|
tab.find('.segment-changed').should('have.text', 'false');
|
||||||
|
|
||||||
|
cy.get('#tab-button-contact').click();
|
||||||
|
tab = testTabTitle('Tab 2 - Page 1');
|
||||||
|
tab.find('.segment-changed').should('have.text', 'false');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should simulate stack + double tab click', () => {
|
||||||
|
let tab = getSelectedTab();
|
||||||
|
tab.find('#goto-tab1-page2').click();
|
||||||
|
testTabTitle('Tab 1 - Page 2 (1)');
|
||||||
|
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab1-nested']);
|
||||||
|
testState(1, 'account');
|
||||||
|
|
||||||
|
// When you call find on tab above it changes the value of tab
|
||||||
|
// so we need to redefine it
|
||||||
|
tab = getSelectedTab();
|
||||||
|
tab.find('ion-back-button').should('be.visible');
|
||||||
|
|
||||||
|
cy.get('#tab-button-contact').click();
|
||||||
|
testTabTitle('Tab 2 - Page 1');
|
||||||
|
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab1-nested', 'app-tabs-tab2']);
|
||||||
|
testState(2, 'contact');
|
||||||
|
|
||||||
|
cy.get('#tab-button-account').click();
|
||||||
|
testTabTitle('Tab 1 - Page 2 (1)');
|
||||||
|
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab1-nested', 'app-tabs-tab2']);
|
||||||
|
testState(3, 'account');
|
||||||
|
|
||||||
|
tab = getSelectedTab();
|
||||||
|
tab.find('ion-back-button').should('be.visible');
|
||||||
|
|
||||||
|
cy.get('#tab-button-account').click();
|
||||||
|
testTabTitle('Tab 1 - Page 1');
|
||||||
|
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab2']);
|
||||||
|
testState(3, 'account');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should simulate stack + back button click', () => {
|
||||||
|
const tab = getSelectedTab();
|
||||||
|
tab.find('#goto-tab1-page2').click();
|
||||||
|
testTabTitle('Tab 1 - Page 2 (1)');
|
||||||
|
testState(1, 'account');
|
||||||
|
|
||||||
|
cy.get('#tab-button-contact').click();
|
||||||
|
testTabTitle('Tab 2 - Page 1');
|
||||||
|
testState(2, 'contact');
|
||||||
|
|
||||||
|
cy.get('#tab-button-account').click();
|
||||||
|
testTabTitle('Tab 1 - Page 2 (1)');
|
||||||
|
testState(3, 'account');
|
||||||
|
|
||||||
|
cy.get('ion-back-button').click();
|
||||||
|
testTabTitle('Tab 1 - Page 1');
|
||||||
|
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab2']);
|
||||||
|
testState(3, 'account');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should navigate deep then go home', () => {
|
||||||
|
const tab = getSelectedTab();
|
||||||
|
tab.find('#goto-tab1-page2').click();
|
||||||
|
testTabTitle('Tab 1 - Page 2 (1)');
|
||||||
|
|
||||||
|
cy.get('#goto-next').click();
|
||||||
|
testTabTitle('Tab 1 - Page 2 (2)');
|
||||||
|
|
||||||
|
cy.get('#tab-button-contact').click();
|
||||||
|
testTabTitle('Tab 2 - Page 1');
|
||||||
|
|
||||||
|
cy.get('#tab-button-account').click();
|
||||||
|
testTabTitle('Tab 1 - Page 2 (2)');
|
||||||
|
cy.testStack('ion-tabs ion-router-outlet', [
|
||||||
|
'app-tabs-tab1',
|
||||||
|
'app-tabs-tab1-nested',
|
||||||
|
'app-tabs-tab1-nested',
|
||||||
|
'app-tabs-tab2'
|
||||||
|
]);
|
||||||
|
|
||||||
|
cy.get('#tab-button-account').click();
|
||||||
|
testTabTitle('Tab 1 - Page 1');
|
||||||
|
cy.testStack('ion-tabs ion-router-outlet', [
|
||||||
|
'app-tabs-tab1',
|
||||||
|
'app-tabs-tab2'
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should switch tabs and go back', () => {
|
||||||
|
cy.get('#tab-button-contact').click();
|
||||||
|
const tab = testTabTitle('Tab 2 - Page 1');
|
||||||
|
|
||||||
|
tab.find('#goto-tab1-page1').click();
|
||||||
|
testTabTitle('Tab 1 - Page 1');
|
||||||
|
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab2']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should switch tabs and go to nested', () => {
|
||||||
|
cy.get('#tab-button-contact').click();
|
||||||
|
const tab = testTabTitle('Tab 2 - Page 1');
|
||||||
|
|
||||||
|
tab.find('#goto-tab1-page2').click();
|
||||||
|
testTabTitle('Tab 1 - Page 2 (1)');
|
||||||
|
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab2', 'app-tabs-tab1-nested']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load lazy loaded tab', () => {
|
||||||
|
cy.get('#tab-button-lazy').click();
|
||||||
|
cy.ionPageVisible('app-tabs-tab3');
|
||||||
|
testTabTitle('Tab 3 - Page 1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use ion-back-button defaultHref', () => {
|
||||||
|
let tab = getSelectedTab();
|
||||||
|
tab.find('#goto-tab3-page2').click();
|
||||||
|
testTabTitle('Tab 3 - Page 2');
|
||||||
|
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab3-nested']);
|
||||||
|
|
||||||
|
tab = getSelectedTab();
|
||||||
|
tab.find('ion-back-button').click();
|
||||||
|
testTabTitle('Tab 3 - Page 1');
|
||||||
|
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1', 'app-tabs-tab3']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should preserve navigation extras when switching tabs', () => {
|
||||||
|
const expectUrlToContain = 'search=hello#fragment';
|
||||||
|
let tab = getSelectedTab();
|
||||||
|
tab.find('#goto-nested-page1-with-query-params').click();
|
||||||
|
testTabTitle('Tab 1 - Page 2 (1)');
|
||||||
|
testUrlContains(expectUrlToContain);
|
||||||
|
|
||||||
|
cy.get('#tab-button-contact').click();
|
||||||
|
testTabTitle('Tab 2 - Page 1');
|
||||||
|
|
||||||
|
cy.get('#tab-button-account').click();
|
||||||
|
tab = testTabTitle('Tab 1 - Page 2 (1)');
|
||||||
|
testUrlContains(expectUrlToContain);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set root when clicking on an active tab to navigate to the root', () => {
|
||||||
|
const expectNestedTabUrlToContain = 'search=hello#fragment';
|
||||||
|
cy.url().then(url => {
|
||||||
|
const tab = getSelectedTab();
|
||||||
|
tab.find('#goto-nested-page1-with-query-params').click();
|
||||||
|
testTabTitle('Tab 1 - Page 2 (1)');
|
||||||
|
testUrlContains(expectNestedTabUrlToContain);
|
||||||
|
|
||||||
|
cy.get('#tab-button-account').click();
|
||||||
|
testTabTitle('Tab 1 - Page 1');
|
||||||
|
|
||||||
|
testUrlEquals(url);
|
||||||
|
})
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('entry tab contains navigation extras', () => {
|
||||||
|
const expectNestedTabUrlToContain = 'search=hello#fragment';
|
||||||
|
const rootUrlParams = 'test=123#rootFragment';
|
||||||
|
const rootUrl = `/tabs/account?${rootUrlParams}`;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit(rootUrl);
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should preserve root url navigation extras when clicking on an active tab to navigate to the root', () => {
|
||||||
|
const tab = getSelectedTab();
|
||||||
|
tab.find('#goto-nested-page1-with-query-params').click();
|
||||||
|
|
||||||
|
testTabTitle('Tab 1 - Page 2 (1)');
|
||||||
|
testUrlContains(expectNestedTabUrlToContain);
|
||||||
|
|
||||||
|
cy.get('#tab-button-account').click();
|
||||||
|
testTabTitle('Tab 1 - Page 1');
|
||||||
|
|
||||||
|
testUrlContains(rootUrl);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should preserve root url navigation extras when changing tabs', () => {
|
||||||
|
getSelectedTab();
|
||||||
|
cy.get('#tab-button-contact').click();
|
||||||
|
testTabTitle('Tab 2 - Page 1');
|
||||||
|
|
||||||
|
cy.get('#tab-button-account').click();
|
||||||
|
testTabTitle('Tab 1 - Page 1');
|
||||||
|
|
||||||
|
testUrlContains(rootUrl);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should navigate deep then go home and preserve navigation extras', () => {
|
||||||
|
let tab = getSelectedTab();
|
||||||
|
tab.find('#goto-tab1-page2').click();
|
||||||
|
tab = testTabTitle('Tab 1 - Page 2 (1)');
|
||||||
|
|
||||||
|
tab.find('#goto-next').click();
|
||||||
|
testTabTitle('Tab 1 - Page 2 (2)');
|
||||||
|
|
||||||
|
cy.get('#tab-button-contact').click();
|
||||||
|
testTabTitle('Tab 2 - Page 1');
|
||||||
|
|
||||||
|
cy.get('#tab-button-account').click();
|
||||||
|
testTabTitle('Tab 1 - Page 2 (2)');
|
||||||
|
|
||||||
|
cy.get('#tab-button-account').click();
|
||||||
|
testTabTitle('Tab 1 - Page 1');
|
||||||
|
|
||||||
|
testUrlContains(rootUrl);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('entry url - /tabs/account/nested/1', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit('/tabs/account/nested/1');
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should only display the back-button when there is a page in the stack', () => {
|
||||||
|
let tab = getSelectedTab();
|
||||||
|
tab.find('ion-back-button').should('not.be.visible');
|
||||||
|
testTabTitle('Tab 1 - Page 2 (1)');
|
||||||
|
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1-nested']);
|
||||||
|
|
||||||
|
cy.get('#tab-button-account').click();
|
||||||
|
tab = testTabTitle('Tab 1 - Page 1');
|
||||||
|
|
||||||
|
tab.find('#goto-tab1-page2').click();
|
||||||
|
tab = testTabTitle('Tab 1 - Page 2 (1)');
|
||||||
|
tab.find('ion-back-button').should('be.visible');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not reuse the same page', () => {
|
||||||
|
let tab = testTabTitle('Tab 1 - Page 2 (1)');
|
||||||
|
tab.find('#goto-next').click();
|
||||||
|
tab = testTabTitle('Tab 1 - Page 2 (2)');
|
||||||
|
|
||||||
|
tab.find('#goto-next').click();
|
||||||
|
tab = testTabTitle('Tab 1 - Page 2 (3)');
|
||||||
|
|
||||||
|
cy.testStack('ion-tabs ion-router-outlet', [
|
||||||
|
'app-tabs-tab1-nested',
|
||||||
|
'app-tabs-tab1-nested',
|
||||||
|
'app-tabs-tab1-nested'
|
||||||
|
]);
|
||||||
|
|
||||||
|
tab = getSelectedTab();
|
||||||
|
tab.find('ion-back-button').click();
|
||||||
|
tab = testTabTitle('Tab 1 - Page 2 (2)');
|
||||||
|
tab.find('ion-back-button').click();
|
||||||
|
tab = testTabTitle('Tab 1 - Page 2 (1)');
|
||||||
|
|
||||||
|
tab.find('ion-back-button').should('not.be.visible');
|
||||||
|
|
||||||
|
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab1-nested']);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('entry url - /tabs/lazy', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit('/tabs/lazy');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not display the back-button if coming from a different stack', () => {
|
||||||
|
let tab = testTabTitle('Tab 3 - Page 1');
|
||||||
|
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab3']);
|
||||||
|
|
||||||
|
tab = getSelectedTab();
|
||||||
|
tab.find('#goto-tab1-page2').click();
|
||||||
|
cy.testStack('ion-tabs ion-router-outlet', ['app-tabs-tab3', 'app-tabs-tab1-nested']);
|
||||||
|
|
||||||
|
tab = testTabTitle('Tab 1 - Page 2 (1)');
|
||||||
|
tab.find('ion-back-button').should('not.be.visible');
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('enter url - /tabs/contact/one', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit('/tabs/contact/one');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return to correct tab after going to page in different outlet', () => {
|
||||||
|
const tab = getSelectedTab();
|
||||||
|
tab.find('#goto-nested-page1').click();
|
||||||
|
cy.testStack('app-nested-outlet ion-router-outlet', ['app-nested-outlet-page']);
|
||||||
|
|
||||||
|
const nestedOutlet = cy.get('app-nested-outlet');
|
||||||
|
nestedOutlet.find('ion-back-button').click();
|
||||||
|
|
||||||
|
testTabTitle('Tab 2 - Page 1');
|
||||||
|
});
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
function testTabTitle(title) {
|
||||||
|
const tab = getSelectedTab();
|
||||||
|
|
||||||
|
// Find is used to get a direct descendant instead of get
|
||||||
|
tab.find('ion-title').should('have.text', title);
|
||||||
|
return getSelectedTab();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSelectedTab() {
|
||||||
|
cy.get('ion-tabs ion-router-outlet > *:not(.ion-page-hidden)').should('have.length', 1);
|
||||||
|
return cy.get('ion-tabs ion-router-outlet > *:not(.ion-page-hidden)').first();
|
||||||
|
}
|
||||||
|
|
||||||
|
function testState(count, tab) {
|
||||||
|
cy.get('#tabs-state').should('have.text', `${count}.${tab}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function testUrlContains(urlFragment) {
|
||||||
|
cy.location().should((location) => {
|
||||||
|
expect(location.href).to.contain(urlFragment);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function testUrlEquals(url) {
|
||||||
|
cy.url().should('eq', url);
|
||||||
|
}
|
@ -1,73 +0,0 @@
|
|||||||
import { browser } from 'protractor';
|
|
||||||
|
|
||||||
export function goBack() {
|
|
||||||
return browser.executeScript(`return window.history.back()`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getProperty(selector: string, property: string) {
|
|
||||||
return browser.executeScript(`
|
|
||||||
return document.querySelector('${selector}')['${property}'];
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getText(selector: string) {
|
|
||||||
return browser.executeScript(`
|
|
||||||
return document.querySelector('${selector}').textContent;
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setProperty(selector: string, property: string, value: any) {
|
|
||||||
const text = JSON.stringify(value);
|
|
||||||
return browser.executeScript(`
|
|
||||||
document.querySelector('${selector}')['${property}'] = ${text};
|
|
||||||
`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function waitTime(time: number) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
setTimeout(resolve, time);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LifeCycleCount {
|
|
||||||
ionViewWillEnter: number;
|
|
||||||
ionViewDidEnter: number;
|
|
||||||
ionViewWillLeave: number;
|
|
||||||
ionViewDidLeave: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function handleErrorMessages() {
|
|
||||||
return browser.manage().logs().get('browser').then(browserLog => {
|
|
||||||
for (let i = 0; i <= browserLog.length - 1; i++) {
|
|
||||||
if (browserLog[i].level.name_ === 'SEVERE') {
|
|
||||||
fail(browserLog[i].message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function testLifeCycle(selector: string, expected: LifeCycleCount) {
|
|
||||||
await waitTime(50);
|
|
||||||
const results = await Promise.all([
|
|
||||||
getText(`${selector} #ngOnInit`),
|
|
||||||
getText(`${selector} #ionViewWillEnter`),
|
|
||||||
getText(`${selector} #ionViewDidEnter`),
|
|
||||||
getText(`${selector} #ionViewWillLeave`),
|
|
||||||
getText(`${selector} #ionViewDidLeave`),
|
|
||||||
]);
|
|
||||||
|
|
||||||
expect(results[0]).toEqual('1');
|
|
||||||
expect(results[1]).toEqual(expected.ionViewWillEnter.toString());
|
|
||||||
expect(results[2]).toEqual(expected.ionViewDidEnter.toString());
|
|
||||||
expect(results[3]).toEqual(expected.ionViewWillLeave.toString());
|
|
||||||
expect(results[4]).toEqual(expected.ionViewDidLeave.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function testStack(selector: string, expected: string[]) {
|
|
||||||
const children = await browser.executeScript(`
|
|
||||||
return Array.from(
|
|
||||||
document.querySelector('${selector}').children
|
|
||||||
).map(el => el.tagName.toLowerCase());
|
|
||||||
`);
|
|
||||||
expect(children).toEqual(expected);
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
import { browser, element, by } from 'protractor';
|
|
||||||
import { handleErrorMessages, waitTime } from './utils';
|
|
||||||
|
|
||||||
describe('view-child', () => {
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await browser.get('/view-child');
|
|
||||||
await waitTime(30);
|
|
||||||
});
|
|
||||||
afterEach(() => {
|
|
||||||
return handleErrorMessages();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should get a reference to all children', async () => {
|
|
||||||
// button should be red
|
|
||||||
expect(await element(by.css('#color-button.ion-color-danger')).isPresent()).toBeTruthy();
|
|
||||||
|
|
||||||
// tabs should be found
|
|
||||||
expect(await element(by.css('#tabs-result')).getText()).toEqual('all found');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
14
angular/test/test-app/e2e/src/view-child.spec.ts
Normal file
14
angular/test/test-app/e2e/src/view-child.spec.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
describe('View Child', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit('/view-child');
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should get a reference to all children', () => {
|
||||||
|
// button should be red
|
||||||
|
cy.get('#color-button').should('have.class', 'ion-color-danger');
|
||||||
|
|
||||||
|
// tabs should be found
|
||||||
|
cy.get('#tabs-result').should('have.text', 'all found');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -1,18 +0,0 @@
|
|||||||
import { browser, element, by } from 'protractor';
|
|
||||||
import { waitTime, handleErrorMessages } from './utils';
|
|
||||||
|
|
||||||
describe('virtual-scroll', () => {
|
|
||||||
afterEach(() => {
|
|
||||||
return handleErrorMessages();
|
|
||||||
});
|
|
||||||
beforeEach(async () => {
|
|
||||||
await browser.get('/virtual-scroll');
|
|
||||||
await waitTime(30);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should open virtual-scroll', () => {
|
|
||||||
const virtualElements = element.all(by.css('ion-virtual-scroll > *'));
|
|
||||||
expect(virtualElements.count()).toBeGreaterThan(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
14
angular/test/test-app/e2e/src/virtual-scroll.spec.ts
Normal file
14
angular/test/test-app/e2e/src/virtual-scroll.spec.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
describe('Virtual Scroll', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit('/virtual-scroll');
|
||||||
|
cy.wait(30);
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should open virtual-scroll', () => {
|
||||||
|
cy.document().then((doc) => {
|
||||||
|
const virtualElements = doc.querySelectorAll('ion-virtual-scroll > *');
|
||||||
|
expect(virtualElements.length).to.be.greaterThan(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -4,14 +4,17 @@
|
|||||||
"strictMetadataEmit" : true
|
"strictMetadataEmit" : true
|
||||||
},
|
},
|
||||||
"extends": "../tsconfig.json",
|
"extends": "../tsconfig.json",
|
||||||
|
"include": [
|
||||||
|
"src/**spec.ts",
|
||||||
|
"../cypress/support/index.d.ts"
|
||||||
|
],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "../out-tsc/app",
|
"outDir": "../out-tsc/app",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"types": [
|
"types": [
|
||||||
"jasmine",
|
"cypress",
|
||||||
"jasminewd2",
|
|
||||||
"node"
|
"node"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
// Karma configuration file, see link for more information
|
|
||||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
|
||||||
|
|
||||||
module.exports = function (config) {
|
|
||||||
config.set({
|
|
||||||
basePath: '',
|
|
||||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
|
||||||
plugins: [
|
|
||||||
require('karma-jasmine'),
|
|
||||||
require('karma-chrome-launcher'),
|
|
||||||
require('karma-jasmine-html-reporter'),
|
|
||||||
require('karma-coverage-istanbul-reporter'),
|
|
||||||
require('@angular-devkit/build-angular/plugins/karma')
|
|
||||||
],
|
|
||||||
client: {
|
|
||||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
|
||||||
},
|
|
||||||
coverageIstanbulReporter: {
|
|
||||||
dir: require('path').join(__dirname, '../coverage'),
|
|
||||||
reports: ['html', 'lcovonly', 'text-summary'],
|
|
||||||
fixWebpackSourcePaths: true
|
|
||||||
},
|
|
||||||
reporters: ['progress', 'kjhtml'],
|
|
||||||
port: 9876,
|
|
||||||
colors: true,
|
|
||||||
logLevel: config.LOG_INFO,
|
|
||||||
autoWatch: true,
|
|
||||||
browsers: ['Chrome'],
|
|
||||||
customLaunchers: {
|
|
||||||
ChromeHeadlessCI: {
|
|
||||||
base: 'ChromeHeadless',
|
|
||||||
flags: ['--no-sandbox']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
singleRun: false,
|
|
||||||
restartOnFileChange: true
|
|
||||||
});
|
|
||||||
};
|
|
20057
angular/test/test-app/package-lock.json
generated
20057
angular/test/test-app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -8,15 +8,16 @@
|
|||||||
"sync:build": "sh scripts/build-ionic.sh",
|
"sync:build": "sh scripts/build-ionic.sh",
|
||||||
"sync": "sh scripts/sync.sh",
|
"sync": "sh scripts/sync.sh",
|
||||||
"build": "npm run sync && ng build --prod --no-progress",
|
"build": "npm run sync && ng build --prod --no-progress",
|
||||||
"pretest": "webdriver-manager update --versions.chrome 89.0.4389.23",
|
|
||||||
"test": "ng e2e --prod --webdriver-update=false",
|
|
||||||
"test.dev": "npm run sync && ng e2e",
|
|
||||||
"lint": "ng lint",
|
"lint": "ng lint",
|
||||||
"postinstall": "npm run sync && ngcc",
|
"postinstall": "npm run sync && ngcc",
|
||||||
"serve:ssr": "node dist/test-app/server/main.js",
|
"serve:ssr": "node dist/test-app/server/main.js",
|
||||||
"build:ssr": "ng build --prod && ng run test-app:server:production",
|
"build:ssr": "ng build --prod && ng run test-app:server:production",
|
||||||
"dev:ssr": "ng run test-app:serve-ssr",
|
"dev:ssr": "ng run test-app:serve-ssr",
|
||||||
"prerender": "ng run test-app:prerender"
|
"prerender": "ng run test-app:prerender",
|
||||||
|
"cy.open": "cypress open",
|
||||||
|
"cy.run": "cypress run",
|
||||||
|
"test": "concurrently \"npm run start\" \"wait-on http-get://localhost:4200 && npm run cy.run\" --kill-others --success first",
|
||||||
|
"test.watch": "concurrently \"npm run start\" \"wait-on http-get://localhost:4200 && npm run cy.open\" --kill-others --success first"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular/animations": "^9.1.12",
|
"@angular/animations": "^9.1.12",
|
||||||
@ -34,7 +35,6 @@
|
|||||||
"angular-in-memory-web-api": "^0.11.0",
|
"angular-in-memory-web-api": "^0.11.0",
|
||||||
"core-js": "^2.6.11",
|
"core-js": "^2.6.11",
|
||||||
"express": "^4.15.2",
|
"express": "^4.15.2",
|
||||||
"jasmine-marbles": "^0.6.0",
|
|
||||||
"rxjs": "^6.5.5",
|
"rxjs": "^6.5.5",
|
||||||
"tslib": "^1.13.0",
|
"tslib": "^1.13.0",
|
||||||
"zone.js": "^0.10.3"
|
"zone.js": "^0.10.3"
|
||||||
@ -46,22 +46,15 @@
|
|||||||
"@angular/language-service": "^9.1.12",
|
"@angular/language-service": "^9.1.12",
|
||||||
"@nguniversal/builders": "9.0.0-next.9",
|
"@nguniversal/builders": "9.0.0-next.9",
|
||||||
"@types/express": "^4.17.7",
|
"@types/express": "^4.17.7",
|
||||||
"@types/jasmine": "^3.5.13",
|
|
||||||
"@types/jasminewd2": "^2.0.8",
|
|
||||||
"@types/node": "^12.12.54",
|
"@types/node": "^12.12.54",
|
||||||
"codelyzer": "^5.2.2",
|
"codelyzer": "^5.2.2",
|
||||||
"jasmine-core": "^3.5.0",
|
"concurrently": "^6.0.0",
|
||||||
"jasmine-spec-reporter": "^4.2.1",
|
"cypress": "^6.7.1",
|
||||||
"karma": "^4.4.1",
|
|
||||||
"karma-chrome-launcher": "^3.1.0",
|
|
||||||
"karma-coverage-istanbul-reporter": "^2.1.1",
|
|
||||||
"karma-jasmine": "^3.0.3",
|
|
||||||
"karma-jasmine-html-reporter": "^1.5.4",
|
|
||||||
"protractor": "^5.4.4",
|
|
||||||
"ts-loader": "^6.2.2",
|
"ts-loader": "^6.2.2",
|
||||||
"ts-node": "^8.3.0",
|
"ts-node": "^8.3.0",
|
||||||
"tslint": "^6.1.3",
|
"tslint": "^6.1.3",
|
||||||
"typescript": "^3.8.3",
|
"typescript": "^3.8.3",
|
||||||
|
"wait-on": "^5.2.1",
|
||||||
"webpack-cli": "^3.3.12"
|
"webpack-cli": "^3.3.12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ export class ModalComponent {
|
|||||||
async open(TheModalComponent: any) {
|
async open(TheModalComponent: any) {
|
||||||
const modal = await this.modalCtrl.create({
|
const modal = await this.modalCtrl.create({
|
||||||
component: TheModalComponent,
|
component: TheModalComponent,
|
||||||
|
animated: false,
|
||||||
componentProps: {
|
componentProps: {
|
||||||
value: '123',
|
value: '123',
|
||||||
prop: '321'
|
prop: '321'
|
||||||
@ -40,7 +41,7 @@ export class ModalComponent {
|
|||||||
modal.onDidDismiss().then(() => {
|
modal.onDidDismiss().then(() => {
|
||||||
NgZone.assertInAngularZone();
|
NgZone.assertInAngularZone();
|
||||||
if (!this.onWillDismiss) {
|
if (!this.onWillDismiss) {
|
||||||
throw new Error('onWillDismiss should be emited first');
|
throw new Error('onWillDismiss should be emitted first');
|
||||||
}
|
}
|
||||||
this.onDidDismiss = true;
|
this.onDidDismiss = true;
|
||||||
});
|
});
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
|
|
||||||
|
|
||||||
import 'zone.js/dist/zone-testing';
|
|
||||||
import { getTestBed } from '@angular/core/testing';
|
|
||||||
import {
|
|
||||||
BrowserDynamicTestingModule,
|
|
||||||
platformBrowserDynamicTesting
|
|
||||||
} from '@angular/platform-browser-dynamic/testing';
|
|
||||||
|
|
||||||
declare const require: any;
|
|
||||||
|
|
||||||
// First, initialize the Angular testing environment.
|
|
||||||
getTestBed().initTestEnvironment(
|
|
||||||
BrowserDynamicTestingModule,
|
|
||||||
platformBrowserDynamicTesting()
|
|
||||||
);
|
|
||||||
// Then we find all the tests.
|
|
||||||
const context = require.context('./', true, /\.spec\.ts$/);
|
|
||||||
// And load the modules.
|
|
||||||
context.keys().map(context);
|
|
@ -3,7 +3,6 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "./out-tsc/spec",
|
"outDir": "./out-tsc/spec",
|
||||||
"types": [
|
"types": [
|
||||||
"jasmine",
|
|
||||||
"node"
|
"node"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -47,12 +47,6 @@ Cypress.Commands.add('ionPageVisible', (pageId) => {
|
|||||||
// cy.get(`div.ion-page[data-pageid=${pageId}]`).should('have.attr', 'style', 'z-index: 101;')
|
// cy.get(`div.ion-page[data-pageid=${pageId}]`).should('have.attr', 'style', 'z-index: 101;')
|
||||||
});
|
});
|
||||||
|
|
||||||
Cypress.Commands.add('ionPageInvisible', (pageId) => {
|
|
||||||
cy.get(`div.ion-page[data-pageid=${pageId}]`)
|
|
||||||
.should('have.class', 'ion-page-invisible')
|
|
||||||
.should('have.length', 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
Cypress.Commands.add('ionPageHidden', (pageId) => {
|
Cypress.Commands.add('ionPageHidden', (pageId) => {
|
||||||
cy.get(`div.ion-page[data-pageid=${pageId}]`)
|
cy.get(`div.ion-page[data-pageid=${pageId}]`)
|
||||||
.should('have.class', 'ion-page-hidden')
|
.should('have.class', 'ion-page-hidden')
|
||||||
|
@ -47,12 +47,6 @@ Cypress.Commands.add('ionPageVisible', (pageId) => {
|
|||||||
.should('have.length', 1)
|
.should('have.length', 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
Cypress.Commands.add('ionPageInvisible', (pageId) => {
|
|
||||||
cy.get(`div.ion-page[data-pageid=${pageId}]`)
|
|
||||||
.should('have.class', 'ion-page-invisible')
|
|
||||||
.should('have.length', 1)
|
|
||||||
})
|
|
||||||
|
|
||||||
Cypress.Commands.add('ionPageHidden', (pageId) => {
|
Cypress.Commands.add('ionPageHidden', (pageId) => {
|
||||||
cy.get(`div.ion-page[data-pageid=${pageId}]`)
|
cy.get(`div.ion-page[data-pageid=${pageId}]`)
|
||||||
.should('have.class', 'ion-page-hidden')
|
.should('have.class', 'ion-page-hidden')
|
||||||
|
Reference in New Issue
Block a user