diff --git a/src/dom/rect.js b/src/dom/rect.js index b20d69e..3a832bb 100644 --- a/src/dom/rect.js +++ b/src/dom/rect.js @@ -10,7 +10,6 @@ import isRange from './isrange'; import isWindow from './iswindow'; import getBorderWidths from './getborderwidths'; -import log from '../log'; import isText from './istext'; import { isElement } from 'lodash-es'; @@ -67,26 +66,16 @@ export default class Rect { } ); if ( isElement( source ) || isSourceRange ) { - const sourceNode = isSourceRange ? source.startContainer : source; - - if ( !sourceNode.ownerDocument || !sourceNode.ownerDocument.body.contains( sourceNode ) ) { - /** - * The `Rect` class depends on `getBoundingClientRect` and `getClientRects` DOM methods. - * If the {@link #constructor source} of a rect in an HTML element or a DOM range but it does - * not belong to any rendered DOM tree, these methods will fail to obtain the geometry and - * the rect instance makes little sense to the features using it. - * - * To get rid of this warning make sure the source passed to the constructor - * is a descendant of `window.document.body`. - * - * @error rect-source-not-in-dom - * @param {String} source The source of the Rect instance. - */ - log.warn( - 'rect-source-not-in-dom: The source of this rect does not belong to any rendered DOM tree.', - { source } - ); - } + // The `Rect` class depends on `getBoundingClientRect` and `getClientRects` DOM methods. If the source + // of a rect in an HTML element or a DOM range but it does not belong to any rendered DOM tree, these methods + // will fail to obtain the geometry and the rect instance makes little sense to the features using it. + // To get rid of this warning make sure the source passed to the constructor is a descendant of `window.document.body`. + // @if CK_DEBUG // const sourceNode = isSourceRange ? source.startContainer : source; + // @if CK_DEBUG // if ( !sourceNode.ownerDocument || !sourceNode.ownerDocument.body.contains( sourceNode ) ) { + // @if CK_DEBUG // console.warn( + // @if CK_DEBUG // 'rect-source-not-in-dom: The source of this rect does not belong to any rendered DOM tree.', + // @if CK_DEBUG // { source } ); + // @if CK_DEBUG // } if ( isSourceRange ) { copyRectProperties( this, Rect.getDomRangeRects( source )[ 0 ] ); diff --git a/src/log.js b/src/log.js deleted file mode 100644 index c1dc540..0000000 --- a/src/log.js +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license - */ - -/* global console */ - -/** - * @module utils/log - */ - -import { attachLinkToDocumentation } from './ckeditorerror'; - -/** - * The logging module. - * - * This object features two functions that should be used across CKEditor code base to log errors and warnings. - * Despite being an overridable interface for native `console.*` this module serves also the goal to limit the - * code size of a minified CKEditor package. During minification process the messages will be shortened and - * links to their documentation will be logged to the console. - * - * All errors and warning should be documented in the following way: - * - * /** - * * Error thrown when a plugin cannot be loaded due to JavaScript errors, lack of plugins with a given name, etc. - * * - * * @error plugin-load - * * @param pluginName The name of the plugin that could not be loaded. - * * @param moduleName The name of the module which tried to load this plugin. - * * / - * log.error( 'plugin-load: It was not possible to load the "{$pluginName}" plugin in module "{$moduleName}', { - * pluginName: 'foo', - * moduleName: 'bar' - * } ); - * - * ### Warning vs Error vs Throw - * - * * Whenever a potentially incorrect situation occurs, which does not directly lead to an incorrect behavior, - * log a warning. - * * Whenever an incorrect situation occurs, but the app may continue working (although perhaps incorrectly), - * log an error. - * * Whenever it's really bad and it does not make sense to continue working, throw a {@link module:utils/ckeditorerror~CKEditorError}. - * - * @namespace - */ -const log = { - /** - * Logs an error to the console. - * - * Read more about error logging in the {@link module:utils/log} module. - * - * @param {String} message The error message in an `error-name: Error message.` format. - * During the minification process the "Error message" part will be removed to limit the code size - * and a link to this error documentation will be logged to the console. - * @param {Object} [data] Additional data describing the error. - */ - error( message, data ) { - console.error( attachLinkToDocumentation( message ), data ); - }, - - /** - * Logs a warning to the console. - * - * Read more about error logging in the {@link module:utils/log} module. - * - * @param {String} message The warning message in a `warning-name: Warning message.` format. - * During the minification process the "Warning message" part will be removed to limit the code size - * and a link to this error documentation will be logged to the console. - * @param {Object} [data] Additional data describing the warning. - */ - warn( message, data ) { - console.warn( attachLinkToDocumentation( message ), data ); - } -}; - -export default log; diff --git a/src/version.js b/src/version.js index 143e07f..21a6e8c 100644 --- a/src/version.js +++ b/src/version.js @@ -9,8 +9,8 @@ /* globals window, global */ -import log from './log'; import { version } from 'ckeditor5/package.json'; +import CKEditorError from './ckeditorerror'; const windowOrGlobal = typeof window === 'object' ? window : global; @@ -138,7 +138,10 @@ if ( windowOrGlobal.CKEDITOR_VERSION ) { * * @error ckeditor-duplicated-modules */ - log.error( 'ckeditor-duplicated-modules: Some CKEditor 5 modules are duplicated.' ); + throw new CKEditorError( + 'ckeditor-duplicated-modules: Some CKEditor 5 modules are duplicated.', + null + ); } else { windowOrGlobal.CKEDITOR_VERSION = version; } diff --git a/tests/_utils-tests/utils.js b/tests/_utils-tests/utils.js index ea193f6..b4e7852 100644 --- a/tests/_utils-tests/utils.js +++ b/tests/_utils-tests/utils.js @@ -29,7 +29,7 @@ describe( 'utils - testUtils', () => { } ); it( 'should create an observer', () => { - function Emitter() { } + function Emitter() {} Emitter.prototype = EmitterMixin; expect( observer ).to.be.instanceof( Emitter ); diff --git a/tests/collection.js b/tests/collection.js index a3f215c..0dc77c6 100644 --- a/tests/collection.js +++ b/tests/collection.js @@ -522,7 +522,7 @@ describe( 'Collection', () => { sinon.assert.calledWithExactly( spy, callback, ctx ); expect( ret ).to.deep.equal( [ 'foo' ], 'ret value was forwarded' ); - function callback() { } + function callback() {} } ); } ); @@ -538,7 +538,7 @@ describe( 'Collection', () => { sinon.assert.calledWithExactly( spy, callback, ctx ); expect( ret ).to.equal( needl, 'ret value was forwarded' ); - function callback() { } + function callback() {} } ); } ); @@ -555,7 +555,7 @@ describe( 'Collection', () => { sinon.assert.calledWithExactly( spy, callback, ctx ); expect( ret ).to.deep.equal( [ needl ], 'ret value was forwarded' ); - function callback() { } + function callback() {} } ); } ); @@ -700,7 +700,7 @@ describe( 'Collection', () => { } ); it( 'does not chain', () => { - const returned = collection.bindTo( new Collection() ).using( () => { } ); + const returned = collection.bindTo( new Collection() ).using( () => {} ); expect( returned ).to.be.undefined; } ); diff --git a/tests/dom/rect.js b/tests/dom/rect.js index ba1408e..47ebc4d 100644 --- a/tests/dom/rect.js +++ b/tests/dom/rect.js @@ -3,17 +3,13 @@ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ -/* global window, document */ +/* global window, document, console */ import Rect from '../../src/dom/rect'; -import log from '../../src/log'; -import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils'; describe( 'Rect', () => { let geometry; - testUtils.createSinonSandbox(); - beforeEach( () => { geometry = { top: 10, @@ -24,7 +20,11 @@ describe( 'Rect', () => { height: 20 }; - testUtils.sinon.stub( log, 'warn' ); + sinon.stub( console, 'warn' ); + } ); + + afterEach( () => { + sinon.restore(); } ); describe( 'constructor()', () => { @@ -38,7 +38,7 @@ describe( 'Rect', () => { it( 'should accept HTMLElement', () => { const element = document.createElement( 'div' ); - testUtils.sinon.stub( element, 'getBoundingClientRect' ).returns( geometry ); + sinon.stub( element, 'getBoundingClientRect' ).returns( geometry ); assertRect( new Rect( element ), geometry ); } ); @@ -47,7 +47,7 @@ describe( 'Rect', () => { const range = document.createRange(); range.selectNode( document.body ); - testUtils.sinon.stub( range, 'getClientRects' ).returns( [ geometry ] ); + sinon.stub( range, 'getClientRects' ).returns( [ geometry ] ); assertRect( new Rect( range ), geometry ); } ); @@ -57,7 +57,7 @@ describe( 'Rect', () => { const range = document.createRange(); range.collapse(); - testUtils.sinon.stub( range, 'getClientRects' ).returns( [ geometry ] ); + sinon.stub( range, 'getClientRects' ).returns( [ geometry ] ); assertRect( new Rect( range ), geometry ); } ); @@ -69,8 +69,8 @@ describe( 'Rect', () => { range.setStart( element, 0 ); range.collapse(); - testUtils.sinon.stub( range, 'getClientRects' ).returns( [] ); - testUtils.sinon.stub( element, 'getBoundingClientRect' ).returns( geometry ); + sinon.stub( range, 'getClientRects' ).returns( [] ); + sinon.stub( element, 'getBoundingClientRect' ).returns( geometry ); const expectedGeometry = Object.assign( {}, geometry ); expectedGeometry.right = expectedGeometry.left; @@ -80,10 +80,10 @@ describe( 'Rect', () => { } ); it( 'should accept the window (viewport)', () => { - testUtils.sinon.stub( window, 'innerWidth' ).value( 1000 ); - testUtils.sinon.stub( window, 'innerHeight' ).value( 500 ); - testUtils.sinon.stub( window, 'scrollX' ).value( 100 ); - testUtils.sinon.stub( window, 'scrollY' ).value( 200 ); + sinon.stub( window, 'innerWidth' ).value( 1000 ); + sinon.stub( window, 'innerHeight' ).value( 500 ); + sinon.stub( window, 'scrollX' ).value( 100 ); + sinon.stub( window, 'scrollY' ).value( 200 ); assertRect( new Rect( window ), { top: 0, @@ -124,10 +124,10 @@ describe( 'Rect', () => { const range = document.createRange(); range.selectNode( iframeWindow.document.body ); - testUtils.sinon.stub( range, 'getClientRects' ).returns( [ geometry ] ); + sinon.stub( range, 'getClientRects' ).returns( [ geometry ] ); assertRect( new Rect( range ), geometry ); - testUtils.sinon.stub( element, 'getBoundingClientRect' ).returns( geometry ); + sinon.stub( element, 'getBoundingClientRect' ).returns( geometry ); assertRect( new Rect( element ), geometry ); iframe.remove(); @@ -161,29 +161,6 @@ describe( 'Rect', () => { assertRect( geometry, sourceGeometry ); } ); - - it( 'should warn if the source does not belong to rendered DOM tree (HTML element)', () => { - const element = document.createElement( 'div' ); - - testUtils.sinon.stub( element, 'getBoundingClientRect' ).returns( geometry ); - - const rect = new Rect( element ); - sinon.assert.calledOnce( log.warn ); - sinon.assert.calledWithExactly( log.warn, sinon.match( /^rect-source-not-in-dom/ ), { source: element } ); - assertRect( rect, geometry ); - } ); - - it( 'should warn if the source does not belong to rendered DOM tree (DOM Range)', () => { - const range = document.createRange(); - - range.collapse(); - testUtils.sinon.stub( range, 'getClientRects' ).returns( [ geometry ] ); - - const rect = new Rect( range ); - sinon.assert.calledOnce( log.warn ); - sinon.assert.calledWithExactly( log.warn, sinon.match( /^rect-source-not-in-dom/ ), { source: range } ); - assertRect( rect, geometry ); - } ); } ); describe( 'clone()', () => { @@ -452,7 +429,7 @@ describe( 'Rect', () => { } ); it( 'should not fail when the rect is for document#body', () => { - testUtils.sinon.stub( document.body, 'getBoundingClientRect' ).returns( { + sinon.stub( document.body, 'getBoundingClientRect' ).returns( { top: 0, right: 100, bottom: 100, @@ -482,7 +459,7 @@ describe( 'Rect', () => { ancestor.appendChild( element ); iframeWindow.document.body.appendChild( ancestor ); - testUtils.sinon.stub( ancestor, 'getBoundingClientRect' ).returns( { + sinon.stub( ancestor, 'getBoundingClientRect' ).returns( { top: 0, right: 50, bottom: 50, @@ -491,7 +468,7 @@ describe( 'Rect', () => { height: 50 } ); - testUtils.sinon.stub( element, 'getBoundingClientRect' ).returns( { + sinon.stub( element, 'getBoundingClientRect' ).returns( { top: 0, right: 100, bottom: 100, @@ -517,7 +494,7 @@ describe( 'Rect', () => { } ); it( 'should return the visible rect (HTMLElement), partially cropped', () => { - testUtils.sinon.stub( element, 'getBoundingClientRect' ).returns( { + sinon.stub( element, 'getBoundingClientRect' ).returns( { top: 0, right: 100, bottom: 100, @@ -526,7 +503,7 @@ describe( 'Rect', () => { height: 100 } ); - testUtils.sinon.stub( ancestorA, 'getBoundingClientRect' ).returns( { + sinon.stub( ancestorA, 'getBoundingClientRect' ).returns( { top: 50, right: 150, bottom: 150, @@ -546,7 +523,7 @@ describe( 'Rect', () => { } ); it( 'should return the visible rect (HTMLElement), fully visible', () => { - testUtils.sinon.stub( element, 'getBoundingClientRect' ).returns( { + sinon.stub( element, 'getBoundingClientRect' ).returns( { top: 0, right: 100, bottom: 100, @@ -555,7 +532,7 @@ describe( 'Rect', () => { height: 100 } ); - testUtils.sinon.stub( ancestorA, 'getBoundingClientRect' ).returns( { + sinon.stub( ancestorA, 'getBoundingClientRect' ).returns( { top: 0, right: 150, bottom: 150, @@ -578,7 +555,7 @@ describe( 'Rect', () => { ancestorB.appendChild( ancestorA ); document.body.appendChild( ancestorB ); - testUtils.sinon.stub( element, 'getBoundingClientRect' ).returns( { + sinon.stub( element, 'getBoundingClientRect' ).returns( { top: 0, right: 100, bottom: 100, @@ -587,7 +564,7 @@ describe( 'Rect', () => { height: 100 } ); - testUtils.sinon.stub( ancestorA, 'getBoundingClientRect' ).returns( { + sinon.stub( ancestorA, 'getBoundingClientRect' ).returns( { top: 50, right: 100, bottom: 100, @@ -596,7 +573,7 @@ describe( 'Rect', () => { height: 50 } ); - testUtils.sinon.stub( ancestorB, 'getBoundingClientRect' ).returns( { + sinon.stub( ancestorB, 'getBoundingClientRect' ).returns( { top: 0, right: 150, bottom: 100, @@ -619,7 +596,7 @@ describe( 'Rect', () => { range.setStart( ancestorA, 0 ); range.setEnd( ancestorA, 1 ); - testUtils.sinon.stub( range, 'getClientRects' ).returns( [ { + sinon.stub( range, 'getClientRects' ).returns( [ { top: 0, right: 100, bottom: 100, @@ -628,7 +605,7 @@ describe( 'Rect', () => { height: 100 } ] ); - testUtils.sinon.stub( ancestorA, 'getBoundingClientRect' ).returns( { + sinon.stub( ancestorA, 'getBoundingClientRect' ).returns( { top: 50, right: 150, bottom: 150, @@ -648,7 +625,7 @@ describe( 'Rect', () => { } ); it( 'should return null if there\'s no visible rect', () => { - testUtils.sinon.stub( element, 'getBoundingClientRect' ).returns( { + sinon.stub( element, 'getBoundingClientRect' ).returns( { top: 0, right: 100, bottom: 100, @@ -657,7 +634,7 @@ describe( 'Rect', () => { height: 100 } ); - testUtils.sinon.stub( ancestorA, 'getBoundingClientRect' ).returns( { + sinon.stub( ancestorA, 'getBoundingClientRect' ).returns( { top: 150, right: 200, bottom: 200, @@ -818,8 +795,8 @@ describe( 'Rect', () => { it( 'should exclude scrollbars and borders of a HTMLElement', () => { const element = document.createElement( 'div' ); - testUtils.sinon.stub( element, 'getBoundingClientRect' ).returns( geometry ); - testUtils.sinon.stub( window, 'getComputedStyle' ).returns( { + sinon.stub( element, 'getBoundingClientRect' ).returns( geometry ); + sinon.stub( window, 'getComputedStyle' ).returns( { borderTopWidth: '5px', borderRightWidth: '10px', borderLeftWidth: '5px', @@ -853,12 +830,12 @@ describe( 'Rect', () => { } ); it( 'should exclude scrollbars from viewport\'s rect', () => { - testUtils.sinon.stub( window, 'innerWidth' ).value( 1000 ); - testUtils.sinon.stub( window, 'innerHeight' ).value( 500 ); - testUtils.sinon.stub( window, 'scrollX' ).value( 100 ); - testUtils.sinon.stub( window, 'scrollY' ).value( 200 ); + sinon.stub( window, 'innerWidth' ).value( 1000 ); + sinon.stub( window, 'innerHeight' ).value( 500 ); + sinon.stub( window, 'scrollX' ).value( 100 ); + sinon.stub( window, 'scrollY' ).value( 200 ); - testUtils.sinon.stub( document, 'documentElement' ).value( { + sinon.stub( document, 'documentElement' ).value( { clientWidth: 990, clientHeight: 490 } ); @@ -878,11 +855,11 @@ describe( 'Rect', () => { // Mock the properties of the top window. Then make sure the ones // from the child are used. - testUtils.sinon.stub( window, 'innerWidth' ).value( 1000 ); - testUtils.sinon.stub( window, 'innerHeight' ).value( 500 ); - testUtils.sinon.stub( window, 'scrollX' ).value( 100 ); - testUtils.sinon.stub( window, 'scrollY' ).value( 200 ); - testUtils.sinon.stub( document, 'documentElement' ).value( { + sinon.stub( window, 'innerWidth' ).value( 1000 ); + sinon.stub( window, 'innerHeight' ).value( 500 ); + sinon.stub( window, 'scrollX' ).value( 100 ); + sinon.stub( window, 'scrollY' ).value( 200 ); + sinon.stub( document, 'documentElement' ).value( { clientWidth: 990, clientHeight: 490 } ); @@ -890,12 +867,12 @@ describe( 'Rect', () => { iframe.addEventListener( 'load', () => { const iframeWindow = iframe.contentWindow; - testUtils.sinon.stub( iframeWindow, 'innerWidth' ).value( 500 ); - testUtils.sinon.stub( iframeWindow, 'innerHeight' ).value( 250 ); - testUtils.sinon.stub( iframeWindow, 'scrollX' ).value( 50 ); - testUtils.sinon.stub( iframeWindow, 'scrollY' ).value( 100 ); + sinon.stub( iframeWindow, 'innerWidth' ).value( 500 ); + sinon.stub( iframeWindow, 'innerHeight' ).value( 250 ); + sinon.stub( iframeWindow, 'scrollX' ).value( 50 ); + sinon.stub( iframeWindow, 'scrollY' ).value( 100 ); - testUtils.sinon.stub( iframeWindow.document, 'documentElement' ).value( { + sinon.stub( iframeWindow.document, 'documentElement' ).value( { clientWidth: 480, clientHeight: 230 } ); @@ -911,7 +888,7 @@ describe( 'Rect', () => { // Safari fails because of "afterEach()" hook tries to restore values from removed element. // We need to restore these values manually. - testUtils.sinon.restore(); + sinon.restore(); iframe.remove(); done(); } ); @@ -925,7 +902,7 @@ describe( 'Rect', () => { const range = document.createRange(); range.selectNode( document.body ); - testUtils.sinon.stub( range, 'getClientRects' ).returns( [ geometry ] ); + sinon.stub( range, 'getClientRects' ).returns( [ geometry ] ); const rects = Rect.getDomRangeRects( range ); expect( rects ).to.have.length( 1 ); @@ -938,7 +915,7 @@ describe( 'Rect', () => { const secondGeometry = { top: 20, right: 80, bottom: 60, left: 40, width: 40, height: 40 }; range.collapse(); - testUtils.sinon.stub( range, 'getClientRects' ).returns( [ geometry, secondGeometry ] ); + sinon.stub( range, 'getClientRects' ).returns( [ geometry, secondGeometry ] ); const rects = Rect.getDomRangeRects( range ); expect( rects ).to.have.length( 2 ); @@ -954,8 +931,8 @@ describe( 'Rect', () => { range.setStart( element, 0 ); range.collapse(); - testUtils.sinon.stub( range, 'getClientRects' ).returns( [] ); - testUtils.sinon.stub( element, 'getBoundingClientRect' ).returns( geometry ); + sinon.stub( range, 'getClientRects' ).returns( [] ); + sinon.stub( element, 'getBoundingClientRect' ).returns( geometry ); const expectedGeometry = Object.assign( {}, geometry ); expectedGeometry.right = expectedGeometry.left; @@ -975,8 +952,8 @@ describe( 'Rect', () => { range.setStart( textNode, 3 ); range.collapse(); - testUtils.sinon.stub( range, 'getClientRects' ).returns( [] ); - testUtils.sinon.stub( element, 'getBoundingClientRect' ).returns( geometry ); + sinon.stub( range, 'getClientRects' ).returns( [] ); + sinon.stub( element, 'getBoundingClientRect' ).returns( geometry ); const expectedGeometry = Object.assign( {}, geometry ); expectedGeometry.right = expectedGeometry.left; diff --git a/tests/log.js b/tests/log.js deleted file mode 100644 index fbcc961..0000000 --- a/tests/log.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @license Copyright (c) 2003-2019, CKSource - Frederico Knabben. All rights reserved. - * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license - */ - -/* globals console */ - -import log from '../src/log'; -import { DOCUMENTATION_URL } from '../src/ckeditorerror'; - -describe( 'log', () => { - let spy; - - beforeEach( () => { - if ( spy ) { - spy.restore(); - } - } ); - - describe( 'warn()', () => { - it( 'logs the message to the console using console.warn()', () => { - spy = sinon.stub( console, 'warn' ); - const data = { bar: 1 }; - - log.warn( 'foo', data ); - - sinon.assert.calledOnce( spy ); - sinon.assert.calledWith( spy, 'foo', data ); - - log.warn( 'bar' ); - sinon.assert.calledTwice( spy ); - sinon.assert.calledWith( spy, 'bar' ); - } ); - - it( 'contains a link which leads to the documentation', () => { - spy = sinon.stub( console, 'warn' ); - - log.warn( 'model-schema-no-item: Specified item cannot be found.' ); - - const logMessage = 'model-schema-no-item: Specified item cannot be found. ' + - `Read more: ${ DOCUMENTATION_URL }#error-model-schema-no-item\n`; - - sinon.assert.calledOnce( spy ); - sinon.assert.calledWith( spy, logMessage ); - } ); - } ); - - describe( 'error()', () => { - it( 'logs the message to the console using console.error()', () => { - spy = sinon.stub( console, 'error' ); - const data = { bar: 1 }; - - log.error( 'foo', data ); - - sinon.assert.calledOnce( spy ); - sinon.assert.calledWith( spy, 'foo', data ); - - log.error( 'bar' ); - sinon.assert.calledTwice( spy ); - sinon.assert.calledWith( spy, 'bar' ); - } ); - - it( 'contains a link which leads to the documentation', () => { - spy = sinon.stub( console, 'error' ); - - log.error( 'model-schema-no-item: Specified item cannot be found.' ); - - const logMessage = 'model-schema-no-item: Specified item cannot be found. ' + - `Read more: ${ DOCUMENTATION_URL }#error-model-schema-no-item\n`; - - sinon.assert.calledOnce( spy ); - sinon.assert.calledWith( spy, logMessage ); - } ); - } ); -} );