Skip to content
Snippets Groups Projects
Commit 6078d066 authored by Anton Guz's avatar Anton Guz
Browse files

Merge branch 'MAGETWO-32485' into MAGETWO-31191

parents ae883b8a 680a68fe
Branches
No related merge requests found
...@@ -6,12 +6,7 @@ ...@@ -6,12 +6,7 @@
var config = { var config = {
map: { map: {
'*': { '*': {
formKey: 'Magento_PageCache/js/form-key',
pageCache: 'Magento_PageCache/js/page-cache' pageCache: 'Magento_PageCache/js/page-cache'
} }
}, }
deps: [ };
'Magento_PageCache/js/form-key',
'Magento_PageCache/js/msg-box'
]
};
\ No newline at end of file
...@@ -7,15 +7,12 @@ ...@@ -7,15 +7,12 @@
<?php /** @var \Magento\PageCache\Block\Javascript $this */ ?> <?php /** @var \Magento\PageCache\Block\Javascript $this */ ?>
<script> <script>
require([ require([
"jquery", 'jquery',
"mage/mage" 'pageCache',
], function(jQuery){ 'domReady!'
], function($){
//<![CDATA[ 'use strict';
jQuery(function () {
jQuery('body').mage('pageCache', <?php echo $this->getScriptOptions(); ?>);
});
//]]>
$('body').pageCache(<?php echo $this->getScriptOptions(); ?>);
}); });
</script> </script>
...@@ -4,15 +4,109 @@ ...@@ -4,15 +4,109 @@
* Copyright © 2015 Magento. All rights reserved. * Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details. * See COPYING.txt for license details.
*/ */
/*jshint browser:true jquery:true expr:true*/
define([ define([
"jquery", 'jquery',
"jquery/ui", 'domReady',
"mage/cookies", 'jquery/ui',
"Magento_PageCache/js/comments" 'mage/cookies'
], function($){ ], function ($, domReady) {
"use strict"; 'use strict';
/**
* Nodes tree to flat list converter
* @returns {Array}
*/
$.fn.comments = function () {
var elements = [];
/**
* @param {jQuery} element - Comment holder
*/
(function lookup(element) {
$(element).contents().each(function (index, el) {
switch (el.nodeType) {
case 1: // ELEMENT_NODE
lookup(el);
break;
case 8: // COMMENT_NODE
elements.push(el);
break;
case 9: // DOCUMENT_NODE
var hostName = window.location.hostname,
iFrameHostName = $('<a>')
.prop('href', element.prop('src'))
.prop('hostname');
if (hostName === iFrameHostName) {
lookup($(el).find('body'));
}
break;
}
});
})(this);
return elements;
};
/**
* MsgBox Widget checks if message box is displayed and sets cookie
*/
$.widget('mage.msgBox', {
options: {
msgBoxCookieName: 'message_box_display',
msgBoxSelector: '.main div.messages'
},
/**
* Creates widget 'mage.msgBox'
* @private
*/
_create: function () {
if ($.mage.cookies.get(this.options.msgBoxCookieName)) {
$.mage.cookies.clear(this.options.msgBoxCookieName);
} else {
$(this.options.msgBoxSelector).hide();
}
}
});
/**
* FormKey Widget - this widget is generating from key, saves it to cookie and
*/
$.widget('mage.formKey', {
options: {
inputSelector: 'input[name="form_key"]',
allowedCharacters: '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
length: 16
},
/**
* Creates widget 'mage.formKey'
* @private
*/
_create: function () {
var date,
formKey = $.mage.cookies.get('form_key');
if (!formKey) {
formKey = generateRandomString(this.options.allowedCharacters, this.options.length);
date = new Date();
date.setTime(date.getTime() + (365 * 24 * 60 * 60 * 1000));
$.mage.cookies.set('form_key', formKey, {
expires: date,
path: '/'
});
}
$(this.options.inputSelector).val(formKey);
}
});
/**
* PageCache Widget
*/
$.widget('mage.pageCache', { $.widget('mage.pageCache', {
options: { options: {
url: '/', url: '/',
...@@ -21,26 +115,46 @@ define([ ...@@ -21,26 +115,46 @@ define([
versionCookieName: 'private_content_version', versionCookieName: 'private_content_version',
handles: [] handles: []
}, },
/**
* Creates widget 'mage.pageCache'
* @private
*/
_create: function () { _create: function () {
var version = $.mage.cookies.get(this.options.versionCookieName); var placeholders,
version = $.mage.cookies.get(this.options.versionCookieName);
if (!version) { if (!version) {
return ; return;
} }
var placeholders = this._searchPlaceholders(this.element.comments()); placeholders = this._searchPlaceholders(this.element.comments());
if (placeholders.length) {
if (placeholders && placeholders.length) {
this._ajax(placeholders, version); this._ajax(placeholders, version);
} }
}, },
/**
* Parse page for placeholders.
* @param {Array} elements
* @returns {Array}
* @private
*/
_searchPlaceholders: function (elements) { _searchPlaceholders: function (elements) {
var placeholders = [], var placeholders = [],
tmp = {}; tmp = {},
if (!elements.length) { ii,
len,
el, matches, name;
if (!(elements && elements.length)) {
return placeholders; return placeholders;
} }
for (var i = 0; i < elements.length; i++) {
var el = elements[i], for (ii = 0, len = elements.length; ii < len; ii++) {
matches = this.options.patternPlaceholderOpen.exec(el.nodeValue), el = elements[ii];
name = null; matches = this.options.patternPlaceholderOpen.exec(el.nodeValue);
name = null;
if (matches) { if (matches) {
name = matches[1]; name = matches[1];
...@@ -50,8 +164,10 @@ define([ ...@@ -50,8 +164,10 @@ define([
}; };
} else { } else {
matches = this.options.patternPlaceholderClose.exec(el.nodeValue); matches = this.options.patternPlaceholderClose.exec(el.nodeValue);
if (matches) { if (matches) {
name = matches[1]; name = matches[1];
if (tmp[name]) { if (tmp[name]) {
tmp[name].closeElement = el; tmp[name].closeElement = el;
placeholders.push(tmp[name]); placeholders.push(tmp[name]);
...@@ -60,44 +176,74 @@ define([ ...@@ -60,44 +176,74 @@ define([
} }
} }
} }
return placeholders; return placeholders;
}, },
_replacePlaceholder: function(placeholder, html) {
/**
* Parse for page and replace placeholders
* @param {Object} placeholder
* @param {Object} html
* @protected
*/
_replacePlaceholder: function (placeholder, html) {
if (!placeholder || !html) {
return;
}
var parent = $(placeholder.openElement).parent(), var parent = $(placeholder.openElement).parent(),
contents = parent.contents(), contents = parent.contents(),
startReplacing = false, startReplacing = false,
prevSibling = null; prevSibling = null,
for (var y = 0; y < contents.length; y++) { yy,
var element = contents[y]; len,
element;
for (yy = 0, len = contents.length; yy < len; yy++) {
element = contents[yy];
if (element == placeholder.openElement) { if (element == placeholder.openElement) {
startReplacing = true; startReplacing = true;
} }
if (startReplacing) { if (startReplacing) {
$(element).remove(); $(element).remove();
} else if (element.nodeType != 8) { } else if (element.nodeType != 8) {
//due to comment tag doesn't have siblings we try to find it manually //due to comment tag doesn't have siblings we try to find it manually
prevSibling = element; prevSibling = element;
} }
if (element == placeholder.closeElement) { if (element == placeholder.closeElement) {
break; break;
} }
} }
if (prevSibling) { if (prevSibling) {
$(prevSibling).after(html); $(prevSibling).after(html);
} else { } else {
$(parent).prepend(html); $(parent).prepend(html);
} }
// trigger event to use mage-data-init attribute // trigger event to use mage-data-init attribute
$(parent).trigger('contentUpdated'); $(parent).trigger('contentUpdated');
}, },
/**
* AJAX helper
* @param {Object} placeholders
* @param {String} version
* @private
*/
_ajax: function (placeholders, version) { _ajax: function (placeholders, version) {
var data = { var ii,
blocks: [], data = {
handles: this.options.handles, blocks: [],
version: version handles: this.options.handles,
}; version: version
for (var i = 0; i < placeholders.length; i++) { };
data.blocks.push(placeholders[i].name);
for (ii = 0; ii < placeholders.length; ii++) {
data.blocks.push(placeholders[ii].name);
} }
data.blocks = JSON.stringify(data.blocks.sort()); data.blocks = JSON.stringify(data.blocks.sort());
data.handles = JSON.stringify(data.handles); data.handles = JSON.stringify(data.handles);
...@@ -108,18 +254,54 @@ define([ ...@@ -108,18 +254,54 @@ define([
cache: true, cache: true,
dataType: 'json', dataType: 'json',
context: this, context: this,
/**
* Response handler
* @param {Object} response
*/
success: function (response) { success: function (response) {
for (var i = 0; i < placeholders.length; i++) { var placeholder, i;
var placeholder = placeholders[i];
if (!response.hasOwnProperty(placeholder.name)) { for (i = 0; i < placeholders.length; i++) {
continue; placeholder = placeholders[i];
if (response.hasOwnProperty(placeholder.name)) {
this._replacePlaceholder(placeholder, response[placeholder.name]);
} }
this._replacePlaceholder(placeholder, response[placeholder.name]);
} }
} }
}); });
} }
}); });
return $.mage.pageCache; domReady(function () {
$('body')
.pageCache()
.msgBox()
.formKey();
});
return {
'pageCache': $.mage.pageCache,
'formKey': $.mage.formKey,
'msgBox': $.mage.msgBox
};
/**
* Helper. Generate random string
* TODO: Merge with mage/utils
* @param {String} chars - list of symbols
* @param {Number} length - length for need string
* @returns {String}
*/
function generateRandomString(chars, length) {
var result = '';
length = length > 0 && Number.isFinite(length) ? length : 1;
while (length--) {
result += chars[Math.round(Math.random() * (chars.length - 1))];
}
return result;
}
}); });
/**
* Copyright © 2015 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
/*global describe*/
/*global beforeEach*/
/*global afterEach*/
/*global it*/
/*global expect*/
/*global jasmine*/
/*global spyOn*/
define([
'jquery',
'Magento_PageCache/js/page-cache'
], function ($) {
'use strict';
if (!Function.prototype.bind) {
/**
* @param {Object} bind
* @returns {Function}
*/
Function.prototype.bind = function (bind) {
var self = this;
/**
* @returns {Function}
*/
return function () {
var args = Array.prototype.slice.call(arguments);
return self.apply(bind || null, args);
};
};
}
describe('Testing html-comments-parser $.fn.comments behavior', function () {
var element,
iframe,
comment,
host;
beforeEach(function () {
element = $('<div />');
iframe = $('<iframe />');
comment = '<!--COMMENT CONTENT-->';
host = window.location.hostname;
$('body')
.append(element)
.append(iframe);
});
afterEach(function () {
$(element).remove();
$(iframe).remove();
});
it('comments fn exists', function () {
expect($.fn.comments).toBeDefined();
expect($.fn.comments()).toEqual([]);
});
it('on empty node comments() returns empty Array', function () {
expect($(element).comments()).toEqual([]);
expect($(iframe).insertAfter('body').comments()).toEqual([]);
});
it('on non-empty node comments() returns empty Array with nodes', function () {
element.html(comment);
expect($(element).comments().length).toEqual(1);
expect($(element).comments()[0].nodeType).toEqual(8);
expect($(element).comments()[0].nodeValue).toEqual('COMMENT CONTENT');
});
it('on iframe from same host returns Array with nodes', function () {
iframe.contents().find('body').html(comment);
iframe.attr('src', '//' + host + '/');
expect(iframe.comments().length).toEqual(1);
expect(iframe.comments()[0].nodeType).toEqual(8);
expect(iframe.comments()[0].nodeValue).toEqual('COMMENT CONTENT');
});
it('on iframe from other host returns empty Array', function () {
iframe.contents().find('body').html(comment);
iframe.attr('src', '//' + host + '.otherHost/');
expect(iframe.comments().length).toEqual(0);
});
});
describe('Testing msgBox Widget', function () {
var wdContainer,
msgCookieName,
msgContainer;
beforeEach(function () {
wdContainer = $('<div />');
msgContainer = $('<div />');
msgCookieName = 'FAKE_COOKIE';
});
afterEach(function () {
$(wdContainer).remove();
$(msgContainer).remove();
});
it('widget extends jQuery object', function () {
expect($.fn.msgBox).toBeDefined();
});
it('widget gets options', function () {
wdContainer.msgBox({
'msgBoxCookieName': msgCookieName
});
expect(wdContainer.msgBox('option', 'msgBoxCookieName')).toBe('FAKE_COOKIE');
});
it('widget disables cookie if it exist', function () {
spyOn($.mage.cookies, 'get').and.returnValue('FAKE_MAGE_COOKIE');
spyOn($.mage.cookies, 'clear');
wdContainer.msgBox({
'msgBoxSelector': msgContainer
});
expect($.mage.cookies.get).toHaveBeenCalled();
expect($.mage.cookies.clear).toHaveBeenCalled();
});
it('widget disables messageBox if cookie not exist', function () {
spyOn($.mage.cookies, 'get');
wdContainer.msgBox({
'msgBoxSelector': msgContainer
});
expect($.mage.cookies.get).toHaveBeenCalled();
expect(msgContainer.is(':hidden')).toBeTruthy();
});
it('widget exist on load on body', function (done) {
$(function () {
expect($('body').data('mageMsgBox')).toBeDefined();
done();
});
});
});
describe('Testing FormKey Widget', function () {
var wdContainer,
msgCookieName,
inputContainer;
beforeEach(function () {
wdContainer = $('<div />');
inputContainer = $('<input />');
msgCookieName = 'FAKE_COOKIE';
});
afterEach(function () {
$(wdContainer).remove();
$(inputContainer).remove();
});
it('widget extends jQuery object', function () {
expect($.fn.formKey).toBeDefined();
});
it('widget set value to input[form_key]', function () {
spyOn($.mage.cookies, 'get').and.returnValue('FAKE_COOKIE');
wdContainer.formKey({
'inputSelector': inputContainer
});
expect($.mage.cookies.get).toHaveBeenCalled();
expect(inputContainer.val()).toBe('FAKE_COOKIE');
});
it('widget set value to input[form_key]', function () {
spyOn($.mage.cookies, 'set');
spyOn($.mage.cookies, 'get');
wdContainer.formKey({
'inputSelector': inputContainer
});
expect($.mage.cookies.get).toHaveBeenCalled();
expect($.mage.cookies.set).toHaveBeenCalled();
expect(inputContainer.val()).toEqual(jasmine.any(String));
});
it('widget exist on load on body', function (done) {
$(function () {
expect($('body').data('mageFormKey')).toBeDefined();
done();
});
});
});
describe('Testing PageCache Widget', function () {
var wdContainer,
versionCookieName,
pageBlockContainer;
beforeEach(function () {
wdContainer = $('<div />');
pageBlockContainer = $('<div />');
versionCookieName = 'FAKE_COOKIE';
});
afterEach(function () {
$(wdContainer).remove();
$(pageBlockContainer).remove();
});
it('widget extends jQuery object', function () {
expect($.fn.pageCache).toBeDefined();
});
it('widget breaks if no private_content_version cookie', function () {
spyOn($.mage.cookies, 'get');
spyOn($.fn, 'comments');
wdContainer.pageCache();
expect($.mage.cookies.get).toHaveBeenCalled();
expect($.fn.comments).not.toHaveBeenCalled();
});
it('_searchPlaceholders called only when HTML_COMMENTS', function () {
var nodes;
spyOn($.mage.cookies, 'get').and.returnValue('FAKE_VERSION_COOKIE');
spyOn($.mage.pageCache.prototype, '_searchPlaceholders');
wdContainer
.html('<!-- BLOCK FAKE_BLOCK -->FAKE_TEXT<!-- /BLOCK FAKE_BLOCK -->')
.pageCache();
nodes = wdContainer.comments();
expect(nodes.length).toEqual(2);
expect($.mage.cookies.get).toHaveBeenCalled();
expect($.mage.pageCache.prototype._searchPlaceholders).toHaveBeenCalled();
expect($.mage.pageCache.prototype._searchPlaceholders).toHaveBeenCalledWith(nodes);
});
it('_searchPlaceholders return Array of blocks', function () {
var nodes,
searches;
spyOn($.mage.cookies, 'get').and.returnValue('FAKE_VERSION_COOKIE');
wdContainer
.html('<!-- BLOCK FAKE_BLOCK -->FAKE_TEXT<!-- /BLOCK FAKE_BLOCK -->')
.pageCache();
nodes = wdContainer.comments();
searches = wdContainer.data('pageCache')._searchPlaceholders(nodes);
expect(wdContainer.data('pageCache')._searchPlaceholders()).toEqual([]);
expect(searches[0]).toEqual(jasmine.objectContaining({
name: 'FAKE_BLOCK'
}));
expect(searches[0].openElement.nodeType).toBeDefined();
expect(searches[0].closeElement.nodeType).toBeDefined();
});
it('_searchPlaceholders called only when HTML_COMMENTS', function () {
var nodes;
spyOn($.mage.cookies, 'get').and.returnValue('FAKE_VERSION_COOKIE');
spyOn($.mage.pageCache.prototype, '_searchPlaceholders');
wdContainer
.html('<!-- BLOCK FAKE_BLOCK -->FAKE_TEXT<!-- /BLOCK FAKE_BLOCK -->')
.pageCache();
nodes = wdContainer.comments();
expect(nodes.length).toEqual(2);
expect($.mage.cookies.get).toHaveBeenCalled();
expect($.mage.pageCache.prototype._searchPlaceholders).toHaveBeenCalled();
expect($.mage.pageCache.prototype._searchPlaceholders).toHaveBeenCalledWith(nodes);
});
it('_replacePlaceholder append HTML after sibling node', function () {
var replacer,
searcher,
placeholders,
context;
context = {
options: {
patternPlaceholderOpen: /^ BLOCK (.+) $/,
patternPlaceholderClose: /^ \/BLOCK (.+) $/
}
};
replacer = $.mage.pageCache.prototype._replacePlaceholder.bind(context);
searcher = $.mage.pageCache.prototype._searchPlaceholders.bind(context);
wdContainer
.html('<span></span><!-- BLOCK FAKE_BLOCK -->FAKE_TEXT<!-- /BLOCK FAKE_BLOCK -->');
placeholders = searcher(wdContainer.comments());
replacer(placeholders[0], '<span>FAKE_HTML</span>');
expect(wdContainer.html()).toEqual('<span></span><span>FAKE_HTML</span>');
});
it('_replacePlaceholder prepend HTML if no sibling', function () {
var replacer,
searcher,
placeholders,
context;
context = {
options: {
patternPlaceholderOpen: /^ BLOCK (.+) $/,
patternPlaceholderClose: /^ \/BLOCK (.+) $/
}
};
replacer = $.mage.pageCache.prototype._replacePlaceholder.bind(context);
searcher = $.mage.pageCache.prototype._searchPlaceholders.bind(context);
wdContainer
.html('<!-- BLOCK FAKE_BLOCK -->FAKE_TEXT<!-- /BLOCK FAKE_BLOCK -->');
placeholders = searcher(wdContainer.comments());
replacer(placeholders[0], '<span>FAKE_HTML</span>');
expect(wdContainer.html()).toEqual('<span>FAKE_HTML</span>');
});
it('widget exist on load on body', function (done) {
$(function () {
expect($('body').data('magePageCache')).toBeDefined();
done();
});
});
});
});
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment