From 6c34c3d4faddc9fee686ef6161bc16f5d0882045 Mon Sep 17 00:00:00 2001 From: Faisal Salman Date: Tue, 14 Feb 2023 23:28:09 +0700 Subject: [PATCH] Add new utility methods: is() & toString() --- dist/ua-parser.min.js | 4 +- dist/ua-parser.pack.js | 4 +- readme.md | 147 +++++++++++++++++++++++++++++------------ src/ua-parser.js | 115 +++++++++++++++++++++++--------- test/test.js | 98 ++++++++++++++++++++++++++- 5 files changed, 290 insertions(+), 78 deletions(-) diff --git a/dist/ua-parser.min.js b/dist/ua-parser.min.js index d586986..767bddc 100644 --- a/dist/ua-parser.min.js +++ b/dist/ua-parser.min.js @@ -1,4 +1,4 @@ -/* UAParser.js v0.7.31 +/* UAParser.js v0.7.32 Copyright © 2012-2021 Faisal Salman MIT License */ -(function(window,undefined){"use strict";var LIBVERSION="0.7.31",EMPTY="",UNKNOWN="?",FUNC_TYPE="function",UNDEF_TYPE="undefined",OBJ_TYPE="object",STR_TYPE="string",MAJOR="major",MODEL="model",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",EMBEDDED="embedded",UA_MAX_LENGTH=350;var AMAZON="Amazon",APPLE="Apple",ASUS="ASUS",BLACKBERRY="BlackBerry",BROWSER="Browser",CHROME="Chrome",EDGE="Edge",FIREFOX="Firefox",GOOGLE="Google",HUAWEI="Huawei",LG="LG",MICROSOFT="Microsoft",MOTOROLA="Motorola",OPERA="Opera",SAMSUNG="Samsung",SHARP="Sharp",SONY="Sony",XIAOMI="Xiaomi",ZEBRA="Zebra",FACEBOOK="Facebook";var extend=function(regexes,extensions){var mergedRegexes={};for(var i in regexes){if(extensions[i]&&extensions[i].length%2===0){mergedRegexes[i]=extensions[i].concat(regexes[i])}else{mergedRegexes[i]=regexes[i]}}return mergedRegexes},enumerize=function(arr){var enums={};for(var i=0;i0){if(q.length===2){if(typeof q[1]==FUNC_TYPE){this[q[0]]=q[1].call(this,match)}else{this[q[0]]=q[1]}}else if(q.length===3){if(typeof q[1]===FUNC_TYPE&&!(q[1].exec&&q[1].test)){this[q[0]]=match?q[1].call(this,match,q[2]):undefined}else{this[q[0]]=match?match.replace(q[1],q[2]):undefined}}else if(q.length===4){this[q[0]]=match?q[3].call(this,match.replace(q[1],q[2])):undefined}}else{this[q]=match?match:undefined}}}}i+=2}},strMapper=function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;jUA_MAX_LENGTH?trim(ua,UA_MAX_LENGTH):ua;return this};this.setUA(_ua);return this};UAParser.VERSION=LIBVERSION;UAParser.BROWSER=enumerize([NAME,VERSION,MAJOR]);UAParser.CPU=enumerize([ARCHITECTURE]);UAParser.DEVICE=enumerize([MODEL,VENDOR,TYPE,CONSOLE,MOBILE,SMARTTV,TABLET,WEARABLE,EMBEDDED]);UAParser.ENGINE=UAParser.OS=enumerize([NAME,VERSION]);if(typeof exports!==UNDEF_TYPE){if(typeof module!==UNDEF_TYPE&&module.exports){exports=module.exports=UAParser}exports.UAParser=UAParser}else{if(typeof define===FUNC_TYPE&&define.amd){define(function(){return UAParser})}else if(typeof window!==UNDEF_TYPE){window.UAParser=UAParser}}var $=typeof window!==UNDEF_TYPE&&(window.jQuery||window.Zepto);if($&&!$.ua){var parser=new UAParser;$.ua=parser.getResult();$.ua.get=function(){return parser.getUA()};$.ua.set=function(ua){parser.setUA(ua);var result=parser.getResult();for(var prop in result){$.ua[prop]=result[prop]}}}})(typeof window==="object"?window:this); \ No newline at end of file +(function(window,undefined){"use strict";var LIBVERSION="0.7.32",EMPTY="",UNKNOWN="?",FUNC_TYPE="function",UNDEF_TYPE="undefined",OBJ_TYPE="object",STR_TYPE="string",MAJOR="major",MODEL="model",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",EMBEDDED="embedded",UA_MAX_LENGTH=350;var AMAZON="Amazon",APPLE="Apple",ASUS="ASUS",BLACKBERRY="BlackBerry",BROWSER="Browser",CHROME="Chrome",EDGE="Edge",FIREFOX="Firefox",GOOGLE="Google",HUAWEI="Huawei",LG="LG",MICROSOFT="Microsoft",MOTOROLA="Motorola",OPERA="Opera",SAMSUNG="Samsung",SHARP="Sharp",SONY="Sony",XIAOMI="Xiaomi",ZEBRA="Zebra",FACEBOOK="Facebook";var extend=function(regexes,extensions){var mergedRegexes={};for(var i in regexes){if(extensions[i]&&extensions[i].length%2===0){mergedRegexes[i]=extensions[i].concat(regexes[i])}else{mergedRegexes[i]=regexes[i]}}return mergedRegexes},enumerize=function(arr){var enums={};for(var i=0;i0){if(q.length===2){if(typeof q[1]==FUNC_TYPE){this[q[0]]=q[1].call(this,match)}else{this[q[0]]=q[1]}}else if(q.length===3){if(typeof q[1]===FUNC_TYPE&&!(q[1].exec&&q[1].test)){this[q[0]]=match?q[1].call(this,match,q[2]):undefined}else{this[q[0]]=match?match.replace(q[1],q[2]):undefined}}else if(q.length===4){this[q[0]]=match?q[3].call(this,match.replace(q[1],q[2])):undefined}}else{this[q]=match?match:undefined}}}}i+=2}},strMapper=function(str,map){for(var i in map){if(typeof map[i]===OBJ_TYPE&&map[i].length>0){for(var j=0;jUA_MAX_LENGTH?trim(ua,UA_MAX_LENGTH):ua;return this};this.setUA(_ua);return this}UAParser.VERSION=LIBVERSION;UAParser.BROWSER=enumerize([NAME,VERSION,MAJOR]);UAParser.CPU=enumerize([ARCHITECTURE]);UAParser.DEVICE=enumerize([MODEL,VENDOR,TYPE,CONSOLE,MOBILE,SMARTTV,TABLET,WEARABLE,EMBEDDED]);UAParser.ENGINE=UAParser.OS=enumerize([NAME,VERSION]);if(typeof exports!==UNDEF_TYPE){if(typeof module!==UNDEF_TYPE&&module.exports){exports=module.exports=UAParser}exports.UAParser=UAParser}else{if(typeof define===FUNC_TYPE&&define.amd){define(function(){return UAParser})}else if(typeof window!==UNDEF_TYPE){window.UAParser=UAParser}}var $=typeof window!==UNDEF_TYPE&&(window.jQuery||window.Zepto);if($&&!$.ua){var parser=new UAParser;$.ua=parser.getResult();$.ua.get=function(){return parser.getUA()};$.ua.set=function(ua){parser.setUA(ua);var result=parser.getResult();for(var prop in result){$.ua[prop]=result[prop]}}}})(typeof window==="object"?window:this); \ No newline at end of file diff --git a/dist/ua-parser.pack.js b/dist/ua-parser.pack.js index 18c0cdc..5c33553 100644 --- a/dist/ua-parser.pack.js +++ b/dist/ua-parser.pack.js @@ -1,4 +1,4 @@ -/* UAParser.js v0.7.31 +/* UAParser.js v0.7.32 Copyright © 2012-2021 Faisal Salman MIT License */ -!function(r,d){"use strict";function i(i){for(var e={},o=0;oS?L(i,S):i,this},this.setUA(o),this}Q.prototype.is=function(i){for(var e in this.propIs)if(o(this[this.propIs[e]],this.rgxIs)==o(i,this.rgxIs))return!0;return!1},Q.prototype.toString=function(){var i,e="";for(i in this.propToString)typeof this[this.propToString[i]]!==s&&(e+=(e?" ":"")+this[this.propToString[i]]);return e||s},Y.prototype=new Q([l,h],[[l],/\s?browser$/i]),J.prototype=new Q([f],[[f]]),ii.prototype=new Q([m,r],[[p,r,m]]),ei.prototype=new Q([l,h],[[l]]),oi.prototype=new Q([l,h],[[l],/\s?os$/i]),ti.VERSION="0.7.32",ti.BROWSER=i([l,h,w]),ti.CPU=i([f]),ti.DEVICE=i([r,m,p,g,v,k,x,y,_]),ti.ENGINE=ti.OS=i([l,h]),typeof exports!==s?(typeof module!==s&&module.exports&&(exports=module.exports=ti),exports.UAParser=ti):typeof define==u&&define.amd?define(function(){return ti}):typeof a!==s&&(a.UAParser=ti);var ai,ni=typeof a!==s&&(a.jQuery||a.Zepto);ni&&!ni.ua&&(ai=new ti,ni.ua=ai.getResult(),ni.ua.get=function(){return ai.getUA()},ni.ua.set=function(i){ai.setUA(i);var e,o=ai.getResult();for(e in o)ni.ua[e]=o[e]})}("object"==typeof window?window:this); \ No newline at end of file diff --git a/readme.md b/readme.md index a45e17e..514e949 100644 --- a/readme.md +++ b/readme.md @@ -19,10 +19,7 @@ JavaScript library to detect Browser, Engine, OS, CPU, and Device type/model fro * Source : https://github.com/faisalman/ua-parser-js # Documentation -### UAParser([user-agent][,extensions]) -typeof `user-agent` "string". - -typeof `extensions` "array". +### UAParser([user-agent:string][,extensions:object]) In The Browser environment you dont need to pass the user-agent string to the function, you can just call the funtion and it should automatically get the string from the `window.navigator.userAgent`, but that is not the case in nodejs. The user-agent string must be passed in nodejs for the function to work. Usually you can find the user agent in: @@ -32,7 +29,7 @@ Usually you can find the user agent in: ## Constructor When you call `UAParser` with the `new` keyword `UAParser` will return a new instance with an empty result object, you have to call one of the available methods to get the information from the user-agent string. Like so: -* `new UAParser([uastring][,extensions])` +* `new UAParser([user-agent:string][,extensions:object])` ```js let parser = new UAParser("user-agent"); // you need to pass the user-agent for nodejs console.log(parser); // {} @@ -49,7 +46,7 @@ console.log(parserResults); ``` When you call UAParser without the `new` keyword, it will automatically call `getResult()` function and return the parsed results. -* `UAParser([uastring][,extensions])` +* `UAParser([user-agent:string][,extensions:object])` * returns result object `{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} }` ## Methods @@ -67,13 +64,12 @@ The methods are self explanatory, here's a small overview on all the available m * `getUA()` - returns the user-agent string. * `setUA(user-agent)` - set a custom user-agent to be parsed. - --- -* `getResult()` - * returns `{ ua: '', browser: {}, cpu: {}, device: {}, engine: {}, os: {} }` +* `getResult() : UAResult` + * returns `{ ua: '', browser: UABrowser {}, cpu: UACPU {}, device: UADevice {}, engine: UAEngine {}, os: UAOS {} }` -* `getBrowser()` +* `getBrowser() : UABrowser` * returns `{ name: '', version: '' }` ```sh @@ -97,7 +93,7 @@ Vivaldi, Waterfox, WeChat, Weibo, Yandex, baidu, iCab, w3m, Whale Browser... # 'browser.version' determined dynamically ``` -* `getDevice()` +* `getDevice() : UADevice` * returns `{ model: '', type: '', vendor: '' }` ```sh @@ -121,7 +117,7 @@ Siemens, Sony[Ericsson], Sprint, Tesla, Vivo, Vodafone, Xbox, Xiaomi, Zebra, ZTE # 'device.model' determined dynamically ``` -* `getEngine()` +* `getEngine() : UAEngine` * returns `{ name: '', version: '' }` ```sh @@ -132,7 +128,7 @@ NetSurf, Presto, Tasman, Trident, w3m, WebKit # 'engine.version' determined dynamically ``` -* `getOS()` +* `getOS() : UAOS` * returns `{ name: '', version: '' }` ```sh @@ -149,7 +145,7 @@ Ubuntu, Unix, VectorLinux, Viera, WebOS, Windows [Phone/Mobile], Zenwalk, ... # 'os.version' determined dynamically ``` -* `getCPU()` +* `getCPU() : UACPU` * returns `{ architecture: '' }` ```sh @@ -157,13 +153,92 @@ Ubuntu, Unix, VectorLinux, Viera, WebOS, Windows [Phone/Mobile], Zenwalk, ... 68k, amd64, arm[64/hf], avr, ia[32/64], irix[64], mips[64], pa-risc, ppc, sparc[64] ``` -* `getUA()` +* `getUA() : string` * returns UA string of current instance * `setUA(uastring)` * set UA string to be parsed * returns current instance +#### * is() utility `since@1.1` + +```js +let uap = new UAParser('Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 635) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537'); + +uap.getBrowser().name; // "IEMobile" +uap.getBrowser().is("IEMobile"); // true +uap.getCPU().is("ARM"); // true + +uap.getOS().name; // "Windows Phone" +uap.getOS().is("Windows Phone"); // true + +uap.getDevice(); // { vendor: "Nokia", model: "Lumia 635", type: "mobile" } +uap.getResult().device; // { vendor: "Nokia", model: "Lumia 635", type: "mobile" } + +uap.getDevice().is("mobile"); // true +uap.getDevice().is("Lumia 635"); // true +uap.getDevice().is("Nokia"); // true +uap.getDevice().is("iPhone"); // false +uap.getResult().device.is("Nokia"); // true +uap.getResult().device.model; // "Lumia 635" + +uap.setUA("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"); +uap.getBrowser().is("IEMobile"); // false +uap.getBrowser().is("Chrome"); // true +uap.getResult().browser.is("Edge"); // false +uap.getResult().os.is("Mac OS"); // true +uap.getResult().os.version; // "10.6.8" +uap.getEngine().is("Blink"); // true +``` + +#### * toString() utility `since@1.1` + +```js +let uap = new UAParser('Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 635) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537'); + +uap.getDevice(); // { vendor: "Nokia", model: "Lumia 635", type: "mobile" } +uap.getDevice().toString(); // "Nokia Lumia 635" + +uap.getResult().os.name; // "Windows Phone" +uap.getResult().os.version; // "8.1" +uap.getResult().os.toString(); // "Windows Phone 8.1" + +uap.setUA("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"); +uap.getBrowser().name; // Chrome +uap.getBrowser().version; // 28.0.1500.95 +uap.getBrowser().major; // 28 +uap.getBrowser().toString(); // "Chrome 28.0.1500.95" +``` + +## Extending Regex + +If you want to detect something that's not currently provided by UAParser.js (eg: bots, specific apps, etc), you can pass a list of regexes to extend internal UAParser.js regexes with your own. + +* `UAParser([uastring,] extensions)` + +```js +// Example: +let myOwnListOfBrowsers = [ + [/(mybrowser)\/([\w\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION] +]; +let myParser = new UAParser({ browser: myOwnListOfBrowsers }); +let myUA = 'Mozilla/5.0 MyBrowser/1.3'; +console.log(myParser.setUA(myUA).getBrowser()); // {name: "MyBrowser", version: "1.3"} + +// Another example: +let myOwnListOfDevices = [ + [/(mytab) ([\w ]+)/i], [UAParser.DEVICE.VENDOR, UAParser.DEVICE.MODEL, [UAParser.DEVICE.TYPE, UAParser.DEVICE.TABLET]], + [/(myphone)/i], [UAParser.DEVICE.VENDOR, [UAParser.DEVICE.TYPE, UAParser.DEVICE.MOBILE]] +]; +let myParser2 = new UAParser({ + browser: myOwnListOfBrowsers, + device: myOwnListOfDevices +}); +let myUA2 = 'Mozilla/5.0 MyTab 14 Pro Max'; +console.log(myParser2.setUA(myUA2).getDevice()); // {vendor: "MyTab", model: "14 Pro Max", type: "tablet"} +``` + + # Usage ## Using HTML @@ -175,8 +250,8 @@ Ubuntu, Unix, VectorLinux, Viera, WebOS, Windows [Phone/Mobile], Zenwalk, ... @@ -248,11 +323,11 @@ $ npm install ua-parser-js ```js var http = require('http'); -var parser = require('ua-parser-js'); +var uap = require('ua-parser-js'); http.createServer(function (req, res) { // get user-agent header - var ua = parser(req.headers['user-agent']); + var ua = uap(req.headers['user-agent']); // write the result as response res.end(JSON.stringify(ua, null, ' ')); }) @@ -296,20 +371,6 @@ console.log(parseInt($.ua.browser.version.split('.')[0], 10)); // 4 $('body').addClass('ua-browser-' + $.ua.browser.name + ' ua-devicetype-' + $.ua.device.type); ``` -## Using Extension - -* `UAParser([uastring,] extensions)` - -```js -// Example: -var myOwnListOfBrowsers = [ - [/(mybrowser)\/([\w\.]+)/i], [UAParser.BROWSER.NAME, UAParser.BROWSER.VERSION] -]; -var myParser = new UAParser({ browser: myOwnListOfBrowsers }); -var myUA = 'Mozilla/5.0 MyBrowser/1.3'; -console.log(myParser.setUA(myUA).getBrowser()); // {name: "MyBrowser", version: "1.3"} -``` - # Development ## Sponsors diff --git a/src/ua-parser.js b/src/ua-parser.js index 4a22f67..c38b14d 100755 --- a/src/ua-parser.js +++ b/src/ua-parser.js @@ -17,7 +17,7 @@ ///////////// - var LIBVERSION = '0.7.32', + var LIBVERSION = '1.1.34', EMPTY = '', UNKNOWN = '?', FUNC_TYPE = 'function', @@ -56,7 +56,6 @@ SAMSUNG = 'Samsung', SHARP = 'Sharp', SONY = 'Sony', - VIERA = 'Viera', XIAOMI = 'Xiaomi', ZEBRA = 'Zebra', FACEBOOK = 'Facebook'; @@ -87,11 +86,14 @@ return typeof str1 === STR_TYPE ? lowerize(str2).indexOf(lowerize(str1)) !== -1 : false; }, lowerize = function (str) { - return str.toLowerCase(); + return typeof(str) === STR_TYPE ? str.toLowerCase() : UNDEF_TYPE; }, majorize = function (version) { return typeof(version) === STR_TYPE ? version.replace(/[^\d\.]/g, EMPTY).split('.')[0] : undefined; }, + sanitize = function (str, rgx) { + return rgx ? lowerize(str).replace(rgx, EMPTY) : lowerize(str); + }, trim = function (str, len) { if (typeof(str) === STR_TYPE) { str = str.replace(/^\s\s*/, EMPTY); @@ -200,6 +202,10 @@ '8.1' : 'NT 6.3', '10' : ['NT 6.4', 'NT 10.0'], 'RT' : 'ARM' + }, + archEquivalenceMap = { + 'amd64' : ['x86-64', 'x64'], + 'ia32' : ['x86'] }; ////////////// @@ -775,7 +781,70 @@ // Constructor //////////////// - var UAParser = function (ua, extensions) { + function UAItem (propToString, propIs) { + this.propToString = propToString; + this.propIs = propIs[0]; + this.rgxIs = propIs[1]; + } + UAItem.prototype.is = function (strCheck) { + for (var i in this.propIs) { + if (sanitize(this[this.propIs[i]], this.rgxIs) == sanitize(strCheck, this.rgxIs)) { + return true; + } + } + return false; + }; + UAItem.prototype.toString = function () { + var str = ''; + for (var i in this.propToString) { + if (typeof(this[this.propToString[i]]) !== UNDEF_TYPE) { + str += (str ? ' ' : '') + this[this.propToString[i]]; + } + } + return str ? str : UNDEF_TYPE; + }; + + function UABrowser () { + this[NAME] = undefined; + this[VERSION] = undefined; + this[MAJOR] = undefined; + } + UABrowser.prototype = new UAItem([NAME, VERSION], [[NAME], /\s?browser$/i]); + + function UACPU () { + this[ARCHITECTURE] = undefined; + } + UACPU.prototype = new UAItem([ARCHITECTURE], [[ARCHITECTURE]]); + + function UADevice () { + this[VENDOR] = undefined; + this[MODEL] = undefined; + this[TYPE] = undefined; + } + UADevice.prototype = new UAItem([VENDOR, MODEL], [[TYPE, MODEL, VENDOR]]); + + function UAEngine () { + this[NAME] = undefined; + this[VERSION] = undefined; + } + UAEngine.prototype = new UAItem([NAME, VERSION], [[NAME]]); + + function UAOS () { + this[NAME] = undefined; + this[VERSION] = undefined; + } + UAOS.prototype = new UAItem([NAME, VERSION], [[NAME], /\s?os$/i]); + + function UAResult (uap) { + this.ua = uap.getUA(); + this.browser = uap.getBrowser(); + this.cpu = uap.getCPU(); + this.device = uap.getDevice(); + this.engine = uap.getEngine(); + this.os = uap.getOS(); + } + + function UAParser (ua, extensions) { if (typeof ua === OBJ_TYPE) { extensions = ua; @@ -790,25 +859,20 @@ var _uach = (typeof window !== UNDEF_TYPE && window.navigator && window.navigator.userAgentData) ? window.navigator.userAgentData : undefined; var _rgxmap = extensions ? extend(regexes, extensions) : regexes; + // public methods this.getBrowser = function () { - var _browser = {}; - _browser[NAME] = undefined; - _browser[VERSION] = undefined; + var _browser = new UABrowser(); rgxMapper.call(_browser, _ua, _rgxmap.browser); - _browser.major = majorize(_browser.version); + _browser[MAJOR] = majorize(_browser[VERSION]); return _browser; }; this.getCPU = function () { - var _cpu = {}; - _cpu[ARCHITECTURE] = undefined; + var _cpu = new UACPU(); rgxMapper.call(_cpu, _ua, _rgxmap.cpu); return _cpu; }; this.getDevice = function () { - var _device = {}; - _device[VENDOR] = undefined; - _device[MODEL] = undefined; - _device[TYPE] = undefined; + var _device = new UADevice(); rgxMapper.call(_device, _ua, _rgxmap.device); if (!_device[TYPE] && _uach && _uach.mobile) { _device[TYPE] = MOBILE; @@ -816,31 +880,22 @@ return _device; }; this.getEngine = function () { - var _engine = {}; - _engine[NAME] = undefined; - _engine[VERSION] = undefined; + var _engine = new UAEngine(); rgxMapper.call(_engine, _ua, _rgxmap.engine); return _engine; }; this.getOS = function () { - var _os = {}; - _os[NAME] = undefined; - _os[VERSION] = undefined; + var _os = new UAOS(); rgxMapper.call(_os, _ua, _rgxmap.os); if (!_os[NAME] && _uach && _uach.platform != 'Unknown') { - _os[NAME] = _uach.platform.replace(/chrome/i, 'Chromium').replace(/mac/i, 'Mac '); + _os[NAME] = _uach.platform + .replace(/chrome os/i, 'Chromium OS') + .replace(/macos/i, 'Mac OS'); // backward compatibility } return _os; }; this.getResult = function () { - return { - ua : this.getUA(), - browser : this.getBrowser(), - engine : this.getEngine(), - os : this.getOS(), - device : this.getDevice(), - cpu : this.getCPU() - }; + return new UAResult(this); }; this.getUA = function () { return _ua; @@ -851,7 +906,7 @@ }; this.setUA(_ua); return this; - }; + } UAParser.VERSION = LIBVERSION; UAParser.BROWSER = enumerize([NAME, VERSION, MAJOR]); diff --git a/test/test.js b/test/test.js index e1fd175..18ec189 100644 --- a/test/test.js +++ b/test/test.js @@ -79,7 +79,7 @@ for (var i in methods) { describe('Returns', function () { it('getResult() should returns JSON', function(done) { - assert.deepStrictEqual(new UAParser('').getResult(), + assert.deepEqual(new UAParser('').getResult(), { ua : '', browser: { name: undefined, version: undefined, major: undefined }, @@ -166,3 +166,99 @@ describe('Testing regexes', function () { }); }); }); + + +describe('is() utility method', function () { + let uap = new UAParser('Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 635) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537'); + + it('Should match full name', function () { + assert.strictEqual(uap.getBrowser().name, "IEMobile"); + assert.strictEqual(uap.getBrowser().is("IEMobile"), true); + assert.strictEqual(uap.getBrowser().is("IE"), false); + + it('Should ignore spaces and "Browser" suffix', function () { + assert.strictEqual(uap.getBrowser().is("I EMo b i l e Browser"), true); + }); + }); + + it('Should ignore case', function () { + assert.strictEqual(uap.getEngine().name, "Trident"); + assert.strictEqual(uap.getEngine().is("tRiDeNt"), true); + }); + + it('Should get exact name', function () { + assert.strictEqual(uap.getOS().name, "Windows Phone"); + assert.strictEqual(uap.getOS().is("Windows Phone"), true); + assert.strictEqual(uap.getOS().is("Windows Phone OS"), true); + assert.strictEqual(uap.getOS().is("Windows Mobile"), false); + assert.strictEqual(uap.getOS().is("Android"), false); + }); + + it('Should check all device properties', function () { + assert.deepEqual(uap.getDevice(), { + vendor : "Nokia", + model : "Lumia 635", + type : "mobile" + }); + assert.strictEqual(uap.getDevice().is("Nokia"), true); + assert.strictEqual(uap.getDevice().is("Lumia 635"), true); + assert.strictEqual(uap.getDevice().is("mobile"), true); + + assert.strictEqual(uap.getResult().device.is("Nokia"), true); + + uap.setUA("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15"); + assert.strictEqual(uap.getDevice().is("undefined"), true); + }); + + it('Should get result after reassignment', function () { + uap.setUA("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"); + assert.strictEqual(uap.getOS().name, "Mac OS"); + assert.strictEqual(uap.getOS().is("Mac OS"), true); + assert.strictEqual(uap.getOS().is("M ac"), false); + assert.strictEqual(uap.getOS().is("macOS"), true); + assert.strictEqual(uap.getOS().is("mac OS"), true); + assert.strictEqual(uap.getOS().is("M a c "), false); + assert.strictEqual(uap.getOS().is("Mac OS OS"), false); + assert.strictEqual(uap.getOS().is("Mac OS X"), false); + + assert.strictEqual(uap.getBrowser().is("Chrome"), true); + assert.strictEqual(uap.getEngine().is("Blink"), true); + }); + + it('Should accept arch equivalent name', function () { + uap.setUA("Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:19.0) Gecko/20100101 Firefox/19.0"); + assert.strictEqual(uap.getCPU().architecture, "ia32"); + assert.strictEqual(uap.getCPU().is("ia32"), true); + assert.strictEqual(uap.getCPU().is("x86"), false); + + uap.setUA("Opera/9.80 (X11; Linux x86_64; U; Linux Mint; en) Presto/2.2.15 Version/10.10"); + assert.strictEqual(uap.getCPU().architecture, "amd64"); + assert.strictEqual(uap.getCPU().is("amd64"), true); + assert.strictEqual(uap.getCPU().is("x86-64"), false); + assert.strictEqual(uap.getCPU().is("x64"), false); + }); +}); + +describe('toString() utility method', function () { + let uap = new UAParser('Mozilla/5.0 (Mobile; Windows Phone 8.1; Android 4.0; ARM; Trident/7.0; Touch; rv:11.0; IEMobile/11.0; NOKIA; Lumia 635) like iPhone OS 7_0_3 Mac OS X AppleWebKit/537 (KHTML, like Gecko) Mobile Safari/537'); + assert.strictEqual(uap.getBrowser().name, "IEMobile"); + assert.strictEqual(uap.getBrowser().version, "11.0"); + assert.strictEqual(uap.getBrowser().major, "11"); + assert.strictEqual(uap.getBrowser().toString(), "IEMobile 11.0"); + + assert.strictEqual(uap.getCPU().architecture, "arm"); + assert.strictEqual(uap.getCPU().toString(), "arm"); + + assert.strictEqual(uap.getDevice().vendor, "Nokia"); + assert.strictEqual(uap.getDevice().model, "Lumia 635"); + assert.strictEqual(uap.getDevice().type, "mobile"); + assert.strictEqual(uap.getDevice().toString(), "Nokia Lumia 635"); + + assert.strictEqual(uap.getEngine().name, "Trident"); + assert.strictEqual(uap.getEngine().version, "7.0"); + assert.strictEqual(uap.getEngine().toString(), "Trident 7.0"); + + assert.strictEqual(uap.getOS().name, "Windows Phone"); + assert.strictEqual(uap.getOS().version, "8.1"); + assert.strictEqual(uap.getOS().toString(), "Windows Phone 8.1"); +}); \ No newline at end of file