From 202b54afbb7bd2a1b731f5a2f6bcac51c5ed01e8 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Mon, 27 Feb 2017 11:18:00 -0800 Subject: [PATCH] Convert CharMeasure phantom test to jsdom --- src/utils/CharMeasure.phantom.ts | 65 --------------------------- src/utils/CharMeasure.test.ts | 77 ++++++++++++++++++++++++++++++++ src/utils/CharMeasure.ts | 6 ++- src/xterm.js | 2 +- 4 files changed, 82 insertions(+), 68 deletions(-) delete mode 100644 src/utils/CharMeasure.phantom.ts create mode 100644 src/utils/CharMeasure.test.ts diff --git a/src/utils/CharMeasure.phantom.ts b/src/utils/CharMeasure.phantom.ts deleted file mode 100644 index f8173dc..0000000 --- a/src/utils/CharMeasure.phantom.ts +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @license MIT - */ -import { ICharMeasure, ITerminal } from '../Interfaces'; - -declare var assert: Chai.Assert; -declare var Terminal: ITerminal; - -// Do not describe tests unless in PhantomJS environment -if (typeof Terminal !== 'undefined') { - - const CharMeasure = (Terminal).CharMeasure; - - describe('CharMeasure', () => { - const parentElement = document.createElement('div'); - let charMeasure: ICharMeasure; - - beforeEach(() => { - charMeasure = new CharMeasure(parentElement); - document.querySelector('#xterm').appendChild(parentElement); - }); - - afterEach(() => { - if (parentElement && parentElement.parentElement) { - parentElement.parentElement.removeChild(parentElement); - } - }); - - describe('measure', () => { - it('should be performed async on first call', done => { - assert.equal(charMeasure.width, null); - charMeasure.measure(); - assert.equal(charMeasure.width, null); - setTimeout(() => { - assert.isTrue(charMeasure.width > 0); - done(); - }, 0); - }); - - it('should be performed sync on successive calls', done => { - charMeasure.measure(); - setTimeout(() => { - const firstWidth = charMeasure.width; - parentElement.style.fontSize = '2em'; - charMeasure.measure(); - assert.equal(charMeasure.width, firstWidth * 2); - done(); - }, 0); - }); - - it('should NOT do a measure when the parent is hidden', done => { - charMeasure.measure(); - setTimeout(() => { - const firstWidth = charMeasure.width; - parentElement.style.display = 'none'; - parentElement.style.fontSize = '2em'; - charMeasure.measure(); - assert.equal(charMeasure.width, firstWidth); - done(); - }, 0); - }); - }); - }); - -} diff --git a/src/utils/CharMeasure.test.ts b/src/utils/CharMeasure.test.ts new file mode 100644 index 0000000..17e675d --- /dev/null +++ b/src/utils/CharMeasure.test.ts @@ -0,0 +1,77 @@ +/** + * @license MIT + */ +import jsdom = require('jsdom'); +import { assert } from 'chai'; +import { ICharMeasure, ITerminal } from '../Interfaces'; +import { CharMeasure } from './CharMeasure'; + +describe('CharMeasure', () => { + let window: Window; + let document: Document; + + let container: HTMLElement; + let charMeasure: ICharMeasure; + + beforeEach(done => { + jsdom.env('', (err, w) => { + window = w; + document = window.document; + container = document.createElement('div'); + document.body.appendChild(container); + charMeasure = new CharMeasure(document, container); + done(); + }); + }); + + describe('measure', () => { + it('should set _measureElement on first call', () => { + charMeasure.measure(); + assert.isDefined((charMeasure)._measureElement, 'CharMeasure.measure should have created _measureElement'); + }); + + it('should be performed async on first call', done => { + assert.equal(charMeasure.width, null); + charMeasure.measure(); + // Mock getBoundingClientRect since jsdom doesn't have a layout engine + (charMeasure)._measureElement.getBoundingClientRect = () => { + return { width: 1, height: 1 }; + }; + assert.equal(charMeasure.width, null); + setTimeout(() => { + assert.equal(charMeasure.width, 1); + done(); + }, 0); + }); + + it('should be performed sync on successive calls', done => { + charMeasure.measure(); + // Mock getBoundingClientRect since jsdom doesn't have a layout engine + (charMeasure)._measureElement.getBoundingClientRect = () => { + return { width: 1, height: 1 }; + }; + setTimeout(() => { + const firstWidth = charMeasure.width; + // Mock getBoundingClientRect since jsdom doesn't have a layout engine + (charMeasure)._measureElement.getBoundingClientRect = () => { + return { width: 2, height: 2 }; + }; + charMeasure.measure(); + assert.equal(charMeasure.width, firstWidth * 2); + done(); + }, 0); + }); + + it('should NOT do a measure when the parent is hidden', done => { + charMeasure.measure(); + setTimeout(() => { + const firstWidth = charMeasure.width; + container.style.display = 'none'; + container.style.fontSize = '2em'; + charMeasure.measure(); + assert.equal(charMeasure.width, firstWidth); + done(); + }, 0); + }); + }); +}); diff --git a/src/utils/CharMeasure.ts b/src/utils/CharMeasure.ts index fdad40a..45b06f5 100644 --- a/src/utils/CharMeasure.ts +++ b/src/utils/CharMeasure.ts @@ -9,13 +9,15 @@ import { EventEmitter } from '../EventEmitter.js'; * Utility class that measures the size of a character. */ export class CharMeasure extends EventEmitter { + private _document: Document; private _parentElement: HTMLElement; private _measureElement: HTMLElement; private _width: number; private _height: number; - constructor(parentElement: HTMLElement) { + constructor(document: Document, parentElement: HTMLElement) { super(); + this._document = document; this._parentElement = parentElement; } @@ -29,7 +31,7 @@ export class CharMeasure extends EventEmitter { public measure(): void { if (!this._measureElement) { - this._measureElement = document.createElement('span'); + this._measureElement = this._document.createElement('span'); this._measureElement.style.position = 'absolute'; this._measureElement.style.top = '0'; this._measureElement.style.left = '-9999em'; diff --git a/src/xterm.js b/src/xterm.js index 9e68f47..3b6b2e1 100644 --- a/src/xterm.js +++ b/src/xterm.js @@ -647,7 +647,7 @@ Terminal.prototype.open = function(parent) { } this.parent.appendChild(this.element); - this.charMeasure = new CharMeasure(this.helperContainer); + this.charMeasure = new CharMeasure(document, this.helperContainer); this.charMeasure.on('charsizechanged', function () { self.updateCharSizeCSS(); });