feat: VivesPOS landing on Winter CMS 1.2 — theme + plugin + Dockerfile
Some checks are pending
Module sub-split / Sub-split (push) Waiting to run

- Base: wintercms/winter branch 1.2 (full framework)
- Theme vivespos: Canvas 7 + Bootstrap 5 CDN, custom CSS
- Layout: deferred GTM/GA4 tracking, JSON-LD SoftwareApplication
- Partials: hero (offline-first), features, modes (offline/nube toggle),
  screenshots, pricing (3 planes), comparison, FAQ, CTA
- Plugin VivesPOS.Site with ContactForm
- Dockerfile: PHP 8.2 Apache, port 80, healthcheck
- Added winter/wn-pages, blog, sitemap, seo plugins
- Active theme set to vivespos
This commit is contained in:
2026-08-21 19:29:00 -06:00
commit 1f72193a64
3266 changed files with 531480 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
import FakeDom from '../../helpers/FakeDom';
jest.setTimeout(2000);
describe('Original AJAX Framework library', function () {
it('can get data from the current form and a series of parent forms', function (done) {
FakeDom
.new()
.addScript([
'modules/backend/assets/js/vendor/jquery.min.js',
'modules/system/assets/js/framework.js',
])
.render(
'<form name="grandParentForm" id="grandParentForm" data-request-data="formOne: \'valueOne\'>' +
'<input name="fieldOne" value="valueOne" type="text">' +
'<input name="fieldFive" value="valueFive" type="text">' +
'<input name="multiField[]" value="multiOne" type="text">' +
'</form>' +
'<form name="parentForm" id="parentForm" data-request-parent="#grandParentForm" data-request-data="formTwo: \'valueTwo\'">' +
'<input name="fieldOne" value="overrideOne" type="text">' +
'<input name="fieldTwo" value="valueTwo" type="text">' +
'<input name="multiField[]" value="multiTwo" type="text">' +
'</form>' +
'<form name="childForm" id="childForm" data-request-parent="#parentForm" data-request="onTest" data-request-data="formThree: \'valueThree\'">' +
'<input name="fieldOne" value="overrideTwo" type="text">' +
'<input name="fieldThree" value="valueThree" type="text">' +
'<input name="fieldFour" value="valueFour" type="text">' +
'<input name="multiField[]" value="multiThree" type="text">' +
'<input name="multiFieldTwo[]" value="multiOne" type="text">' +
'<input name="multiFieldTwo[]" value="multiTwo" type="text">' +
'</form>'
)
.then(
(dom) => {
const parentDataSpy = jest.spyOn(dom.window.jQuery.fn, 'getRequestParentData');
jest.spyOn(dom.window, 'alert').mockImplementation(() => {});
jest.spyOn(dom.window.jQuery, 'ajax').mockImplementation(() => {
expect(parentDataSpy.mock.results[0].value).toMatchObject({
'formOne': 'valueOne',
'fieldOne': 'overrideTwo',
'fieldFive': 'valueFive',
'formTwo': 'valueTwo',
'fieldTwo': 'valueTwo',
'fieldThree': 'valueThree',
'fieldFour': 'valueFour',
'multiField[]': 'multiThree',
'multiFieldTwo[]': ['multiOne', 'multiTwo'],
});
done();
return dom.window.jQuery.Deferred();
});
dom.window.jQuery('#childForm').trigger('submit');
}
);
});
});

View File

@@ -0,0 +1,149 @@
import FakeDom from '../../helpers/FakeDom';
jest.setTimeout(5000);
describe('Form Widget dependsOn', function () {
/**
* Build a FakeDom with jQuery, WinterCMS foundation, stubs, and the form widget.
* The FormWidgetStubs fixture provides minimal implementations of ocJSON,
* $.fn.render, $.fn.request (synchronous success), and $.fn.loadIndicator
*/
function buildDom(html) {
return FakeDom
.new()
.addScript([
'modules/backend/assets/js/vendor/jquery.min.js',
'modules/system/assets/ui/js/foundation.baseclass.js',
'modules/system/assets/ui/js/foundation.controlutils.js',
'modules/system/tests/js/fixtures/formWidget/FormWidgetStubs.js',
'modules/backend/widgets/form/assets/js/winter.form.js',
])
.render(html);
}
/**
* Build form HTML with fields and their dependsOn declarations.
*
* Collects all field names (both keys and referenced dependencies) and creates
* a div for each. Fields that have dependencies get data-field-depends attributes.
*
* @param {Object} fields - Map of field names to arrays of field names they depend on.
* e.g. { a: ['b'], b: ['a'] } for circular deps.
*/
function buildFormHtml(fields) {
// Collect all unique field names (both dependents and their dependencies)
var allFields = {};
for (var name in fields) {
allFields[name] = fields[name];
fields[name].forEach(function (dep) {
if (!(dep in allFields)) {
allFields[dep] = null;
}
});
}
var fieldHtml = '';
for (var fieldName in allFields) {
fieldHtml += '<div data-field-name="' + fieldName + '"';
if (allFields[fieldName] !== null) {
fieldHtml += " data-field-depends='" + JSON.stringify(allFields[fieldName]) + "'";
}
fieldHtml += '><input type="text" name="' + fieldName + '"></div>';
}
return '<form>'
+ '<div data-control="formwidget" data-refresh-handler="onRefreshField">'
+ fieldHtml
+ '</div>'
+ '</form>';
}
it('refreshes dependent fields when a field changes', function (done) {
buildDom(buildFormHtml({ fieldB: ['fieldA'] }))
.then(function (dom) {
var $ = dom.window.jQuery;
var requestSpy = jest.spyOn($.fn, 'request');
$('[data-field-name="fieldA"]').trigger('change');
// The form widget debounces with a 300ms timer
setTimeout(function () {
try {
expect(requestSpy).toHaveBeenCalledTimes(1);
expect(requestSpy).toHaveBeenCalledWith(
'onRefreshField',
expect.objectContaining({
data: expect.objectContaining({ fields: ['fieldB'] })
})
);
done();
} catch (e) {
done(e);
}
}, 500);
});
});
it('prevents infinite loop with circular dependsOn declarations', function (done) {
buildDom(buildFormHtml({ fieldA: ['fieldB'], fieldB: ['fieldA'] }))
.then(function (dom) {
var $ = dom.window.jQuery;
var requestSpy = jest.spyOn($.fn, 'request');
$('[data-field-name="fieldA"]').trigger('change');
// With 300ms debounce per step, an unguarded circular loop would fire
// many times in 2 seconds. The fix should limit this to exactly 2
// requests: A refreshes B, B refreshes A (blocked by cascade chain).
setTimeout(function () {
try {
expect(requestSpy.mock.calls.length).toBe(2);
done();
} catch (e) {
done(e);
}
}, 2000);
});
});
it('allows transitive cascading (A -> B -> C) without blocking', function (done) {
buildDom(buildFormHtml({ fieldB: ['fieldA'], fieldC: ['fieldB'] }))
.then(function (dom) {
var $ = dom.window.jQuery;
var requestSpy = jest.spyOn($.fn, 'request');
$('[data-field-name="fieldA"]').trigger('change');
// A->B (300ms) then B->C (600ms). Allow time for both.
setTimeout(function () {
try {
expect(requestSpy.mock.calls.length).toBe(2);
done();
} catch (e) {
done(e);
}
}, 1500);
});
});
it('stops cycle in a three-field circular chain (A -> B -> C -> A)', function (done) {
buildDom(buildFormHtml({ fieldA: ['fieldC'], fieldB: ['fieldA'], fieldC: ['fieldB'] }))
.then(function (dom) {
var $ = dom.window.jQuery;
var requestSpy = jest.spyOn($.fn, 'request');
$('[data-field-name="fieldA"]').trigger('change');
// A->B (300ms), B->C (600ms), C tries to refresh A but A is already
// in the cascade chain [fieldA, fieldB] so it stops. Total: 3 requests.
setTimeout(function () {
try {
expect(requestSpy.mock.calls.length).toBe(3);
done();
} catch (e) {
done(e);
}
}, 2000);
});
});
});

