Skip to content
Permalink
Browse files
fix(protractor): detect the browser name and version, as well as the …
…platform name and version

re #455
  • Loading branch information
jan-molak committed Feb 8, 2020
1 parent bc4a038 commit 99659187b99bb2d97f8cc51910a4f12f2685875c
@@ -13,9 +13,14 @@ export class BrowserTag extends Tag {

constructor(
public readonly browserName: string,
public readonly browserVersion: string,
public readonly browserVersion: string = '',
) {
super([ browserName, browserVersion ].join(' '), BrowserTag.Type);
super(
[ browserName, browserVersion ]
.filter(_ => !! _)
.join(' '),
BrowserTag.Type,
);
}

toJSON() {
@@ -1,3 +1,4 @@
import { JSONObject } from 'tiny-types';
import { Tag } from './Tag';

/**
@@ -6,7 +7,28 @@ import { Tag } from './Tag';
export class PlatformTag extends Tag {
static readonly Type = 'platform';

constructor(platform: string) {
super(platform, PlatformTag.Type);
static fromJSON(o: JSONObject) {
return new PlatformTag(o.platformName as string, o.platformVersion as string);
}

constructor(
public readonly platformName: string,
public readonly platformVersion: string = '',
) {
super(
[ platformName, platformVersion ]
.filter(_ => !! _)
.join(' '),
PlatformTag.Type,
);
}

toJSON() {
return {
name: this.name,
type: PlatformTag.Type,
platformName: this.platformName,
platformVersion: this.platformVersion,
};
}
}
@@ -1,4 +1,4 @@
import { ensure, isDefined, isString, JSONObject, TinyType } from 'tiny-types';
import { ensure, isDefined, isGreaterThan, isString, JSONObject, property, TinyType } from 'tiny-types';
import * as TagTypes from './index';

/**
@@ -19,6 +19,9 @@ export abstract class Tag extends TinyType {

protected constructor(public readonly name: string, public readonly type: string) {
super();

ensure('Tag name', name, isDefined(), property('length', isGreaterThan(0)));
ensure('Tag type', type, isDefined(), property('length', isGreaterThan(0)));
}

toJSON(): { name: string, type: string } {
@@ -0,0 +1,91 @@
import 'mocha';

import { expect } from '@integration/testing-tools';
import { given } from 'mocha-testdata';
import { Capabilities, ProtractorBrowser } from 'protractor';
import * as sinon from 'sinon';

import { StandardisedCapabilities } from '../../../src/adapter/browser-detector';

describe('StandardisedCapabilities', () => {

given([
{
actual: { browserName: 'MicrosoftEdge', browserVersion: '42.17134.1.0', platformName: 'windows', platform: 'WINDOWS', platformVersion: '10' },
expected: { browserName: 'MicrosoftEdge', browserVersion: '42.17134.1.0', platformName: 'windows', platformVersion: '10' },
}, {
actual: { browserName: 'chrome', version: '79.0.3945.79', platform: 'WINDOWS' },
expected: { browserName: 'chrome', browserVersion: '79.0.3945.79', platformName: 'WINDOWS' },
}, {
actual: { browserName: 'MicrosoftEdge', version: '79.0.309.18', platform: 'Mac OS X' },
expected: { browserName: 'MicrosoftEdge', browserVersion: '79.0.309.18', platformName: 'Mac OS X' },
}, {
actual: { browserName: 'firefox', browserVersion: '72.0', platformName: 'windows', platformVersion: '6.1' },
expected: { browserName: 'firefox', browserVersion: '72.0', platformName: 'windows', platformVersion: '6.1' },
}, {
actual: { browserName: 'internet explorer', version: '10', platform: 'WINDOWS' },
expected: { browserName: 'internet explorer', browserVersion: '10', platformName: 'WINDOWS' },
}, {
actual: { browserName: 'chrome', version: '79.0.3945.79', platform: 'MAC' },
expected: { browserName: 'chrome', browserVersion: '79.0.3945.79', platformName: 'MAC' },
}, {
actual: { browserName: 'chrome', deviceManufacturer: 'samsung', deviceModel: 'SM-G950F', platformName: 'Android', platform: 'LINUX', platformVersion: '7.0' },
expected: { browserName: 'chrome', browserVersion: 'samsung SM-G950F', platformName: 'Android', platformVersion: '7.0' },
}, {
actual: { browserName: 'opera', version: '12.16', platformName: 'ANY', platform: 'WINDOWS' },
expected: { browserName: 'opera', browserVersion: '12.16', platformName: 'WINDOWS' },
}, {
actual: { browserName: 'firefox', browserVersion: '72.0', platformName: 'mac', platformVersion: '13.4.0' },
expected: { browserName: 'firefox', browserVersion: '72.0', platformName: 'mac', platformVersion: '13.4.0' },
}, {
actual: {
browserName: 'safari',
version: '',
mobile: { browser: 'mobile', version: 'iPhone 7-10.3' },
platformName: 'iOS',
platform: 'MAC',
platformVersion: '11.0',
},
expected: { browserName: 'safari', browserVersion: 'iPhone 7-10.3', platformName: 'iOS', platformVersion: '11.0' },
}, {
actual: { browserName: 'safari', version: '6.0.5', platform: 'MAC' },
expected: { browserName: 'safari', browserVersion: '6.0.5', platformName: 'MAC' },
}, {
actual: { browserName: 'opera', version: '12.15', platformName: 'ANY', platform: 'MAC' },
expected: { browserName: 'opera', browserVersion: '12.15', platformName: 'MAC' },
}, {
actual: { browserName: 'chrome', deviceManufacturer: 'motorola', deviceModel: 'XT1092', platformName: 'Android', platform: 'LINUX', platformVersion: '6.0' },
expected: { browserName: 'chrome', browserVersion: 'motorola XT1092', platformName: 'Android', platformVersion: '6.0' },
}, {
actual: {
browserName: 'safari',
version: '',
mobile: { browser: 'mobile', version: 'iPhone 8 Plus-11.0' },
platformName: 'iOS',
platform: 'MAC',
platformVersion: '11.0',
},
expected: { browserName: 'safari', browserVersion: 'iPhone 8 Plus-11.0', platformName: 'iOS', platformVersion: '11.0' },
}, {
actual: { browserName: 'safari', version: '7.1.8', platform: 'MAC' },
expected: { browserName: 'safari', browserVersion: '7.1.8', platformName: 'MAC' },
}, {
actual: { browserName: 'internet explorer', version: '6', platform: 'WINDOWS' },
expected: { browserName: 'internet explorer', browserVersion: '6', platformName: 'WINDOWS' },
},
]).
it(`works`, ({ actual, expected }) => {
const fakeBrowser = {
getCapabilities: () => Promise.resolve(new Capabilities(actual)),
};

const capabilities = StandardisedCapabilities.of(() => fakeBrowser as unknown as ProtractorBrowser);

return Promise.all([
expect(capabilities.browserName()).to.eventually.equal(expected.browserName),
expect(capabilities.browserVersion()).to.eventually.equal(expected.browserVersion),
expect(capabilities.platformName()).to.eventually.equal(expected.platformName),
expect(capabilities.platformVersion()).to.eventually.equal(expected.platformVersion),
]);
});
});
@@ -3,8 +3,8 @@ import { ArtifactArchiver, Serenity } from '@serenity-js/core';
import deepmerge = require('deepmerge');
const isPlainObject = require('is-plain-object'); // tslint:disable-line:no-var-requires fails when using default import

import { Runner } from 'protractor';
import { BrowserDetector } from './browser-detector';
import { protractor, Runner } from 'protractor';
import { BrowserDetector, StandardisedCapabilities } from './browser-detector';

import { Config } from './Config';
import { ProtractorReport, ProtractorReporter } from './reporter';
@@ -41,7 +41,7 @@ export class ProtractorFrameworkAdapter {
cueTimeout: config.serenity.cueTimeout,
actors: config.serenity.actors,
crew: [
new BrowserDetector(),
BrowserDetector.with(StandardisedCapabilities.of(() => protractor.browser)),
...config.serenity.crew,
reporter,
],
@@ -2,7 +2,9 @@ import { Stage } from '@serenity-js/core';
import { AsyncOperationAttempted, AsyncOperationCompleted, DomainEvent, SceneStarts, SceneTagged } from '@serenity-js/core/lib/events';
import { BrowserTag, CorrelationId, Description, PlatformTag } from '@serenity-js/core/lib/model';
import { StageCrewMember } from '@serenity-js/core/lib/stage';
import { platform } from 'os';
import { protractor } from 'protractor';
import { StandardisedCapabilities } from './StandardisedCapabilities';

/**
* @private
@@ -13,13 +15,18 @@ import { protractor } from 'protractor';
*/
export class BrowserDetector implements StageCrewMember {

static with(capabilities: StandardisedCapabilities) {
return new BrowserDetector(capabilities);
}

constructor(
private readonly capabilities: StandardisedCapabilities,
private readonly stage: Stage = null,
) {
}

assignedTo(stage: Stage): StageCrewMember {
return new BrowserDetector(stage);
return new BrowserDetector(this.capabilities, stage);
}

notifyOf(event: DomainEvent): void {
@@ -32,11 +39,13 @@ export class BrowserDetector implements StageCrewMember {
this.stage.currentTime(),
));

protractor.browser.getCapabilities().then(capabilities => {
const
platform = capabilities.get('platform'),
browserName = capabilities.get('browserName'),
browserVersion = capabilities.get('version');
Promise.all([
this.capabilities.browserName(),
this.capabilities.browserVersion(),
this.capabilities.platformName(),
this.capabilities.platformVersion(),
]).
then(([browserName, browserVersion, platformName, platformVersion]) => {

this.stage.announce(new SceneTagged(
event.value,
@@ -46,7 +55,7 @@ export class BrowserDetector implements StageCrewMember {

this.stage.announce(new SceneTagged(
event.value,
new PlatformTag(platform),
new PlatformTag(platformName, platformVersion),
this.stage.currentTime(),
));

@@ -0,0 +1,56 @@
import { Capabilities, ProtractorBrowser } from 'protractor';

/**
* @private
*/
export class StandardisedCapabilities {
static of(currentBrowser: () => ProtractorBrowser) {
return new StandardisedCapabilities(currentBrowser);
}

constructor(private currentBrowser: () => ProtractorBrowser) {
}

browserName(): PromiseLike<string> {
return this.get(
caps => caps.get('browserName'),
);
}

browserVersion(): PromiseLike<string> {
return this.get(
caps => caps.get('version'),
caps => caps.get('browserVersion'),
caps => caps.has('deviceManufacturer') && caps.has('deviceModel')
? `${ caps.get('deviceManufacturer') } ${ caps.get('deviceModel') }`
: undefined,
caps => caps.has('mobile') && caps.get('mobile').version,
);
}

platformName(): PromiseLike<string> {
return this.get(
caps => (caps.has('platformName') && ! /any/i.test(caps.get('platformName')))
? caps.get('platformName')
: caps.get('platform'),
);
}

platformVersion(): PromiseLike<string> {
return this.get(
caps => caps.get('platformVersion'),
);
}

private get(...fetchers: Array<(capabilities: Capabilities) => string>): PromiseLike<string> {
return this.currentBrowser().getCapabilities().then(caps => {
for (const fetcher of fetchers) {
const result = fetcher(caps);
if (!! result) {
return result;
}
}
return undefined;
});
}
}
@@ -1 +1,2 @@
export * from './BrowserDetector';
export * from './StandardisedCapabilities';

0 comments on commit 9965918

Please sign in to comment.