Skip to content

Commit

Permalink
Move feature detection into its own method: withFeatureCheck
Browse files Browse the repository at this point in the history
  • Loading branch information
faisalman committed Apr 9, 2023
1 parent 05747db commit 16b416d
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 37 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
node_modules/
npm-debug.log
playwright-report/
test-results/

### vim ###
.*.s[a-w][a-z]
Expand Down
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- What's new:
- Add some new methods in result object:
- Add support for client hints: `withClientHints()`
- Add support for feature detection: `withFeatureCheck()`
- Utility for easy comparison: `is()`
- Utility to print full-name: `toString()`
- Add support for ES module `import { UAParser } from 'ua-parser-js'`
Expand Down
15 changes: 15 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,21 @@ new UAParser(request.headers)
});
```

#### * `withFeatureCheck():object` `since@2.0`

This method allows us to examine other features beyond `navigator.userAgent` to further improve detection of the following:
- browser : Brave (check for `navigator.isBrave`)
- device : iPad (check for `navigator.standalone` & `navigator.maxTouchPoints`)

```js
// suppose this code runs on iPad
const withoutFeatureCheck = UAParser();
const withFeatureCheck = UAParser().withFeatureCheck();

console.log(withoutFeatureCheck.device); // { vendor : "Apple", model : "Macintosh", type : undefined }
console.log(withFeatureCheck.device); // { vendor : "Apple", model : "iPad", type : "tablet" }
```

## 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.
Expand Down
22 changes: 19 additions & 3 deletions src/ua-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -862,6 +862,10 @@
});
};

UAParserData.prototype.withFeatureCheck = function () {
return item.detectFeature().get();
};

if (itemType != UA_RESULT) {
UAParserData.prototype.is = function (strToCheck) {
var is = false;
Expand Down Expand Up @@ -978,6 +982,20 @@
if (!this.get(NAME) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) {
this.set(NAME, NAVIGATOR_UADATA[PLATFORM]);
}
break;
case UA_RESULT:
var data = this.data;
var detect = function (itemType) {
return data[itemType]
.getItem()
.detectFeature()
.get();
};
this.set(UA_BROWSER, detect(UA_BROWSER))
.set(UA_CPU, detect(UA_CPU))
.set(UA_DEVICE, detect(UA_DEVICE))
.set(UA_ENGINE, detect(UA_ENGINE))
.set(UA_OS, detect(UA_OS));
}
}
return this;
Expand Down Expand Up @@ -1046,8 +1064,7 @@
.parseCH()
.get();
};
this.set('ua', ua)
.set(UA_BROWSER, parse(UA_BROWSER))
this.set(UA_BROWSER, parse(UA_BROWSER))
.set(UA_CPU, parse(UA_CPU))
.set(UA_DEVICE, parse(UA_DEVICE))
.set(UA_ENGINE, parse(UA_ENGINE))
Expand Down Expand Up @@ -1118,7 +1135,6 @@
return function () {
return new UAParserItem(itemType, userAgent, regexMap[itemType], HTTP_UACH)
.parseUA()
.detectFeature()
.get();
};
}
Expand Down
89 changes: 55 additions & 34 deletions test/playwright-test-browser.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,63 @@ import { test, expect } from '@playwright/test';
import path from 'path';
import url from 'url';

const localHtml = `file://${path.resolve(path.dirname(url.fileURLToPath(import.meta.url)), '../')}/dist/ua-parser.html`;

test('read client hints data', async ({ page }) => {
await page.addInitScript(() => {
Object.defineProperty(navigator, 'userAgentData', {
value : {
brands : [],
platform : '',
mobile : false,
getHighEntropyValues : () => {
return Promise.resolve({
brands : [
{
brand : 'Chromium',
version : '110'
},
{
brand : 'Not(A:Brand',
version : '110'
},
{
brand : 'New Browser',
version : '110'
}
],
platform : 'New OS'
});
}
}
await page.addInitScript(() => {
Object.defineProperty(navigator, 'userAgentData', {
value: {
brands: [],
platform: '',
mobile: false,
getHighEntropyValues: () => {
return Promise.resolve({
brands: [
{
brand: 'Chromium',
version: '110'
},
{
brand: 'Not(A:Brand',
version: '110'
},
{
brand: 'New Browser',
version: '110'
}
],
platform: 'New OS'
});
}
}
});
});
});

const dirname = path.resolve(path.dirname(url.fileURLToPath(import.meta.url)), '../');
await page.goto(`file://${dirname}/dist/ua-parser.html`);
await page.goto(localHtml);

// @ts-ignore
const uap = await page.evaluate(async () => await UAParser().withClientHints());

expect(uap).toHaveProperty('browser.name', 'New Browser');
expect(uap).toHaveProperty('os.name', 'New OS');
});

test('detect Brave', async ({ page }) => {
await page.addInitScript(() => {
Object.defineProperty(navigator, 'brave', {
value: {
isBrave: () => true
}
});
});

await page.goto(localHtml);

// @ts-ignore
let uap = await page.evaluate(() => UAParser());
expect(uap).toHaveProperty('browser.name', 'Chrome Headless');

// @ts-ignore
const uap = await page.evaluate(async () => await UAParser().withClientHints());

expect(uap).toHaveProperty('browser.name', 'New Browser');
expect(uap).toHaveProperty('os.name', 'New OS');
// @ts-ignore
uap = await page.evaluate(() => UAParser().withFeatureCheck());
expect(uap).toHaveProperty('browser.name', 'Brave');
});

0 comments on commit 16b416d

Please sign in to comment.