Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#1067@major: Changes the default user agent. #1068

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions packages/happy-dom/src/navigator/Navigator.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import MimeTypeArray from './MimeTypeArray.js';
import PluginArray from './PluginArray.js';
import IWindow from '../window/IWindow.js';

/**
* Browser Navigator API.
Expand All @@ -10,6 +11,16 @@ import PluginArray from './PluginArray.js';
* https://html.spec.whatwg.org/multipage/system-state.html#dom-navigator.
*/
export default class Navigator {
private _ownerWindow: IWindow;

/**
*
* @param ownerWindow
*/
constructor(ownerWindow: IWindow) {
this._ownerWindow = ownerWindow;
}

/**
* False if setting a cookie will be ignored and true otherwise.
*/
Expand Down Expand Up @@ -84,14 +95,19 @@ export default class Navigator {
* Browser app version.
*/
public get appVersion(): string {
return '5.0 (Windows)';
const userAgent = this.userAgent;
const index = userAgent.indexOf('/');
return index > -1 ? userAgent.substring(index + 1) : '';
}

/**
* Browser platform.
*/
public get platform(): string {
return 'Win32';
const userAgent = this.userAgent;
const indexStart = userAgent.indexOf('(');
const indexEnd = userAgent.indexOf(')');
return indexStart > -1 && indexEnd > -1 ? userAgent.substring(indexStart + 1, indexEnd) : '';
}

/**
Expand Down Expand Up @@ -128,7 +144,7 @@ export default class Navigator {
* "appCodeName/appVersion number (Platform; Security; OS-or-CPU; Localization; rv: revision-version-number) product/productSub Application-Name Application-Name-version".
*/
public get userAgent(): string {
return 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0';
return this._ownerWindow.happyDOM.settings.navigator.userAgent;
}

/**
Expand Down
29 changes: 29 additions & 0 deletions packages/happy-dom/src/navigator/NavigatorUtility.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import FS from 'fs';
import Path from 'path';

/**
* Utility for navigator.
*/
export default class NavigatorUtility {
/**
* Returns the package version.
*
* @returns Package version.
*/
public static getHappyDOMVersion(): string {
const content = FS.readFileSync(Path.join(__dirname, '..', '..', 'package.json')).toString();
const json = JSON.parse(content);
return json.version;
}

/**
* Returns platform.
*
* @returns Platform.
*/
public static getPlatform(): string {
const platform = process.platform;
const platformCapitalized = platform.charAt(0).toUpperCase() + platform.slice(1);
return 'X11; ' + platformCapitalized + ' ' + process.arch;
}
}
3 changes: 3 additions & 0 deletions packages/happy-dom/src/window/IHappyDOMOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ export default interface IHappyDOMOptions {
disableIframePageLoading?: boolean;
disableComputedStyleRendering?: boolean;
enableFileSystemHttpRequests?: boolean;
navigator?: {
userAgent?: string;
};
device?: {
prefersColorScheme?: string;
mediaType?: string;
Expand Down
3 changes: 3 additions & 0 deletions packages/happy-dom/src/window/IHappyDOMSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ export default interface IHappyDOMSettings {
disableIframePageLoading: boolean;
disableComputedStyleRendering: boolean;
enableFileSystemHttpRequests: boolean;
navigator: {
userAgent: string;
};
device: {
prefersColorScheme: string;
mediaType: string;
Expand Down
10 changes: 9 additions & 1 deletion packages/happy-dom/src/window/Window.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ import WindowErrorUtility from './WindowErrorUtility.js';
import VirtualConsole from '../console/VirtualConsole.js';
import VirtualConsolePrinter from '../console/VirtualConsolePrinter.js';
import IHappyDOMSettings from './IHappyDOMSettings.js';
import NavigatorUtility from '../navigator/NavigatorUtility.js';

const ORIGINAL_SET_TIMEOUT = setTimeout;
const ORIGINAL_CLEAR_TIMEOUT = clearTimeout;
Expand Down Expand Up @@ -210,6 +211,9 @@ export default class Window extends EventTarget implements IWindow {
disableIframePageLoading: false,
disableComputedStyleRendering: false,
enableFileSystemHttpRequests: false,
navigator: {
userAgent: `Mozilla/5.0 (${NavigatorUtility.getPlatform()}) AppleWebKit/537.36 (KHTML, like Gecko) HappyDOM/${NavigatorUtility.getHappyDOMVersion()}`
},
device: {
prefersColorScheme: 'light',
mediaType: 'screen'
Expand Down Expand Up @@ -457,7 +461,7 @@ export default class Window extends EventTarget implements IWindow {

this.customElements = new CustomElementRegistry();
this.location = new Location();
this.navigator = new Navigator();
this.navigator = new Navigator(this);
this.history = new History();
this.screen = new Screen();
this.sessionStorage = new Storage();
Expand Down Expand Up @@ -488,6 +492,10 @@ export default class Window extends EventTarget implements IWindow {
this.happyDOM.settings = {
...this.happyDOM.settings,
...options.settings,
navigator: {
...this.happyDOM.settings.navigator,
...options.settings.navigator
},
device: {
...this.happyDOM.settings.device,
...options.settings.device
Expand Down
29 changes: 26 additions & 3 deletions packages/happy-dom/test/window/Window.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ import '../types.d.js';
import { beforeEach, afterEach, describe, it, expect, vi } from 'vitest';
import VirtualConsole from '../../src/console/VirtualConsole.js';
import VirtualConsolePrinter from '../../src/console/VirtualConsolePrinter.js';
import NavigatorUtility from '../../src/navigator/NavigatorUtility.js';
import PackageJson from '../../package.json';

const GET_NAVIGATOR_PLATFORM = (): string => {
const processPlatform = process.platform;
const processPlatformCapitalized =
processPlatform.charAt(0).toUpperCase() + processPlatform.slice(1);
return 'X11; ' + processPlatformCapitalized + ' ' + process.arch;
};

describe('Window', () => {
let window: IWindow;
Expand Down Expand Up @@ -100,6 +109,9 @@ describe('Window', () => {
console: globalThis.console,
settings: {
disableJavaScriptEvaluation: true,
navigator: {
userAgent: 'test'
},
device: {
prefersColorScheme: 'dark'
}
Expand All @@ -119,6 +131,7 @@ describe('Window', () => {
expect(windowWithOptions.happyDOM.settings.disableCSSFileLoading).toBe(false);
expect(windowWithOptions.happyDOM.settings.disableIframePageLoading).toBe(false);
expect(windowWithOptions.happyDOM.settings.enableFileSystemHttpRequests).toBe(false);
expect(windowWithOptions.happyDOM.settings.navigator.userAgent).toBe('test');
expect(windowWithOptions.happyDOM.settings.device.prefersColorScheme).toBe('dark');
expect(windowWithOptions.happyDOM.settings.device.mediaType).toBe('screen');

Expand All @@ -136,6 +149,11 @@ describe('Window', () => {
expect(windowWithoutOptions.happyDOM.settings.disableCSSFileLoading).toBe(false);
expect(windowWithoutOptions.happyDOM.settings.disableIframePageLoading).toBe(false);
expect(windowWithoutOptions.happyDOM.settings.enableFileSystemHttpRequests).toBe(false);
expect(windowWithoutOptions.happyDOM.settings.navigator.userAgent).toBe(
`Mozilla/5.0 (${GET_NAVIGATOR_PLATFORM()}) AppleWebKit/537.36 (KHTML, like Gecko) HappyDOM/${
PackageJson.version
}`
);
expect(windowWithoutOptions.happyDOM.settings.device.prefersColorScheme).toBe('light');
expect(windowWithoutOptions.happyDOM.settings.device.mediaType).toBe('screen');
});
Expand Down Expand Up @@ -432,11 +450,16 @@ describe('Window', () => {

describe('get navigator()', () => {
it('Returns an instance of Navigator with browser data.', () => {
const platform = GET_NAVIGATOR_PLATFORM();

expect(window.navigator instanceof Navigator).toBe(true);

const referenceValues = {
appCodeName: 'Mozilla',
appName: 'Netscape',
appVersion: '5.0 (Windows)',
appVersion: `5.0 (${NavigatorUtility.getPlatform()}) AppleWebKit/537.36 (KHTML, like Gecko) HappyDOM/${
PackageJson.version
}`,
cookieEnabled: true,
credentials: null,
doNotTrack: 'unspecified',
Expand All @@ -451,13 +474,13 @@ describe('Window', () => {
},
onLine: true,
permissions: null,
platform: 'Win32',
platform,
plugins: {
length: 0
},
product: 'Gecko',
productSub: '20100101',
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:97.0) Gecko/20100101 Firefox/97.0',
userAgent: `Mozilla/5.0 (${platform}) AppleWebKit/537.36 (KHTML, like Gecko) HappyDOM/${PackageJson.version}`,
vendor: '',
vendorSub: '',
webdriver: true
Expand Down