Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

[breaks-compat] Natural language browser config & semver #40

Closed
wants to merge 3 commits into from

3 participants

@jakub-g
Owner

Regarding the required browsers for the campaign:

The old config properties majorVersion, minorVersion and revision were removed. Instead, semver-compliant version matching was put in place.

Browser config based on verbose entries with browserName, os, version entries and name for display alias, was replaced with simple processing of natural-language string (like "Chrome 27 on Android").


Those commits are not backward compatible.

@jakub-g jakub-g referenced this pull request from a commit in jakub-g/attester
@jakub-g jakub-g Using semver for flexible browser version detection
This change is backward incompatible; the old config properties
`majorVersion`, `minorVersion` and `revision` were replaced with
semver-compliant `browserVersion`.

Close #40.
16e19de
@jakub-g jakub-g referenced this pull request from a commit in jakub-g/attester
@jakub-g jakub-g Using semver for flexible browser version detection
This change is backward incompatible; the old config properties
`majorVersion`, `minorVersion` and `revision` were replaced with
semver-compliant `browserVersion`.

Close #40.
f92918e
@jakub-g jakub-g referenced this pull request from a commit in jakub-g/attester
@jakub-g jakub-g Using semver for flexible browser version detection
This change is backward incompatible; the old config properties
`majorVersion`, `minorVersion` and `revision` were replaced with
semver-compliant `browserVersion`.

Close #40.
a5a52db
@jakub-g jakub-g referenced this pull request from a commit in jakub-g/attester
@jakub-g jakub-g Using semver for flexible browser version detection
This change is backward incompatible; the old config properties
`majorVersion`, `minorVersion` and `revision` were replaced with
semver-compliant `browserVersion`.

Close #40.
eda684c
@jakub-g jakub-g referenced this pull request from a commit in jakub-g/attester
@jakub-g jakub-g Semver and text parsing for flexible non-verbose browser cfg
Regarding the required browsers for the campaign:

The old config properties `majorVersion`, `minorVersion` and `revision`
were removed. Instead, semver-compliant version matching was put in place.

Browser config based on verbose entries with `browserName`, `os`, version
entries and `name` for display alias, was replaced with simple processing
of natural-language string (like "Chrome 27 on Android").

Close #40.
2f67468
@jakub-g jakub-g referenced this pull request from a commit in jakub-g/attester
@jakub-g jakub-g Semver and text parsing for flexible non-verbose browser cfg
Regarding the required browsers for the campaign:

The old config properties `majorVersion`, `minorVersion` and `revision`
were removed. Instead, semver-compliant version matching was put in place.

Browser config based on verbose entries with `browserName`, `os`, version
entries and `name` for display alias, was replaced with simple processing
of natural-language string (like "Chrome 27 on Android").

Close #40.
dd6571d
@jakub-g jakub-g referenced this pull request from a commit in jakub-g/attester
@jakub-g jakub-g Semver and text parsing for flexible non-verbose browser cfg
Regarding the required browsers for the campaign:

The old config properties `majorVersion`, `minorVersion` and `revision`
were removed. Instead, semver-compliant version matching was put in place.

Browser config based on verbose entries with `browserName`, `os`, version
entries and `name` for display alias, was replaced with simple processing
of natural-language string (like "Chrome 27 on Android").

Close #40.
0d0f9fb
@jakub-g jakub-g referenced this pull request from a commit in jakub-g/attester
@jakub-g jakub-g Semver and text parsing for flexible non-verbose browser cfg
Regarding the required browsers for the campaign:

The old config properties `majorVersion`, `minorVersion` and `revision`
were removed. Instead, semver-compliant version matching was put in place.

Browser config based on verbose entries with `browserName`, `os`, version
entries and `name` for display alias, was replaced with simple processing
of natural-language string (like "Chrome 27 on Android").

Close #40.
93e424c
@jakub-g
Owner

Ready for code review.

@jakub-g jakub-g referenced this pull request from a commit in jakub-g/attester
@jakub-g jakub-g Semver and text parsing for flexible non-verbose browser cfg
Regarding the required browsers for the campaign:

The old config properties `majorVersion`, `minorVersion` and `revision`
were removed. Instead, semver-compliant version matching was put in place.

