New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

gardr-ext

Package Overview
Dependencies
Maintainers
7
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gardr-ext - npm Package Compare versions

Comparing version 0.6.2 to 1.0.0-alpha.2

CHANGELOG.md

116

karma.conf.js

@@ -1,80 +0,64 @@

// Karma configuration
// Generated on Mon Feb 17 2014 15:34:15 GMT+0100 (CET)
module.exports = function(config) {
config.set({
var settings = {
basePath: '',
frameworks: ['mocha', 'browserify', 'es5-shim', 'sinon'],
// base path, that will be used to resolve files and exclude
basePath: '',
// frameworks to use
frameworks: ['mocha', 'browserify', 'sinon-chai'],
// list of files / patterns to load in the browser
files: [
'test/lib/Function-polyfill.js'
],
// list of files to exclude
exclude: [
],
// test results reporter to use
// possible values: 'dots', 'progress', 'junit', 'growl', 'coverage'
reporters: ['progress'],
preprocessors: {
'/**/*.browserify': 'browserify'
},
browserify: {
watch: true,
debug: true,
files: [
'lib/**/*.js',
'test/**/*.js'
]
},
'node_modules/normalize.css/normalize.css',
'test/**/*.test.js'
],
// web server port
port: 9876,
reporters: ['progress'],
preprocessors: {
'test/**/*.test.js': 'browserify'
},
// enable / disable colors in the output (reporters and logs)
colors: true,
browserify: {
bundle: true,
watch: true,
plugin: [require('proxyquireify').plugin],
debug: true
},
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['PhantomJS'],
captureTimeout: 60000,
singleRun: false,
plugins: ['karma-*']
};
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,
if (process.env.SAUCE_USERNAME && process.env.SAUCE_ACCESS_KEY) {
settings.browserDisconnectTimeout = 60000;
settings.browserNoActivityTimeout = 60000;
settings.captureTimeout = 60000 * 3;
settings.autoWatch = false;
settings.sauceLabs = {
testName: 'Gardr ext',
tags: ['gardr', 'ext']
};
settings.reporters = ['dots', 'saucelabs'];
settings.customLaunchers = {};
// only 3 vmms / browsers per run because of
var key = process.env.BROWSER_TYPE;
var target = require('./ci-browsers.js')[key];
if (!target) {
console.error('Missing / Unknown BROWSER_TYPE ' + process.env.BROWSER_TYPE);
process.exit(1);
}
// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,
Object.keys(target).forEach(function(key){
settings.customLaunchers[key] = target[key];
});
console.log('Running CI tests on', Object.keys(settings.customLaunchers).join(', '));
settings.browsers = Object.keys(settings.customLaunchers);
}
// Start these browsers, currently available:
// - Chrome
// - ChromeCanary
// - Firefox
// - Opera (has to be installed with `npm install karma-opera-launcher`)
// - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`)
// - PhantomJS
// - IE (only Windows; has to be installed with `npm install karma-ie-launcher`)
browsers: ['PhantomJS'],
// If browser does not capture in given timeout [ms], kill it
captureTimeout: 60000,
// Continuous Integration mode
// if true, it capture browsers, run tests and exit
singleRun: false
});
config.set(settings);
};

@@ -6,6 +6,17 @@ 'use strict';

