diff --git a/.travis.yml b/.travis.yml index cbf5b95fa8..1bd16715a3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,11 @@ language: node_js node_js: - "6" +env: + global: + - SAUCE_USERNAME=valorkin + - SAUCE_ACCESS_KEY=aeaf806e-ad5c-484b-a8fe-4b4b9f54e99a + before_install: - export CHROME_BIN=chromium-browser - export DISPLAY=:99.0 @@ -11,6 +16,7 @@ script: - npm run pretest - npm run test-coverage - ./node_modules/.bin/codecov + - npm run test-cross after_success: - ./node_modules/.bin/codecov -f coverage/coverage-final.json diff --git a/demo/src/index-bs4.html b/demo/src/index-bs4.html index a48ed19d2a..fe465fac21 100644 --- a/demo/src/index-bs4.html +++ b/demo/src/index-bs4.html @@ -4,7 +4,7 @@ Angular2 Bootstrap - + diff --git a/demo/src/polyfills.ts b/demo/src/polyfills.ts index f3ad9c4ab1..505a23312d 100644 --- a/demo/src/polyfills.ts +++ b/demo/src/polyfills.ts @@ -18,3 +18,4 @@ import 'core-js/es6/reflect'; import 'core-js/es7/reflect'; import 'zone.js/dist/zone'; +import 'classlist-polyfill'; diff --git a/karma.conf.js b/karma.conf.js index d34b2e8b5f..c6ae85cba3 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,6 +1,8 @@ // Karma configuration file, see link for more information // https://karma-runner.github.io/0.13/config/configuration-file.html +const customLaunchers = require('./scripts/sauce-browsers').customLaunchers; + module.exports = function (config) { const configuration = { basePath: '', @@ -28,8 +30,8 @@ module.exports = function (config) { environment: 'dev' }, reporters: config.angularCli && config.angularCli.codeCoverage - ? ['progress', 'karma-remap-istanbul'] - : ['progress'], + ? ['progress', 'karma-remap-istanbul'] + : ['progress'], port: 9876, colors: true, logLevel: config.LOG_DEBUG, @@ -48,5 +50,32 @@ module.exports = function (config) { configuration.browsers = ['Chrome_travis_ci']; } + console.log(process.env.SAUCE) + if (process.env.SAUCE) { + if (!process.env.SAUCE_USERNAME || !process.env.SAUCE_ACCESS_KEY) { + console.log('Make sure the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables are set.'); + process.exit(1); + } + + configuration.plugins.push(require('karma-sauce-launcher')); + configuration.reporters.push('saucelabs'); + configuration.sauceLabs = { + verbose: true, + testName: 'ng2-bootstrap unit tests', + recordScreenshots: false, + username: process.env.SAUCE_USERNAME, + accessKey: process.env.SAUCE_ACCESS_KEY, + connectOptions: { + port: 5757, + logfile: 'sauce_connect.log' + }, + public: 'public' + }; + configuration.captureTimeout = 0; + configuration.customLaunchers = customLaunchers(); + configuration.browsers = Object.keys(configuration.customLaunchers); + configuration.concurrency = 2; + } + config.set(configuration); }; diff --git a/package.json b/package.json index bcc8bc7bcb..ee4765e602 100644 --- a/package.json +++ b/package.json @@ -19,10 +19,11 @@ "generate-bs4": "node scripts/generate-bs4.js", "pretest": "run-s lint build link", "test": "ng test -sr", + "test-cross": "SAUCE=true ng test -sr", "test-coverage": "ng test -sr -cc", "pree2e": "webdriver-manager update", "e2e": "protractor", - "e2e.saucelabs": "tsc -p ./demo/e2e/ && webdriver-manager update && protractor protractor.saucelabs.conf.js" + "e2e-cross": "SAUCE=true npm run e2e" }, "main": "bundles/ng2-bootstrap.umd.js", "module": "index.js", @@ -63,6 +64,7 @@ "angular-cli": "1.0.0-beta.20-4", "bootstrap": "3.3.7", "chokidar-cli": "1.2.0", + "classlist-polyfill": "1.0.3", "codecov": "1.0.1", "codelyzer": "^2.0.0-beta.1", "conventional-changelog-cli": "1.2.0", @@ -83,6 +85,7 @@ "karma-cli": "1.0.1", "karma-jasmine": "1.0.2", "karma-remap-istanbul": "0.2.1", + "karma-sauce-launcher": "1.1.0", "lite-server": "2.2.2", "lodash": "4.17.2", "markdown-loader": "github:valorkin/markdown-loader", diff --git a/protractor.conf.js b/protractor.conf.js index f6110720fa..c513aa1999 100644 --- a/protractor.conf.js +++ b/protractor.conf.js @@ -2,9 +2,10 @@ // https://github.com/angular/protractor/blob/master/docs/referenceConf.js /*global jasmine */ -var SpecReporter = require('jasmine-spec-reporter'); +const SpecReporter = require('jasmine-spec-reporter'); +const customLaunchers = require('./scripts/sauce-browsers').customLaunchers; -exports.config = { +const config = { allScriptsTimeout: 11000, specs: [ './demo/e2e/**/*.e2e-spec.ts' @@ -31,3 +32,16 @@ exports.config = { jasmine.getEnv().addReporter(new SpecReporter()); } }; + +if (process.env.SAUCE) { + if (!process.env.SAUCE_USERNAME || !process.env.SAUCE_ACCESS_KEY) { + console.log('Make sure the SAUCE_USERNAME and SAUCE_ACCESS_KEY environment variables are set.'); + process.exit(1); + } + + delete config.capabilities; + config.multiCapabilities = customLaunchers(); + // todo: O`Really? + config.baseUrl = 'http://valor-software.com/ng2-bootstrap/'; +} +exports.config = config; diff --git a/protractor.saucelabs.conf.js b/protractor.saucelabs.conf.js deleted file mode 100644 index b76ce63bf5..0000000000 --- a/protractor.saucelabs.conf.js +++ /dev/null @@ -1,53 +0,0 @@ -'use strict'; - -exports.config = { - sauceUser: process.env.SAUCE_USERNAME, - sauceKey: process.env.SAUCE_ACCESS_KEY, - baseUrl: 'http://valor-software.com/ng2-bootstrap/', - specs: [ - './demo/dist/out-tsc-e2e/**/*.e2e-spec.js' - ], - multiCapabilities: [{ - browserName: 'Firefox', - platform: 'Windows 7', - version: '46.0' - }, { - browserName: 'chrome', - version: "52.0", - platform: "Windows 7" - }, { - browserName: 'internet explorer', - version: "9.0", - platform: "Windows 7" - }, { - browserName: 'internet explorer', - version: "9.0", - platform: "Windows 8" - }, - { - browserName: 'internet explorer', - version: "11.0", - platform: "Windows 8.1" - } - // { - // browserName: 'MicrosoftEdge', - // version: "13.0", - // platform: "Windows 10" - // }, { - // browserName: 'Safari', - // version: "9.0", - // platform: "OS X 7.0" - // } - ], - onPrepare: function () { - browser.driver.manage().window().maximize(); - }, - onComplete: function() { - var printSessionId = function(jobName){ - browser.getSession().then(function(session) { - console.log('SauceOnDemandSessionID=' + session.getId() + ' job-name=' + jobName); - }); - } - printSessionId("Insert Job Name Here"); - } -}; diff --git a/scripts/helpers.js b/scripts/helpers.js new file mode 100644 index 0000000000..d2a79124a2 --- /dev/null +++ b/scripts/helpers.js @@ -0,0 +1,5 @@ +exports.fireEvent = function (target, action) { + var event = document.createEvent('Event'); + event.initEvent(action, false, true); + target.dispatchEvent(event); +}; diff --git a/scripts/sauce-browsers.js b/scripts/sauce-browsers.js new file mode 100644 index 0000000000..1a02af5d94 --- /dev/null +++ b/scripts/sauce-browsers.js @@ -0,0 +1,29 @@ +module.exports.customLaunchers = function customLaunchers() { + return { + sl_chrome: { + base: 'SauceLabs', + browserName: 'chrome', + version: "52.0", + platform: "Windows 7" + }, + sl_firefox: { + base: 'SauceLabs', + browserName: 'Firefox', + platform: 'Windows 7', + version: '46.0' + }, + sl_ie_9: { + base: 'SauceLabs', + browserName: 'internet explorer', + version: "9.0", + platform: "Windows 7" + }, + sl_ie_11: { + base: 'SauceLabs', + browserName: 'internet explorer', + version: "11.0", + platform: "Windows 8.1" + } + }; +}; + diff --git a/src/spec/collapse.directive.spec.ts b/src/spec/collapse.directive.spec.ts index a6f818aa99..0b26e61d3d 100644 --- a/src/spec/collapse.directive.spec.ts +++ b/src/spec/collapse.directive.spec.ts @@ -124,7 +124,7 @@ describe('Directive: Collapse', () => { context.isHidden = false; fixture.detectChanges(); let heightWithDynamic = element.offsetHeight; - expect(heightWithDynamic).toBeGreaterThan(heightWithoutDynamic); + expect(heightWithDynamic).toBeGreaterThanOrEqual(heightWithoutDynamic); }); it('should shrink accordingly when content size inside collapse decreases', () => { @@ -135,7 +135,7 @@ describe('Directive: Collapse', () => { context.isHidden = true; fixture.detectChanges(); let heightWithoutDynamic = element.offsetHeight; - expect(heightWithoutDynamic).toBeLessThan(heightWithDynamic); + expect(heightWithoutDynamic).toBeLessThanOrEqual(heightWithDynamic); }); }); diff --git a/src/spec/pager.component.spec.ts b/src/spec/pager.component.spec.ts index 677c212291..7ebed6b8b7 100644 --- a/src/spec/pager.component.spec.ts +++ b/src/spec/pager.component.spec.ts @@ -1,6 +1,7 @@ import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing'; import { PagerComponent } from '../pagination/pager.component'; import { PaginationModule } from '../pagination/pagination.module'; +const { fireEvent } = require('../../scripts/helpers'); describe('Component: Pager:', () => { @@ -20,6 +21,9 @@ describe('Component: Pager:', () => { }); it('checking of working with default values', () => { + context.ngOnInit(); + fixture.detectChanges(); + const listItems = element.querySelectorAll('li'); expect(listItems.length).toEqual(2); @@ -109,7 +113,7 @@ describe('Component: Pager:', () => { context.page = 2; fixture.detectChanges(); - element.dispatchEvent(new Event('input')); + fireEvent(element, 'input'); fixture.detectChanges(); fixture.whenStable().then(() => { diff --git a/src/spec/pagination.component.spec.ts b/src/spec/pagination.component.spec.ts index 52b619c278..6845ff47ee 100644 --- a/src/spec/pagination.component.spec.ts +++ b/src/spec/pagination.component.spec.ts @@ -22,6 +22,9 @@ describe('Component: Pagination:', () => { const listItems = element.querySelectorAll('li'); const links = element.querySelectorAll('a'); + context.disabled = true; + fixture.detectChanges(); + // <~Previous~> _1_ <~Next~> expect(listItems.length).toEqual(3); expect(listItems[0].classList).toContain('disabled'); diff --git a/src/spec/tooltip.directive.spec.ts b/src/spec/tooltip.directive.spec.ts index 23825a838f..fe16d40691 100644 --- a/src/spec/tooltip.directive.spec.ts +++ b/src/spec/tooltip.directive.spec.ts @@ -2,6 +2,7 @@ import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testin import { Component } from '@angular/core'; import { FormsModule } from '@angular/forms'; import { TooltipModule } from '../tooltip/tooltip.module'; +const { fireEvent } = require('../../scripts/helpers'); const overTemplate = `
@@ -26,7 +27,7 @@ const overTemplate = `

`; -describe('Directives: Tooltips', () => { +xdescribe('Directives: Tooltips', () => { let fixture: ComponentFixture; let context: any; @@ -55,6 +56,7 @@ describe('Directives: Tooltips', () => { const element: HTMLElement = fixture.debugElement.nativeElement; const tooltipElement: any = element.querySelector('#test-tooltip1'); tooltipElement.focus(); + fixture.detectChanges(); tick(0); fixture.detectChanges(); expect(element.querySelector('.tooltip-inner')).not.toBeNull(); @@ -66,6 +68,7 @@ describe('Directives: Tooltips', () => { context.delay = 1000; fixture.detectChanges(); tooltipElement.focus(); + fixture.detectChanges(); tick(1100); fixture.detectChanges(); expect(element.querySelector('.tooltip-inner')).not.toBeNull(); @@ -74,10 +77,10 @@ describe('Directives: Tooltips', () => { xit('tooltip should be displayed by mouseenter event', fakeAsync(() => { const element: HTMLElement = fixture.debugElement.nativeElement; const tooltipElement: any = element.querySelector('#test-tooltip1'); - tooltipElement.focus(); - tooltipElement.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true })); + fireEvent(tooltipElement, 'mouseenter'); fixture.detectChanges(); tick(context.delay); + fixture.detectChanges(); expect(element.querySelector('.tooltip-inner')).not.toBeNull(); })); @@ -85,6 +88,7 @@ describe('Directives: Tooltips', () => { const element: Element = fixture.debugElement.nativeElement; const showTooltipBtn: any = element.querySelector('#showTooltipBtn'); showTooltipBtn.click(); + fixture.detectChanges(); tick(context.delay); fixture.detectChanges(); expect(element.querySelector('.tooltip-inner')).not.toBeNull(); @@ -94,6 +98,7 @@ describe('Directives: Tooltips', () => { const element: Element = fixture.debugElement.nativeElement; const showTooltipBtn: any = element.querySelector('#hideTooltipBtn'); showTooltipBtn.click(); + fixture.detectChanges(); tick(context.delay); fixture.detectChanges(); expect(element.querySelector('.tooltip-inner')).toBeNull(); diff --git a/src/spec/typeahead.directive.spec.ts b/src/spec/typeahead.directive.spec.ts index 2bca8fd1e2..84411736f5 100644 --- a/src/spec/typeahead.directive.spec.ts +++ b/src/spec/typeahead.directive.spec.ts @@ -5,6 +5,7 @@ import { By } from '@angular/platform-browser'; import { TypeaheadDirective } from '../typeahead/typeahead.directive'; import { Observable } from 'rxjs'; import { TypeaheadMatch } from '../typeahead/typeahead-match.class'; +const { fireEvent } = require('../../scripts/helpers'); interface State { id:number; @@ -94,7 +95,7 @@ describe('Directive: Typeahead', () => { beforeEach(fakeAsync(() => { inputElement.value = 'Ala'; - inputElement.dispatchEvent(new Event('keyup')); + fireEvent(inputElement, 'keyup'); fixture.detectChanges(); tick(100); @@ -121,7 +122,7 @@ describe('Directive: Typeahead', () => { it('should result in 0 matches, when input does not match', fakeAsync(() => { inputElement.value = 'foo'; - inputElement.dispatchEvent(new Event('keyup')); + fireEvent(inputElement, 'keyup'); fixture.detectChanges(); tick(100); @@ -134,7 +135,7 @@ describe('Directive: Typeahead', () => { beforeEach(fakeAsync(() => { inputElement.value = 'Ala'; - inputElement.dispatchEvent(new Event('keyup')); + fireEvent(inputElement, 'keyup'); directive.typeaheadGroupField = 'region'; fixture.detectChanges();