Skip to content

Commit

Permalink
gh-743 Update Karma tests to include new browser versions
Browse files Browse the repository at this point in the history
* Add `karma-firefox-launcher`
  - Adds the ability to run unit tests against Firefox using `ng test --browsers=Firefox`
* Add `karma-safari-launcher`
  - Adds the ability to run unit tests against Firefox using `ng test --browsers=Safari`
* Add `karma-edge-launcher`
  - Adds the ability (on Windows 10) to run unit tests against Edge using `ng test --browsers=Edge`

* Fix tests for Firefox
  - Adjust Flo unit tests for FF
* Fix tests for Edge
* Add SauceLabs Browser Targets for Karma unit tests
  - Chrome 67, Mac OS
  - Safari 11, Mac OS
  - Firefox 59, Mac OS
  - Edge 16, Windows 10
  - Chrome 67, Windows 10
  - Firefox 59, Windows 10
* Add BrowserStack Browser Targets for Karma unit tests
  - Chrome 65, Mac OS
  - Safari, Mac OS
  - Firefox 59, Mac OS
  - Edge 16, Windows 10
  - Chrome 67, Windows 10
  - Firefox 59, Windows 10
* Update Readme with BrowserStack + SauceLabs badges
* Minimize Logging for BrowserStack and Karma
  - Keep in mind 4MB logging maximum on Travis CI
  - Use dots reporter for Karma
  - Only log Warn+Error messages

Fix Windows CI build

gh-743 Add ability to use stand-alone SauceConnect tunnel

* Add support for boolean environment variable `SAUCE_CONNECT_USE_EMBEDDED`
* Add documentation on how to use stand-alone SauceConnect tunnel

Fix Browserstack test failures
  • Loading branch information