var CLIPPING_OVERFLOW_VALUES = ['scroll', 'hidden', 'auto', 'overlay'];
function isNotOverflowing(element) {
var of = computedStyle(element, 'overflow');
if (of === '') {
// we only need to check either X or Y because
// if either isnt visible, they will both be a hidden value.
of = computedStyle(element, 'overflow-x');
}
return CLIPPING_OVERFLOW_VALUES.indexOf(of) === -1;
}
var FILTER_POSITION_VALUES = ['absolute', 'fixed'];
function isStaticPosition(position) {
return FILTER_POSITION_VALUES.indexOf(position) === -1;
}
var rectStore = null;
function toArray (nodeList) {

@@ -18,36 +29,40 @@ // Array.prototype.slice does not work on HTMLCollection in IE8

function filterChildren (children) {
return toArray(children).filter(function (child) {
var position = computedStyle(child, 'position');
child._rect = child.getBoundingClientRect(); // store rect for later
return (
FILTER_POSITION_VALUES.indexOf(position) === -1 &&
!(child._rect.width === 0 && child._rect.height === 0)
);
function filterChildren (nodeList) {
return toArray(nodeList).filter(function (node) {
// Ignore everything but element nodes
if (node.nodeType !== 1) {
return false;
}
return isStaticPosition(computedStyle(node, 'position'));
});
}
var storeNodeRect = function (node) {
var rectStore = null;
var storeNodeRect = function (element) {
var children = filterChildren(node.children);
var overflow = computedStyle(node, 'overflow');
var children = filterChildren(element.childNodes);
var rect = element.getBoundingClientRect();
if (rectStore === null) {
rectStore = {
top: node._rect.top,
right: node._rect.right,
bottom: node._rect.bottom,
left: node._rect.left
top: rect.top,
right: rect.right,
bottom: rect.bottom,
left: rect.left
};
}
rectStore.top = Math.min(rectStore.top, node._rect.top);
rectStore.right = Math.max(rectStore.right, node._rect.right);
rectStore.bottom = Math.max(rectStore.bottom, node._rect.bottom);
rectStore.left = Math.min(rectStore.left, node._rect.left);
// TODO, need more work: what about other "inline"-like display values?
if (CLIPPING_OVERFLOW_VALUES.indexOf(overflow) === -1) {
// if no element children, lets use this element size
if (children.length === 0 || computedStyle(element, 'display') !== 'inline') {
rectStore.top = Math.min(rectStore.top, rect.top);
rectStore.bottom = Math.max(rectStore.bottom, rect.bottom);
}
rectStore.right = Math.max(rectStore.right, rect.right);
rectStore.left = Math.min(rectStore.left, rect.left);
if (isNotOverflowing(element)) {
children.forEach(function (el) {

@@ -57,6 +72,5 @@ storeNodeRect(el);

}
};
function run (baseNode) {
module.exports = function getChildrenSize(baseNode) {

@@ -70,3 +84,3 @@ if (!baseNode) {

filterChildren(baseNode.children).forEach(function (el) {
filterChildren(baseNode.childNodes).forEach(function (el) {
storeNodeRect(el);

@@ -79,4 +93,2 @@ });

};
}
module.exports = run;
};

@@ -10,2 +10,8 @@ /* jshint evil: true */

var extend = require('util-extend');
var timer = timeoutWrap;
var doc = document;
var win = window;
function timeoutWrap(fn, time) {
return window.setTimeout(fn, time);
}

@@ -30,5 +36,5 @@ var defaultOpts = {

// Don't use location.hash until Firefox fixes this bug: https://bugzilla.mozilla.org/show_bug.cgi?id=483304
var urlFragment = document.location.href.split('#')[1];
var urlFragment = doc.location.href.split('#')[1];
if (urlFragment) { urlFragment = decodeURIComponent(urlFragment); }
var params = JSON.parse(urlFragment || window.name);
var params = JSON.parse(urlFragment || win.name);
checkAllowedDomains(allowedDomains, params);

@@ -39,10 +45,11 @@ return params;

function checkAllowedDomains (allowedDomains, params) {
var a=document.createElement('a');
a.href=params.url;
if (a.protocol !== ':' && a.protocol.indexOf('http') === -1) {
throw new Error('url protocol is "' + a.protocol.replace(':','') + '", but have to be http/https');
var a = doc.createElement('a');
a.href = params.url;
// IE11 does not resolve relative urls, e.g. protocol will be empty in certain schenarios.
if (a.protocol !== '' && a.protocol !== ':' && a.protocol.indexOf('http') === -1) {
throw new Error('Gardr script url protocol is "' + a.protocol.replace(':','') + '", but have to be http/https');
}
var sameDomain = (!a.hostname || a.hostname == location.hostname);
if (!sameDomain && allowedDomains.indexOf(a.hostname) == -1) {
throw new Error('Script ' + params.url + ' is not on a allowed domain.');
throw new Error('Gardr script ' + params.url + ' is not on a allowed domain.');
}

@@ -72,17 +79,17 @@ }

gardr.log = logger.create(gardr.id, gardr.params.loglevel, getAppender(gardr.params.logto));
// IE 8 and 9 will not write into correct container (!) if we document.write directly from script-file-context.
gardr.inject = function inject() {
gardr.log.debug('Loading url: ' + gardr.params.url);
var str = ['<scr', 'ipt id="gardr-injected-script" type="text/javascript" src="',
gardr.params.url, '"></scr', 'ipt>'].join('');
doc.write(str);
gardr.container = doc.getElementById('gardr-injected-script').parentNode;
pluginApi.trigger('element:containercreated', gardr.container);
};
// TODO requestAnimationFrame polyfill
gardr.log.debug('Loading url: ' + gardr.params.url);
document.write(['<div id="gardr"><scr', 'ipt src="', gardr.params.url, '" ></scr', 'ipt></div>'].join(''));
gardr.container = document.getElementById('gardr');
gardr.container.style.overflow = 'hidden'; // avoid iOS Safari bug http://stackoverflow.com/q/6721310
pluginApi.trigger('element:containercreated', gardr.container);
var com = comClient(gardr.id, window.parent, gardr.params.origin);
eventListener.add(global, 'load', function () {
var com = comClient(gardr.id, win.parent, gardr.params.origin);
eventListener.add(global, 'load', function onloadDelayedHandler() {
// phantomjs doesn't calculate sizes correctly unless we give it a break
setTimeout(function () {
timer(function () {
// parent.console.log(document.body.innerHTML);
var size = childrenSize(gardr.container);

@@ -93,6 +100,13 @@ pluginApi.trigger('banner:rendered', size);

});
return gardr;
};
bootStrap._setComClient = function (client) {
comClient = client;
bootStrap._mock = function (_doc, _win, _timer) {
doc = _doc;
win = _win;
timer = _timer;
return function(){
timer = timeoutWrap;
};
};

@@ -99,0 +113,0 @@

@@ -5,3 +5,8 @@ var insertCSS = require('../../style/insertCss.js');

var OUTPUT_ID = 'logoutput';
var overideTimeout;
function timeoutWrap(fn, ms){
return overideTimeout ? overideTimeout(fn, ms) : window.setTimeout(fn, ms);
}
function addOutDivToBody () {

@@ -11,3 +16,3 @@ if (document.body) {

} else {
setTimeout(addOutDivToBody, 0);
timeoutWrap(addOutDivToBody, 0);
}

@@ -84,3 +89,4 @@ }

docFrag.appendChild(el);
timer = setTimeout(function () {
timer = timeoutWrap(function () {
outDiv.appendChild(docFrag);

@@ -115,2 +121,9 @@ docFrag = null;

module.exports = logOut;
logOut._setTimeoutFn = function(fn) {
overideTimeout = fn;
return function() {
overideTimeout = null;
};
};
module.exports = logOut;

@@ -34,2 +34,10 @@ #!/usr/bin/env node

target.ci = function () {
target.lint();
['ie', 'ienew', 'chrome', 'android', 'ios', 'firefox'].forEach(function(browserType){
env['BROWSER_TYPE'] = browserType;
karma('start', '--single-run');
});
};
target.watch = function () {

@@ -36,0 +44,0 @@ target.lint();

{
"name": "gardr-ext",
"version": "0.6.2",
"version": "1.0.0-alpha.2",
"description": "The js part of Gardr which embeds external content inside the iframe",

@@ -9,2 +9,3 @@ "main": "./lib/index.js",

"test": "node make test",
"test-ci": "node make ci",
"watch": "node make watch"

@@ -25,22 +26,24 @@ },

"Gregers Rygg <gregers@finn.no>",
"Michael Gunnulfsen <michael.gunnulfsen@finn.no>"
"Michael Gunnulfsen <michael.gunnulfsen@finn.no>",
"Sveinung Rosaker <sveinung.rosaker@finn.no>"
],
"license": "MIT",
"devDependencies": {
"browserify": "3.46.1",
"browserify": "^9.0.8",
"chai": "1.9.1",
"expect.js": "^0.3.1",
"jshint": "2.5.1",
"jshint-stylish": "0.2.0",
"karma": "0.12.16",
"karma-browserifast": "0.6.1",
"karma-chai": "0.1.0",
"karma": "^0.12.31",
"karma-browserify": "^4.1.2",
"karma-chrome-launcher": "0.1.4",
"karma-coffee-preprocessor": "0.2.1",
"karma-firefox-launcher": "0.1.3",
"karma-html2js-preprocessor": "0.1.0",
"karma-mocha": "0.1.4",
"karma-phantomjs-launcher": "0.1.4",
"karma-script-launcher": "0.1.0",
"karma-sinon-chai": "0.2.0",
"mocha": "1.20.1",
"karma-es5-shim": "0.0.4",
"karma-mocha": "^0.1.10",
"karma-phantomjs-launcher": "^0.1.4",
"karma-sauce-launcher": "^0.2.10",
"karma-sinon": "^1.0.4",
"mocha": "^2.2.4",
"normalize.css": "^3.0.3",
"proxyquire": "^1.4.0",
"proxyquireify": "^2.0.0",
"shelljs": "0.3.0",

@@ -52,3 +55,3 @@ "sinon": "1.12.2"

"eventlistener": "^0.0.1",
"cross-domain-events": "^0.0.2",
"cross-domain-events": "^0.0.4",
"computed-style": "^0.3.0",

@@ -55,0 +58,0 @@ "gardr-core-plugin": "^0.1.0",

@@ -10,4 +10,12 @@ # Garðr (ext)

[![Sauce Test Status](https://saucelabs.com/browser-matrix/gardr-ext.svg)](https://saucelabs.com/u/gardr-ext)
This project is part of the [Garðr](http://gardr.github.io/) family of projets.
`gardr-ext` is the part which embeds external content inside the iframe. It uses postMessage to communicate with the parent page. You will need to have `gardr-host` running there.
This project adheres to [Semantic Versioning](http://semver.org/).
[gardr-ext changelog](CHANGELOG.md)
/* jshint expr: true */
var childrenSize = require('../lib/childrensize.js');
var insertCss = require('../lib/style/insertCss.js');
var expect = require('expect.js');
function createElement (tag, width, height) {
var element = document.createElement(tag);
if (width) { element.style.width = width; }
if (height) { element.style.height = height; }
element.style.padding = 0;
element.style.margin = 0;
return element;
function createElement (tagName, width, height) {
var el = document.createElement(tagName);
if (tagName === 'a') {
el.style.display = 'block';
}
if (tagName === 'img') {
// firefox does not let you style img tags without a src
/* jshint ignore:start */
el.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfQAAACbCAYAAACUA2mxAABCuUlEQVR42uzca2jVdRzH8e//nGMkWIQmFFJPhB4oSJSCTxKELOiRlycFmZaXqXnJtVypeSudecl5Tx0I+UQKK1O36bzVpnNqc16m05lOJZAoWzIpovz2Of/5SLB0Tt1+//cX3gzG2fmf//fHnxeDMXN3IiIiauclfgFERESATkRERIBOREREgE5ERESATkREBOhEREQE6ERERAToREREdGvQbeTWw9GobQNt9LbImGTNsM2PRW98M9OGfv1i0h8KIqIQQP9ZoLtAP2Y5xa9ZTknGmKAn/eaWrjb82zkCvVGgu0B/KekPBRFRCKCfugG6C3RVciE1piTXxpY+akxQkxqxtYe9tWWdQP9DoLtA9xugv5D0h4KIKATQK24C3QW6C/Sr0bjty+3tHT2Nab8zujhjo4oH2shtpQLdBboLdL8J9N5JfyiIiEIAfdMtQHeB7gLdbfyOchtf9rpN2NnRmHYxqTGlT+ssZwn0SwLdBbr/B+g9k/5QEBGFAPra2wBdlblA/90m7iyKJu3qZ+/s5o/o2tjorDrZuB3Dbez23QL9evYsBbrfBujdk/5QEBGFAHrBHYDuAt0Fugv0izZ592KbvKev5e0F9wc1E3d11LkM0fls1FldE+gu0F2g+x2A/kTSHwoiohBAz2sh6C7Q1R4X6BfVkg7vftff3vu+gzH3dLTzLtr/UJ3DFwK9SefSfD46qxaC3inpDwURUQigD20F0OMEugv0xsyU8o2WXz4s9X5FN2PuerTTlHb7vHacb7l7y7Xzf7T/5nOYqO4e9HTSHwoiohBAf6WVQXeB7gLdBbrbB/tORlP3LctM2z8oM62yqzH/O9pZpN31sPyKMdrll9rpr9pt855zlXbeiqD/ZsZ/DyQiCgH0PvcYdBfoLtBVpdv0yrrUhweKHppRNSKaWdUrM+tg4v+RjfbxiE0/0F/7mRJN3b9ZO/sluzuB3rxL7fQegl4H6EREYYD+5H0G3QWYC3QX6C7Qr2VmHdpnsw8vS805PNI++qFv9HF1Jwt0dI/dbPahl3XfedHMgxu0hzrt47pAj/cj0OOd3UfQdwE6EVEYoKcF+t8PEHR1yAW6CzsX6C7QPTO3+pzNO1KaLqhZqibY/KMD7JNjz9iCYw9bGx991s6pgqPP2ryaIZm5R6bqXtbrnip0b1ey9yjQ4/sW6Nk9xPt4gKBvAHQiohBA1wj0n9og6C7QXZjHCUkX6G4L1MLjl9OLThy0xbWb1Oro05MzbMmpHCs8NSi9tK6fLTvdK1p++ilbcaZ1ftNfUZ+y5We66H276/17W2HdAF3vVV13kq5fkFpUu94WniixBcdr9Rmbsp9VoLtAd4GuqrP3FN9bGwR9PqATEYUDelU7A90FugvTOMHqAtYFugtcF7wu0F2gq3q3lWeb0qvOXrHVPzbYZ+fqbc25GltzvsbWNtSk1zXUWNGF5q9rz8ff12sa9NpL+plGW1n/V/Y9BHr8vvH7FypdT9eNry/QXaC7QI8/YzsDfTygExGFA/pXgYPuwtmFtAtrF+jqvAt0F+Qu0OOvAr35+3qNXhv/jED3wEEfDOhEROGAXgjoiQW9N6ATEYUDei6gJxb0xwGdiCgc0AcDeiJBbzINoBMRhQP6c4CeSNBPADoRUVigdwb0RIK+FdCJiMIBPR6BfrUFoF8XLnmCpkz9Cej3HfTLAv1znUtRC0FfBehE/7J3PzBVXXccwA/Ig8f7D+9P/YPin46adHMshDmYGtamhq2hm2Bno9NlJCSSiq6zres2VqN1S5zThE1tWqWxbqFIi10FM+1GGchERaj1T5zr1KICokAUUEHw7nuS85K7G1jxcO/l8fx9k28k8nxPHnA/95x777lUaviB3iQ5Qp/OEGBjAzrfAz5FQOhfBLohoPcD9H/gPX8N7/838H2IYAi+L4WSoK8l0KlUKjX8QC+TBH0hGyIAfSJQeh44/QGgfwrQBwn0hwa9B6AfBuiFAD0DoNuYJgL0PZKgf59Ap1Kp1PADfaMk6AVsBAHoboCVCdB/CcDKAVkzgf4/oA/g/fkMoBcD9BcBeipAj2KaDAN6vSToswl0KpVKDT/QfywJehGTDED3A7ZMgP4aQH8X2DUAvZ5HAPQWfN1VAP2PAH0lQE8F6LFMIgL0LgnQBwF6NIFOpVKp4Qf6tyVBP8R0DvCbBgQXAvQ1wHwbWg4kG4Fl5zgBfRCgXwHoRwD6n/C1vIGvKRegpwF0D9Mzq//ukzzL/T8MIdCpVCo1/ED3SoL+BTMxAN0J0J8E6M8A06XoS4D1twB2F0CvBLhHAO8pgH4ZoHcC434dQO8F6G143s/x/E0A/RO8Xhledwde/3WAng/QFwP0eQB9JkC3MJMC0BdIgv5XAp1KpVLDEXQEoHdJXofuYiEcgB4DnD1A2g+spwN09NJ0gP4kIE8G6Mn48ysAHX+P4jF4rIf/G4AewUI4AD1fEvQiAp1KpVLDF/QaSdDTGWWsQN8uCfrKhwE9TBPxUKVQKJTQyv8F/U1J0PMYZaxAr5EEfX6Yg65FO1J0gqpRopYvaZToBNFIXsKeQqGEMuirJUEvYpSxAr1TEnRPGIKuBVyLdjQag1rRWFGbqH2Y2kRjRa1ojHguixZ6Ap5CoYQK6BmSoFcxiunB92GK5Fru1xgSNqCrAUfVeKvQdqBO1IW6UQ8ah8aj3i9pvHisB3WL53AEwdcgH0W4UyiUUADdLwn6TUYZC9AzJUE/PO5BF1iqRuEWFeB21KGCOx71oYGkpKQp27dvT62url505syZFy9evPirq1evbmlvb9+F7r558+afOzs7S/nHvC0tLVv5Y/hjq6qqntu8eXOy3W6fiOfyoz7x3J4g8kHgtbgT7JRQDZ0/Eq6gI0DghgTovNMYxWzQfyEJ+tZxC7oYjatH4irEnQJXL+rPycmZWVdXl9Pc3PybW7duVdy7d+/8gwcP7iujDJ6j986dO592dHSUXLhw4ZXS0tIFAnmfGMm7g7irR+40aqeE0uEomdLhpfEHepUk6NmMYjboZZKg/0QC9FCDPAa1aRAPVFZWZvIRd29v73HAO6CYlIGBgY6urq4Pzp49W5CXl5ckRvDxqAu1o7HqUTttDClj+fujPZ9khLWKRqMWmn0aH6D/ThL0NxjFbNAvSoKeLAF6qGyIrAJIlwAzUFJSMr+1tXVHf3//F0oIBDsS/d3d3X87ffr0ynnz5k0TI3cP6iDYKWOUCM3vkNgZFoelRl436gzOPgVhp5/h0AX9BUnQKxnFtOD9j+ffBwnQ+wC6RQL0UIHcjXr5sXA+GsbU9wklhIORe9f169ff2rlz5zfFqD0Odaphp1EOxYREolH19fUJV65cycShomdPnTr1XENDww/4Yalga2pqFg/V4OePHj2azf/NihUrpqh/jgn10AV9tiTobYxiJujPSIJ+giGhDLr6ZDfV1LoL9WZmZk6/dOnS+vv377cq4ysDOI5feeDAgYVB2NUjdpq+pJgBekFBgauvr++gMspgR7o6LS2No+5BbVrUtcfs1aWfc3NBjwTo3RKgK7hn9xRGMQv0n0uC/qYU6OaPyqMFdk40fs6cOQmA/NcY8bYr4zyA/fD+/fufFrB7BOxW1ELT8BQjQUetixYt8uIE0U+UUQaHlT6eO3duwhCoRw51zF5VC10BYhboCECvkQR9MaOYBXq5JOgrJUA3DXPVqNyOelD/8ePHl2FU8bkSXhnkl8itX79+jjihz4XaaBqeYvCsVwzqWLZsWQJG2XUGoR7Fqzl51aGqHY0Vn7PQWfPGg14kCfoWRjEL9DZJ0FNDEPSIIUbl3sLCwq/xaWoljDM4ONjDr3P3+XyTVNPwVjrZiGLQDrMFjUXd2dnZibga5J86o25HraI21IXzXXxY02HjyZMnswOBwGNiB9aDOlWPjybcjQP9R5KgH2UUw4P3fCZ//yVA7wfoMRKgmzXFbguOynGGeD6w61IekfDr2vft2/eUOCPehdro2DrFwB1nGxqXlZU1Qy/UU1NTp4orT9yicYmJiZNu375drjpJtBUnie7A2g3fwecDGtxtqJVmqfQH/XFJ0PvYKzUxjGI06EslQT/GEAnQzZhid6BxS5YsmYUFW0qVRzC43K3v8uXLG/1+/0TVaCeGNm6U8YA61mH4aPLkyfwyzcd48fFU/N2HyjDBcfxz/Od906ZNyQL3+ODOLP3c6wW6CEBvlwBdAehpjGI06DskQd8mCbqR03/W4BT7nj170nCs/N/KIx5sXOs2bNjwdTF6cQan4GnjRgl11LFs8l+wQ/q41WqdwT8e6ZGnnp6emvPnz69evnz5jCF3ZimjBv0jSdBfZhSjQW+UBP2HkqAbeSzPhfqOHTu2FFPstxQTwl+HrySHmYD3sKrc77EhebWpqSmvtrb2efW1t42Njbn43Do8Zise+8Hdu3c/wyj6nknXr9/g/wfVFHwsHVenjAfUcby84tq1a+/JLquM6fv3cZ18TkZGhoN2ZPUDfZ0k6B8yinH5WbUD7/mAJOgJkqAbibkfv7wvc2cNxPE6QH7/3Llza3bv3s1nkCaiAdQfvJuaaJym8aJe8djArFmzph48ePC7fKoQG54jYm14ozKIS/VeF6/tJtQpoYC6STvdLVjI5qu0aI1+oC+QBL0z6tVamiIxDvRn+XsuAXozQyRBNwJzNxrgdzMzaoU2jBSKDx06lGWz2SZxFDV3RnOijqHueT7MvdIdqqUy4wTygdzc3Cewo/ASx50PMBQDgqnLErGIhwu10jQkJZxRB+Y3KioqUvj/h0bo+oFuA+gDEqArAD2FUYwCfYsk6KXGgC6POV9/XdEz4kQbnCG/Jj09PVEgrr37mbj+VbvIxfAd5mYWdu2NYYqLi9Pb2trexgap14Cz4GvWrl2bKF7XQqBTwg11gXkHVlPMCM5I0c6rXqAjAP2EJOh0HN040BskQV+jL+jy0+xGYA7Iz2Kd6uXiDFuvCvFY7XWuopGiESNspOgEDfJWFe5xqD8/P/8JHHffho3TbUXH4OYzp7HTMJWmISkGo25XoV5v4n0POsvLy58SM2l2+jnXH/TNkqBXMIruwXvsBuiDkqAnmwy69tI0q8DcD+y26rgRaMeU90/F/ci9qEuzWEWUAYtVRAxzO9dY1IF6UN+qVatmY8S+S6/j7Lie952UlBQ3begoZqHObwXM10gwEXMv6qAz3I0BPVMS9G62rjaKUfQGPQugKxKgdwL0SLNB12DuRH18PXZFp+BEtxLc9SlJnAnuDkJu8opTEZqRe7QGdv/evXvn80vRlFEEMxpbxAyAjabcKWaizs8TMRJ1YN5VVlb2dBBzugbdONAdQGJAAnQFoH+LUfQGvUgS9P+ydybAURVpHO/JYUJCMgmTABrkCKcSwQWF3VVWpZBFkJIFxcKARkXEgyAIqFlURCKBcCggiOLKsiwWBbgcWssVATkC4diAYAghSBA5FhRYEWXZ0Pv/qvpVdXUxGHree3PY/6quwGQyk3T39K/76+9YyiA3ga7mjkbzIfXj43RNZkdIF8o4ZpPpXi1uEsTMah7ZIqEWlyELQllZ2XANM3w1ogBGik1LkrXYmYXOyEWo13EK6vg8/ICokZ7W/DYwdxDoJEBikybQRzMju4F+QBPoz9gDdP0FAV6rf4Tp+YINSVeKkeO9rWVe1yo/6n6hmQRhQUibMmXKbfgbNtUwJvcnxMcPlGPRjdevkdvFXARo0/v169cac3e3nTBH1cFe5PdiOcEZmDsP9HGaQN/CjGwT+jaT+riGQL8AoC8H0J8G0BswyEWgq05wKfDOboX65UdtSFjx12bNmjUIkyImHmrSHXu8ld6WCrF88803haq1Qk1+U1RU9CeCuckWZxTkYi6JYgPdAI5y7fBZPmVHpuMFCxb0w2s2REu3TufGN8R5oHfRBHp11MubfMzILqA/cxWgX8b4lGKspgDo9wHotZgkt4EuO8FRXnLEaG8I9MOPimRjLRN7OBUuUc3w0mk9fcOGDX3lAjRyAQsq1CKnfjUnF6Mgmt1rW0CvqKiYxG0S8ryvbd26dTP6XFs5Fsx1kvNAjwfQf9YAOgfQs5mRXUBfLgGdMsXtwDhMA9AfxLikM0VBArq6CKQho1p+oJY5xJXn0ofeMsuFo5e3fFqXS8TOmjWrA/LXl3EhymU/Y8aMdnRNYRyEjOyVvpUNrT4cWidwm3X27NmiLl26ZJpQNbeADgHoazWBPp8Z2QX06ejj4QD6H9DniUxRUIGuLgIiOcWyZcvuxT3wfwOB+e7du5+l02xE5DNXw/iEJzzC25ogT/w6wLxk9OjRzU2lNSNNOZbRsaqqqsDBYkRbevToQVBPNVB3B+jDNYF+mr2yOZoZuaDgA10ClbdFixYZSPZSxgMQZXxTYR7ucPPjCV/7zjvvTB08eHBdKxmOqYVupCFHai3A32O8CxUGt1HMu4G6O0BvqQl0DqCbcqoRC3T/pvZAFwHrzjyCvbs9Sux6nJSSNsYsZkaasjUJFO7M87hLorA4Co8zUHca6BCAXqkJ9AJmFOFAFwuBuG+je+FAyoyeOnVqnnVnHuGhWmpKWWpR5lRuFApOcJWVla9wl0W1GPLy8rKsO3XL890kUrIf6NM0gV7BjCIQ6P7jVeG9uiIA09v2rKysG2lj8CuLu/YYiBsFS2p0Cixso3iQBKiXjx07tq3lGGqg7gzQu2kCnXvyNt/CjCIS6Koj3Jo1a3oEkAHuu/z8/FutFKfG5GZk5LxUKxssZMN4kAUH0aqpU6eaaA8HgR4PoF/QBPqbzCgSga6ezusGEnNeUlLyuJXP2cDcyMh9oA8ZMiQZRYCmoLJfqW59fypGdO7cuW12QJ1KEhuoOwF0CEBfrgn0MmYUkUCX7s5T161b1yuAQiuLTYKJyJBadraGzWOuHUKqJrqXQigRafLE6dOn5wKuB2sKc6wDg+Pi4lp8++23f+cBClnpThDUTeEWZ4A+QBPoPObPW1oxo4gCuuJEk47T+Rrd0olID3uzMLXXMtXEwkn+68WLdp3U4uSmfC+Wfs44BoZU/YEkqxQwWt2JEyfeum/fvlxsvhcBtN9e6aO8cePGQXhuY7QmaE3hWDfTjmJMVFrVQN1+oNcB0C9pAv1V5rTeLvNEv7P/d2xaeSz7Neq51U2R+rW3S6lfPbJn+/z58+/QNdEhNOZlWjSMqT0sIa6G3sXTnBBASBRjmiRastykx2uL59YSPx9nAd7E4gcvR4JU4z9RgrtPWNKunzlzZidUEMyDE+ynBF0UEnoBjzdCayi+ZqK1LC0tnWBTvfR7TTpkO4EOAegrNYG+n7kgAL0BgL7EM728kM04cDubURGRg43+vxHj0BOpX8dio7USPg7fAejfAeidXDqhR0nV1NJQOOVDzXuyClFwxWtM7aEtPxCPF/CuLSCdIiwtPrFJSxcAqEeNCtNY/6bHRUsTz08VP59kAd6CuwF78Ddr1jhLp/b6aBkSwBtbbdiwYR1QFvXRLVu2jES2x0mIXqmwozrbqlWr7jdQtxfoT2oCHa24A3NBAHqMAPplAP0oe/fgu9EzD/Zisyp9LMyEvrwefXq3KM4yHalfN6DPz1yh2tohAL2lCyZ31RkuuWPHjg2wgz7DNbR3795nxQc00ZjawwLkscri7hVOS2kEaxSVuWv//v25x44dm4qT21JKFkKV9rAYn8X96kUuiR7Dhu4QFvuNVEkPdd9HLVq06G7UjifY+yS4Jxiwh8y4J4ox94lNWQOCeWFh4d3l5eX5yM2+HuN9kjskgjqKGvWm+Wagbg/Q6wAk/9ME+gzmogD0PwDolQA6B9A5gM7Ze4f2stmHPmSzv36OvX/4jugPDntZEHXda9tio17dmslGb+2M/hnoydsyDn22AH23jb206Sz1JfUp9e1Vqq1tBdDTGeQi0GOsULU9e/Y8pXk6PwgI3GCdzo2pPeQX9HixoCeL03Q6atPfQlcm8GpeicX2Pxyywbx6Eve0CzZv3txHwL0OvacF9hpk0vNoNL9y4T30Ew25XykwWYxHvZEjR96K4kuFiBuv4C4KG8OfNm3a1NdRqLs//h6/4y++5wzQIYCkSBPop9no4lh3oV6RAKBPANAvCaBzAB3taw6gcwCdszlVp/B1M3v/6/l4fAKeMxTP7Yuf6cLerWiP18hk0w+k4eSfApN+NFMUNWlfEivcm8ImfpnCJuypxwp2N48av7s9e6u0c0z+v3rF5O/K8Yzb9QJ7c+f4qLE7PmJvbF8ZM6Zkt+f1kpMA+mUAnQPo1D8cQOfUZ9R3ADqvAdA/AdATXHaKi5Kc4bQTyRAIzOlcKMRrucsnM8rTD+/nwSJEsdrheOSDNE/ICiRAknSlXPd+TMXUYq/SYjTu6eX3iNZ7DzT/4IyVTNzCWVCFlfsbOcnUnr506dIu+Mz/Qy285DbUd+7c+bibULdxjnnU15SvN9Txl3/WKaAP1gQ6B9B7sSAIcL4ZkF7tB+j0Ff/HY3icnkPwp1M9gM4BdA6gcwCdA+icvY02tYx7pnzF2eR9HEDnADoH0DmAzgF0DqBzAJ0D6Gi7OIDOAXQOoHMAnQPoHEDnADoPAOhTAfRot73cZXN7t27dGuPD9aOO6UxUWEoxp3MNuX8q83Xv3r0RSmiOgUn1OHdZiIs+vGvXricJKFeoRhctA8iPc57aEiwnvJrmz1cX3hq9B5pfXwAZDuL1FEdC+pqgenUHwdvdS+CklM4A+Seq82sQoX4Jc+IJAXUR7upYZkmPTXNMHX+1UFOi4ixaS/rZKKeAngqgXNQE+hIWRAHW9wPoX4Y50KvR/7nBCFtTY8+3b98+QDPufAEtzpZnuzmdhwzM1VNZaqNGja6nUzJM4f/mQRaZ9keNGnWTlGwkXgmRqyXd7aeK5/nUJh5PFSBIVGFQA9AlWk6ANXgPr1pFj5o/CwiSuzQ9cuTIcFgnNq9YsaId/ax8AnV5/OugXnnD48ePzyCA8tBTNULphmhUZdTuG4055lXmqjT+Ys5Kzobz5s27Ddn6ClFSeVWrVq18Sk57j+1AF17WSzSBfhEAq8uCKAA9CuB+DEA/GIZAv4A+78WgIAI9VkwyH5yZ5nANff75573FhE8wnu3BlXpSlE9ln332WTfcke7lISRsLI7Dg/o+ydu5lmgJ8ILO+v777yfQgggITYZz3pSjR49OVRs9Tt+n59HzlZzhnl/IilgbG9I35Peg5u89Tp48OYneA/e+t0lQj1UtIAUFBW3x3Fmyxev8+fOf0vfU38/JxDJS6dQ0SuWMjcVhHtqqhkPei05CXa5Eh7Wrtc4cGzRoUJp0WledDNMwp7tiw/pP2QICH4UXlVTY4m+yH+gPaAKdAPYSCwEB6DEAeT8A/aswAfpJAL1DcBPLiPtzkeoVi/0BnZztxhkuBOT/5JnSsmXLG7AgvU3DxTXk8h2qVyzkXsRCP8A1JE5HCf58OZQ64Sl4/3MaPiMDLK99+VTWtm3bDJzIx+E1L/Ar6IsvvniAFnX593N4M5dCzogo0FIQzPHX6N88J6CuhukiMqcn19CYMWMaS5aaBMsCgsezcJWx2F9SnUceeSRTDut1CuixAPopTaAfAshCxsQKoHsA9PsA9NUhDPQT6OMmIZApLlpMLG9OTk5zWls1zO0Ljbk9BGEuFhgqkINwsx08xEUmYAD8KSmWPZ084zWB7lPm49XyLvh0PPphGs4RVimvaL45c+Z0wKb4y1+oPlYqvP2T5Q2wnTCXNnOp/fv3byayPoadcKLNt7v0suo3tGPHDq0U17m5uc0tE7xlXsemtD/m0lVDfrGxfsdP4i0bgQ4B6NM0gU4g685CUAB6awB9OoB+NsSAfhF9XMqGow1bV4oNVSl8GUpZLtqQtaUIW7vJaaCr9+dIGtGPa4juvIy5PaRgHi9Ojr7Vq1d3l+/KwwHq69ev70cJTqitXbv2Ya4hAYGkXwS6KBGsA3Th1FfPSraDzceDFItfw8/M81JEiPgd7d/MUYUzKl/Kw1hkWVChHsgmSD3I6G4aBw4cSGt0XTH+9cgqQ1O4BnP8ZxoXqaS08KWwH+i3BwD05SyEBaDHA+gDAPT1APrlYAG9hnHo5S6c0NX48zr44IznGho/fvxvrMlpzO0hA/M0ODg+SqZsHmYCFM9Nnjz5HsofDieybE2gWyfgOH9Al6oK1tMBOjbAT4tELBkoYPLwtfQ15U6niBK7MipeCeYLFy68h/wTeAQId9cz7TupC/8Ccd2iC/Ts7OxbrI1nVVVVAb8GkUlebASSZF8Ke4EOAS77NIFe7Xl9W0MWBgLQMwD0FwH07SEK9BEuAF11iEvDJFuicX9+Qlk8o5lR0GFOJ0DhxRyWgkdweVZWVpvFixc/pgn0+jUEerIu0HEX/gxtOiirGm1CdE6esuk1UEDJMKfiJ5QvnUeQ4GD4Pl1VBAp1FegYxwe5hnr37t2Oxh+WmuE6xqhly5Z1U30pnAD6EE2gcwD9LRZmAtAzAfQXAPQiAP1SCAD9EoBe1w2gqwlldLyf4cW52tyfB0nqyUzAHMUzBjudIIZEEKRymJQJDv8+78D96d8+/vjjJ0IV6EVFRc/Xr1//ZvgnlGn233nKzCebXrXhJPwB3IQ5fv8fyckLc+AY9Z8b8eyIwvmLVZZZMVd73AZ6z549b0fFum7427WsYEiRXGz9LfIp3W6gewGaHzWBfgZgq83CVAC6F0DvC6DPAdAPBgnoS1x0ilMXtTOaprA0KzucMbe7KvVk5ispKcl24GReDWjtQj3s6Xj9nLlz597RtGnTGwmacmvfvn1D5H7vjA3F01TcR4qY0NVlvNa0UAX6ypUrhyLD3kQegFCbfL56lx4AzFNnz57dkTZYDmT4q6D8/CjM8ixVSevatWsTdfwzMjIaoGLbb4uLi7MpzAvA2oq5aLtXPV57Mh0i1IxybgMdffB75Lov5gEITqA5UpnpGPuBDgE0H2gCncA2lEWIAPSGAHoOgP4RgF4GoF92Aeid3QK6BANvnz59MrmGUG5xuHGIs1P6JzOY8O6186SMRbwKeou85MW1SpoY6xTJsztZNK+cmMNyFEJSjbto06db7IdOP6EKdMQvv4a/64dAw/CxMehEcLrGUsMeNfRu6NChLTFmldwm0ZidOHHiPdqkif5Ml6voKeNPzSsl5kmjfh0xYkQWaqi/rr+58++IqxHPbyvQ4XD6kg0ZEyvbtGlTV06X7QTQ2wUA9MMxY7bHsAgUgJ4MoHcG0F8G0JcA6BUAerWNQC8D0D2uAl14esK02YlrCMk1HrZ2mAbo9khnMadsa+RoZRPIj9BGTZTBTZMysNVW0l/GKS1ejsmVi7489NBDzchxSHiBayj0gA6fk502+QsUqc5R15IYBS2Zsv9RLn67nBJprGjMBMT1x1+Ec/2fvfMPrqK64vi+BAVCTQgkiCX+qNBUwaJUcSikLaVqtFgntuVHLcWWSmmKdiZlKkMKYulUBCIVjLE2YcYxDDpQYggg0wzCUEok5UdqkCQCQyvyByEISItT28Dt98y8ndk545s+zt19e+97e2b2Lw27+3b3fu759T05OTnXoT3sMb/ATpP+tmzZUkqbBxbdiKUK6BcuXDjkU23Ak+49+Al0DvVWIdBx7JvuZIgB6P0A9NG47+kA+hL8Dmc1gP7zVPahe19qeBsPKYHV19d/xc0BRgVxqQO6dzGnQiEokP3Zh0WyF2H16okTJ95EizCTOO3L9KvdI4sPN/HO3GYymIXz58//IkDYZCTQw7H/wtoBlZHMQ7+SVEtBXDRI2/BstkAY5Q5XY9+FOB8uk+D58wE3fZms6uBRo0bdgM3CMmrd8uGH+2D27NnFvP1LAvQQ2zQvYJOz2S2MCxLoP9QA+n4nAw1Av0Vj2tpFAD03hUDnGu4zlcAqKytvc1tvIqCnNtTu5s3R/7pEaRp59/B4JlORjmchTziE4komWDF963wCKOXZqagqE4FO+WgSF0Hb28OlpaXXkXfOq7aTic647abo239YtwiSVO1QD/BEPLWS727kBM/f4c/fO6jG3dhRSx3NzvdhA9KQoP3LVKBfQm3BXzAUaTFaMktyc3MHedIGfYIEen9A57QQ6Mgr778/A4H+ikbIvdqBhQV0yB/OVQKjsGwE9NQZC7Xnr1u3roTCj0rDqHipoqJiVDwnmcsWcrEqF59AxXXlEd2ZSHn6TAA6FSpCUXFDU1PTA3FoDiaYMHC6MEo2OpNHE/NIm13X043nyQvjzyaHP386fJKi7e+KHkEC9fNIE7ylNA2h/EdpY+PNQ5sGdOo6wMb7ubhmx5D4889jg4T8rXLnBugs0gD6XieDDPd9I4DeKwT6ZQB9eJhAxzCECt2FMxOBzmd3J3OwvxFVtbva+wRjzWln2+MhduYpBDfdyqtkRyF4hBy70hno8CIbV65ceXd8IR/k5qMTjmFNPjpTgILDF3Xn01dVVd3pDsbhcKEjQFni/KKiomGkf6EbXaKNDRfpMQHoeK8+phQDdQV46hGucUHOR/0GDfQCwOeiEOhUAX5/BgH9ZY2iuAYHFiLQB0mATiFTvnBmYnEayxtencTBFnAcSRgPtba3t8/RhHkzxFuup0XGLcrhYEmF1vysWbO+gMKwQ+kGdOrR37Vr19S4Rz7IM8ilr0You48Lotra2nHw/P+jAfPjtKEimMs3c/qDY6hgjuZBaLayVfH2v7CBTn3my5Ytu8utR+CbOPb8BVruAgN8quVAzwwvHUVxI3DfvRpAn2Aj0EnqUg/o9sOc5YgHxD/aaxIc9N8GcM/sSipzXQgVFxcP0wlXo6/8wOTJk2/+FJjHUrUJ8kKdwIL7+bvFQOeLeQvmoI8kLzp+jpwE3ri0dqIQG7ImjRBwT3V19ZcZzAXXJbIYhzp56gi/79BIaVxcsGDBSO6lhwV0Ki6lCZTuRi5xPQK34IF+MyB0SQh06tV+IAOA/opG29peJ25RyN0q4yNK8zz910MSHIUsd9qPFUIl7Z3T89LwHLupP5j+HQ7zMEVxqGed+uhtBzpV8ZPIjieNoR3G5t45isq+ShyTdjNgVve3aLMh6OMOCur5ZWVlw6lgUEPv/QV6j1guPeVAP3LkyMJ4VGYgXUsSkQ8J0OUGCK3XAHoberZjady2diuA3qsB9DITgI4K13IlsPHjx3tzV9mZKOqCheRxeDwf0AFYnvx/B/1/8JAb+GKabO6c2tSw8L0nTeuhKnqK65kFAnN5TUABlMjKbQY6epPfIpizyIduGJvLNBcgRP26EhpyukvdOeNMaS30jo0NGzZ8Q1rkSUqXlEvnY2lTCfTjx48voc07Ky5kG7nwgT5WA+gKQJ+exkDfpCEsQ+NTYyECPdsFOiQ9ZwiH/I+mjyITge72gaMFaaFATKQlWQ1vvvmCtOZUJTQof62JLzhs0QvFuEBKHsEVcppv2gh0FPcdJTEWn9MY/H3Lmzdv3i1S6JGEL4WCBb3bqdrUFdIMdCU0RK68ypVXpRLoPT09r7meuWDMqwTocgPQmzSA/g+oq/Vz0sxwbyWa0q+CjU4gSnEDMXf6QSUwtE19LdOEZXj4E1OznhIsrG/z8GCy3hlVTQvzpmeoAI2Aw/qewzTeV52PgRdfor5om4BOgMW3MCmgyEfMm26BF7hIepnxtjn+3sXC9ou83xMVakolbPFdtfJhUakAOnVqULcIm57GfluzgD5GA+gKQJ/vpJFRGgH31qIB9A4APcsQoOehJ3i8Elhra+sjGSb9yufI5yOEuVjS+81HZyZTDEcztKkYUSO3VyAATsq9NCoqsgno6DFeSZGPJAROxOF297cBtNqEuf032HQvk55/lmcuwWAIXc1SQsMs/TEsDRgLGOiXt23b9pBgMxci0GGAUqMG0D9ynmkbkkZA/77mcJaZDixMoHtBMWnSpBuVwLq6up50Q1wZCvRBUH16WgJ07kkkE25HjvkxqbAF9cLyML+hUY98KtojL90GoOO3Pc1/W3ZO38LtNChHCW3jxo33sHB0lqFprDxqZZMWyCGCUcnWpECBjnqGPwrSWEYAfYwG0BWA/pKTBoZ7ycE9ndQAegeAnmUA0LM8XtG1WJg+FORka73jUyOg+wN0Xt3uei5YPF4TttGs4ucztdDQFc3Bva63AeiYJvbrT4m2xIKIBlGOWAkMLWEtdJ8meefcmJdecPTo0flCfYU3+fMIEOiX6+rqJgg2SuEDnQxwatAAem/20r/dngZA/63m+NQyBxYm0HluVhrKw0Kx0w01uh9PBHR/ge6FHMYtnlACo5Yw01MjPFeMgUHfNh3opARGEqYBRT74hq6AtMuFkbRf8ty56bUpVO9BwjmSHnu2eQkM6DThTrBRMgroIwH0y0KgKwD9bRxZ9sK87VbcyycaQG8F0GOGAD3mXSwkHhF59bwXPQK6P0DndQ7oKLhNWLDzHl90LOgeyKNqbHq/TAY6hVuD3NDyDZ1ETIigSHBkxatGRtL4/VIboBLY2rVrJ7A8eiBApzZLwUbJIKDDAPQ6DaDTMcfSeegxAH0n3YsG0O9xYCYAnYMJhT2/UQKrqakZxxeLCOj6QOcLz969e6cLW9V+nyAEafyCfvbs2TdMBnpbW9tsWtBZm5QvxutcZsyYMUKoWneAe6wmf1veFBPSGU8pgWHY1M94RMpvoJNAz8yZM4v52mcj0IcC6P/SAPo559l3rrUQ6I8C6EoD6H9yYKYAnYe49uzZ8x0lsM7Ozl94F7UI6L4CvY+nXelXSmAHDx6cxYuEbFnQkTOuNBjol6ZNm1Yc1GaWt5Zi3OZ9QgW1l9wNncCLDLU4srGxsVQJDK2kK9g77zvQ8Q3vF2yUzAM6GYC+UAPoCkBfZ5WAzNJ3BgPoPRpA7wXQR5kEdB7SxeI0nBYpyTQpDqcI6PpA53A7ffp0nRIY9XVz6Njy29JwE1OBTpPKBKkMMdykw3gwe/4ntmzo+Jo0bNiwIkkenUbVsmJd34GOyFcdi3xZDfT+ANZJDaArZ1l7mUVAfx1AVxpAr3FgpgGdhziRb+0QFAadJzEI3vsZAd0foLuCMijA2S4doGOLPC+HGMnUmgp0bGQ382cY5HsGr/NZJTDycm3SiuDPhjZOgu/rr/zZ+A30jo6OCh6ZtBboZADWDzSBfspZ3l7gGG641ikAutIA+nkAvdBEoHMvELvOl5XAdu/e/T2vFxABXR/ovAsBf7NPIkfKw4I2AZ0WW1OBjlB2DfcCg0w/dHd3i75NKoizTJ6ZF8btFLz3nfS3QQKdokdso2Q90GMAeqsG0BWAvsEx2HCNQ3GtPZpAr3BgJgKdL6AtLS2PSKt9OaAioPsHdGn0hM5jQ1shX2xtADoKtp4m0KYK6GfOnHlVonvjRmhs6ULhG1laWwQTBU+y9953oKMVtITLXlsNdDIA/S4A7JIc6DhWHJpmMNA30bVqAP0QgN7HVKDzStqSkpIbsLj9U9KPSxWfvB83AroW0HkP+vuC6V87madiE9AHmgx0KgYNMirF20olYKP7srCtNMubasLQk3qJMmLQQF+1atWdPPJhP9BhANiLmkA/l1317ucc02z5oZ/SNWoCvcSBGQ50PvxjkxIYwLbYDUG6H1EEdP+ATl6HQDWrmc4TAd1/oB8+fPjxVAKdnqUAbN0JfgtjjdeOoBh0jWQjEzTQy8vLKZWRl45AHwiQndIAugLQW53nDl/lmGIr3r0dQP+3JtDXODDTgc7D7mhz+rGCCap+T4wYMaKIF8dFQPfNQz8h8NB3RB56MECn7yTgYrMYU4nLVA/9VYmHHgFdwwCy72oCXQHoVUa8TVWHPwOgdwHoSgPopwD0wTYAnU/0Gj16dBEpdOn0pHu99AjoUQ5dmkOPgO54c+j1gi6HKIceAV1mAHqjJtDpmGwA0OsBdKUJ9KkOzGygJ9aMRkXtH4Re+vtjx469nl5070IXAV0EdK61v08i+xpVuacH0KXfJGnNW17lvsPEKve5c+cWpzvQPwuwndcE+rnYyo5iJyTD+Z8A0JUm0BsdmE1A56pxtbW142iDrzN9is8GjoAeSh/6x14PLepDtw3o+n3oDQ0N93quM9vCPvSjgu9rH31fEdA1DWCboQl0BaB3Or/rzHVSbDjv13H+Xk2g9wDoQ+0BemKP0C3CkeTtMEjkDlpEvCMFI6CHoxRHM7QtVoqbFgGdKcUJ9OYtV4r7RCD6s55rBERAFxqA3qAJdAWgb3ae70wZBHC+m3DeD+n8mkCf4sBsBDpfQLZv3/6gEhqpaHmH/rsLSQT01Gu5Hzhw4EeWarkXHDt2bFGmAp1ruW/duvVeoZZ7ja1a7hRdEGq5L/e+8xHQ9YBeCKB3awJdAehLnVTY8125OF87nVcT6GsdmI1A58Vxbv6K5v0qocGjmOsuJN5ZwRHQ5dPWpMM5bJ22ho3hlgjo2tPW9rkFYrZNW8OGbqFw7ZnjPpsI6D4YgF7qA9BV9qqucidAw79/NYDeTOfTBPpxAD3PcqCTZXl3yM3Nzd9UQsMi+dHq1avvju+UB3jz6RHQ/8femQBJWVxx/BtA92KPORYkgIAgHiAmHEGwgogUWSEIikgiBIgRCYoGCsJlsBIg4RBZCHIJFiCiBchREEBDCSFoKGQt5AyyCovhdOUo4kIkUp3/s7qrPl/N7Oz29Mx8s9v/qi5gmZ2d/b6v+/fe69fvVb4f+sSJE1to9kM/nIr90CncSn0CqjnQeT/0z20/9OhatGhRew5bC/QYBdi9YgDoN5y/fBqXJi54Xx/e/w0AXcQI9G8B9A4OVAWAzr30fOqmJjR17dq1A1R9jiYO20/3WaBXCOi8ec4xzTKVD3D4eNU7U9cVZYh/IaDqDHS+BYGja28aOE7qybA7T8wlI4SMEY0z6Gd5RMIC3QzQ0wC9ohiBLgDeq765n3aMA9Cn0/sbAPp4B6oiQOdeel5hYWFr6toVw3762qysLJVpneGGugV6dKCzxLjlQkOnT5+e462KcdG3e8iQtED//p4ywPy80BC2zv4ZJkrj86J3rowX9MIfp7nerHfnDFigGxSg1wTwuxQj0AWAftF59dg9jinNPTaO3tcA0DcD6L4qAnT+wKuM92BJScmfRAw6derULFqkw0HdAl0BNvqCvn//fq0qfvBaLnXr1q1JYmvt64OLMvNhRP7PAv372xDTpk27V/c46dq1a7uqRDEGOs9tt4RCoR/otE0lwRCgaITfnRBngW5QgF9PA0AXAHqp82pxzFDHe4wE0IUBoJcA6AEHqipA5wusmmDNmzevj3DvQRGDiouLJ6jMdw51C3SnRkUSowoKChoDdGVCQ5QxrlEfICneuarfbYGu30aXi3o00LX1oJfuY79jsKio6Gnd1J1Ro0bd6QatBXocBAhONgB0jOJSZ95n+lCfVzwM7yEMAP0agN7Ggaog0Hm4l8DlX79+/UPyTKi2jh49OoZ76mrSWaAzRW6es07TS78wfPjwOxWEPOKl+dhzFli4cGEH2ju1QA+fW4DCTeOFprZs2dKTl2ZO9tzjW3wdO3ZsBO+8RHNrYXu4eWWBbh7oNQD0jQaALgD0UzXnf9bSqaTwPc8C6MIQ0Ps7UBUHOg+9h6ijmmDS8BRfdEE9k3mLGEweP1oTb6DzcPSHH37YR2iK9uA9VB+AL+a5lGuBRXmHgCzQw4ejCSS6OS0oH7y/QYMG9dnWSwKhHj0J9+TJkzNiOCo7hIfbLdDjJAA9BzD/lwGgC8D5K2fB5+2dCgqv/T2+RxgC+kwHqgZA56H3HCy4dbHgbhNQjHvqs2WiXJ4EYxpbXFKmeQSVuo0z0PmiR9nuR4Wmdu/e3T+Z9QE4zN2LOfY/xwvIAj3yM6eb7a70xRdfFHKjLjGRmui5Ohs3bnxYNzqDhiynaWvQvaVggR5nAeZNML40AHQBSH/tLDz+kFOeFp3w4TWz8FphCOgbAfSa1QHoPCSqJgA9yNSERTDpZKPSnjCFEeWETvd4CN7Hw4MEjmPHjk02DXQuHpZGtvNwAemG3qk0b5LrA9RQRgpbzP9rgR79SNfy5cs70K3U3WemGvnSqMvmxnQSYJ6FEaBjatSCWWiKImXhjuZZoMcf6h0AyWsGgC4A6+vOouOPO+H02ombAfSleI0wBPSPAfRMB6oaQNeffKtWrXoQi+B/BJPOOfX58+ffJxeXHBWC95i37lPXQC4U6cqjzMjIuPXcuXNvxRvovMVtfn7+LapphW6xGVlsxM+hniijyA3zWbNmtYWHdU5AFugRrxvPpVgTQ9GnSytWrOgsAVibQz3BMPe3adPmVpoTMRipX3bv3r0RT4azQE+QAMm+gOUNA0AXADrGiQnOayU+R6rm4pIAgL4DXxeGgF4CoNdzoGoIdJKPe1R79ux5knkJWiLDAMexnpVhQL98/wwFmSSC3ccARJ8nU0IghAnd4vLly9sEZB7o0b10qtEupHTPJvfo0eM2ei/tbQ99mKer52jGjBmtYZwcF5AFesW99Llz57ZVEQ3dEPX06dPbSqhnY6Qn8P6nKZjTnj7m0ZYYT9CMDeedW6AnUIDlcwaBLgD0FQB5mrPk5B34sxhAF4aAXgqgN3egagx0ko/teYYQbh4tDIkmtQwFh1x76+ncY0+gF1nTBfIM+Tv7Mep88MEHT2JBPCMgXaBrNMwIV2v/H4Kk/zn2kKcecdsDw+T1VFs3yihasmTJ/Wr7xgK98kmqZ86cmSVI+lA/u3Tp0p/Qe7HjpKYNaR7hos8fIIMSXR1lW2D9aFOjRo3q0ed3e+cW6EkQgP5Hg0AXAHkRgH4JfwpDQP8aQG/nQBboDvewcjDysXfFksJi89bRVWxSu3btGkqLO5d57GyxMQMcBh218KTJn1tbGhj5U6dO/RFvGKKZbbybFfmo0O/B8xmoZjXLeNbZ9jiMmvvRtj0w9Lcq3F6ZupboE/AohUoFZIGulaSa26lTp4asAItOuPri9u3bH6N7wpNUmWFnIsKljLkgGe/sTL2ObuAo3sPhWjVboCdJAPosg0AXALowBPSrAHoXB7JAD58YpqCOdoVThUFRcgzVn27WrFkDl8eeLSdtugvutRTgXcNXgVGDAbwWg3iW/N38GPljx45tQW0osfBfFZABoL/Pq7bpZgbDAJpgwJC6jOz3QWG3PdQ15teWiV9fZhhlyvsXyMzMrEcnA2CIfCsgC3T9c/uqgZKBa/ktqkFOoXtD98g119KYER3NwPOVE+GqrSJcO3bseNyEMYc5+Wq4YkkW6MkFug9AX+AxoF8H0Ls5kAV6eYuKeajzfT4Aa/KIESPukrAJyEmULaGbISdUmoK8a9Tiw/V/N8uRJr8/Uy4KORK0Qfp5y5Yt64Skt9cI5AaNlaNIBGzFj43FeJTwb8KALly4sHb06NEt6X5GM6L4YNf4ZnVd3VsV1CQGXtlHQsoC3TGRzxLC3JsmDIg85pUrVz6oDLtI9z/KM8Dvv4pwhWh7p7S0dAUvX6t7pr5Vq1YNFFTd98ACPckC0H2A6QKPAP06gP6IA1mgVw7qsorVDWFYVKEOoe5N+/btG9K5c+fGcsEJykUnV/782jQk6DMjjCwa8nXZLoAHpKVfl0KBVNEOi1uRMCwsQh+PHz/+zjA17ZN6lJBnQKNOwMxhw4bdIcHOjahMZUixkeG6xtluw2j27NntsJCvVPXZLdBjVg1u1GEv2ohRR/eI7hVOHvzYNc/yKnn/a8tnJoCR37dv32a0lQavvFQw6fYmoKRAHmq3QPeQANPvoJ5koF8F0AscyAJdC+ohQPdptq9rVPTeVE2MQoTbtm3rJZuO1MWoI6EclCMQZgTla/Ll62+ZOXNmG8oYR0eyeUiwOSTiJCy4f5VHa/J4hTwTR39wlLAT9aA3mc+Ahf3Nd999t5cMxdZxXde8MMPvMozqNG3atCFOQgxEsuNmXZAjQnPRAr1iRt3gwYNvx/N7RECmwI5ndgvNjRYtWtzqml8BDL/rvueqv7vmWD7dgw0bNvyU6vKTkWjycwHCfSLVUbBA9xjUAdbZSQJ6GX5+FweyQNdaWNT57CBA2wNW9DmRGN2g2s+A/PsUzkP48WUqL4uqYyM/+eSToTTo7zjaMp7C9wihLyRvHx74x5QQJBIgZCPPIS/KDMwj76fTQmeqOAtPnKJrRl4WID2ItiImTpx4L3leAwcObE7d0ag2ARlzKN05/cqVK9tj3aagimEoczvFAj36/Vf76XPmzGlD/cCFYdG9xPzaiSpzL2M+PUOd2+i4IUVxKFN9woQJLfFM3I8e9k8iSvcSFY2SdQWM68iRI7+NVOnQAt2jAmAnJhjopQB6eweyQDdyvjgwadKkexFi/khUYxEoyMMhj0WF2c3APHJ9APp50iNOaWHhnv32228/ZYFeuaJPVEWOqgGKKiicqHlJVbjjZWst0D0uAH0ogHsjAUD/N4B+twNZoBstGpFHtZXJOyW2iWom2i9fvHjxfapwB+8uFw9jStUHSHWowxssCgaDd61bt26gBXqljbrA6tWrH2CeesoL0YHJ0jDmNeh9FugpIgC3J8BbFkeg7wPQ6zuQBboZuLAwYC4BZufOnY/JpK0qLwIpkspekY0i/PqlNfWhrir5AVRlIsVEx5lGjhxJCVlNNm3a1N8CXaM2vvTUq8icu4ECVmNcMM/gSXAW6CkkgLc1gH42DkDfAqDXdiALdHOKUPc80LNnzybnz59fRGt2FfbK98E76kJGDG8PGwvMdaEOIHajamAptEVRhkSq7vjs9TEavPfeez+3QNeGuh95Di0oUpTCW1ZliDYNdhU9Sucwt0BPQQHo9QH0vQaB/jKAXtOBLNCdhITglbdOwENC2i5RhQSv8isk3o2ipim0kCapexy/5iqX4R5c790pENm4hpK6T8hs6nwCLSqYPWGBrhchU9te7du3b4B2qytEignRhRNr1qzpXF6teQv0FBaAng4Yr4gR6NfwHv0dKQv0hC0wN/FqUXv37v0l1WFO8aS3MqqnTUeGaOEx0zHOfC4D1bqm7H+qKObV5EFktD+uzjzLEaI2nxboesBi2175Bw4ceEYeH/O8kCW/ul+/fk3L27KyQK8iAtCfA5y/0QB6MYD+QweyQE+K58AbnQToKBcWxqcQFtybYiC/jLKTc1Ek5m5XeD3LQHMTo4YU7xCHcHZXalnrMU+shM7Qu0qOZqnoAiDfRxPodaMB3d3kRgfoOL71lEeBzre91HwL0skTnC3fJDwqqgwJQ3+gOhUSL+PYDXR6xnSBrp4xC/QYBTi3BaRPVALo7+B7ch3IAl14oad4mgs0AYw6W7du7U6WObzIq8KjQkThKNVO79Onz22seUy6yb3yOHa48tO2AG0PUPKZBzyxdwYNGtSUbVOoZyMP9eUfExqSQMiO1JqW9RbP1wE6PN5f0WdkHb4My3y0BiN/165dfb0UHcOc/y7S1bt378bKsONHPGmYRIhqcKP7jL3wwgu30+dURqMFeowCpHMB67eiAL0MrxnqSFmgJ/c5idK4w48RGjBgQDMCDhWyoOIiHtgfP49qV8vI4GD15MO3d/WSIvdzD1LVOpzr/QN5RUnwyouxkPYL54m5E/uKiop6Cw2p3thRgH6TOrutA3Q0DxqkFnQvAp3PN94GmKJj+/fv/3UyIzZ03anpEUW6lIGcmN78KnlQ/xkbN27cbaopjAW6QQHoAwDuK2GAXoSv3+FAFugaQE882DN4DeghQ4Y0hyc0FE1D3rp+/frJRK0z1PgBHsNsJGX1CoVC9XjHt+SDXD86wpIUg3S8Dtd4CAyov9PvHu8IBzRC9q/28/P5PKnr0KFDPYWGKlAr3+fqGJgLw7HSJXMRqRnASo96VryNLY+OoftZb4qWkKcsEiCaX1S5Ue6TB/mWVQIiXTVifcamTJnSSD1jFuiGBXA3BNA3S6B/gz9fBNBrOZAFuuDDqx5ELdalScHdr+qD4xjOPXSMhcJz2AvcTICQIXrtUB/Vv8ZitgGFK/6M0pV9aZFhTSlyXJ3d0jQXHC8aUem8TSwa07TEmd/f4dpupTwBQ/uiZ5Fl/QaMo0dUhEMlD3JPjIeJFyxYUJ8WXPKiKDRK+52UxMQHfR3n7h9F6dle8Jx/xmt8R0scO3z4cAF9L71HeT+DPgN9FvpM6ErWSKNamaejYwUFBY3JuLt48eIq3LczJk8w0MkWKg7z+uuvd0h2pEv3GaP/V89Y165dc93RGQv0OAggbwig56h/W6CHHx6Urxy4Z6gOXi7ABxXkMeqOGTOGqop1ISDTgiRrt4+lkDINeFMv0tcOHjz4Gwr14nz2Q/Q9rKlLwNVsIjsMxGvpg9z7CzuLjoSgepSshsXreRhQhVSfm87ZY6E/RbCnDng8URCh9OO0cNMWBW2b0PeH6diVWZ5hxKMJ7N7nRRoqnyGcoRBtK4K3zw03+LOheSzR69GxHLcBXVhY2JrmE7VGRpRsFe7tHoqUUWlZ5c2rYkoUPqdng/bmydhGKH0ejMPRaO5TQG1OVee+ZEa6DD1j2fwZMw10O+yo1GBKBbjfxACf6W6ByiaiX44AG/4wXaJyeFtI1lvdPMS9Hx3hcPPzLnXKkGJDfT3EWttma0Q4fOxzpal7X85Ij/z+0cFWqZ+hIMRhnvr3Py2CAR0o5/7zZyCfPQMqylWbQTyBkS7zzxiHuQX6/9s7gxUAQSAKsiAUUf7/58ZCggyKtCwJtsJc8uDh+RzxUhBCfyF3Cl5BEVnGA6CYCuRNgSvrD+kd7p3/XF8PGZTvZyXw3f7CwdzHGLITxbLGBBFNuEDb8sceQM9m98t/j4XQgxC6n+RZxjSgeTAvK3D/C1RhA9UcBO4rP2ngPYT8PP9kyF9JX0hwpfxvcgOfywpOnWcAAAAASUVORK5CYII=';
/* jshint ignore:end */
}
if (width) {
el.style.width = width;
}
if (height) {
el.style.height = height;
}
el.style.padding = 0;
el.style.margin = 0;
return el;
}
var createDiv = createElement.bind(null, 'div');

@@ -23,3 +42,5 @@

childrenSize( document.body.appendChild( createDiv('100%', '10px') ) );
expect(sliceSpy).not.to.have.been.calledOn( sinon.match(instanceOfHTMLCollection) );
expect(sliceSpy.called).to.not.be.ok();
var match = sliceSpy.calledOn( sinon.match(instanceOfHTMLCollection) );
expect(match).to.not.be.ok();
});

@@ -29,3 +50,3 @@

var res = childrenSize();
expect(res).to.be.undefined;
expect(res).to.be(undefined);
});

@@ -36,3 +57,3 @@

var res = childrenSize(div);
expect(res).to.exist;
expect(res).to.be.ok();
expect(res.width).to.equal(0);

@@ -48,3 +69,3 @@ expect(res.height).to.equal(0);

var res = childrenSize(parent);
expect(res).to.exist;
expect(res).to.be.ok();
expect(res.width).to.equal(10);

@@ -68,3 +89,3 @@ expect(res.height).to.equal(10);

var res = childrenSize(parent);
expect(res).to.exist;
expect(res).to.be.ok();
expect(res.width).to.equal(30, 'width');

@@ -89,3 +110,4 @@ expect(res.height).to.equal(40, 'height');

var res = childrenSize(parent);
expect(res).to.exist;
expect(res).to.be.ok();
expect(res.width).to.equal(40, 'width');

@@ -115,3 +137,3 @@ expect(res.height).to.equal(50, 'height');

var res = childrenSize(parent);
expect(res).to.exist;
expect(res).to.be.ok();
expect(res.width).to.equal(300, 'width');

@@ -121,7 +143,6 @@ expect(res.height).to.equal(400, 'height');

it('should take overflow:hidden into account when calculating nested children size', function () {
var parent = createDiv('100%');
var a = createElement('a', '10px', '10px');
var img = createElement('img', '30px', '50px');
var a = createElement('a', '100px', '100px');
var img = createElement('img', '300px', '500px');

@@ -136,5 +157,5 @@ a.style.display = 'block';

var res = childrenSize(parent);
expect(res).to.exist;
expect(res.width).to.equal(10, 'width');
expect(res.height).to.equal(10, 'height');
expect(res).to.be.ok();
expect(res.width).to.equal(100, 'width');
expect(res.height).to.equal(100, 'height');
});

@@ -144,16 +165,19 @@

var parent = createDiv('100%');
var a = createElement('a', '10px', '10px');
var img = createElement('img', '30px', '50px');
// be aware that IE adds scrollbars to size if element is to small,
// so e.g. a size 10 instead of 100 here wont fly.
var el = createElement('a', '100px', '100px');
var img = createElement('img', '300px', '500px');
a.style.display = 'block';
a.style.overflow = 'scroll';
el.style.display = 'block';
el.style.overflow = 'scroll';
a.appendChild(img);
parent.appendChild(a);
el.appendChild(img);
parent.appendChild(el);
document.body.appendChild(parent);
var res = childrenSize(parent);
expect(res).to.exist;
expect(res.width).to.equal(10, 'width');
expect(res.height).to.equal(10, 'height');
expect(res).to.be.ok();
expect(res.width).to.equal(100, 'width');
expect(res.height).to.equal(100, 'height');
});

@@ -163,16 +187,16 @@

var parent = createDiv('100%');
var a = createElement('a', '10px', '10px');
var img = createElement('img', '30px', '50px');
var el = createElement('a', '100px', '100px');
var img = createElement('img', '300px', '500px');
a.style.display = 'block';
a.style.overflow = 'auto';
el.style.display = 'block';
el.style.overflow = 'auto';
a.appendChild(img);
parent.appendChild(a);
el.appendChild(img);
parent.appendChild(el);
document.body.appendChild(parent);
var res = childrenSize(parent);
expect(res).to.exist;
expect(res.width).to.equal(10, 'width');
expect(res.height).to.equal(10, 'height');
expect(res).to.be.ok();
expect(res.width).to.equal(100, 'width');
expect(res.height).to.equal(100, 'height');
});

@@ -182,26 +206,18 @@

var parent = createDiv('100%');
var a = createElement('a', '10px', '10px');
var img = createElement('img', '30px', '50px');
var a = createElement('a', '100px', '100px');
var img = createElement('img', '300px', '500px');
a.style.display = 'block';
a.style.overflow = 'overlay';
try {
a.style.display = 'block';
a.style.overflow = 'overlay';
} catch(e) {
a.cssText = 'display:block;overflow:overlay;';
}
a.appendChild(img);
parent.appendChild(a);
document.body.appendChild(parent);
// overlay works the same way as auto
if (a.style.overflow !== 'overlay') {
a.style.display = 'block';
a.style.overflow = 'auto';
}
var res = childrenSize(parent);
expect(res).to.exist;
expect(res.width).to.equal(10, 'width');
expect(res.height).to.equal(10, 'height');
});
it('should take overflow-x:hidden into account when calculating nested children size', function () {
var parent = createDiv('100%');
var a = createElement('a', '10px', '10px');
var img = createElement('img', '30px', '50px');
a.style.display = 'block';
a.style.overflowX = 'hidden';
a.appendChild(img);

@@ -212,8 +228,10 @@ parent.appendChild(a);

var res = childrenSize(parent);
expect(res).to.exist;
expect(res.width).to.equal(10, 'width');
expect(res.height).to.equal(10, 'height');
expect(res).to.be.ok();
expect(res.width).to.equal(100, 'width');
expect(res.height).to.equal(100, 'height');
});
it('should take overflow-y:hidden into account when calculating nested children size', function () {
// overflow-y and overflow-x does not work as you might think:
// http://www.brunildo.org/test/Overflowxy2.html
it('should take overflow-:hidden into account when calculating nested children size', function () {
var parent = createDiv('100%');

@@ -231,5 +249,6 @@ var a = createElement('a', '10px', '10px');

var res = childrenSize(parent);
expect(res).to.exist;
expect(res).to.be.ok();
expect(res.height).to.equal(10, 'height');
expect(res.width).to.equal(10, 'width');
expect(res.height).to.equal(10, 'height');
});

@@ -263,3 +282,3 @@

var res = childrenSize(parent);
expect(res).to.exist;
expect(res).to.be.ok();
expect(res.width).to.equal(200, 'width');

@@ -272,2 +291,3 @@ expect(res.height).to.equal(400, 'height');

insertCss('#fixed-position { position: fixed; display: inline-block; }');
var parent = createDiv('100%');

@@ -277,10 +297,10 @@ parent.appendChild(createDiv('10px', '10px')).id = 'absolute-position';

parent.appendChild(createElement('span', '10px', '10px')).style.display = 'inline-block';
document.body.appendChild(parent);
var res = childrenSize(parent);
expect(res).to.exist;
expect(res).to.be.ok();
expect(res.width).to.equal(10, 'width');
expect(res.height).to.equal(10, 'height');
});
});
/* jshint expr: true */
var comClient = require('../lib/comClient.js');
var expect = require('expect.js');
describe('comClient', function () {
var id = 'pos_id', win = window.top, origin = 'http://www.someorigin.com';
var xde;
var id = 'pos_id';
var win = window.top;
var origin = 'http://www.someorigin.com';
beforeEach(function() {
xde = { sendTo : sinon.spy() };
comClient._setXde(xde);
this.xde = { sendTo : sinon.spy() };
comClient._setXde(this.xde);
});
it('should throw if comClient is called with wrong parameters', function () {
expect(comClient).to.throw();
expect(comClient).to.throwError();
expect(function () {
comClient(id, 'http://www.someOrigin.com', win);
}).to.throw();
}).to.throwError();
});

@@ -22,3 +24,3 @@

var com = comClient(id, win, origin);
expect(com).to.exist;
expect(com).to.be.ok();
});

@@ -30,3 +32,3 @@

com.rendered();
expect(xde.sendTo).to.have.been.calledOnce;
expect(this.xde.sendTo.calledOnce).to.be.ok();
});

@@ -37,4 +39,7 @@

com.rendered();
expect(xde.sendTo).to.have.been.calledWith(win, 'rendered', {id: id});
expect(xde.targetOrigin).to.equal(origin);
var args = this.xde.sendTo.getCall(0).args;
expect(args[0]).to.be(win);
expect(args[1]).to.be('rendered');
expect(args[2].id).to.be(id);
expect(this.xde.targetOrigin).to.equal(origin);
});

@@ -44,6 +49,15 @@

var com = comClient(id, win, origin);
com.rendered({width: 20, height: 10});
expect(xde.sendTo).to.have.been.calledWith(win, 'rendered', {id: id, width: 20, height: 10});
com.rendered({
width: 20,
height: 10
});
var args = this.xde.sendTo.getCall(0).args;
expect(args[0]).to.be(win);
expect(args[1]).to.be('rendered');
expect(args[2].id).to.be(id);
expect(args[2].width).to.be(20);
expect(args[2].height).to.be(10);
});
});
});
/* jshint evil: true, expr: true */
/* global gardr:false */
var gardrExt = require('../lib/index.js');
var extend = require('util-extend');
var pluginCore = require('gardr-core-plugin');
var defaultParams = {
id: 'pos-id',
name: 'posname',
minSize: 100,
timeout: 200,
url: 'http://gardr.github.io/foobar.js',
height: 225,
origin: 'http://github.com'
};
var expect = require('expect.js');
var proxyquire = require('proxyquireify')(require);
var eventlistener = require('eventlistener');
var bannerAppender = require('../lib/log/appender/banner.js');
var triggerOnLoad;
var comClientSpy;
var gardrExt = proxyquire('../lib/index.js', {
'./log/getAppender.js': proxyquire('../lib/log/getAppender.js', {
'./appender/banner.js': bannerAppender
}),
'./comClient.js': function com(a, b, c){
return comClientSpy(a, b, c);
},
eventlistener: {
add: function fake(ctx, name, fn){
if (name === 'load') {
triggerOnLoad = fn;
} else {
return eventlistener.add(ctx, name, fn);
}
}
}
});
function getDefaultParams() {
return {
logto: 'console',
id: 'pos-id',
name: 'posname',
minSize: 100,
timeout: 200,
url: 'http://gardr.github.io/foobar.js?'+(+new Date()),
height: 225,
origin: 'http://github.com'
};
}
var extOpts = {

@@ -20,76 +49,102 @@ allowedDomains: ['gardr.github.io', 'foobar.com']

function paramsStr (data) {
return JSON.stringify(extend(extend({}, defaultParams), data));
function createIframe() {
var iframe = document.createElement('iframe');
iframe.src = 'about:blank';
iframe.style.width = '100px';
iframe.style.height = '100px';
iframe.style.overflow = 'hidden';
document.body.appendChild(iframe);
return iframe;
}
function setUrlFragment (data) {
document.location.hash = '#'+encodeURIComponent(paramsStr(data));
}
function setName (data) {
window.name = paramsStr(data);
}
function triggerOnLoad () {
var clock = sinon.useFakeTimers();
var evt;
try {
evt = new UIEvent('load');
} catch (e) {
evt = document.createEvent('UIEvent');
evt.initUIEvent('load', false, true, null, null);
}
window.dispatchEvent(evt);
clock.tick(10);
clock.restore();
}
describe('Garðr ext - gardrExt', function () {
var orgWrite = document.write;
var comClient;
var com;
var injected = [];
beforeEach(function () {
this.iframe = createIframe();
this.document = this.iframe.contentDocument;
this.window = this.iframe.contentWindow;
this.document.open();
// head
this.document.write(['<scr', 'ipt>', 'window.gardr = window.parent.gardr;', '</scr', 'ipt>'].join(''));
// body
this.document.write('<body><div id="gardr" style="overflow:hidden;">');
// overwrrite iframe write
var _write = this.document.write;
this.document.write = sinon.spy(function (str){
_write.call(this.document, str);
}.bind(this));
// overwrite parent write and pass on to iframe write
document.write = sinon.spy(function (str) {
var tmp = document.createElement('span');
tmp.innerHTML = str;
injected.push(tmp.children[0]);
document.body.appendChild(tmp.children[0]);
this.document.write.call(this.document, str);
}.bind(this));
function paramsStr (data) {
return JSON.stringify(extend(extend({}, getDefaultParams()), data));
}
this.setUrlFragment = function (data) {
this.document.location.hash = '#' + encodeURIComponent(paramsStr(data));
}.bind(this);
this.setName = function (data) {
this.window.name = paramsStr(data);
};
this.com = undefined;
comClientSpy = this.comClientSpy = sinon.spy(function () {
this.com = {rendered: sinon.spy()};
return this.com;
}.bind(this));
this.restore = gardrExt._mock(this.document, this.window, function (fn){
return fn();
});
comClient = sinon.spy(function () {
com = {rendered: sinon.spy()};
return com;
});
gardrExt._setComClient(comClient);
setUrlFragment();
this.setUrlFragment();
});
afterEach(function () {
delete window.gardr;
this.iframe.contentDocument.close();
document.body.removeChild(this.iframe);
this.restore();
try {
delete window.gardr;
} catch(e){
window.gardr = null;
}
document.write = orgWrite;
window.name = null;
injected.forEach(function (el) {
el.parentElement && el.parentElement.removeChild(el);
});
document.location.hash = '#';
});
it('should throw an error if url is not on a valid domain', function () {
expect(gardrExt.bind(null, {allowedDomains: ['example.com']})).to.throw();
expect(function(){
gardrExt({allowedDomains: ['example.com']});
}).to.throwError(/domain/);
});
it('should throw an error if url is a data-uri', function () {
setUrlFragment({
this.setUrlFragment({
url: 'data:text/javascript;plain,void(0);'
});
expect(gardrExt).to.throw('protocol');
expect(function(){
gardrExt();
}).to.throwError(/protocol/);
});
it('should not throw an error if a relative url', function () {
setUrlFragment({
this.setUrlFragment({
url: '/foo/bar.js'
});
expect(gardrExt).not.to.throw();
expect(function(){
gardrExt().inject();
}).not.to.throwError();
});

@@ -99,3 +154,5 @@

['http://foobar.com', '//foobar.com', 'https://foobar.com', 'foobar.com/'].forEach(function (domain) {
expect(gardrExt.bind(null, {allowedDomains: [domain]})).to.throw('Invalid domain');
expect(function(){
gardrExt({allowedDomains: [domain]}).inject();
}).to.throwError(/Invalid domain/);
});

@@ -105,6 +162,8 @@ });

it('should not throw an error if url is on a valid domain', function () {
setUrlFragment({
this.setUrlFragment({
url: 'http://foobar.com/foo/bar'
});
expect(gardrExt.bind(null, extOpts)).not.to.throw();
expect(function(){
gardrExt(extOpts).inject();
}).not.to.throwError();
});

@@ -115,10 +174,11 @@

expect(window.gardr).to.exist;
expect(window.gardr).to.be.ok();
});
it('should read parameters from location.hash', function () {
setUrlFragment({url: 'http://gardr.github.io/ad|123'});
this.timeout(5000); // ie8
this.setUrlFragment({url: 'http://gardr.github.io/ad|123'});
gardrExt(extOpts);
expect(gardr.params).to.exist;
expect(gardr.params).to.be.ok();
expect(gardr.id).to.equal('pos-id');

@@ -131,7 +191,7 @@ expect(gardr.params.origin).to.equal('http://github.com');

it('should read parameters from window.name', function () {
document.location.hash = '';
setName({url: 'http://gardr.github.io/ad|123'});
this.document.location.hash = '';
this.setName({url: 'http://gardr.github.io/ad|123'});
gardrExt(extOpts);
expect(gardr.params).to.exist;
expect(gardr.params).to.be.ok();
expect(gardr.id).to.equal('pos-id');

@@ -144,17 +204,34 @@ expect(gardr.params.origin).to.equal('http://github.com');

it('should log to div by default', function () {
setUrlFragment({loglevel: 4});
gardrExt(extOpts);
gardr.log.debug('test');
var restore = bannerAppender._setTimeoutFn(function triggerTimeoutSync2(fn){
fn();
});
this.setUrlFragment({
loglevel: 5, logto: 'banner'
});
gardrExt(extOpts).inject();
var logDiv = document.getElementById('logoutput');
expect(logDiv).to.exist;
expect(logDiv).to.not.be(null);
expect(logDiv.children.length).to.equal(1);
gardr.log.debug('test-with-log-level-4');
expect(logDiv.children.length).to.equal(2);
restore();
});
it('should document.write out a gardr container to the document', function () {
gardrExt(extOpts);
document.write.should.have.been.calledWithMatch(/<div id="gardr"><scr.pt src=".*"\s*><\/scr.pt><\/div>/);
gardrExt(extOpts).inject();
var assertion = this.document.write.calledWithMatch(/^<scr.pt\s*id=".*"\s*src=".*"\s*><\/scr.pt>$/);
expect(assertion).to.be.ok();
});
it('should assign the gardr container to gardr.container', function () {
gardrExt(extOpts);
expect(gardr.container).to.exist;
gardrExt(extOpts).inject();
expect(gardr.container).to.be.ok();
expect(gardr.container.id).to.equal('gardr');

@@ -164,3 +241,3 @@ }),

it('should set overflow:hidden on the gardr container', function () {
gardrExt(extOpts);
gardrExt(extOpts).inject();
expect(gardr.container.style.overflow).to.equal('hidden');

@@ -171,38 +248,45 @@ });

var scriptUrl = 'http://gardr.github.io/script.js?q=1';
setUrlFragment({url: scriptUrl});
gardrExt(extOpts);
this.setUrlFragment({url: scriptUrl});
gardrExt(extOpts).inject();
document.write.should.have.been.calledWithMatch(function (value) {
var assertion = this.document.write.calledWithMatch(function (value) {
return value.indexOf('<script') >= 0 && value.indexOf(scriptUrl) >= 0;
});
expect(assertion).to.be.ok();
});
it('should trigger comClient.rendered when all resources are loaded', function () {
it('should trigger comClientSpy.rendered when all resources are loaded', function () {
gardrExt(extOpts);
expect(comClient).to.have.been.calledOnce;
expect(comClient).to.have.been.calledWith(gardr.id, window.parent, 'http://github.com');
expect(this.comClientSpy.calledOnce).to.be.ok();
expect(this.comClientSpy.calledWith(gardr.id, this.window.parent, 'http://github.com')).to.be.ok();
triggerOnLoad();
expect(com.rendered).to.have.been.calledOnce;
expect(this.com.rendered.calledOnce).to.be.ok();
});
it('should detect the size of the rendered banner', function () {
gardrExt(extOpts);
var el = document.getElementById('gardr');
var span = document.createElement('span');
gardrExt(extOpts).inject();
var el = this.document.getElementById('gardr');
var span = this.document.createElement('span');
span.innerHTML = '<span style="width:20px;height:10px;margin:0;padding:0;display:inline-block;">x</span>';
el.appendChild(span);
triggerOnLoad();
expect(com.rendered).to.have.been.calledWithMatch(function (obj) {
var assertion = this.com.rendered.calledWithMatch(function (obj) {
return typeof obj.width === 'number' && typeof obj.height === 'number';
});
expect(this.com.rendered.calledOnce).to.be.ok();
expect(assertion).to.be.ok();
});
describe('plugins', function () {
it('should allow to register plugins', function () {
expect(function () {
gardrExt.plugin(function () {});
}).not.to.throw();
}).not.to.throwError();
});

@@ -212,7 +296,10 @@

var spy = sinon.spy();
gardrExt.plugin(spy);
gardrExt(extOpts);
expect(spy).to.have.been.calledOnce;
expect(spy.lastCall.args[0]).to.be.an.instanceof(pluginCore.PluginApi);
expect(spy.calledOnce).to.be.ok();
expect(spy.lastCall.args[1]).to.have.keys( Object.keys(extOpts) );
// expect(spy.lastCall.args[0].id).to.be(0);
});

@@ -225,8 +312,9 @@

});
setUrlFragment({foo: 'bar'});
this.setUrlFragment({foo: 'bar'});
gardrExt(extOpts);
expect(spy).to.have.been.calledOnce;
expect(spy).to.have.been.calledWithMatch(function (data) {
expect(spy.calledOnce).to.be.ok();
expect(spy.calledWithMatch(function (data) {
return data.foo === 'bar';
});
})).to.be.ok();
});

@@ -239,8 +327,8 @@

});
setUrlFragment({foo: 'bar'});
gardrExt(extOpts);
expect(spy).to.have.been.calledOnce;
expect(spy).to.have.been.calledWithMatch(function (el) {
this.setUrlFragment({foo: 'bar'});
gardrExt(extOpts).inject();
expect(spy.calledOnce).to.be.ok();
expect(spy.calledWithMatch(function (el) {
return el.id === 'gardr';
});
})).to.be.ok();
});

@@ -253,10 +341,10 @@

});
gardrExt(extOpts);
gardrExt(extOpts).inject();
triggerOnLoad();
expect(spy).to.have.been.calledOnce;
expect(spy).to.have.been.calledWithMatch(function (data) {
expect(spy.calledOnce).to.be.ok();
expect(spy.calledWithMatch(function (data) {
return data.width === 0 && data.height === 0;
});
})).to.be.ok();
});
});
});