View File

@@ -0,0 +1,42 @@
import FakeDom from '../../../helpers/FakeDom';
jest.setTimeout(2000);
describe('Data Attribute Request AJAX library', function () {
it('can parse request data', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.request.js',
'modules/system/assets/js/snowboard/build/snowboard.data-attr.js',
])
.render()
.then(
(dom) => {
const DataAttributeSingleton = dom.window.Snowboard.attributeRequest();
expect(
DataAttributeSingleton.parseData('{foo: "bar"}')
).toEqual({ foo: 'bar' });
expect(
DataAttributeSingleton.parseData('foo: \'bar\'')
).toEqual({ foo: 'bar' });
expect(
DataAttributeSingleton.parseData('{"key": "value", "nested": { "otherKey": "otherValue" }}')
).toEqual({
"key": "value",
"nested": {
"otherKey": "otherValue"
}
});
done();
}
);
});
});

View File

@@ -0,0 +1,706 @@
import FakeDom from '../../../helpers/FakeDom';
import FetchMock from '../../../helpers/FetchMock';
jest.setTimeout(2000);
describe('Request AJAX library', function () {
it('can be setup via a global event', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.request.js'
])
.render()
.then(
(dom) => {
dom.window.Snowboard.getPlugin('request').mock('doAjax', (instance) => {
// Simulate success response
const resolved = Promise.resolve({
success: true
});
// Mock events
instance.snowboard.globalEvent('ajaxStart', instance, resolved);
if (instance.element) {
const event = new dom.window.Event('ajaxPromise');
event.promise = resolved;
instance.element.dispatchEvent(event);
}
return resolved;
});
// Listen to global event
dom.window.Snowboard.addPlugin('testListener', class TestListener extends dom.window.Snowboard.Singleton {
listens() {
return {
ajaxSetup: 'ajaxSetup',
};
}
ajaxSetup(instance) {
instance.handler = 'onChanged';
}
});
dom.window.Snowboard.request(undefined, 'onTest', {
complete: (data, instance) => {
expect(instance.handler).toEqual('onChanged');
done();
}
});
}
);
});
it('can be cancelled on setup via a global event', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.request.js'
])
.render()
.then(
(dom) => {
dom.window.Snowboard.getPlugin('request').mock('doAjax', (instance) => {
// Simulate success response
const resolved = Promise.resolve({
success: true
});
// Mock events
instance.snowboard.globalEvent('ajaxStart', instance, resolved);
if (instance.element) {
const event = new dom.window.Event('ajaxPromise');
event.promise = resolved;
instance.element.dispatchEvent(event);
}
return resolved;
});
// Listen to global event
dom.window.Snowboard.addPlugin('testListener', class TestListener extends dom.window.Snowboard.Singleton {
listens() {
return {
ajaxSetup: 'ajaxSetup',
};
}
ajaxSetup() {
// Should cancel
return false;
}
});
const instance = dom.window.Snowboard.request(undefined, 'onTest', {
complete: (data, instance) => {
done(new Error('Request did not cancel'));
}
});
expect(instance.cancelled).toEqual(true);
done();
}
);
});
it('can be setup via a listener on the HTML element', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.request.js'
])
.render('<button id="testElement">Test</button>')
.then(
(dom) => {
dom.window.Snowboard.getPlugin('request').mock('doAjax', (instance) => {
// Simulate success response
const resolved = Promise.resolve({
success: true
});
// Mock events
instance.snowboard.globalEvent('ajaxStart', instance, resolved);
if (instance.element) {
const event = new dom.window.Event('ajaxPromise');
event.promise = resolved;
instance.element.dispatchEvent(event);
}
return resolved;
});
// Listen to HTML element event
const element = dom.window.document.getElementById('testElement');
element.addEventListener('ajaxSetup', (event) => {
expect(event.request).toBeDefined();
event.request.handler = 'onChanged';
});
dom.window.Snowboard.request(element, 'onTest', {
complete: (data, instance) => {
expect(instance.handler).toEqual('onChanged');
done();
}
});
}
);
});
it('can be cancelled on setup via a listener on the HTML element', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.request.js'
])
.render('<button id="testElement">Test</button>')
.then(
(dom) => {
dom.window.Snowboard.getPlugin('request').mock('doAjax', (instance) => {
// Simulate success response
const resolved = Promise.resolve({
success: true
});
// Mock events
instance.snowboard.globalEvent('ajaxStart', instance, resolved);
if (instance.element) {
const event = new dom.window.Event('ajaxPromise');
event.promise = resolved;
instance.element.dispatchEvent(event);
}
return resolved;
});
// Listen to HTML element event
const element = dom.window.document.getElementById('testElement');
element.addEventListener('ajaxSetup', (event) => {
event.preventDefault();
});
const instance = dom.window.Snowboard.request(element, 'onTest', {
complete: (data, instance) => {
done(new Error('Request did not cancel'));
}
});
expect(instance.cancelled).toEqual(true);
done();
}
);
});
it('can do a request and listen for completion', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.request.js'
])
.render()
.then(
(dom) => {
dom.window.Snowboard.getPlugin('request').mock('doAjax', (instance) => {
// Simulate success response
const resolved = Promise.resolve({
success: true
});
// Mock events
instance.snowboard.globalEvent('ajaxStart', instance, resolved);
if (instance.element) {
const event = new Event('ajaxPromise');
event.promise = resolved;
instance.element.dispatchEvent(event);
}
return resolved;
});
dom.window.Snowboard.request(undefined, 'onTest', {
complete: (data, instance) => {
expect(data).toEqual({
success: true,
});
expect(instance.responseData).toEqual({
success: true,
});
expect(instance.responseError).toEqual(null);
done();
return false;
}
});
}
);
});
it('can do a request and listen for completion via a global event', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.request.js'
])
.render()
.then(
(dom) => {
dom.window.Snowboard.getPlugin('request').mock('doAjax', (instance) => {
// Simulate success response
const resolved = Promise.resolve({
success: true
});
// Mock events
instance.snowboard.globalEvent('ajaxStart', instance, resolved);
if (instance.element) {
const event = new Event('ajaxPromise');
event.promise = resolved;
instance.element.dispatchEvent(event);
}
return resolved;
});
// Listen to global event
dom.window.Snowboard.addPlugin('testListener', class TestListener extends dom.window.Snowboard.Singleton {
listens() {
return {
ajaxDone: 'ajaxDone',
};
}
ajaxDone(data, instance) {
expect(data).toEqual({
success: true,
});
expect(instance.responseData).toEqual({
success: true,
});
expect(instance.responseError).toEqual(null);
done();
}
});
dom.window.Snowboard.request(undefined, 'onTest');
}
);
});
it('can do a request and listen for completion via a listener on the HTML element', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.request.js'
])
.render('<button id="testElement">Test</button>')
.then(
(dom) => {
dom.window.Snowboard.getPlugin('request').mock('doAjax', (instance) => {
// Simulate success response
const resolved = Promise.resolve({
success: true
});
// Mock events
instance.snowboard.globalEvent('ajaxStart', instance, resolved);
if (instance.element) {
const event = new dom.window.Event('ajaxPromise');
event.promise = resolved;
instance.element.dispatchEvent(event);
}
return resolved;
});
// Listen to HTML element event
const element = dom.window.document.getElementById('testElement');
element.addEventListener('ajaxAlways', (event) => {
expect(event.request).toBeDefined();
expect(event.responseData).toEqual({
success: true
});
expect(event.responseError).toEqual(null);
done();
});
dom.window.Snowboard.request(element, 'onTest');
}
);
});
it('can do a request and listen for success', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.request.js'
])
.render()
.then(
(dom) => {
dom.window.Snowboard.getPlugin('request').mock('doAjax', (instance) => {
// Simulate success response
const resolved = Promise.resolve({
success: true
});
// Mock events
instance.snowboard.globalEvent('ajaxStart', instance, resolved);
if (instance.element) {
const event = new Event('ajaxPromise');
event.promise = resolved;
instance.element.dispatchEvent(event);
}
return resolved;
});
dom.window.Snowboard.request(undefined, 'onTest', {
success: (data, instance) => {
expect(data).toEqual({
success: true,
});
expect(instance.responseData).toEqual({
success: true,
});
expect(instance.responseError).toEqual(null);
},
complete: (data, instance) => {
expect(data).toEqual({
success: true,
});
expect(instance.responseData).toEqual({
success: true,
});
expect(instance.responseError).toEqual(null);
done();
},
});
}
);
});
it('can do a request and listen for success via a global event', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.request.js'
])
.render()
.then(
(dom) => {
dom.window.Snowboard.getPlugin('request').mock('doAjax', (instance) => {
// Simulate success response
const resolved = Promise.resolve({
success: true
});
// Mock events
instance.snowboard.globalEvent('ajaxStart', instance, resolved);
if (instance.element) {
const event = new Event('ajaxPromise');
event.promise = resolved;
instance.element.dispatchEvent(event);
}
return resolved;
});
// Listen to global event
dom.window.Snowboard.addPlugin('testListener', class TestListener extends dom.window.Snowboard.Singleton {
listens() {
return {
ajaxSuccess: 'ajaxSuccess',
};
}
ajaxSuccess(data, instance) {
expect(data).toEqual({
success: true,
})
expect(instance.responseData).toEqual({
success: true,
});
expect(instance.responseError).toEqual(null);
done();
}
});
dom.window.Snowboard.request(undefined, 'onTest');
}
);
});
it('can do a request and listen for failure', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.request.js'
])
.render()
.then(
(dom) => {
dom.window.Snowboard.getPlugin('request').mock('doAjax', (instance) => {
// Simulate error response
const resolved = Promise.reject('This is an error');
// Mock events
instance.snowboard.globalEvent('ajaxStart', instance, resolved);
if (instance.element) {
const event = new Event('ajaxPromise');
event.promise = resolved;
instance.element.dispatchEvent(event);
}
return resolved;
});
dom.window.Snowboard.request(undefined, 'onTest', {
error: (data, instance) => {
expect(data).toEqual('This is an error');
expect(instance.responseData).toEqual(null);
expect(instance.responseError).toEqual('This is an error');
},
complete: (data, instance) => {
// Data will be null because no data was provided in the response.
expect(data).toBeNull();
expect(instance.responseData).toEqual(null);
expect(instance.responseError).toEqual('This is an error');
done();
},
});
}
);
});
it('can do a request and listen for failure via global event', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.request.js'
])
.render()
.then(
(dom) => {
dom.window.Snowboard.getPlugin('request').mock('doAjax', (instance) => {
// Simulate error response
const resolved = Promise.reject('This is an error');
// Mock events
instance.snowboard.globalEvent('ajaxStart', instance, resolved);
if (instance.element) {
const event = new Event('ajaxPromise');
event.promise = resolved;
instance.element.dispatchEvent(event);
}
return resolved;
});
// Listen to global event
dom.window.Snowboard.addPlugin('testListener', class TestListener extends dom.window.Snowboard.Singleton {
listens() {
return {
ajaxError: 'ajaxError',
};
}
ajaxError(data, instance) {
expect(data).toEqual('This is an error')
expect(instance.responseData).toEqual(null);
expect(instance.responseError).toEqual('This is an error');
done();
}
});
dom.window.Snowboard.request(undefined, 'onTest');
}
);
});
it('requires a valid HTML element if provided', function () {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.request.js'
])
.render()
.then(
(dom) => {
expect(() => {
const docFragment = dom.window.document.createDocumentFragment();
dom.window.Snowboard.request(docFragment, 'onTest');
}).toThrow('The element provided must be an Element instance');
}
);
});
it('requires a handler to be specified', function () {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.request.js'
])
.render()
.then(
(dom) => {
expect(() => {
dom.window.Snowboard.request(undefined, undefined);
}).toThrow('The AJAX handler name is not specified');
}
);
});
it('requires a handler to be of the correct format', function () {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.request.js'
])
.render()
.then(
(dom) => {
expect(() => {
dom.window.Snowboard.request(undefined, 'notRight');
}).toThrow('Invalid AJAX handler name');
}
);
});
it('can be run detached from an element with two parameters (handler and options)', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.request.js'
])
.render()
.then(
(dom) => {
dom.window.Snowboard.getPlugin('request').mock('doAjax', (instance) => {
// Simulate success response
const resolved = Promise.resolve({
success: true
});
// Mock events
instance.snowboard.globalEvent('ajaxStart', instance, resolved);
if (instance.element) {
const event = new Event('ajaxPromise');
event.promise = resolved;
instance.element.dispatchEvent(event);
}
return resolved;
});
dom.window.Snowboard.request('onTest', {
complete: (data, instance) => {
done();
return false;
}
});
}
);
});
it('can correctly receive a mocked 404 JSON response', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.request.js'
])
.render()
.then(
(dom) => {
dom.window.fetch = FetchMock(
dom,
404,
'{"title":"404 Popup","markup":"<div>\\n <div class=\\"w-full bg-black\\">\\n <h2 class=\\"p-6 text-white text-2xl\\">Content not found<\\/h2>\\n<\\/div> <div class=\\"container p-6 mx-auto\\">\\n The requested popup could not be found, please try again.\\n<\\/div><\\/div>\\n"}',
{
'Content-Type': 'application/json'
}
);
dom.window.Snowboard.request('onTest', {
error: (error, instance) => {
expect(error).toEqual({
title: '404 Popup',
markup: '<div>\n <div class="w-full bg-black">\n <h2 class="p-6 text-white text-2xl">Content not found</h2>\n</div> <div class="container p-6 mx-auto">\n The requested popup could not be found, please try again.\n</div></div>\n'
})
expect(instance).toBeDefined();
expect(instance.responseData).toEqual(null);
expect(instance.responseError).toEqual({
title: '404 Popup',
markup: '<div>\n <div class="w-full bg-black">\n <h2 class="p-6 text-white text-2xl">Content not found</h2>\n</div> <div class="container p-6 mx-auto">\n The requested popup could not be found, please try again.\n</div></div>\n'
});
done();
}
});
}
);
});
});

View File

@@ -0,0 +1,316 @@
import FakeDom from '../../../helpers/FakeDom';
jest.setTimeout(2000);
describe('The Data Config extra functionality', function () {
it('can read the config from an element\'s data attributes', function (done) {
FakeDom
.new()
.addCss([
'modules/system/assets/css/snowboard.extras.css',
])
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.extras.js',
'modules/system/tests/js/fixtures/dataConfig/DataConfigFixture.js',
])
.render(
`<div
id="testElement"
data-id="389"
data-string-value="Hi there"
data-boolean="true"
></div>
<div
id="testElementTwo"
data-string-value="Hi there again"
data-name="Ben"
data-boolean="false"
data-extra-attr="This should not be available"
data-base64="base64:SSdtIGEgQmFzZTY0LWRlY29kZWQgc3RyaW5n"
></div>`
)
.then(
(dom) => {
const instance = dom.window.Snowboard.dataConfigFixture(
dom.window.document.querySelector('#testElement')
);
try {
expect(instance.config.get('id')).toEqual(389);
// Name should be null as it's the default value and not specified above
expect(instance.config.get('name')).toBeNull();
expect(instance.config.get('stringValue')).toBe('Hi there');
// Missing should be undefined as it's neither defined nor part of the default data
expect(instance.config.get('missing')).toBeUndefined();
expect(instance.config.get('boolean')).toBe(true);
expect(instance.config.get()).toMatchObject({
id: 389,
name: null,
stringValue: 'Hi there',
boolean: true,
base64: null,
});
} catch (error) {
done(error);
return;
}
const instanceTwo = dom.window.Snowboard.dataConfigFixture(
dom.window.document.querySelector('#testElementTwo')
);
try {
// ID is null as it's the default value and not specified above
expect(instanceTwo.config.get('id')).toBeNull();
expect(instanceTwo.config.get('name')).toBe('Ben');
expect(instanceTwo.config.get('stringValue')).toBe('Hi there again');
expect(instanceTwo.config.get('missing')).toBeUndefined();
expect(instanceTwo.config.get('boolean')).toBe(false);
// Extra attr is specified above, but it should not be available as a config value
// because it's not part of the `defaults()` in the fixture
expect(instanceTwo.config.get('extraAttr')).toBeUndefined();
// Base-64 decoded string
expect(instanceTwo.config.get('base64')).toBe('I\'m a Base64-decoded string');
done();
} catch (error) {
done(error);
}
}
);
});
it('can read the config from every data attribute of an element with "acceptAllDataConfigs" enabled', function (done) {
FakeDom
.new()
.addCss([
'modules/system/assets/css/snowboard.extras.css',
])
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.extras.js',
'modules/system/tests/js/fixtures/dataConfig/DataConfigFixture.js',
])
.render(
`<div
id="testElementTwo"
data-string-value="Hi there again"
data-name="Ben"
data-boolean="false"
data-extra-attr="This should now be available"
data-json="{ &quot;name&quot;: &quot;Ben&quot; }"
data-another-base64="base64:dHJ1ZQ=="
data-json-base64="base64:eyAiaWQiOiAxLCAidGl0bGUiOiAiU29tZSB0aXRsZSIgfQ=="
></div>`
)
.then(
(dom) => {
const instance = dom.window.Snowboard.dataConfigFixture(
dom.window.document.querySelector('#testElementTwo')
);
instance.acceptAllDataConfigs = true;
instance.config.refresh();
try {
// ID is null as it's the default value and not specified above
expect(instance.config.get('id')).toBeNull();
expect(instance.config.get('name')).toBe('Ben');
expect(instance.config.get('stringValue')).toBe('Hi there again');
expect(instance.config.get('missing')).toBeUndefined();
expect(instance.config.get('boolean')).toBe(false);
// These attributes below are specified above, and although they're not part of the
// defaults, they should be available because "acceptAllDataConfigs" is true
expect(instance.config.get('extraAttr')).toBe('This should now be available');
expect(instance.config.get('json')).toMatchObject({
name: 'Ben'
});
expect(instance.config.get('anotherBase64')).toBe(true);
expect(instance.config.get('jsonBase64')).toMatchObject({
id: 1,
title: 'Some title',
});
expect(instance.config.get()).toMatchObject({
id: null,
name: 'Ben',
stringValue: 'Hi there again',
boolean: false,
extraAttr: 'This should now be available',
json: {
name: 'Ben',
},
anotherBase64: true,
jsonBase64: {
id: 1,
title: 'Some title',
},
});
done();
} catch (error) {
done(error);
}
}
);
});
it('can refresh the config from the data attributes on the fly', function (done) {
FakeDom
.new()
.addCss([
'modules/system/assets/css/snowboard.extras.css',
])
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.extras.js',
'modules/system/tests/js/fixtures/dataConfig/DataConfigFixture.js',
])
.render(
`<div
id="testElement"
data-string-value="Hi there again"
data-name="Ben"
data-boolean="no"
></div>`
)
.then(
(dom) => {
const instance = dom.window.Snowboard.dataConfigFixture(
dom.window.document.querySelector('#testElement')
);
try {
expect(instance.config.get('id')).toBeNull();
expect(instance.config.get('name')).toBe('Ben');
expect(instance.config.get('stringValue')).toBe('Hi there again');
expect(instance.config.get('boolean')).toBe(false);
expect(instance.config.get()).toMatchObject({
id: null,
name: 'Ben',
stringValue: 'Hi there again',
boolean: false,
});
dom.window.document.querySelector('#testElement').setAttribute('data-id', '456');
dom.window.document.querySelector('#testElement').setAttribute('data-string-value', 'Changed');
dom.window.document.querySelector('#testElement').removeAttribute('data-boolean');
// Refresh config
instance.config.refresh();
expect(instance.config.get('id')).toBe(456);
expect(instance.config.get('name')).toBe('Ben');
expect(instance.config.get('stringValue')).toBe('Changed');
expect(instance.config.get('boolean')).toBeNull();
expect(instance.config.get()).toMatchObject({
id: 456,
name: 'Ben',
stringValue: 'Changed',
boolean: null,
});
done();
} catch (error) {
done(error);
}
}
);
});
it('can set config values at runtime', function (done) {
FakeDom
.new()
.addCss([
'modules/system/assets/css/snowboard.extras.css',
])
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.extras.js',
'modules/system/tests/js/fixtures/dataConfig/DataConfigFixture.js',
])
.render(
`<div
id="testElement"
data-string-value="Hi there again"
data-name="Ben"
data-boolean="false"
></div>`
)
.then(
(dom) => {
const instance = dom.window.Snowboard.dataConfigFixture(
dom.window.document.querySelector('#testElement')
);
try {
expect(instance.config.get('name')).toBe('Ben');
// Set config
instance.config.set('name', 'Luke');
expect(instance.config.get('name')).toBe('Luke');
// Refresh config
instance.config.refresh();
expect(instance.config.get('name')).toBe('Ben');
done();
} catch (error) {
done(error);
}
}
);
});
it('can set config values at runtime that persist through a reset', function (done) {
FakeDom
.new()
.addCss([
'modules/system/assets/css/snowboard.extras.css',
])
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/assets/js/snowboard/build/snowboard.extras.js',
'modules/system/tests/js/fixtures/dataConfig/DataConfigFixture.js',
])
.render(
`<div
id="testElement"
data-string-value="Hi there again"
data-name="Ben"
data-boolean="no"
></div>`
)
.then(
(dom) => {
const instance = dom.window.Snowboard.dataConfigFixture(
dom.window.document.querySelector('#testElement')
);
try {
expect(instance.config.get('name')).toBe('Ben');
// Set config
instance.config.set('name', 'Luke', true);
expect(instance.config.get('name')).toBe('Luke');
// Refresh config
instance.config.refresh();
expect(instance.config.get('name')).toBe('Luke');
done();
} catch (error) {
done(error);
}
}
);
});
});

