mirror of
https://github.com/lancedikson/bowser
synced 2025-12-05 06:02:14 +00:00
Merge remote-tracking branch 'origin/master' into add-bot-platforms
# Conflicts: # src/constants.js
This commit is contained in:
commit
4cdac37e03
@ -1 +1 @@
|
|||||||
repo_token: Ba2bS7pOlSLZWuESBnff8qxDjIS8Mg1Z0
|
|
||||||
|
|||||||
129
.github/copilot-instructions.md
vendored
Normal file
129
.github/copilot-instructions.md
vendored
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
# Copilot Instructions for Bowser
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
Bowser is a small, fast, and rich-API browser/platform/engine detector for both browser and Node.js environments. It's designed to parse User-Agent strings and provide detailed information about browsers, operating systems, platforms, and rendering engines.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Core Components
|
||||||
|
|
||||||
|
- **`src/bowser.js`**: Main entry point and public API. Provides static methods `getParser()` and `parse()`.
|
||||||
|
- **`src/parser.js`**: Core parsing engine that orchestrates all parsers and returns structured results.
|
||||||
|
- **`src/parser-browsers.js`**: Browser detection logic using regex patterns.
|
||||||
|
- **`src/parser-os.js`**: Operating system detection logic.
|
||||||
|
- **`src/parser-platforms.js`**: Platform type detection (desktop, tablet, mobile).
|
||||||
|
- **`src/parser-engines.js`**: Rendering engine detection (WebKit, Blink, Gecko, etc.).
|
||||||
|
- **`src/constants.js`**: Centralized constants including browser aliases and mappings.
|
||||||
|
- **`src/utils.js`**: Utility functions for string matching and manipulation.
|
||||||
|
|
||||||
|
### Build Output
|
||||||
|
|
||||||
|
- **`es5.js`**: ES5 transpiled version (default export).
|
||||||
|
- **`bundled.js`**: ES5 version with babel-polyfill included.
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
|
||||||
|
### Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Key Commands
|
||||||
|
|
||||||
|
- **Build**: `npm run build` - Compiles source files using Webpack and Babel.
|
||||||
|
- **Test**: `npm test` - Runs unit and acceptance tests using AVA.
|
||||||
|
- **Lint**: `npm run lint:check` - Checks code style using ESLint.
|
||||||
|
- **Lint Fix**: `npm run lint:fix` - Auto-fixes linting issues.
|
||||||
|
- **Watch Mode**: `npm run watch` - Builds on file changes.
|
||||||
|
- **Test Watch**: `npm run test:watch` - Runs tests on file changes.
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
- Tests are located in `test/acceptance/` and `test/unit/`.
|
||||||
|
- Acceptance tests use real User-Agent strings from `test/acceptance/useragentstrings.yml`.
|
||||||
|
- Always update `useragentstrings.yml` when adding browser support.
|
||||||
|
- Test framework: AVA with Babel integration.
|
||||||
|
|
||||||
|
## Coding Standards
|
||||||
|
|
||||||
|
### Style Guide
|
||||||
|
|
||||||
|
- **ESLint Config**: Based on Airbnb Base style guide.
|
||||||
|
- **Parser**: Uses `babel-eslint`.
|
||||||
|
- **Exceptions**:
|
||||||
|
- Underscore-dangle allowed for private properties.
|
||||||
|
- `no-void` disabled.
|
||||||
|
- ES6 imports must include `.js` extension.
|
||||||
|
|
||||||
|
### Naming Conventions
|
||||||
|
|
||||||
|
- **Browser Aliases**: Use lowercase letters, replace spaces/dashes with underscores, drop "browser" suffix.
|
||||||
|
- Examples: `Opera Coast` → `opera_coast`, `UC Browser` → `uc`, `SeaMonkey` → `seamonkey`.
|
||||||
|
- **Private Properties**: Prefix with underscore (e.g., `_ua`).
|
||||||
|
- **Constants**: Use `UPPER_SNAKE_CASE` for constant maps and aliases.
|
||||||
|
|
||||||
|
### Code Patterns
|
||||||
|
|
||||||
|
- Use ES6 modules with explicit `.js` extensions.
|
||||||
|
- Prefer static methods in Bowser class.
|
||||||
|
- Use class-based structure for Parser.
|
||||||
|
- Regex patterns should be well-documented and tested.
|
||||||
|
- Keep parsers modular and focused on single responsibility.
|
||||||
|
|
||||||
|
## Adding Browser Support
|
||||||
|
|
||||||
|
When adding support for a new browser:
|
||||||
|
|
||||||
|
1. Add regex pattern to `src/parser-browsers.js`.
|
||||||
|
2. Add browser name to `BROWSER_ALIASES_MAP` in `src/constants.js`.
|
||||||
|
3. Add corresponding entry to `BROWSER_MAP`.
|
||||||
|
4. Add test cases to `test/acceptance/useragentstrings.yml`.
|
||||||
|
5. Run tests to verify: `npm test`.
|
||||||
|
6. Check for duplicates before adding aliases.
|
||||||
|
|
||||||
|
## Branching Strategy
|
||||||
|
|
||||||
|
- **`master`**: Development branch.
|
||||||
|
- **`production`**: Production branch.
|
||||||
|
- **New Features**: Branch from `master`, PR back to `master`.
|
||||||
|
- **Hot-fixes/Browser Support**: Branch from `production`, PR back to `production`.
|
||||||
|
|
||||||
|
## Important Files
|
||||||
|
|
||||||
|
- **`index.d.ts`**: TypeScript definitions.
|
||||||
|
- **`.babelrc`**: Babel configuration for ES5 transpilation.
|
||||||
|
- **`webpack.config.js`**: Build configuration.
|
||||||
|
- **`.eslintrc.yml`**: Linting rules.
|
||||||
|
- **`package.json`**: Dependencies and scripts.
|
||||||
|
|
||||||
|
## API Design Principles
|
||||||
|
|
||||||
|
- Keep the API simple and intuitive.
|
||||||
|
- Bowser class should be stateless and provide factory methods.
|
||||||
|
- Parser class handles instance-specific logic.
|
||||||
|
- Results should be structured and predictable.
|
||||||
|
- Support both immediate parsing and lazy parsing.
|
||||||
|
|
||||||
|
## Performance Considerations
|
||||||
|
|
||||||
|
- Parsers use lazy evaluation where possible.
|
||||||
|
- Regex patterns are optimized for common browsers first.
|
||||||
|
- Optional `skipParsing` parameter for delayed parsing.
|
||||||
|
- Minimal bundle size is a priority (~4.8kB gzipped).
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- Use JSDoc comments for all public APIs.
|
||||||
|
- Document parameters, return types, and provide examples.
|
||||||
|
- Update README.md for API changes.
|
||||||
|
- Generate docs with: `npm run generate-docs`.
|
||||||
|
|
||||||
|
## Common Pitfalls
|
||||||
|
|
||||||
|
- Always check `BROWSER_ALIASES_MAP` for existing aliases before adding new ones.
|
||||||
|
- User-Agent strings can be complex; test edge cases thoroughly.
|
||||||
|
- Remember to update both the alias map and the reverse map in constants.
|
||||||
|
- Browser versions should be treated as strings, not numbers.
|
||||||
|
- Keep regex patterns readable with comments explaining their purpose.
|
||||||
19
.github/release-drafter.yml
vendored
Normal file
19
.github/release-drafter.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
name-template: 'v$RESOLVED_VERSION 🌈'
|
||||||
|
tag-template: 'v$RESOLVED_VERSION'
|
||||||
|
version-resolver:
|
||||||
|
major:
|
||||||
|
labels:
|
||||||
|
- major
|
||||||
|
minor:
|
||||||
|
labels:
|
||||||
|
- minor
|
||||||
|
patch:
|
||||||
|
labels:
|
||||||
|
- patch
|
||||||
|
default: patch
|
||||||
|
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
|
||||||
|
change-title-escapes: '\<*_&'
|
||||||
|
template: |
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
$CHANGES
|
||||||
20
.github/workflows/draft-or-update-next-release.yml
vendored
Normal file
20
.github/workflows/draft-or-update-next-release.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
name: 📝 Draft or update next release
|
||||||
|
concurrency: draft_or_update_next_release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
prepare-deployment:
|
||||||
|
name: 📝 Draft or update next release
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 30
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: release-drafter/release-drafter@v5
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
7
.github/workflows/merge-to-master.yml
vendored
7
.github/workflows/merge-to-master.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
name: 'Merge to master'
|
name: "Merge to master"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@ -23,11 +23,12 @@ jobs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: echo "BRANCH_NAME=$(echo ${GITHUB_HEAD_REF} | tr / -)" >> $GITHUB_ENV
|
run: echo "BRANCH_NAME=$(echo ${GITHUB_HEAD_REF} | tr / -)" >> $GITHUB_ENV
|
||||||
|
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v4
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
|
- run: npm i -g nyc@15
|
||||||
- run: npm ci
|
- run: npm ci
|
||||||
- run: npm run build
|
- run: npm run build
|
||||||
- run: nyc npm test && nyc report --reporter=text-lcov | ./node_modules/coveralls/bin/coveralls.js
|
- run: nyc npm test && nyc report --reporter=text-lcov | ./node_modules/coveralls/bin/coveralls.js
|
||||||
|
|||||||
63
.github/workflows/publish.yml
vendored
Normal file
63
.github/workflows/publish.yml
vendored
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
# This job runs when a new release is published
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
# Manual trigger with version input
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
description: "Version to release (e.g., 2.12.1)"
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 12.16.3
|
||||||
|
registry-url: "https://registry.npmjs.org"
|
||||||
|
- uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ~/.npm
|
||||||
|
key: ${{ runner.os }}-node-${{ hashFiles('**/package.json') }}
|
||||||
|
# Store the release version (from release tag or manual input)
|
||||||
|
- name: Set release version
|
||||||
|
run: |
|
||||||
|
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||||
|
echo "RELEASE_VERSION=${{ github.event.inputs.version }}" >> $GITHUB_ENV
|
||||||
|
echo "Manual release triggered for version: ${{ github.event.inputs.version }}"
|
||||||
|
else
|
||||||
|
echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
|
||||||
|
echo "Release triggered from tag: ${GITHUB_REF#refs/*/}"
|
||||||
|
fi
|
||||||
|
- run: npm ci
|
||||||
|
- run: npm version $RELEASE_VERSION --no-git-tag-version
|
||||||
|
- run: npm run build
|
||||||
|
- name: Publish to npm with retry
|
||||||
|
run: |
|
||||||
|
max_attempts=5
|
||||||
|
attempt=1
|
||||||
|
while [ $attempt -le $max_attempts ]; do
|
||||||
|
echo "Attempt $attempt of $max_attempts..."
|
||||||
|
if npm publish --access public; then
|
||||||
|
echo "Successfully published!"
|
||||||
|
break
|
||||||
|
else
|
||||||
|
if [ $attempt -eq $max_attempts ]; then
|
||||||
|
echo "Failed to publish after $max_attempts attempts"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Publish failed, waiting before retry..."
|
||||||
|
sleep_time=$((attempt * 30))
|
||||||
|
echo "Waiting ${sleep_time} seconds before retry..."
|
||||||
|
sleep $sleep_time
|
||||||
|
attempt=$((attempt + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
env:
|
||||||
|
NODE_AUTH_TOKEN: ${{ secrets.BOWSER_NPM_PUBLISH_TOKEN }}
|
||||||
16
.github/workflows/pull-request.yml
vendored
16
.github/workflows/pull-request.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
name: 'Pull Request'
|
name: "Pull Request"
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, reopened, synchronize]
|
types: [opened, reopened, synchronize]
|
||||||
@ -11,12 +11,12 @@ jobs:
|
|||||||
node: [12.16.3]
|
node: [12.16.3]
|
||||||
name: Node ${{ matrix.node }}
|
name: Node ${{ matrix.node }}
|
||||||
steps:
|
steps:
|
||||||
- name: 'Checkout latest code'
|
- name: "Checkout latest code"
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
- name: Set up node
|
- name: Set up node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node }}
|
node-version: ${{ matrix.node }}
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@ -27,17 +27,17 @@ jobs:
|
|||||||
run: npm run test
|
run: npm run test
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
name: 'ESLint'
|
name: "ESLint"
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout latest code
|
- name: Checkout latest code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
- name: Set up node
|
- name: Set up node
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: '16'
|
node-version: "16"
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
- name: Run ESLint
|
- name: Run ESLint
|
||||||
|
|||||||
@ -11,8 +11,6 @@ Don't hesitate to support the project on Github or [OpenCollective](https://open
|
|||||||
# Contents
|
# Contents
|
||||||
- [Overview](#overview)
|
- [Overview](#overview)
|
||||||
- [Use cases](#use-cases)
|
- [Use cases](#use-cases)
|
||||||
- [Advanced usage](#advanced-usage)
|
|
||||||
- [How can I help?](#contributing)
|
|
||||||
|
|
||||||
# Overview
|
# Overview
|
||||||
|
|
||||||
@ -20,7 +18,7 @@ The library is made to help to detect what browser your user has and gives you a
|
|||||||
|
|
||||||
### ⚠️ Version 2.0 breaking changes ⚠️
|
### ⚠️ Version 2.0 breaking changes ⚠️
|
||||||
|
|
||||||
Version 2.0 has drastically changed the API. All available methods are on the [docs page](https://lancedikson.github.io/bowser/docs).
|
Version 2.0 has drastically changed the API. All available methods are on the [docs page](https://bowser-js.github.io/bowser/docs/).
|
||||||
|
|
||||||
_For legacy code, check out the [1.x](https://github.com/lancedikson/bowser/tree/v1.x) branch and install it through `npm install bowser@1.9.4`._
|
_For legacy code, check out the [1.x](https://github.com/lancedikson/bowser/tree/v1.x) branch and install it through `npm install bowser@1.9.4`._
|
||||||
|
|
||||||
|
|||||||
9
index.d.ts
vendored
9
index.d.ts
vendored
@ -2,9 +2,16 @@
|
|||||||
// Project: https://github.com/lancedikson/bowser
|
// Project: https://github.com/lancedikson/bowser
|
||||||
// Definitions by: Alexander P. Cerutti <https://github.com/alexandercerutti>,
|
// Definitions by: Alexander P. Cerutti <https://github.com/alexandercerutti>,
|
||||||
|
|
||||||
export default Bowser;
|
export = Bowser;
|
||||||
export as namespace Bowser;
|
export as namespace Bowser;
|
||||||
|
|
||||||
|
export function getParser(UA: string, skipParsing?: boolean): Bowser.Parser.Parser;
|
||||||
|
export function parse(UA: string): Bowser.Parser.ParsedResult;
|
||||||
|
export const BROWSER_MAP: Record<string, string>;
|
||||||
|
export const ENGINE_MAP: Record<string, string>;
|
||||||
|
export const OS_MAP: Record<string, string>;
|
||||||
|
export const PLATFORMS_MAP: Record<string, string>;
|
||||||
|
|
||||||
declare namespace Bowser {
|
declare namespace Bowser {
|
||||||
/**
|
/**
|
||||||
* Creates a Parser instance
|
* Creates a Parser instance
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "bowser",
|
"name": "bowser",
|
||||||
"version": "2.11.0",
|
|
||||||
"description": "Lightweight browser detector",
|
"description": "Lightweight browser detector",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"browser",
|
"browser",
|
||||||
|
|||||||
@ -75,3 +75,9 @@ class Bowser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default Bowser;
|
export default Bowser;
|
||||||
|
|
||||||
|
export const { getParser } = Bowser;
|
||||||
|
export const { parse } = Bowser;
|
||||||
|
export {
|
||||||
|
BROWSER_MAP, ENGINE_MAP, OS_MAP, PLATFORMS_MAP,
|
||||||
|
};
|
||||||
|
|||||||
@ -126,6 +126,7 @@ export const OS_MAP = {
|
|||||||
WebOS: 'WebOS',
|
WebOS: 'WebOS',
|
||||||
Windows: 'Windows',
|
Windows: 'Windows',
|
||||||
WindowsPhone: 'Windows Phone',
|
WindowsPhone: 'Windows Phone',
|
||||||
|
HarmonyOS: 'HarmonyOS',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ENGINE_MAP = {
|
export const ENGINE_MAP = {
|
||||||
|
|||||||
@ -87,6 +87,18 @@ export default [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/* HarmonyOS */
|
||||||
|
{
|
||||||
|
test: [/OpenHarmony/i],
|
||||||
|
describe(ua) {
|
||||||
|
const version = Utils.getFirstMatch(/OpenHarmony\s+(\d+(\.\d+)*)/i, ua);
|
||||||
|
return {
|
||||||
|
name: OS_MAP.HarmonyOS,
|
||||||
|
version,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
/* Android */
|
/* Android */
|
||||||
{
|
{
|
||||||
test(parser) {
|
test(parser) {
|
||||||
|
|||||||
@ -365,6 +365,20 @@
|
|||||||
type: "mobile"
|
type: "mobile"
|
||||||
engine:
|
engine:
|
||||||
name: "Blink"
|
name: "Blink"
|
||||||
|
-
|
||||||
|
ua: "Mozilla/5.0 (Phone; OpenHarmony 5.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 ArkWeb/4.1.6.1 Mobile HuaweiBrowser/5.1.5.352"
|
||||||
|
spec:
|
||||||
|
browser:
|
||||||
|
name: "Chrome"
|
||||||
|
version: "114.0.0.0"
|
||||||
|
os:
|
||||||
|
name: "HarmonyOS"
|
||||||
|
version: "5.0"
|
||||||
|
platform:
|
||||||
|
type: "mobile"
|
||||||
|
vendor: "Huawei"
|
||||||
|
engine:
|
||||||
|
name: "Blink"
|
||||||
Google Search:
|
Google Search:
|
||||||
-
|
-
|
||||||
ua: "Mozilla/5.0 (iPhone; CPU iPhone OS 12_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) GSA/83.0.268992909 Mobile/15E148 Safari/605.1"
|
ua: "Mozilla/5.0 (iPhone; CPU iPhone OS 12_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) GSA/83.0.268992909 Mobile/15E148 Safari/605.1"
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import test from 'ava';
|
import test from 'ava';
|
||||||
import Bowser from '../../src/bowser';
|
import Bowser, { getParser, parse, BROWSER_MAP, ENGINE_MAP, OS_MAP, PLATFORMS_MAP } from '../../src/bowser';
|
||||||
import Parser from '../../src/parser';
|
import Parser from '../../src/parser';
|
||||||
|
|
||||||
const UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 OPR/43.0.2442.1165';
|
const UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 OPR/43.0.2442.1165';
|
||||||
@ -16,3 +16,64 @@ test('Bowser`s constructor fails if UA is empty', (t) => {
|
|||||||
test('Bowser.parse parses UA and returns result', (t) => {
|
test('Bowser.parse parses UA and returns result', (t) => {
|
||||||
t.deepEqual(Bowser.parse(UA), browser.getResult());
|
t.deepEqual(Bowser.parse(UA), browser.getResult());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Named export getParser works like Bowser.getParser', (t) => {
|
||||||
|
const namedExportParser = getParser(UA);
|
||||||
|
t.truthy(namedExportParser instanceof Parser);
|
||||||
|
t.deepEqual(namedExportParser.getResult(), browser.getResult());
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Named export getParser with skipParsing parameter', (t) => {
|
||||||
|
const parserWithSkip = getParser(UA, true);
|
||||||
|
t.truthy(parserWithSkip instanceof Parser);
|
||||||
|
// With skipParsing=true, the result should be undefined until we explicitly parse
|
||||||
|
t.deepEqual(parserWithSkip.getResult(), Bowser.getParser(UA, true).getResult());
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Named export getParser throws error for invalid UA', (t) => {
|
||||||
|
t.throws(() => getParser(undefined), { message: 'UserAgent should be a string' });
|
||||||
|
t.throws(() => getParser(123), { message: 'UserAgent should be a string' });
|
||||||
|
t.throws(() => getParser(null), { message: 'UserAgent should be a string' });
|
||||||
|
t.throws(() => getParser({}), { message: 'UserAgent should be a string' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Named export parse works like Bowser.parse', (t) => {
|
||||||
|
t.deepEqual(parse(UA), Bowser.parse(UA));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Named export parse produces consistent results', (t) => {
|
||||||
|
const result1 = parse(UA);
|
||||||
|
const result2 = parse(UA);
|
||||||
|
t.deepEqual(result1, result2);
|
||||||
|
t.deepEqual(result1, Bowser.parse(UA));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Named exports of constants are available', (t) => {
|
||||||
|
t.truthy(BROWSER_MAP);
|
||||||
|
t.truthy(ENGINE_MAP);
|
||||||
|
t.truthy(OS_MAP);
|
||||||
|
t.truthy(PLATFORMS_MAP);
|
||||||
|
t.is(BROWSER_MAP, Bowser.BROWSER_MAP);
|
||||||
|
t.is(ENGINE_MAP, Bowser.ENGINE_MAP);
|
||||||
|
t.is(OS_MAP, Bowser.OS_MAP);
|
||||||
|
t.is(PLATFORMS_MAP, Bowser.PLATFORMS_MAP);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Named exports constants are objects with expected structure', (t) => {
|
||||||
|
t.is(typeof BROWSER_MAP, 'object');
|
||||||
|
t.is(typeof ENGINE_MAP, 'object');
|
||||||
|
t.is(typeof OS_MAP, 'object');
|
||||||
|
t.is(typeof PLATFORMS_MAP, 'object');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('All named exports work together', (t) => {
|
||||||
|
// Test that we can use multiple named exports in the same scope
|
||||||
|
const result = parse(UA);
|
||||||
|
const parser = getParser(UA);
|
||||||
|
|
||||||
|
t.deepEqual(result, parser.getResult());
|
||||||
|
t.truthy(BROWSER_MAP);
|
||||||
|
t.truthy(ENGINE_MAP);
|
||||||
|
t.truthy(OS_MAP);
|
||||||
|
t.truthy(PLATFORMS_MAP);
|
||||||
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user