Skip to content

Commit

Permalink
Merge pull request #136 from chrischrischris/author_vh_22
Browse files Browse the repository at this point in the history
#22 Add AuthorVH
  • Loading branch information
auniverseaway authored Aug 17, 2020
2 parents 4656971 + a2d25db commit 50d3899
Show file tree
Hide file tree
Showing 6 changed files with 474 additions and 49 deletions.
Original file line number Diff line number Diff line change
@@ -1,51 +1,8 @@
window.dx = window.dx || {};
window.dx.author = { watch: { functions: [] } };
// Ignore for code coverage
/* istanbul ignore file */

window.dx.author.watch.registerFunction = (func) => {
window.dx.author.watch.functions.push(func);
};

const TAG_SCRIPT = 'SCRIPT';
const WATCH_CONFIG = {
childList: true,
subtree: true,
};

/**
* Watch for Author mutations and run functions when they meet node type criteria.
*
* @param {Array} apps The functions or classes to instantiate when a mutation occurs
* @param {DOMElment} parent The top level parent to start the observation
*/
const watch = (document) => {
const parentToWatch = document.querySelector('body');

const callback = (mutationsList) => {
mutationsList.forEach((mutation) => {
// Attempt to cut down on noise from all mutations.
// An AEM component mutation will have only one added node. No more. No less.
if (window.dx.author.watch.functions.length > 0 && mutation.addedNodes.length === 1) {
const addedNode = mutation.addedNodes[0];
if (addedNode.nodeType === 1 && addedNode.tagName !== TAG_SCRIPT) {
// Loop through each function and instantiate
// it with the added node.
window.dx.author.watch.functions.forEach((app) => {
app(addedNode);
});
}
}
});
};

// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback);
observer.observe(parentToWatch, WATCH_CONFIG);
};

const authorWatch = (document) => {
if (typeof CQ !== 'undefined' && document) {
watch(document);
}
};
import { initAuthorVh } from './utils/authorVh';
import authorWatch from './utils/authorWatch';

authorWatch(document);
initAuthorVh(document);
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<!-- 0 Mobile Only -->
<div data-author-mobile-vh="20" class="has-AuthorVh"></div>
<!-- 1 Tablet -->
<div data-author-mobile-vh="20" data-author-tablet-vh="40" class="has-AuthorVh"></div>
<!-- 2 Desktop -->
<div data-author-mobile-vh="20" data-author-tablet-vh="40" data-author-desktop-vh="60" class="has-AuthorVh"></div>
<!-- 3 Bad Data -->
<div data-author-mobile-vh="asdf" class="has-AuthorVh bad-element"></div>
<!-- No Data -->
<div class="dexter-is-awesome"></div>

<!-- With item vhs set-->
<!-- 4 Mobile Only -->
<div data-author-mobile-vh="20" data-author-mobile-items-vh="100" class="has-AuthorVh"></div>
<!-- 5 Tablet -->
<div data-author-mobile-vh="20" data-author-mobile-items-vh="20,,40" data-author-tablet-vh="40" data-author-tablet-items-vh="0,15,90" class="has-AuthorVh"></div>
<!-- 6 Desktop -->
<div data-author-mobile-vh="20" data-author-mobile-items-vh=",,99,30"
data-author-tablet-vh="40" data-author-tablet-items-vh="0,15,,40"
data-author-desktop-vh="60" data-author-desktop-items-vh="10" class="has-AuthorVh">
<div id="i1">i1</div>
<div id="i2">i2</div>
<div id="i3">i3</div>
<div id="i4">i4</div>
</div>
<!-- 7 Bad Data -->
<div data-author-mobile-vh="asdf" data-author-tablet-items-vh="asdf" class="has-AuthorVh bad-element"></div>

Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import vhHtml from '../__mocks__/vh.html';
import {
initAuthorVh,
findAuthorVhElements,
getEditorHeight,
setVh,
getInitialWidth,
getVhAsPx,
getBreakpointVh,
} from '../authorVh';

// Define our innerWidth
Object.defineProperties(window, {
innerWidth: { value: 300, configurable: true, writable: true },
innerHeight: { value: 720 },
});

document.body.innerHTML = vhHtml;

let elements;
let editorHeight;

beforeAll(() => {
elements = findAuthorVhElements(document);
});

describe('count elements with VH', () => {
test('four total elements', () => {
expect(window.innerWidth).toEqual(300);
expect(elements).toHaveLength(8);
});
});

describe('get editor height', () => {
test('height is height minus AEM toolbar', () => {
editorHeight = getEditorHeight();
expect(editorHeight).toEqual(610);
});
});