ghillert authored and ilayaperumalg committed Aug 21, 2018
1 parent 9fbee39 commit 76f9228
Show file tree
Hide file tree
Showing 34 changed files with 426 additions and 131 deletions.
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@
[![Build status](https://ci.appveyor.com/api/projects/status/7pqco2aqjyaphp36/branch/master?svg=true)](https://ci.appveyor.com/project/ghillert/spring-cloud-dataflow-ui/branch/master)
[![Code Coverage](https://codecov.io/gh/spring-cloud/spring-cloud-dataflow-ui/branch/master/graph/badge.svg)](https://codecov.io/gh/spring-cloud/spring-cloud-dataflow-ui/branch/master)

**SauceLabs Status**

[![Sauce Test Status](https://saucelabs.com/buildstatus/ghillert)](https://saucelabs.com/u/ghillert)

[![Sauce Test Status](https://saucelabs.com/browser-matrix/ghillert.svg)](https://saucelabs.com/u/ghillert)

**BrowserStack Status**

[![BrowserStack Status](https://www.browserstack.com/automate/badge.svg?badge_key=T3pKbzdQK2RpVnkxZ2ZwN2tjeGFUSzdOQUJ2cG1GSDBYSlRvT00zZWV1bz0tLVpuMXk0eTJmN01ienhnbkNPbXJTanc9PQ==--b187f26b476b4d3f262b837e13f4be593c41e44c)](https://www.browserstack.com/automate/public-build/T3pKbzdQK2RpVnkxZ2ZwN2tjeGFUSzdOQUJ2cG1GSDBYSlRvT00zZWV1bz0tLVpuMXk0eTJmN01ienhnbkNPbXJTanc9PQ==--b187f26b476b4d3f262b837e13f4be593c41e44c)

This is the *Spring Cloud Data Flow Dashboard* user interface (UI). The UI uses [Angular][]. Source code documentation is available at http://cloud.spring.io/spring-cloud-dataflow-ui/.

> The Git repository for the main *Spring Cloud Data Flow* project is at: https://github.com/spring-cloud/spring-cloud-dataflow
Expand Down Expand Up @@ -96,6 +106,21 @@ For E2E tests, developers should refrain from using `localhost`. Instead, add `d
$ npm run e2e-saucelabs-local
```

## Slow Internet Connection

By default the tests use an embedded version of Sauce Connect. In case you enounter test failures due to bandwidth constraints,
you may consider establishing a SauceLabs tunnel using the stand-alone **[Sauce Connect](https://wiki.saucelabs.com/display/DOCS/Sauce+Connect+Proxy)**.

Setup instructions can be found [here](https://wiki.saucelabs.com/display/DOCS/Basic+Sauce+Connect+Proxy+Setup).

Make sure you have at least the following environment variables defined:

export SAUCE_CONNECT_USE_EMBEDDED=false
export SAUCE_USER=
export SAUCE_API_KEY=

For a list of further supported configuration options, check the `config_examples/sc_configs` folder in the downloaded Sauce Connect binary.

## Thank You

![SauceLabs Logo](master-ui-assets/images/saucelabs-logo-600x315.png)
Expand Down
5 changes: 1 addition & 4 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,8 @@ install:
- cmd: SET PATH=C:\maven\apache-maven-3.2.5\bin;%JAVA_HOME%\bin;%PATH:C:\Ruby193\bin;=%
- cmd: SET MAVEN_OPTS=-XX:MaxPermSize=2g -Xmx4g
- cmd: SET JAVA_OPTS=-XX:MaxPermSize=2g -Xmx4g
- cmd: mvn --version
- cmd: java -version
build_script:
- mvn clean package -B -Dmaven.test.skip=true
test_script:
- mvn clean install --batch-mode
- mvnw clean install --batch-mode -Dmaven.test.skip=false
cache:
- C:\Users\appveyor\.m2
9 changes: 8 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@
<goal>install-node-and-npm</goal>
</goals>
<configuration>
<nodeVersion>v8.9.4</nodeVersion>
<nodeVersion>v10.8.0</nodeVersion>
</configuration>
</execution>
<execution>
Expand Down Expand Up @@ -155,6 +155,13 @@
<directory>ui/node_modules</directory>
<followSymlinks>false</followSymlinks>
</fileset>
<fileset>
<directory>ui</directory>
<includes>
<include>package-lock.json</include>
</includes>
<followSymlinks>false</followSymlinks>
</fileset>
<fileset>
<directory>ui/dist</directory>
<followSymlinks>false</followSymlinks>
Expand Down
10 changes: 10 additions & 0 deletions ui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@
[![Build status](https://ci.appveyor.com/api/projects/status/7pqco2aqjyaphp36/branch/master?svg=true)](https://ci.appveyor.com/project/ghillert/spring-cloud-dataflow-ui/branch/master)
[![Code Coverage](https://codecov.io/gh/spring-cloud/spring-cloud-dataflow-ui/branch/master/graph/badge.svg)](https://codecov.io/gh/spring-cloud/spring-cloud-dataflow-ui/branch/master)

**SauceLabs Status**

[![Sauce Test Status](https://saucelabs.com/buildstatus/ghillert)](https://saucelabs.com/u/ghillert)

[![Sauce Test Status](https://saucelabs.com/browser-matrix/ghillert.svg)](https://saucelabs.com/u/ghillert)

**BrowserStack Status**

[![BrowserStack Status](https://www.browserstack.com/automate/badge.svg?badge_key=T3pKbzdQK2RpVnkxZ2ZwN2tjeGFUSzdOQUJ2cG1GSDBYSlRvT00zZWV1bz0tLVpuMXk0eTJmN01ienhnbkNPbXJTanc9PQ==--b187f26b476b4d3f262b837e13f4be593c41e44c)](https://www.browserstack.com/automate/public-build/T3pKbzdQK2RpVnkxZ2ZwN2tjeGFUSzdOQUJ2cG1GSDBYSlRvT00zZWV1bz0tLVpuMXk0eTJmN01ienhnbkNPbXJTanc9PQ==--b187f26b476b4d3f262b837e13f4be593c41e44c)

This is the *Spring Cloud Data Flow Dashboard* user interface (UI). The UI uses [Angular][]. Source code documentation is available at http://cloud.spring.io/spring-cloud-dataflow-ui/.

> The Git repository for the main *Spring Cloud Data Flow* project is at: https://github.com/spring-cloud/spring-cloud-dataflow
Expand Down
48 changes: 28 additions & 20 deletions ui/e2e/protractor-saucelabs.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
// https://github.com/angular/protractor/blob/master/lib/config.ts

const { SpecReporter } = require('jasmine-spec-reporter');
const useEmbeddedSauceConnect =
(process.env.SAUCE_CONNECT_USE_EMBEDDED && process.env.SAUCE_CONNECT_USE_EMBEDDED === 'false') ? false : true;
console.log('Use embedded Sauce Connect client?: ' + useEmbeddedSauceConnect);

exports.config = {

jasmineNodeOpts: {
defaultTimeoutInterval: 5000000
},
Expand Down Expand Up @@ -56,25 +60,29 @@ exports.config = {
};

function startSauceConnect(deferred) {
var sauceConnectLauncher = require('sauce-connect-launcher');
console.log('Launching Sauce Connect...')
sauceConnectLauncher(
{
username: process.env.SAUCE_USERNAME,
accessKey: process.env.SAUCE_ACCESS_KEY,
// verbose: true,
// logger: console.log,
// tunnelIdentifier: 'npm-build',
// doctor: false
}, function (err, sauceConnectProcess) {
if (err) {
console.error('Error', err.message);
if (useEmbeddedSauceConnect) {
var sauceConnectLauncher = require('sauce-connect-launcher');
console.log('Launching Sauce Connect...')
sauceConnectLauncher(
{
username: process.env.SAUCE_USERNAME,
accessKey: process.env.SAUCE_ACCESS_KEY,
// verbose: true,
// logger: console.log,
// tunnelIdentifier: 'npm-build',
// doctor: false
}, function (err, sauceConnectProcess) {
if (err) {
console.error('Error', err.message);
}
deferred.resolve();
console.log("Sauce Connect ready");
// sauceConnectProcess.close(function () {
// console.log("Closed Sauce Connect process");
// })
}
deferred.resolve();
console.log("Sauce Connect ready");
// sauceConnectProcess.close(function () {
// console.log("Closed Sauce Connect process");
// })
}
);
);
} else {
deferred.resolve();
}
};
7 changes: 5 additions & 2 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,11 @@
"codelyzer": "4.2.1",
"jasmine-core": "2.99.1",
"jasmine-spec-reporter": "4.2.1",
"karma": "2.0.0",
"karma": "2.0.5",
"karma-chrome-launcher": "2.2.0",
"karma-edge-launcher": "0.4.2",
"karma-firefox-launcher": "1.1.0",
"karma-safari-launcher": "1.0.0",
"karma-sauce-launcher": "1.2.0",
"karma-browserstack-launcher": "1.3.0",
"karma-coverage-istanbul-reporter": "2.0.1",
Expand All @@ -83,7 +86,7 @@
"browserstack-local": "1.3.3",
"napa": "3.0.0",
"webpack-bundle-analyzer": "2.13.1",
"protractor-docker-plugin": "./protractor-docker-plugin"
"protractor-docker-plugin": "file:protractor-docker-plugin"
},
"napa-config": {
"cache": false
Expand Down
9 changes: 6 additions & 3 deletions ui/src/app/analytics/analytics.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ import { ErrorHandler } from '../shared/model/error-handler';
import { AnalyticsService } from './analytics.service';
import { LoggerService } from '../shared/services/logger.service';

xdescribe('AnalyticsService', () => {
describe('AnalyticsService', () => {

const errorHandler = new ErrorHandler();
const notificationService = new MockNotificationService();
const loggerService = new LoggerService();

beforeEach(() => {
this.mockHttp = jasmine.createSpyObj('mockHttp', ['get']);
this.mockHttp = {
get: jasmine.createSpy('get'),
};
this.jsonData = {};
this.analyticsService = new AnalyticsService(this.mockHttp, errorHandler, loggerService, notificationService);
});
Expand All @@ -21,13 +23,14 @@ xdescribe('AnalyticsService', () => {
});

it('interval change is correctly set', () => {
const spy = spyOn(this.analyticsService, 'startPollingForCounters');
this.analyticsService.counterInterval = 1;
expect(this.analyticsService._counterInterval).toBe(1);
expect(spy).toHaveBeenCalled();
});

it('zero interval stops polling', () => {
const spy = spyOn(this.analyticsService, 'stopPollingForCounters');

this.analyticsService.counterInterval = 0;
// interval is not set below 1 but spy that polling stops
expect(this.analyticsService._counterInterval).toBe(2);
Expand Down
6 changes: 4 additions & 2 deletions ui/src/app/analytics/analytics.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,10 @@ export class AnalyticsService {
* All pollers of all {@link DashboarItem}s are stopped.
*/
stopAllDashboardPollers() {
for (const dashboardItemToDisable of this.dashboardItems) {
this.stopPollingOfSingleDashboardItem(dashboardItemToDisable);
if (this.dashboardItems) {
for (const dashboardItemToDisable of this.dashboardItems) {
this.stopPollingOfSingleDashboardItem(dashboardItemToDisable);
}
}
}

Expand Down
18 changes: 13 additions & 5 deletions ui/src/app/apps/app-details/app-details.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,19 @@ import { ConfirmService } from '../../shared/components/confirm/confirm.service'
import { AppVersionLabelComponent } from '../components/app-versions-label/app-versions-label.component';
import { SortComponent } from '../../shared/components/sort/sort.component';
import { OrderByPipe } from '../../shared/pipes/orderby.pipe';
import { MockModalService } from '../../tests/mocks/modal';
import { AppVersionsComponent } from '../app-versions/app-versions.component';
import { BusyService } from '../../shared/services/busy.service';
import { RoutingStateService } from '../../shared/services/routing-state.service';
import { MockRoutingStateService } from '../../tests/mocks/routing-state';
import { NotificationService } from '../../shared/services/notification.service';
import { LoggerService } from '../../shared/services/logger.service';
import { Observable } from 'rxjs';

/**
* Test {@link AppDetailsComponent}.
*
* @author Damien Vitrac
* @author Gunnar Hillert
*/
describe('AppDetailsComponent', () => {
let component: AppDetailsComponent;
Expand All @@ -42,7 +43,8 @@ describe('AppDetailsComponent', () => {
const appsService = new MockAppsService();
const authService = new MockAuthService();
const sharedAboutService = new MocksSharedAboutService();
const modalService = new MockModalService();

let modalService;
const confirmService = new MockConfirmService();
const routingStateService = new MockRoutingStateService();
let activeRoute: MockActivatedRoute;
Expand Down Expand Up @@ -77,7 +79,7 @@ describe('AppDetailsComponent', () => {
{ provide: AppsService, useValue: appsService },
{ provide: AuthService, useValue: authService },
{ provide: ActivatedRoute, useValue: activeRoute },
{ provide: BsModalService, useValue: modalService },
BsModalService,
{ provide: ConfirmService, useValue: confirmService },
{ provide: BusyService, useValue: new BusyService() },
{ provide: RoutingStateService, useValue: routingStateService },
Expand All @@ -95,6 +97,7 @@ describe('AppDetailsComponent', () => {
component = fixture.componentInstance;
notificationService.clearAll();
appsService.mock = Object.assign({}, sourceMock);
modalService = TestBed.get(BsModalService);
});

describe('Application details', () => {
Expand Down Expand Up @@ -273,8 +276,13 @@ describe('AppDetailsComponent', () => {
expect(message).toBeTruthy();
});

it('should open the modal versions', () => {
const spy = spyOn(modalService, 'show');
it('should open the modal versions', () => {
const mockBsModalRef = new BsModalRef();
mockBsModalRef.content = {
open: () => Observable.of('testing')
};
const spy = spyOn(modalService, 'show').and.returnValue(mockBsModalRef);

fixture.debugElement.query(By.css('#no-default-version a')).nativeElement.click();
fixture.detectChanges();
expect(spy).toHaveBeenCalledWith(AppVersionsComponent, { class: 'modal-xl' });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ describe('AppVersionsComponent', () => {

it('should display the confirm modal when unregister a version', () => {
const btn: HTMLElement = fixture.debugElement.queryAll(By.css('#table-versions tbody tr .btn-default'))[1].nativeElement;
const spy = spyOn(confirmService, 'open');
const spy = spyOn(confirmService, 'open').and.callThrough();
btn.click();
fixture.detectChanges();
expect(spy).toHaveBeenCalled();
Expand Down
1 change: 0 additions & 1 deletion ui/src/app/apps/app-versions/app-versions.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Component, EventEmitter, OnDestroy } from '@angular/core';
import { Subscription } from 'rxjs/Subscription';
import { AppRegistration } from '../../shared/model/app-registration.model';
import { AppsService } from '../apps.service';
import { ConfirmService } from '../../shared/components/confirm/confirm.service';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {BusyService} from '../../../shared/services/busy.service';
import {By} from '@angular/platform-browser';
import {AppsBulkImportPropertiesComponent} from './apps-bulk-import-properties.component';
import { NotificationService } from '../../../shared/services/notification.service';
import { Router } from '@angular/router';

/**
* Test {@link AppsBulkImportPropertiesComponent}.
Expand All @@ -18,6 +19,7 @@ import { NotificationService } from '../../../shared/services/notification.servi
describe('AppsBulkImportPropertiesComponent', () => {
let component: AppsBulkImportPropertiesComponent;
let fixture: ComponentFixture<AppsBulkImportPropertiesComponent>;
let router;
const bsModalRef = new BsModalRef();
const notificationService = new MockNotificationService();
const appsService = new MockAppsService();
Expand Down Expand Up @@ -48,6 +50,7 @@ describe('AppsBulkImportPropertiesComponent', () => {
fixture = TestBed.createComponent(AppsBulkImportPropertiesComponent);
component = fixture.componentInstance;
notificationService.clearAll();
router = TestBed.get(Router);
});

it('should be created', () => {
Expand Down Expand Up @@ -82,13 +85,15 @@ describe('AppsBulkImportPropertiesComponent', () => {
});

it('should enable the import action and call the appService.bulkImportApps method', () => {
spyOn(router, 'navigateByUrl');
fixture.detectChanges();
const bt = fixture.debugElement.query(By.css('.footer-actions .btn-primary')).nativeElement;
const inputs = {
properties: fixture.debugElement.query(By.css('#propertiesInput')).nativeElement,
force: fixture.debugElement.query(By.css('#forceInput')).nativeElement
};
const spy = spyOn(appsService, 'bulkImportApps');
const spy = spyOn(appsService, 'bulkImportApps').and.callThrough();

[
{properties: 'foo=http://foo.ly/foo-bar-foo', force: true},
{properties: 'foo=http://foo.ly/foo-bar-foo\nbar=http://foo.ly/foo-bar-foo', force: true}
Expand All @@ -102,14 +107,22 @@ describe('AppsBulkImportPropertiesComponent', () => {
bt.click();
});
expect(spy).toHaveBeenCalledTimes(2);

fixture.whenStable().then(() => {
expect((<any>router.navigateByUrl).calls.mostRecent().args[0].toString()).toBe('/apps');
});
});
});

it('should display a toast after a success import', () => {
spyOn(router, 'navigateByUrl');
component.form.get('properties').setValue('foo=http://foo.ly/foo-bar-foo');
component.submit();
fixture.detectChanges();
expect(notificationService.testSuccess[0]).toContain('Apps Imported');
fixture.whenStable().then(() => {
expect((<any>router.navigateByUrl).calls.mostRecent().args[0].toString()).toBe('/apps');
});
});

it('should load a file in the properties input', (done) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { AppsService } from '../../apps.service';
import { BusyService } from '../../../shared/services/busy.service';
import { AppsBulkImportValidator } from '../apps-bulk-import.validator';
import { NotificationService } from '../../../shared/services/notification.service';
import { BulkImportParams } from '../../components/apps.interface';

/**
* Applications Bulk Import Properties
Expand Down Expand Up @@ -79,7 +80,7 @@ export class AppsBulkImportPropertiesComponent implements OnDestroy {
} catch (e) {
}
}
prepareBulkImportRequest(force, importProps: string) {
prepareBulkImportRequest(force, importProps: string): BulkImportParams {
return {
force: force,
properties: importProps.split('\n'),
Expand Down
Loading

0 comments on commit 76f9228

Please sign in to comment.