Skip to content

Commit

Permalink
Move offset to utils, add tests, test getClass (#318)
Browse files Browse the repository at this point in the history
  • Loading branch information
RobbieTheWagner authored Sep 21, 2019
1 parent 8c8ee36 commit b89f8bc
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 52 deletions.
50 changes: 6 additions & 44 deletions src/js/tether.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Evented } from './evented';
import TetherBase from './utils';
import { addClass, removeClass, updateClasses } from './utils/classes';
import { defer, flush } from './utils/deferred';
import { addOffset, offsetToPx, parseTopLeft } from './utils/offset';
import './constraint';
import './abutment';
import './shift';
Expand Down Expand Up @@ -56,10 +57,7 @@ const position = () => {
};

function now() {
if (typeof performance === 'object' && typeof performance.now === 'function') {
return performance.now();
}
return +new Date;
return performance.now();
}

(() => {
Expand Down Expand Up @@ -148,43 +146,7 @@ const attachmentToOffset = (attachment) => {
return { left, top };
};

function addOffset(...offsets) {
const out = { top: 0, left: 0 };

offsets.forEach(({ top, left }) => {
if (typeof top === 'string') {
top = parseFloat(top, 10);
}
if (typeof left === 'string') {
left = parseFloat(left, 10);
}

out.top += top;
out.left += left;
});

return out;
}

function offsetToPx(offset, size) {
if (typeof offset.left === 'string' && offset.left.indexOf('%') !== -1) {
offset.left = parseFloat(offset.left, 10) / 100 * size.width;
}
if (typeof offset.top === 'string' && offset.top.indexOf('%') !== -1) {
offset.top = parseFloat(offset.top, 10) / 100 * size.height;
}

return offset;
}

const parseOffset = (value) => {
const [top, left] = value.split(' ');
return { top, left };
};
const parseAttachment = parseOffset;

class TetherClass extends Evented {

constructor(options) {
super();
this.position = this.position.bind(this);
Expand Down Expand Up @@ -256,10 +218,10 @@ class TetherClass extends Evented {
throw new Error('Tether Error: You must provide an attachment');
}

this.targetAttachment = parseAttachment(this.options.targetAttachment);
this.attachment = parseAttachment(this.options.attachment);
this.offset = parseOffset(this.options.offset);
this.targetOffset = parseOffset(this.options.targetOffset);
this.targetAttachment = parseTopLeft(this.options.targetAttachment);
this.attachment = parseTopLeft(this.options.attachment);
this.offset = parseTopLeft(this.options.offset);
this.targetOffset = parseTopLeft(this.options.targetOffset);

if (typeof this.scrollParents !== 'undefined') {
this.disable();
Expand Down
33 changes: 33 additions & 0 deletions src/js/utils/offset.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
export function addOffset(...offsets) {
const out = { top: 0, left: 0 };

offsets.forEach(({ top, left }) => {
if (typeof top === 'string') {
top = parseFloat(top);
}
if (typeof left === 'string') {
left = parseFloat(left);
}

out.top += top;
out.left += left;
});

return out;
}

export function offsetToPx(offset, size) {
if (typeof offset.left === 'string' && offset.left.indexOf('%') !== -1) {
offset.left = parseFloat(offset.left) / 100 * size.width;
}
if (typeof offset.top === 'string' && offset.top.indexOf('%') !== -1) {
offset.top = parseFloat(offset.top) / 100 * size.height;
}

return offset;
}

export function parseTopLeft(value) {
const [top, left] = value.split(' ');
return { top, left };
}
120 changes: 114 additions & 6 deletions test/unit/tether.spec.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
import Tether from '../../src/js/tether.js';

describe('Tether', () => {
let element, target;

beforeEach(() => {
element = document.createElement('div');
element.classList.add('element');
document.body.appendChild(element);
target = document.createElement('div');
target.classList.add('target');
document.body.appendChild(target);
});

afterEach(() => {
document.body.removeChild(element);
document.body.removeChild(target);
element = null;
target = null;
});

describe('destroy()', () => {
it('removes classes on destroy', () => {
const element = document.createElement('div');
element.classList.add('element');
document.body.appendChild(element);
const target = document.createElement('div');
target.classList.add('target');
document.body.appendChild(target);
expect(element.classList.length, 'element - only one class').toEqual(1);
expect(target.classList.length, 'target - only one class').toEqual(1);
const tether = new Tether({
Expand All @@ -29,4 +41,100 @@ describe('Tether', () => {
expect(target.classList.length, 'target - destroy sets classes back to initial state').toEqual(1);
});
});

describe('getClass()', () => {
it('gets default classes when no options set', () => {
expect(element.classList.length, 'element - only one class').toEqual(1);
expect(target.classList.length, 'target - only one class').toEqual(1);
const tether = new Tether({
element: '.element',
target: '.target',
attachment: 'top left',
targetAttachment: 'top right'
});

tether.enable();

expect(element.classList.length, 'element - tether classes added').toEqual(12);
expect(element).toHaveClass('tether-element');
expect(element).not.toHaveClass('tether-target');

expect(target.classList.length, 'target - tether classes added').toEqual(12);
expect(target).toHaveClass('tether-target');
expect(target).not.toHaveClass('tether-element');

expect(tether.getClass('element')).toBe('tether-element');
expect(tether.getClass('target')).toBe('tether-target');

tether.destroy();

expect(element.classList.length, 'element - destroy sets classes back to initial state').toEqual(1);
expect(target.classList.length, 'target - destroy sets classes back to initial state').toEqual(1);
});

it('gets prefixed classes when classPrefix set', () => {
expect(element.classList.length, 'element - only one class').toEqual(1);
expect(target.classList.length, 'target - only one class').toEqual(1);
const tether = new Tether({
element: '.element',
target: '.target',
attachment: 'top left',
targetAttachment: 'top right',
classPrefix: 'foo'
});

tether.enable();

expect(element.classList.length, 'element - foo classes added').toEqual(12);
expect(element).toHaveClass('foo-element');
expect(element).not.toHaveClass('foo-target');

expect(target.classList.length, 'target - foo classes added').toEqual(12);
expect(target).toHaveClass('foo-target');
expect(target).not.toHaveClass('foo-element');

expect(tether.getClass('element')).toBe('foo-element');
expect(tether.getClass('target')).toBe('foo-target');

tether.destroy();

expect(element.classList.length, 'element - destroy sets classes back to initial state').toEqual(1);
expect(target.classList.length, 'target - destroy sets classes back to initial state').toEqual(1);
});

it('gets overridden classes', () => {
expect(element.classList.length, 'element - only one class').toEqual(1);
expect(target.classList.length, 'target - only one class').toEqual(1);
const tether = new Tether({
element: '.element',
target: '.target',
attachment: 'top left',
targetAttachment: 'top right',
classes: {
element: 'my-custom-class',
target: 'another-one'
}
});

tether.enable();

expect(element.classList.length, 'element - custom classes added').toEqual(12);
expect(element).toHaveClass('my-custom-class');
expect(element).not.toHaveClass('another-one');
expect(element).not.toHaveClass('tether-element');

expect(target.classList.length, 'target - custom classes added').toEqual(12);
expect(target).toHaveClass('another-one');
expect(target).not.toHaveClass('my-custom-class');
expect(target).not.toHaveClass('tether-target');

expect(tether.getClass('element')).toBe('my-custom-class');
expect(tether.getClass('target')).toBe('another-one');

tether.destroy();

expect(element.classList.length, 'element - destroy sets classes back to initial state').toEqual(1);
expect(target.classList.length, 'target - destroy sets classes back to initial state').toEqual(1);
});
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { addClass, removeClass } from '../../src/js/utils/classes';
import { addClass, removeClass } from '../../../src/js/utils/classes';

describe('Utils - classes', () => {
describe('addClass/removeClass', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { defer, flush } from '../../src/js/utils/deferred';
import { defer, flush } from '../../../src/js/utils/deferred';
import { stub } from 'sinon';

describe('Utils - deferred', () => {
Expand Down
25 changes: 25 additions & 0 deletions test/unit/utils/offset.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { addOffset, offsetToPx, parseTopLeft } from '../../../src/js/utils/offset';

describe('Utils - offset', () => {
describe('addOffset', () => {
it('offsets added together', () => {
const offset1 = { top: 20, left: 50 };
const offset2 = { top: 15, left: 10 };
expect(addOffset(offset1, offset2)).toStrictEqual({ left: 60, top: 35 });
});
});

describe('offsetToPx', () => {
it('calculates px from %', () => {
const offset = { left: '30%', top: '20%' };
const size = { height: 1000, width: 1000 };
expect(offsetToPx(offset, size)).toStrictEqual({ left: 300, top: 200 });
});
});

describe('parseTopLeft', () => {
it('splits string to get top/left', () => {
expect(parseTopLeft('50 100')).toStrictEqual({ left: '100', top: '50' });
});
});
});

0 comments on commit b89f8bc

Please sign in to comment.