Browser config based on verbose entries with `browserName`, `os`, version
entries and `name` for display alias, was replaced with simple processing
of natural-language string (like "Chrome 27 on Android").

Close #40.
74ce396
@jakub-g jakub-g referenced this pull request from a commit in jakub-g/attester
@jakub-g jakub-g Semver and text parsing for flexible non-verbose browser cfg
Regarding the required browsers for the campaign:

The old config properties `majorVersion`, `minorVersion` and `revision`
were removed. Instead, semver-compliant version matching was put in place.

Browser config based on verbose entries with `browserName`, `os`, version
entries and `name` for display alias, was replaced with simple processing
of natural-language string (like "Chrome 27 on Android").

Close #40.
ad978f8
lib/browser-detection.js
@@ -59,11 +74,9 @@ exports.browserMatch = function (config, browserInfo) {
if (config.browserName != null) {
match = match && (config.browserName == browserInfo.family);
}
- if (match && config.majorVersion != null) {
- match = config.majorVersion == browserInfo.major;
- }
- if (match && config.minorVersion != null) {
- match = config.minorVersion == browserInfo.minor;
+ if (match && config.browserVersion != null) {
+ // user may pass version as a number, hence using String()
+ match = semver.satisfies(browserInfo.semverString, String(config.browserVersion));
}
if (match && config.os != null) {
// a little bit verbose to have readable code
@simonarbuckle Collaborator

After running grunt beautify, this file contains incorrect formatting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
lib/launchers/browser.js
@@ -24,7 +24,7 @@ var config = attester.config;
var childProcesses = require("../child-processes.js");
attester.event.once("launcher.connect", function (slaveURL) {
- var browsers = config.browser;
+ var browsers = config["run-browser"];
if (browsers) {
if (!Array.isArray(browsers)) {
browsers = [browsers];
@simonarbuckle Collaborator

After running grunt beautify, this file contains incorrect formatting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@jakub-g jakub-g referenced this pull request from a commit in jakub-g/attester
@jakub-g jakub-g [breaks-compat] Natural language browser config & semver
Regarding the required browsers for the campaign:

The old config properties `majorVersion`, `minorVersion` and `revision`
were removed. Instead, semver-compliant version matching was put in place.

Browser config based on verbose entries with `browserName`, `os`, version
entries and `name` for display alias, was replaced with simple processing
of natural-language string (like "Chrome 27 on Android").

Close #40.
2dd05f0
@jakub-g jakub-g changed the title from Semver and text parsing for flexible non-verbose browser cfg to Natural language browser config & semver
@jakub-g jakub-g [breaks-compat] Natural language browser config & semver
Regarding the required browsers for the campaign:

The old config properties `majorVersion`, `minorVersion` and `revision`
were removed. Instead, semver-compliant version matching was put in place.

Browser config based on verbose entries with `browserName`, `os`, version
entries and `name` for display alias, was replaced with simple processing
of natural-language string (like "Chrome 27 on Android").

Close #40.
f1881b2
@jakub-g jakub-g changed the title from Natural language browser config & semver to [breaks-compat] Natural language browser config & semver
@jakub-g jakub-g [breaks-compat] Refactor confusing browser/browsers options
Renamed `browser` to `run-browser` to avoid confusion with `browsers`
specifying required browsers for the campaign.

Close #36.
6251ee6
@divdavem divdavem self-assigned this
lib/test-campaign/browser.js
@@ -15,18 +15,25 @@
var browserMatch = require('../util/browser-detection.js').browserMatch;
+/**
+ * @see Browser.prototype.parseBrowserConfig
+ * <li> Usage: </li>
+ * <li> Input: 'Chrome >=30 on Desktop Windows as Chrome Canary 30' </li>
+ * <li> Match: [1] = 'Chrome', [2] = '>=30', [3] = 'Desktop Windows', [4] = 'Chrome Canary 30' </li>
+ * Parts 2, 3, 4 are optional, will be undefined if not found.
+ */
+var _browserCfgRegex = /(\S+)(?:\s+(\W*\d\S*))?(?:\s+on\s+(.*?))?(?:\s+as\s+(.*?))?\s*$/i;
@divdavem Owner

I think the regular expression should start with ^ to make sure we match the whole expression and not only the end.
So the full regular expression would be:

var _browserCfgRegex = /^\s*(\S+)(?:\s+(\W*\d\S*))?(?:\s+on\s+(.*?))?(?:\s+as\s+(.*?))?\s*$/i;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@divdavem divdavem commented on the diff
lib/test-campaign/browser.js
((9 lines not shown))
+ return {}; // default, unrestricted browser
+ }
+
+ var match = _browserCfgRegex.exec(cfgString);
+ if (match === null) {
+ return {
+ browserName: "unparsable browser"
+ };
+ } else {
+ // Some of the entries can be undefined, it's fine.
+ // Note that garbage input may also produce valid match.
+ return {
+ browserName: match[1],
+ browserVersion: match[2],
+ os: match[3],
+ logDisplayName: match[4]
@divdavem Owner

I would call this displayName instead of logDisplayName. It is not only used in logs, is it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@jakub-g
Owner

I stayed with logDisplayName as discussed, done some little changes in acfff2c

@divdavem
Owner

:ok: acfff2c seems fine for me.

@jakub-g jakub-g closed this pull request from a commit
@jakub-g jakub-g [breaks-compat] Natural language browser config & semver
Regarding the required browsers for the campaign:

The old config properties `majorVersion`, `minorVersion` and `revision`
were removed. Instead, semver-compliant version matching was put in place.

Browser config based on verbose entries with `browserName`, `os`, version
entries and `name` for display alias, was replaced with simple processing
of natural-language string (like "Chrome 27 on Android").

Close #40.
f8d9116
@jakub-g jakub-g closed this in f8d9116
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Oct 10, 2014
  1. @jakub-g

    [breaks-compat] Natural language browser config & semver

    jakub-g authored
    Regarding the required browsers for the campaign:
    
    The old config properties `majorVersion`, `minorVersion` and `revision`
    were removed. Instead, semver-compliant version matching was put in place.
    
    Browser config based on verbose entries with `browserName`, `os`, version
    entries and `name` for display alias, was replaced with simple processing
    of natural-language string (like "Chrome 27 on Android").
    
    Close #40.
  2. @jakub-g

    [breaks-compat] Refactor confusing browser/browsers options

    jakub-g authored
    Renamed `browser` to `run-browser` to avoid confusion with `browsers`
    specifying required browsers for the campaign.
    
    Close #36.
Commits on Oct 14, 2014
  1. @jakub-g

    WIP code review fixes

    jakub-g authored
This page is out of date. Refresh to see the latest.
View
41 README.md
@@ -131,28 +131,27 @@ browsers:
# and run each test only once (in whatever browser is connected)
# However, if the browsers section is present, each test will be run once in each browser listed here.
# (and browsers not listed here will have nothing to do if they are connected)
- - browserName: 'PhantomJS'
- - browserName: 'Chrome'
+ - 'PhantomJS'
+ - 'Opera'
# It's possible to distinguish browsers by operating systems, read more below
- - browserName: 'Firefox'
- os: 'Windows 7'
- - browserName: 'Firefox'
- os: 'Desktop Linux'
- - browserName: 'Firefox'
- os: 'Android'
- - browserName: 'Opera'
- - browserName: 'Safari'
+ - 'Safari on Mac OS X'
+ - 'Chrome on Windows 7'
+ - 'Chrome on Desktop Linux'
+ - 'Chrome on Android'
# It is also possible to distinguish several versions of the same browser:
- - browserName: 'IE'
- majorVersion: 7
- - browserName: 'IE'
- majorVersion: 8
- - browserName: 'IE'
- majorVersion: 9
- - browserName: 'IE'
- majorVersion: 10
- # Note that 'minorVersion' and 'revision' are also available
- # The 'name' property allows to change the display name of the browser in the reports.
+ - 'IE 7'
+ - 'IE 8'
+ - 'IE 9'
+ - 'IE 10'
+ # Browser version can be also a semver-compliant string; see https://github.com/isaacs/node-semver
+ - 'Firefox 3.6'
+ - 'Firefox >=20'
+ # In the logs, browser will be identified using the name, version and OS as provided. If you want to change that, add an alias at the end using 'as':
+ - 'Chrome 28 as Chrome Stable 28'
+ - 'Chrome 30 as Chrome Canary 30'
+ # You can mix all of that options, and have whitespace as you see fit.
+ - 'Firefox >=25 on Windows 7 as Firefox/Windows'
+ - 'Firefox >=25 on Ubuntu as Firefox/Ubuntu'
```
#### Regarding browser detection by operating system:
@@ -235,7 +234,7 @@ Additionally, a string `auto` can be passed to let the program use the optimal n
`--robot-browser "<browser name>"` Name of the browser to automatically start with the [Selenium Java Robot](https://github.com/ariatemplates/selenium-java-robot).
It can be: `Firefox`, `Chrome`, `Safari` or `Internet Explorer`.
-`--browser <path>` Path to any browser executable to execute the tests. Can be repeated multiple times to start multiple
+`--run-browser <path>` Path to any browser executable to execute the tests. Can be repeated multiple times to start multiple
browsers or multiple instances of the same browser. Each browser is started with one parameter: the URL to open to start tests.
At the end of the tests, all started processes are killed.
View
2  bin/attester.js
@@ -21,7 +21,6 @@ var attester = require('../lib/attester.js');
var merge = require('../lib/util/merge.js');
var opt = optimist.usage('Usage: $0 [options] [config.yml|config.json]').boolean(['flash-policy-server', 'json-console', 'help', 'server-only', 'version', 'colors', 'ignore-errors', 'ignore-failures', 'shutdown-on-campaign-end', 'predictable-urls']).string(['phantomjs-path']).describe({
- 'browser': 'Path to any browser executable to execute the tests. Can be repeated multiple times.',
'colors': 'Uses colors (disable with --no-colors).',
'env': 'Environment configuration file. This file is available in the configuration object under env.',
'flash-policy-port': 'Port used for the built-in Flash policy server (needs --flash-policy-server). Can be 0 for a random port.',
@@ -38,6 +37,7 @@ var opt = optimist.usage('Usage: $0 [options] [config.yml|config.json]').boolean
'port': 'Port used for the web server. If set to 0, an available port is automatically selected.',
'predictable-urls': 'If true, resources served by the campaign have predictable URLs (campaign1, campaign2...). Otherwise, the campaign part in the URL is campaign ID. Useful for debugging.',
'robot-browser': 'Specifies the browser that should be automatically started by the selenium-java-robot (either Firefox, Chrome, Safari or Internet Explorer).',
+ 'run-browser': 'Path to any browser executable to execute the tests. Can be repeated multiple times.',
'server-only': 'Only starts the web server, and configure it for the test campaign but do not start the campaign.',
'shutdown-on-campaign-end': 'Once the campaign is finished, shut down the server and exit the process. Set this to false to facilitate debugging.',
'slow-test-threshold': 'Threshold (in milliseconds) to mark long-running tests in the console report. Use 0 to disable.',
View
2  lib/launchers/browser-launcher.js
@@ -22,7 +22,7 @@ var attester = require("../attester");
*/
function onLauncherConnect(slaveURL) {
- var browsers = attester.config.browser;
+ var browsers = attester.config["run-browser"];
if (browsers) {
if (!Array.isArray(browsers)) {
browsers = [browsers];
View
61 lib/test-campaign/browser.js
@@ -15,18 +15,25 @@
var browserMatch = require('../util/browser-detection.js').browserMatch;
+/**
+ * @see Browser.prototype.parseBrowserConfig
+ * <li> Usage: </li>
+ * <li> Input: 'Chrome >=30 on Desktop Windows as Chrome Canary 30' </li>
+ * <li> Match: [1] = 'Chrome', [2] = '>=30', [3] = 'Desktop Windows', [4] = 'Chrome Canary 30' </li>
+ * Parts 2, 3, 4 are optional, will be undefined if not found.
+ */
+var _browserCfgRegex = /^\s*(\S+)(?:\s+(\W*\d\S*))?(?:\s+on\s+(.*?))?(?:\s+as\s+(.*?))?\s*$/i;
+
var buildNameFromConfig = function (config) {
+ if (config.logDisplayName) {
+ return config.logDisplayName;
+ }
+
var name = "";
if (config.browserName) {
name = config.browserName;
- if (config.majorVersion != null) {
- name += " " + config.majorVersion;
- if (config.minorVersion != null) {
- name += "." + config.minorVersion;
- if (config.revision != null) {
- name += "." + config.revision;
- }
- }
+ if (config.browserVersion != null) {
+ name += " " + config.browserVersion;
}
}
if (config.os) {
@@ -35,10 +42,15 @@ var buildNameFromConfig = function (config) {
return name;
};
-var Browser = function (config) {
- this.name = config.name || buildNameFromConfig(config); // the browser name is only used for display in test results
- this.config = config;
-
+var Browser = function (cfgString) {
+ /**
+ * {browserName, browserVersion, os, logDisplayName}
+ */
+ this.config = Browser.parseBrowserConfig(cfgString);
+ /**
+ * Display name for the logs
+ */
+ this.name = buildNameFromConfig(this.config);
/**
* Contains tasks not yet dispatched.
*/
@@ -72,4 +84,29 @@ Browser.prototype.onTaskFinished = function () {
this.pendingTasks--;
};
+/**
+ * @static
+ */
+Browser.parseBrowserConfig = function (cfgString) {
+ if (cfgString == null || cfgString === "") {
+ return {}; // default, unrestricted browser
+ }
+
+ var match = _browserCfgRegex.exec(cfgString);
+ if (match === null) {
+ return {
+ browserName: "unparsable browser"
+ };
+ } else {
+ // Some of the entries can be undefined, it's fine.
+ // Note that garbage input may also produce valid match.
+ return {
+ browserName: match[1],
+ browserVersion: match[2],
+ os: match[3],
+ logDisplayName: match[4]
@divdavem Owner

I would call this displayName instead of logDisplayName. It is not only used in logs, is it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ };
+ }
+};
+
module.exports = Browser;
View
2  lib/test-campaign/test-campaign.js
@@ -55,7 +55,7 @@ var TestCampaign = function (config, parentLogger) {
} else {
this.logger.logInfo("No specific browsers expected in the campaign");
}
- var browsersCfg = config.browsers || [{}]; // if no browsers required, we create one, unrestricted
+ var browsersCfg = config.browsers || [""];
var browsers = [];
for (var i = 0, l = browsersCfg.length; i < l; i++) {
browsers[i] = new Browser(browsersCfg[i]);
View
23 lib/util/browser-detection.js
@@ -13,14 +13,28 @@
* limitations under the License.
*/
+var semver = require('semver');
var uaParser = require('ua-parser-snapshot');
+// semver-compliant version must be x.y.z
+var toSemVer = function (version) {
+ var nbDots = (version.match(/\./g) || "").length;
+ if (nbDots === 0) {
+ return version + ".0.0";
+ } else if (nbDots === 1) {
+ return version + ".0";
+ } else {
+ return version;
+ }
+};
+
exports.detectBrowser = function (data) {
var parsedAgent = uaParser.parse(data.userAgent);
var ua = parsedAgent.ua;
var osFamily = parsedAgent.os.family;
var res = {
displayName: parsedAgent.toString(),
+ semverString: toSemVer(parsedAgent.toVersionString()),
family: ua.family,
major: ua.major,
minor: ua.minor,
@@ -49,6 +63,7 @@ exports.detectBrowser = function (data) {
res.minor = 0;
res.patch = null;
res.displayName = "IE " + documentMode + ".0";
+ res.semverString = documentMode + ".0.0";
}
}
return res;
@@ -59,11 +74,9 @@ exports.browserMatch = function (config, browserInfo) {
if (config.browserName != null) {
match = match && (config.browserName == browserInfo.family);
}
- if (match && config.majorVersion != null) {
- match = config.majorVersion == browserInfo.major;
- }
- if (match && config.minorVersion != null) {
- match = config.minorVersion == browserInfo.minor;
+ if (match && config.browserVersion != null) {
+ // user may pass version as a number, hence using String()
+ match = semver.satisfies(browserInfo.semverString, String(config.browserVersion));
}
if (match && config.os != null) {
// a little bit verbose to have readable code
View
1  package.json
@@ -39,6 +39,7 @@
"portfinder": "0.2.1",
"q": "1.0.0",
"selenium-java-robot": "0.0.4",
+ "semver": "2.3.1",
"send": "0.9.3",
"socket.io": "0.9.16",
"ua-parser-snapshot": "0.3.201404031741",
View
122 spec/config/parseBrowserConfig.spec.js
@@ -0,0 +1,122 @@
+/* globals expect, describe, it */
+/*
+ * Copyright 2012 Amadeus s.a.s.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var Browser = require("../../lib/test-campaign/browser.js");
+
+describe("parse browser config", function () {
+
+ describe("core tests", function () {
+ it("should read plain browser name", function () {
+ expect(Browser.parseBrowserConfig("IE")).toEqual({
+ browserName: "IE",
+ browserVersion: undefined,
+ os: undefined,
+ logDisplayName: undefined
+ });
+ });
+
+ it("should read name with version", function () {
+ expect(Browser.parseBrowserConfig("IE 10")).toEqual({
+ browserName: "IE",
+ browserVersion: "10",
+ os: undefined,
+ logDisplayName: undefined
+ });
+ });
+
+ it("should read name with semver", function () {
+ expect(Browser.parseBrowserConfig("Firefox >=22")).toEqual({
+ browserName: "Firefox",
+ browserVersion: ">=22",
+ os: undefined,
+ logDisplayName: undefined
+ });
+ });
+
+ it("should read name with os", function () {
+ expect(Browser.parseBrowserConfig("Chrome on Windows 7")).toEqual({
+ browserName: "Chrome",
+ browserVersion: undefined,
+ os: "Windows 7",
+ logDisplayName: undefined
+ });
+ });
+
+ it("should read name with semver and os", function () {
+ expect(Browser.parseBrowserConfig("Chrome 30 on Windows 7")).toEqual({
+ browserName: "Chrome",
+ browserVersion: "30",
+ os: "Windows 7",
+ logDisplayName: undefined
+ });
+ });
+
+ it("should read name with semver and alias", function () {
+ expect(Browser.parseBrowserConfig("Firefox ~25 as Firefox Nightly")).toEqual({
+ browserName: "Firefox",
+ browserVersion: "~25",
+ os: undefined,
+ logDisplayName: "Firefox Nightly"
+ });
+ });
+
+ it("should read name with version, os, and alias", function () {
+ expect(Browser.parseBrowserConfig("Chrome 30 on Desktop Linux as Chrome Canary Linux")).toEqual({
+ browserName: "Chrome",
+ browserVersion: "30",
+ os: "Desktop Linux",
+ logDisplayName: "Chrome Canary Linux"
+ });
+ });
+ });
+
+ describe("whitespace and special chars tests", function () {
+ it("should not care about whitespace", function () {
+ expect(Browser.parseBrowserConfig(" Chrome 30 on Desktop Linux as Chrome Canary 30 ")).toEqual({
+ browserName: "Chrome",
+ browserVersion: "30",
+ os: "Desktop Linux",
+ logDisplayName: "Chrome Canary 30"
+ });
+ });
+
+ it("should allow special chars in alias", function () {
+ expect(Browser.parseBrowserConfig("Chrome 30 on Desktop Linux as Chrome/Linux")).toEqual({
+ browserName: "Chrome",
+ browserVersion: "30",
+ os: "Desktop Linux",
+ logDisplayName: "Chrome/Linux"
+ });
+ });
+ });
+
+ describe("non-standard input tests", function () {
+ it("should return empty object (unrestricted browser) for empty input string", function () {
+ expect(Browser.parseBrowserConfig("")).toEqual({});
+ });
+
+ it("should return empty object (unrestricted browser) for null input string", function () {
+ expect(Browser.parseBrowserConfig(null)).toEqual({});
+ });
+
+ it("should return 'unparsable browser' for no match", function () {
+ expect(Browser.parseBrowserConfig("I have no idea what I'm passing")).toEqual({
+ browserName : "unparsable browser"
+ });
+ });
+ });
+
+});
Something went wrong with that request. Please try again.