describe('setting VH', () => {
test('VH is correctly set on first element', () => {
const mobileElement = setVh(elements[0], 'mobile', editorHeight);
expect(mobileElement.style.minHeight).toEqual('122px');
});
test('bad data is not set on element', () => {
const badElement = document.querySelector('.bad-element');
expect(badElement.style.minHeight).toBeFalsy();
});
});

describe('get initial width', () => {
test('width should be mobile', () => {
const initialWidth = getInitialWidth();
expect(initialWidth).toEqual('mobile');
});

test('width should be tablet', () => {
Object.defineProperties(window, {
innerWidth: { value: 768, configurable: true, writable: true },
});
const initialWidth = getInitialWidth();
expect(initialWidth).toEqual('tablet');
});
test('width should be desktop', () => {
Object.defineProperties(window, {
innerWidth: { value: 1366, configurable: true, writable: true },
});
const initialWidth = getInitialWidth();
expect(initialWidth).toEqual('desktop');
});
});

describe('get vh to px', () => {
test('vh should not convert to px', () => {
const pxValue = getVhAsPx(900, 'foo');
expect(pxValue).toBeNull();
});
test('vh should convert to px', () => {
const pxValue = getVhAsPx(900, 66);
expect(pxValue).toEqual(594);
});
});

describe('get breakpoint vh as px', () => {
test('breakpoint vh should be mobile', () => {
const el = elements[2];
const pxValueMobile = getBreakpointVh('mobile', window.innerHeight, el.dataset);
expect(pxValueMobile.flexVh).toEqual(144);
});

test('breakpoint vh should be tablet', () => {
const el = elements[2];
const pxValueMobile = getBreakpointVh('tablet', window.innerHeight, el.dataset);
expect(pxValueMobile.flexVh).toEqual(288);
});

test('breakpoint vh should be desktop', () => {
const el = elements[2];
const pxValueMobile = getBreakpointVh('desktop', window.innerHeight, el.dataset);
expect(pxValueMobile.flexVh).toEqual(432);
});
});

describe('breakpoint vh with items defined', () => {
test('mobile only', () => {
const el = elements[4];
const { flexVh, itemVhs } = getBreakpointVh('mobile', window.innerHeight, el.dataset);
expect(flexVh).toEqual(144);
expect(itemVhs).toEqual([720]);
});

test('tablet override', () => {
const el = elements[5];
const { flexVh, itemVhs } = getBreakpointVh('mobile', window.innerHeight, el.dataset);
expect(flexVh).toEqual(144);
expect(itemVhs).toEqual([144, null, 288]);

const { flexVh: flexVh1, itemVhs: itemVhs1 } = getBreakpointVh(
'tablet',
window.innerHeight,
el.dataset
);
expect(flexVh1).toEqual(288);
expect(itemVhs1).toEqual([null, 108, 648]);
});

test('desktop override + item inheritance', () => {
const el = elements[6];

const item1 = el.querySelector('#i1');
const item2 = el.querySelector('#i2');
const item3 = el.querySelector('#i3');
const item4 = el.querySelector('#i4');

setVh(el, 'mobile', window.innerHeight, el.dataset);
expect(item1.style.minHeight).toBe('');
expect(item2.style.minHeight).toBe('');
expect(item3.style.minHeight).toBe('712.8px');
expect(item4.style.minHeight).toBe('216px');

setVh(el, 'tablet', window.innerHeight, el.dataset);
expect(item1.style.minHeight).toBe('');
expect(item2.style.minHeight).toBe('108px');
expect(item3.style.minHeight).toBe('712.8px');
expect(item4.style.minHeight).toBe('288px');

setVh(el, 'desktop', window.innerHeight, el.dataset);
expect(item1.style.minHeight).toBe('72px');
expect(item2.style.minHeight).toBe('108px');
expect(item3.style.minHeight).toBe('712.8px');
expect(item4.style.minHeight).toBe('288px');
});
});

describe('initAuthorVh', () => {
test('four total elements', () => {
const addListener = jest.fn();
global.matchMedia = () => ({ addListener });
initAuthorVh(document);
expect(addListener).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ window.MutationObserver = SimulateMutationObserver;
window.CQ = {};

// use require as import is hoisted
require('../app');
const authorWatch = require('../authorWatch.js').default;
authorWatch(document);

describe('authorWatch', () => {
beforeEach(() => {
Expand Down
Loading

0 comments on commit 50d3899

Please sign in to comment.