View File

@@ -0,0 +1,134 @@
import FakeDom from '../../../helpers/FakeDom';
describe('PluginLoader class', function () {
it('can mock plugin methods', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js'
])
.render()
.then(
(dom) => {
dom.window.Snowboard.getPlugin('sanitizer').mock('sanitize', () => {
return 'all good';
});
expect(
dom.window.Snowboard.sanitizer().sanitize('<p onload="derp;"></p>')
).toEqual('all good');
// Test unmock
dom.window.Snowboard.getPlugin('sanitizer').unmock('sanitize');
expect(
dom.window.Snowboard.sanitizer().sanitize('<p onload="derp;"></p>')
).toEqual('<p></p>');
done();
},
(error) => {
done(error);
}
);
});
it('is frozen on construction and doesn\'t allow prototype pollution', function () {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
])
.render()
.then(
(dom) => {
const loader = dom.window.Snowboard.getPlugin('sanitizer');
expect(() => {
loader.newMethod = () => {
return true;
};
}).toThrow(TypeError);
expect(() => {
loader.newProperty = 'test';
}).toThrow(TypeError);
expect(() => {
loader.singleton.test = 'test';
}).toThrow(TypeError);
expect(loader.newMethod).toBeUndefined();
expect(loader.newProperty).toBeUndefined();
},
(error) => {
throw error;
}
);
});
it('should prevent modification of root instances', function () {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/tests/js/fixtures/framework/TestPlugin.js',
'modules/system/tests/js/fixtures/framework/TestSingleton.js',
])
.render()
.then(
(dom) => {
const rootInstance = dom.window.Snowboard.getPlugin('testPlugin').instance;
expect(() => {
rootInstance.newMethod = () => {
return true;
}
}).toThrow(TypeError);
expect(rootInstance.newMethod).toBeUndefined();
// Modifications can however be made to instances retrieved from the loader
const loadedInstance = dom.window.Snowboard.getPlugin('testPlugin').getInstance();
loadedInstance.newMethod = () => {
return true;
};
expect(loadedInstance.newMethod).toEqual(expect.any(Function));
expect(loadedInstance.newMethod()).toBe(true);
// But shouldn't follow through to new instances
const loadedInstanceTwo = dom.window.Snowboard.getPlugin('testPlugin').getInstance();
expect(loadedInstanceTwo.newMethod).toBeUndefined();
// The same rules apply for singletons, except that modifications will follow through to other uses
// of the singleton, since it's only one global instance.
const rootSingleton = dom.window.Snowboard.getPlugin('testSingleton').instance;
expect(() => {
rootSingleton.newMethod = () => {
return true;
}
}).toThrow(TypeError);
const loadedSingleton = dom.window.Snowboard.getPlugin('testSingleton').getInstance();
loadedSingleton.newMethod = () => {
return true;
};
expect(loadedSingleton.newMethod).toEqual(expect.any(Function));
expect(loadedSingleton.newMethod()).toBe(true);
const loadedSingletonTwo = dom.window.Snowboard.getPlugin('testSingleton').getInstance();
expect(loadedSingletonTwo.newMethod).toEqual(expect.any(Function));
expect(loadedSingletonTwo.newMethod()).toBe(true);
}
);
});
});