@@ -1,3 +0,4 @@

module.exports = function (type, extra) {
var event = document.createEvent('CustomEvent');
module.exports = function (type, extra, name) {
name = name || 'CustomEvent';
var event = document.createEvent(name);
event.initEvent(type, false, true);

@@ -8,2 +9,2 @@ for (var key in (extra || {})) {

return event;
};
};
/*jshint expr: true*/
var logToBanner = require('../../../lib/log/appender/banner.js');
describe('logToBanner', function () {
var logObj = {
msg: 'test log',
time: new Date().getTime(),
level: 4,
name: 'testName'
};
var clock;
var expect = require('expect.js');
beforeEach(function () {
clock = sinon.useFakeTimers();
});
describe('banner log appender', function() {
function getLogObj() {
var time = +new Date();
return {
logto: 'banner',
msg: 'test log ' + time,
time: time,
level: 4,
name: 'testName' + time
};
}
afterEach(function () {
logToBanner.reset();
clock.restore();
});
it('should render an overlay the first time it\'s called', function () {
logToBanner(logObj);
var output = document.getElementById('logoutput');
expect(output).to.exist;
});
beforeEach(function() {
this.restoreTimer = logToBanner._setTimeoutFn(function triggerTimeoutSync(fn){
return fn();
});
});
it('should output a div for each log message', function () {
logToBanner(logObj);
var output = document.getElementById('logoutput');
clock.tick(51);
expect(output.children.length).to.equal(1);
expect(output.children[0].textContent).to.have.string(logObj.msg);
});
afterEach(function(){
this.restoreTimer();
logToBanner.reset();
});
it('should include script url and line for script errors', function () {
var errObj = {
msg: 'Uncaught SyntaxError: Test',
time: new Date().getTime(),
level: 1,
url: 'http://gardrtest.com/scripterror.js',
line: 123,
stack: []
};
logToBanner(errObj);
var output = document.getElementById('logoutput');
clock.tick(51);
expect(output.children.length).to.equal(1);
expect(output.children[0].textContent).to.have.string(errObj.url + ':' + errObj.line);
});
});
it('should render an overlay the first time it\'s called', function() {
var logObj = getLogObj();
logToBanner(logObj);
var output = document.getElementById('logoutput');
expect(output).to.be.ok();
});
it('should output a div for each log message', function() {
logToBanner.reset();
var logObj = getLogObj();
logToBanner(logObj);
var output = document.getElementById('logoutput');
expect(output.children.length).to.equal(1);
expect(output.children[0].textContent||output.children[0].innerText).to.have.string(logObj.msg);
});
it('should include script url and line for script errors', function() {
logToBanner.reset();
var errObj = {
msg: 'Uncaught SyntaxError: Test',
time: new Date().getTime(),
level: 1,
url: 'http://gardrtest.com/scripterror.js',
line: 123,
stack: []
};
logToBanner(errObj);
var output = document.getElementById('logoutput');
expect(output.children.length).to.equal(1);
var textEntry = output.children[0].textContent||output.children[0].innerText;
expect(textEntry).to.have.string(errObj.url + ':' + errObj.line);
});
});

@@ -5,10 +5,12 @@ var consoleAppender = require('../../lib/log/appender/console.js');

describe('getAppender', function () {
it('should default to bannerAppender', function () {
expect(getAppender()).to.equal(bannerAppender);
});
var expect = require('expect.js');
it('should return consoleAppender for logTo \'console\'', function () {
expect(getAppender('console')).to.equal(consoleAppender);
});
});
describe('getAppender', function() {
it('should default to bannerAppender', function() {
expect(getAppender()).to.equal(bannerAppender);
});
it('should return consoleAppender for logTo \'console\'', function() {
expect(getAppender('console')).to.equal(consoleAppender);
});
});
/*jshint expr: true*/
var logger = require('../../lib/log/logger.js');
var ErrorEvent = window.ErrorEvent || require('../lib/ErrorEvent.js');
var errorEventShim = require('../lib/ErrorEvent.js');
var ErrorEvent = window.ErrorEvent || errorEventShim;
var expect = require('expect.js');

@@ -13,4 +15,17 @@ function undefine(obj, prop) {

var ifBrowserHasDispatchEventIt = (typeof window.dispatchEvent == 'function' ? it : it.skip);
var ifBrowserHasDispatchEventIt = (function(){
var foundError = false;
try {
undefine(window, 'onerror')();
document.createEvent('ErrorEvent');
} catch(e) {
foundError = true;
}
if (foundError) {
return it.skip;
}
return (typeof window.dispatchEvent == 'function' ? it : it.skip);
})();
describe('logger', function () {

@@ -43,3 +58,5 @@ it('should default logLevel to 0 if not undefined', function () {

var startTime = new Date().getTime();
log.debug('test');
expect(logData.length).to.equal(1);

@@ -57,2 +74,3 @@ expect(logData[0].msg).to.equal('test');

});
var errorData = {

@@ -63,4 +81,12 @@ message: 'Test error',

};
var restoreOnError = undefine(window, 'onerror');
var evt = new ErrorEvent('error', errorData);
var evt;
try {
evt = new ErrorEvent('error', errorData);
} catch(e) {
evt = errorEventShim('error', errorData, 'ErrorEvent');
}
window.dispatchEvent(evt);

@@ -72,9 +98,7 @@

var logObj = logData[0];
expect(logObj.msg).to.equal(errorData.message);
expect(logObj.level).to.equal(1);
expect(logObj.name).to.equal('error_test');
expect(logObj.time).not.to.be.undefined;
expect(logObj.url).to.equal(errorData.filename);
expect(logObj.line).to.equal(errorData.lineno);
expect(logObj.time).not.to.be(undefined);
});
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc