Skip to content

Commit

Permalink
Merge pull request #16370 from ckeditor/ck/16368
Browse files Browse the repository at this point in the history
Fix (utils): Prevented error thrown when editor files are imported in an environment without `window` global object. Closes #16368.
  • Loading branch information
scofalik committed May 16, 2024
2 parents c331903 + 64cd07c commit 0b70608
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 6 deletions.
16 changes: 12 additions & 4 deletions packages/ckeditor5-utils/src/env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
* @module utils/env
*/

import global from './dom/global.js';

/**
* Safely returns `userAgent` from browser's navigator API in a lower case.
* If navigator API is not available it will return an empty string.
*/
export function getUserAgent( ): string {
export function getUserAgent(): string {
// In some environments navigator API might not be available.
try {
return navigator.userAgent.toLowerCase();
Expand Down Expand Up @@ -109,7 +111,9 @@ const env: EnvType = {

isBlink: isBlink( userAgent ),

isMediaForcedColors: isMediaForcedColors(),
get isMediaForcedColors() {
return isMediaForcedColors();
},

get isMotionReduced() {
return isMotionReduced();
Expand Down Expand Up @@ -218,14 +222,18 @@ export function isRegExpUnicodePropertySupported(): boolean {

/**
* Checks if the user agent has enabled a forced colors mode (e.g. Windows High Contrast mode).
*
* Returns `false` in environments where `window` global object is not available.
*/
export function isMediaForcedColors(): boolean {
return window.matchMedia( '(forced-colors: active)' ).matches;
return global.window.matchMedia ? global.window.matchMedia( '(forced-colors: active)' ).matches : false;
}

/**
* Checks if user enabled "prefers reduced motion" setting in browser.
*
* Returns `false` in environments where `window` global object is not available.
*/
export function isMotionReduced(): boolean {
return window.matchMedia( '(prefers-reduced-motion)' ).matches;
return global.window.matchMedia ? global.window.matchMedia( '(prefers-reduced-motion)' ).matches : false;
}
67 changes: 65 additions & 2 deletions packages/ckeditor5-utils/tests/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
*/

import env, {
isMac, isWindows, isGecko, isSafari, isiOS, isAndroid, isRegExpUnicodePropertySupported, isBlink, getUserAgent, isMediaForcedColors
isMac, isWindows, isGecko, isSafari, isiOS, isAndroid, isRegExpUnicodePropertySupported, isBlink, getUserAgent,
isMediaForcedColors, isMotionReduced
} from '../src/env.js';

import global from '../src/dom/global.js';
Expand Down Expand Up @@ -64,9 +65,33 @@ describe( 'Env', () => {
} );

describe( 'isMediaForcedColors', () => {
let matchMediaStub;

beforeEach( () => {
matchMediaStub = sinon.stub( global.window, 'matchMedia' );
} );

it( 'is a boolean', () => {
expect( env.isMediaForcedColors ).to.be.a( 'boolean' );
mockMediaForcedColors();

expect( env.isMediaForcedColors ).to.be.true;
} );

it( 'should watch changes in forced colors setting', () => {
mockMediaForcedColors();

expect( env.isMediaForcedColors ).to.be.true;

mockMediaForcedColors( false );

expect( env.isMediaForcedColors ).to.be.false;
} );

function mockMediaForcedColors( enabled = true ) {
return matchMediaStub
.withArgs( '(forced-colors: active)' )
.returns( { matches: enabled } );
}
} );

describe( 'isMotionReduced', () => {
Expand Down Expand Up @@ -326,6 +351,44 @@ describe( 'Env', () => {

expect( isMediaForcedColors() ).to.be.false;
} );

it( 'returns false if window object is not available', () => {
// `global.window` is an empty object if `window` was not available in global space.
const _window = global.window;
global.window = {};

expect( isMediaForcedColors() ).to.be.false;

global.window = _window;
} );
} );

describe( 'isMotionReduced()', () => {
it( 'returns true if the document media query matches prefers-reduced-motion', () => {
testUtils.sinon.stub( global.window, 'matchMedia' )
.withArgs( '(prefers-reduced-motion)' )
.returns( { matches: true } );

expect( isMotionReduced() ).to.be.true;
} );

it( 'returns false if the document media query does not match prefers-reduced-motion', () => {
testUtils.sinon.stub( global.window, 'matchMedia' )
.withArgs( '(prefers-reduced-motion)' )
.returns( { matches: false } );

expect( isMotionReduced() ).to.be.false;
} );

it( 'returns false if window object is not available', () => {
// `global.window` is an empty object if `window` was not available in global space.
const _window = global.window;
global.window = {};

expect( isMotionReduced() ).to.be.false;

global.window = _window;
} );
} );

describe( 'isRegExpUnicodePropertySupported()', () => {
Expand Down

0 comments on commit 0b70608

Please sign in to comment.