View File

@@ -0,0 +1,620 @@
import FakeDom from '../../../helpers/FakeDom';
describe('Snowboard framework', function () {
it('initialises correctly', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
])
.render()
.then(
(dom) => {
// Run assertions
try {
expect(dom.window.Snowboard).toBeDefined();
expect(dom.window.Snowboard.addPlugin).toBeDefined();
expect(dom.window.Snowboard.addPlugin).toEqual(expect.any(Function));
// Check PluginBase and Singleton abstracts exist
expect(dom.window.Snowboard.PluginBase).toBeDefined();
expect(dom.window.Snowboard.Singleton).toBeDefined();
// Check in-built plugins
expect(dom.window.Snowboard.getPluginNames()).toEqual(
expect.arrayContaining(['jsonparser', 'sanitizer'])
);
expect(dom.window.Snowboard.getPlugin('jsonparser').isFunction()).toEqual(false);
expect(dom.window.Snowboard.getPlugin('jsonparser').isSingleton()).toEqual(true);
expect(dom.window.Snowboard.getPlugin('sanitizer').isFunction()).toEqual(false);
expect(dom.window.Snowboard.getPlugin('sanitizer').isSingleton()).toEqual(true);
done();
} catch (error) {
done(error);
}
},
(error) => {
throw error;
}
);
});
it('is frozen on construction and doesn\'t allow prototype pollution', function () {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/tests/js/fixtures/framework/TestPlugin.js',
])
.render()
.then(
(dom) => {
expect(() => {
dom.window.Snowboard.newMethod = () => {
return true;
};
}).toThrow(TypeError);
expect(() => {
dom.window.Snowboard.newProperty = 'test';
}).toThrow(TypeError);
expect(() => {
dom.window.Snowboard.readiness.test = 'test';
}).toThrow(TypeError);
expect(dom.window.Snowboard.newMethod).toBeUndefined();
expect(dom.window.Snowboard.newProperty).toBeUndefined();
// You should not be able to modify the Snowboard object fed to plugins either
const instance = dom.window.Snowboard.testPlugin();
expect(() => {
instance.snowboard.newMethod = () => {
return true;
};
}).toThrow(TypeError);
},
(error) => {
throw error;
}
);
});
it('can add and remove a plugin', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/tests/js/fixtures/framework/TestPlugin.js',
])
.render()
.then(
(dom) => {
// Run assertions
const Snowboard = dom.window.Snowboard;
try {
// Check plugin caller
expect('testPlugin' in Snowboard).toEqual(true);
expect('testSingleton' in Snowboard).toEqual(false);
expect(Snowboard.hasPlugin('testPlugin')).toBe(true);
expect(Snowboard.getPluginNames()).toEqual(
expect.arrayContaining(['jsonparser', 'sanitizer', 'testplugin'])
);
const instance = Snowboard.testPlugin();
// Check plugin injected methods
expect(instance.snowboard).toBeDefined();
expect(instance.snowboard.getPlugin).toEqual(expect.any(Function));
expect(() => {
const method = instance.snowboard.initialise;
}).toThrow('cannot use');
expect(instance.destructor).toEqual(expect.any(Function));
// Check plugin method
expect(instance.testMethod).toBeDefined();
expect(instance.testMethod).toEqual(expect.any(Function));
expect(instance.testMethod()).toEqual('Tested');
// Check multiple instances
const instanceOne = Snowboard.testPlugin();
instanceOne.changed = true;
const instanceTwo = Snowboard.testPlugin();
expect(instanceOne).not.toEqual(instanceTwo);
const factory = Snowboard.getPlugin('testPlugin');
expect(factory.getInstances()).toEqual([instance, instanceOne, instanceTwo]);
// Remove plugin
Snowboard.removePlugin('testPlugin');
expect(Snowboard.hasPlugin('testPlugin')).toEqual(false);
expect(dom.window.Snowboard.getPluginNames()).toEqual(
expect.arrayContaining(['jsonparser', 'sanitizer'])
);
expect(Snowboard.testPlugin).not.toBeDefined();
done();
} catch (error) {
done(error);
}
},
(error) => {
throw error;
}
);
});
it('can add and remove a singleton', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/tests/js/fixtures/framework/TestSingleton.js',
])
.render()
.then(
(dom) => {
// Run assertions
const Snowboard = dom.window.Snowboard;
try {
expect('testPlugin' in Snowboard).toEqual(false);
expect('testSingleton' in Snowboard).toEqual(true);
// Check plugin caller
expect(Snowboard.hasPlugin('testSingleton')).toBe(true);
expect(Snowboard.getPluginNames()).toEqual(
expect.arrayContaining(['jsonparser', 'sanitizer', 'testsingleton'])
);
expect(Snowboard.testSingleton).toEqual(expect.any(Function));
const instance = Snowboard.testSingleton();
// Check plugin injected methods
expect(instance.snowboard).toBeDefined();
expect(instance.snowboard.getPlugin).toEqual(expect.any(Function));
expect(() => {
const method = instance.snowboard.initialise;
}).toThrow('cannot use');
expect(instance.destructor).toEqual(expect.any(Function));
// Check plugin method
expect(instance.testMethod).toBeDefined();
expect(instance.testMethod).toEqual(expect.any(Function));
expect(instance.testMethod()).toEqual('Tested');
// Check multiple instances (these should all be the same as this instance is a singleton)
const instanceOne = Snowboard.testSingleton();
instanceOne.changed = true;
const instanceTwo = Snowboard.testSingleton();
expect(instanceOne).toEqual(instanceTwo);
const factory = Snowboard.getPlugin('testSingleton');
expect(factory.getInstances()).toEqual([instance]);
// Remove plugin
Snowboard.removePlugin('testSingleton');
expect(Snowboard.hasPlugin('testSingleton')).toEqual(false);
expect(dom.window.Snowboard.getPluginNames()).toEqual(
expect.arrayContaining([ 'jsonparser', 'sanitizer'])
);
expect(Snowboard.testSingleton).not.toBeDefined();
done();
} catch (error) {
done(error);
}
},
(error) => {
throw error;
}
);
});
it('can listen and call global events', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/tests/js/fixtures/framework/TestListener.js',
])
.render()
.then(
(dom) => {
// Run assertions
const Snowboard = dom.window.Snowboard;
try {
expect(Snowboard.listensToEvent('eventOne')).toEqual(['test']);
expect(Snowboard.listensToEvent('eventTwo')).toEqual(['test']);
expect(Snowboard.listensToEvent('eventThree')).toEqual([]);
// Call global event one
const testClass = Snowboard.test();
Snowboard.globalEvent('eventOne', 42);
expect(testClass.eventResult).toEqual('Event called with arg 42');
// Call global event two - should fail as the test plugin doesn't have that method
expect(() => {
Snowboard.globalEvent('eventTwo');
}).toThrow('Missing "notExists" method in "test" plugin');
// Call global event three - nothing should happen
expect(() => {
Snowboard.globalEvent('eventThree');
}).not.toThrow();
done();
} catch (error) {
done(error);
}
},
(error) => {
throw error;
}
);
});
it('can listen and call global events that are simple closures', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/tests/js/fixtures/framework/TestClosureListener.js',
])
.render()
.then(
(dom) => {
// Run assertions
const Snowboard = dom.window.Snowboard;
try {
expect(Snowboard.listensToEvent('eventOne')).toEqual(['testclosure']);
expect(Snowboard.listensToEvent('eventTwo')).toEqual(['testclosure']);
expect(Snowboard.listensToEvent('eventThree')).toEqual([]);
// Call global event one
const testClass = Snowboard.testClosure();
Snowboard.globalEvent('eventOne');
expect(testClass.eventResult).toEqual('Closure eventOne called');
// Call global event two - should fail as the test plugin doesn't have that method
Snowboard.globalEvent('eventTwo', 42);
expect(testClass.eventResult).toEqual('Closure eventTwo called with arg \'42\'');
// Call global event three - nothing should happen
expect(() => {
Snowboard.globalEvent('eventThree');
}).not.toThrow();
done();
} catch (error) {
done(error);
}
},
(error) => {
throw error;
}
);
});
it('can listen and call global promise events', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/tests/js/fixtures/framework/TestPromiseListener.js',
])
.render()
.then(
(dom) => {
// Run assertions
const Snowboard = dom.window.Snowboard;
try {
expect(Snowboard.listensToEvent('promiseOne')).toEqual(['test']);
expect(Snowboard.listensToEvent('promiseTwo')).toEqual(['test']);
expect(Snowboard.listensToEvent('promiseThree')).toEqual([]);
// Call global event one
const testClass = Snowboard.test();
Snowboard.globalPromiseEvent('promiseOne', 'promise').then(
() => {
expect(testClass.eventResult).toEqual('Event called with arg promise');
// Call global event two - it should still work, even though it doesn't return a promise
Snowboard.globalPromiseEvent('promiseTwo', 'promise 2').then(
() => {
expect(testClass.eventResult).toEqual('Promise two called with arg promise 2');
// Call global event three - it should still work
Snowboard.globalPromiseEvent('promiseThree', 'promise 3').then(
() => {
done();
},
(error) => {
done(error);
}
);
},
(error) => {
done(error);
}
);
},
(error) => {
done(error);
}
);
} catch (error) {
done(error);
}
},
(error) => {
throw error;
}
);
});
it('can listen and call global promise events that are simple closures', function (done) {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/tests/js/fixtures/framework/TestPromiseClosureListener.js',
])
.render()
.then(
(dom) => {
// Run assertions
const Snowboard = dom.window.Snowboard;
try {
expect(Snowboard.listensToEvent('promiseOne')).toEqual(['testclosure']);
expect(Snowboard.listensToEvent('promiseTwo')).toEqual(['testclosure']);
expect(Snowboard.listensToEvent('promiseThree')).toEqual([]);
// Call global event one
const testClass = Snowboard.testClosure();
Snowboard.globalPromiseEvent('promiseOne', 'promise').then(
() => {
expect(testClass.eventResult).toEqual('Event called with arg promise');
// Call global event two - it should still work, even though it doesn't return a promise
Snowboard.globalPromiseEvent('promiseTwo', 'promise 2').then(
() => {
expect(testClass.eventResult).toEqual('Promise two called with arg promise 2');
// Call global event three - it should still work
Snowboard.globalPromiseEvent('promiseThree', 'promise 3').then(
() => {
done();
},
(error) => {
done(error);
}
);
},
(error) => {
done(error);
}
);
},
(error) => {
done(error);
}
);
} catch (error) {
done(error);
}
},
(error) => {
throw error;
}
);
});
it('will throw an error when using a plugin that has unfulfilled dependencies', function () {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/tests/js/fixtures/framework/TestHasDependencies.js',
])
.render()
.then(
(dom) => {
// Run assertions
const Snowboard = dom.window.Snowboard;
expect(() => {
Snowboard.testHasDependencies();
}).toThrow('The "testhasdependencies" plugin requires the following plugins: testdependencyone, testdependencytwo');
},
(error) => {
throw error;
}
);
});
it('will throw an error when using a plugin that has some unfulfilled dependencies', function () {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/tests/js/fixtures/framework/TestHasDependencies.js',
'modules/system/tests/js/fixtures/framework/TestDependencyOne.js',
])
.render()
.then(
(dom) => {
// Run assertions
const Snowboard = dom.window.Snowboard;
expect(() => {
Snowboard.testHasDependencies();
}).toThrow('The "testhasdependencies" plugin requires the following plugins: testdependencytwo');
},
(error) => {
throw error;
}
);
});
it('will not throw an error when using a plugin that has fulfilled dependencies', function () {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/tests/js/fixtures/framework/TestDependencyTwo.js',
'modules/system/tests/js/fixtures/framework/TestHasDependencies.js',
'modules/system/tests/js/fixtures/framework/TestDependencyOne.js',
])
.render()
.then(
(dom) => {
// Run assertions
const Snowboard = dom.window.Snowboard;
expect(() => {
Snowboard.testHasDependencies();
}).not.toThrow();
expect(Snowboard.testHasDependencies().testMethod()).toEqual('Tested');
},
(error) => {
throw error;
}
);
});
it('will not initialise a singleton that has unfulfilled dependencies', function () {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/tests/js/fixtures/framework/TestSingletonWithDependency.js',
])
.render()
.then(
(dom) => {
// Run assertions
const Snowboard = dom.window.Snowboard;
expect(() => {
Snowboard.testSingleton();
}).toThrow('The "testsingleton" plugin requires the following plugins: testdependencyone');
expect(Snowboard.listensToEvent('ready')).not.toContain('testsingleton');
expect(() => {
Snowboard.globalEvent('ready');
}).not.toThrow();
},
(error) => {
throw error;
}
);
});
it('will allow plugins to call other plugin methods', function () {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
'modules/system/tests/js/fixtures/framework/TestDependencyOne.js',
'modules/system/tests/js/fixtures/framework/TestSingletonWithDependency.js',
])
.render()
.then(
(dom) => {
// Run assertions
const Snowboard = dom.window.Snowboard;
const instance = Snowboard.testSingleton();
expect(instance.dependencyTest()).toEqual('Tested');
},
(error) => {
throw error;
}
);
});
it('doesn\'t allow PluginBase or Singleton abstracts to be modified', function () {
FakeDom
.new()
.addScript([
'modules/system/assets/js/build/manifest.js',
'modules/system/assets/js/snowboard/build/snowboard.vendor.js',
'modules/system/assets/js/snowboard/build/snowboard.base.js',
])
.render()
.then(
(dom) => {
expect(() => {
dom.window.Snowboard.PluginBase.newMethod = () => {
return true;
};
}).toThrow(TypeError);
expect(() => {
dom.window.Snowboard.PluginBase.destruct = () => {
return true;
};
}).toThrow(TypeError);
expect(() => {
dom.window.Snowboard.PluginBase.prototype.newMethod = () => {
return true;
};
}).toThrow(TypeError);
expect(() => {
dom.window.Snowboard.Singleton.newMethod = () => {
return true;
};
}).toThrow(TypeError);
expect(() => {
dom.window.Snowboard.Singleton.destruct = () => {
return true;
};
}).toThrow(TypeError);
expect(() => {
dom.window.Snowboard.Singleton.prototype.newMethod = () => {
return true;
};
}).toThrow(TypeError);
},
);
});
});