Adds SFRA 6.0

This commit is contained in:
Isaac Vallee
2021-12-21 10:57:31 -08:00
parent d04eb5dd16
commit 823c7608c3
1257 changed files with 137087 additions and 0 deletions

View File

@@ -0,0 +1,584 @@
'use strict';
var assert = require('chai').assert;
var proxyquire = require('proxyquire').noCallThru().noPreserveCache();
describe('forms', function () {
var buildObj = function (obj) {
Object.keys(obj).forEach(function (key) {
this[key] = obj[key];
}, this);
};
var FormGroup = function (obj) { this.init.call(this, obj); };
FormGroup.prototype.init = buildObj;
var FormAction = function (obj) { this.init.call(this, obj); };
FormAction.prototype.init = buildObj;
var FormField = function (obj) { this.init.call(this, obj); };
FormField.prototype.init = buildObj;
var formsRequire = proxyquire('../../../../cartridges/modules/server/forms/forms', {
'dw/web/FormField': FormField,
'dw/web/FormAction': FormAction,
'dw/web/FormGroup': FormGroup,
'./formField': proxyquire('../../../../cartridges/modules/server/forms/formField', {
'dw/web/Resource': { msg: function (value) { return value; } },
'dw/util/SecureEncoder': { forHtmlInDoubleQuoteAttribute: function (something) { return something; } }
})
});
it('should load a form', function () {
var session = {
forms: {
address: {
valid: true,
error: null,
htmlName: 'dwfrm_address',
dynamicHtmlName: 'dwfrm_address_a98dfa9sd8',
firstName: new FormField({
value: 'Jon',
htmlValue: 'Jon',
valid: true,
mandatory: true,
htmlName: 'dwfrm_address_firstName',
dynamicHtmlName: 'dwfrm_address_firstName_asdf8979asd8f',
type: 1,
FIELD_TYPE_STRING: 1,
label: 'hello',
regEx: '/[a-zA-Z]*/',
maxLength: 50,
minLength: 1
})
}
}
};
var forms = formsRequire(session);
var currentForm = forms.getForm('address');
assert.isTrue(currentForm.valid);
assert.isNull(currentForm.error);
assert.equal(currentForm.htmlName, 'dwfrm_address');
assert.isNotNull(currentForm.firstName);
});
it('should load a form with correct string form fields', function () {
var session = {
forms: {
address: {
valid: true,
error: null,
htmlName: 'dwfrm_address',
dynamicHtmlName: 'dwfrm_address_a98dfa9sd8',
firstName: new FormField({
value: 'Jon',
htmlValue: 'Jon',
valid: true,
mandatory: true,
htmlName: 'dwfrm_address_firstName',
dynamicHtmlName: 'dwfrm_address_firstName_asdf8979asd8f',
type: 1,
FIELD_TYPE_STRING: 1,
label: 'hello',
regEx: '/[a-zA-Z]*/',
maxLength: 50,
minLength: 1
})
}
}
};
var forms = formsRequire(session);
var currentForm = forms.getForm('address');
assert.isNotNull(currentForm.firstName);
assert.equal(currentForm.firstName.value, 'Jon');
assert.equal(currentForm.firstName.htmlValue, 'Jon');
assert.isTrue(currentForm.firstName.valid);
assert.isUndefined(currentForm.firstName.error);
assert.isTrue(currentForm.firstName.mandatory);
assert.equal(currentForm.firstName.label, 'hello');
assert.equal(currentForm.firstName.attributes, 'name="dwfrm_address_firstName" required aria-required="true" value="Jon" maxLength="50" minLength="1" pattern="/[a-zA-Z]*/"');
assert.equal(currentForm.firstName.formType, 'formField');
});
it('should load a form with correct bool form fields', function () {
var session = {
forms: {
address: {
valid: true,
error: null,
htmlName: 'dwfrm_address',
dynamicHtmlName: 'dwfrm_address_a98dfa9sd8',
boolField: new FormField({
value: true,
selected: true,
checked: true,
htmlValue: true,
htmlName: 'dwfrm_address_boolField',
dynamicHtmlName: 'dwfrm_address_boolField_a89sa7d9f8a7sd',
type: 2,
FIELD_TYPE_BOOLEAN: 2,
valid: false,
error: 'Found an issue'
})
}
}
};
var forms = formsRequire(session);
var currentForm = forms.getForm('address');
assert.isNotNull(currentForm.boolField);
assert.equal(currentForm.boolField.value, true);
assert.equal(currentForm.boolField.htmlValue, true);
assert.isFalse(currentForm.boolField.valid);
assert.equal(currentForm.boolField.error, 'Found an issue');
assert.equal(currentForm.boolField.attributes, 'name="dwfrm_address_boolField" checked="true" value="true"');
assert.equal(currentForm.boolField.formType, 'formField');
});
it('should invalidate bool form field if mandatory flag is true and checked attribute false', function () {
var session = {
forms: {
address: {
valid: true,
error: null,
htmlName: 'dwfrm_address',
dynamicHtmlName: 'dwfrm_address_a98dfa9sd8',
boolField: new FormField({
value: true,
selected: false,
valid: true,
checked: false,
htmlValue: true,
htmlName: 'dwfrm_address_boolField',
dynamicHtmlName: 'dwfrm_address_boolField_a89sa7d9f8a7sd',
type: 2,
mandatory: true,
FIELD_TYPE_BOOLEAN: 2,
error: 'Found an issue',
invalidateFormElement: function () {
this.valid = false;
}
})
}
}
};
var forms = formsRequire(session);
var currentForm = forms.getForm('address');
assert.isNotNull(currentForm.boolField);
assert.equal(currentForm.boolField.value, true);
assert.equal(currentForm.boolField.htmlValue, true);
assert.equal(currentForm.boolField.formType, 'formField');
assert.isFalse(currentForm.boolField.valid);
assert.equal(currentForm.boolField.error, 'Found an issue');
assert.equal(currentForm.boolField.attributes, 'name="dwfrm_address_boolField" required aria-required="true" value="true"');
});
it('should load a form with correct int form fields', function () {
var session = {
forms: {
address: {
valid: true,
error: null,
htmlName: 'dwfrm_address',
dynamicHtmlName: 'dwfrm_address_a98dfa9sd8',
intField: new FormField({
value: null,
htmlValue: null,
mandatory: true,
htmlName: 'dwfrm_address_intField',
dynamicHtmlName: 'dwfrm_address_intField_as8df7asd98',
type: 3,
FIELD_TYPE_INTEGER: 3,
maxValue: 999,
minValue: 1,
valid: true
})
}
}
};
var forms = formsRequire(session);
var currentForm = forms.getForm('address');
assert.isNotNull(currentForm.intField);
assert.equal(currentForm.intField.value, null);
assert.equal(currentForm.intField.htmlValue, '');
assert.isTrue(currentForm.intField.valid);
assert.isUndefined(currentForm.intField.error);
assert.isTrue(currentForm.intField.mandatory);
assert.equal(currentForm.intField.attributes, 'name="dwfrm_address_intField" required aria-required="true" value="" max="999" min="1"');
assert.equal(currentForm.intField.formType, 'formField');
});
it('should load a form with correct date form fields', function () {
var session = {
forms: {
address: {
valid: true,
error: null,
htmlName: 'dwfrm_address',
dynamicHtmlName: 'dwfrm_address_a98dfa9sd8',
dateField: new FormField({
value: null,
htmlValue: null,
mandatory: true,
htmlName: 'dwfrm_address_dateField',
dynamicHtmlName: 'dwfrm_address_dateField_as8df7asd98',
type: 4,
FIELD_TYPE_DATE: 4,
valid: true
})
}
}
};
var forms = formsRequire(session);
var currentForm = forms.getForm('address');
assert.isNotNull(currentForm.dateField);
assert.equal(currentForm.dateField.value, null);
assert.equal(currentForm.dateField.htmlValue, '');
assert.isTrue(currentForm.dateField.valid);
assert.isUndefined(currentForm.dateField.error);
assert.isTrue(currentForm.dateField.mandatory);
assert.equal(currentForm.dateField.attributes, 'name="dwfrm_address_dateField" required aria-required="true" value=""');
assert.equal(currentForm.dateField.formType, 'formField');
});
it('should load a form with correct string form field with options', function () {
var Options = function () {};
Options.prototype = [];
var options = new Options();
options.push({
checked: false,
htmlValue: 'hello',
optionId: 1,
selected: false,
value: 'hello'
});
options.push({
checked: true,
htmlValue: 'goodbye',
optionId: 2,
selected: true,
value: 'goodbye',
label: 'label'
});
options.optionsCount = 2;
var session = {
forms: {
address: {
valid: true,
error: null,
htmlName: 'dwfrm_address',
dynamicHtmlName: 'dwfrm_address_a98dfa9sd8',
firstName: new FormField({
value: 'Jon',
htmlValue: 'Jon',
valid: true,
mandatory: true,
htmlName: 'dwfrm_address_firstName',
dynamicHtmlName: 'dwfrm_address_firstName_asdf8979asd8f',
type: 1,
FIELD_TYPE_STRING: 1,
options: options,
selectedOption: {
optionId: 2
}
})
}
}
};
var forms = formsRequire(session);
var currentForm = forms.getForm('address');
assert.isNotNull(currentForm.firstName);
assert.isNotNull(currentForm.firstName.options);
assert.equal(currentForm.firstName.options.length, 2);
assert.equal(currentForm.firstName.options[0].id, 1);
assert.isFalse(currentForm.firstName.options[0].selected);
assert.equal(currentForm.firstName.options[1].id, 2);
assert.isTrue(currentForm.firstName.options[1].selected);
assert.equal(currentForm.firstName.selectedOption, 2);
assert.equal(currentForm.firstName.formType, 'formField');
});
it('should load a form with correct actions', function () {
var session = {
forms: {
address: {
valid: true,
error: null,
htmlName: 'dwfrm_address',
dynamicHtmlName: 'dwfrm_address_a98dfa9sd8',
action: new FormAction({
submitted: false,
triggered: false
}),
action2: new FormAction({
description: 'Some action',
label: 'My action',
submitted: true,
triggered: true
})
}
}
};
var forms = formsRequire(session);
var currentForm = forms.getForm('address');
assert.isNotNull(currentForm.action);
assert.isFalse(currentForm.action.submitted);
assert.isFalse(currentForm.action.triggered);
assert.isNull(currentForm.action.description);
assert.isNotNull(currentForm.action2);
assert.isTrue(currentForm.action2.submitted);
assert.isTrue(currentForm.action2.triggered);
assert.equal(currentForm.action2.description, 'Some action');
assert.equal(currentForm.action2.label, 'My action');
assert.equal(currentForm.action.formType, 'formAction');
assert.equal(currentForm.action2.formType, 'formAction');
});
it('should load a form with another form embeded', function () {
var session = {
forms: {
address: {
valid: true,
error: null,
htmlName: 'dwfrm_address',
dynamicHtmlName: 'dwfrm_address_a98dfa9sd8',
innerForm: new FormGroup({
valid: true,
error: null,
htmlName: 'dwfrm_address_innerForm',
dynamicHtmlName: 'dwfrm_address_innerForm_a90a9s8fasd',
firstName: new FormField({
value: 'Jon',
htmlValue: 'Jon',
valid: true,
mandatory: true,
htmlName: 'dwfrm_address_innerForm_firstName',
dynamicHtmlName: 'dwfrm_address_innerForm_firstName_asdf8979asd8f',
type: 1,
FIELD_TYPE_STRING: 1,
label: 'hello',
regEx: '/[a-zA-Z]*/',
maxLength: 50,
minLength: 1
})
})
}
}
};
var forms = formsRequire(session);
var currentForm = forms.getForm('address');
assert.isNotNull(currentForm.innerForm.firstName);
assert.equal(currentForm.innerForm.firstName.value, 'Jon');
assert.equal(currentForm.innerForm.firstName.htmlValue, 'Jon');
assert.isTrue(currentForm.innerForm.firstName.valid);
assert.isUndefined(currentForm.innerForm.firstName.error);
assert.isTrue(currentForm.innerForm.firstName.mandatory);
assert.equal(currentForm.innerForm.firstName.label, 'hello');
assert.equal(currentForm.innerForm.firstName.attributes, 'name="dwfrm_address_innerForm_firstName" required aria-required="true" value="Jon" maxLength="50" minLength="1" pattern="/[a-zA-Z]*/"');
assert.equal(currentForm.innerForm.formType, 'formGroup');
assert.equal(currentForm.innerForm.firstName.formType, 'formField');
});
it('should return updated attributes after form clear', function () {
var session = {
forms: {
shippingaddress: {
valid: true,
error: 'null',
htmlName: 'dwfrm_shippingaddress',
dynamicHtmlName: 'dwfrm_shippingaddress_a98dfa9sd8',
intField: new FormField({
value: 10,
htmlValue: 10,
mandatory: true,
htmlName: 'dwfrm_shippingaddress_intField',
dynamicHtmlName: 'dwfrm_shippingaddress_intField_as8df7asd98',
type: 3,
FIELD_TYPE_INTEGER: 3,
maxValue: 999,
minValue: 1,
valid: true
}),
clearFormElement: function () {
this.intField.value = 0;
this.intField.htmlValue = 0;
}
}
}
};
var forms = formsRequire(session);
var currentForm = forms.getForm('shippingaddress');
assert.equal(currentForm.intField.attributes, 'name="dwfrm_shippingaddress_intField" required aria-required="true" value="10" max="999" min="1"');
currentForm.clear();
assert.equal(currentForm.intField.attributes, 'name="dwfrm_shippingaddress_intField" required aria-required="true" value="0" max="999" min="1"');
});
it('should update htmlValue when value is updated', function () {
var session = {
forms: {
shippingaddress: {
valid: true,
error: null,
htmlName: 'dwfrm_shippingaddress',
dynamicHtmlName: 'dwfrm_shippingaddress_a98dfa9sd8',
intField: new FormField({
value: 10,
htmlValue: 10,
mandatory: true,
htmlName: 'dwfrm_shippingaddress_intField',
dynamicHtmlName: 'dwfrm_shippingaddress_intField_as8df7asd98',
type: 3,
FIELD_TYPE_INTEGER: 3,
maxValue: 999,
minValue: 1,
valid: true
})
}
}
};
var forms = formsRequire(session);
var currentForm = forms.getForm('shippingaddress');
assert.equal(currentForm.intField.htmlValue, 10);
currentForm.intField.value = 22;
assert.equal(currentForm.intField.value, 22);
});
it('should copy the values of a form to an object', function () {
var session = {
forms: {
shippingaddress: {
valid: true,
error: null,
htmlName: 'dwfrm_shippingaddress',
dynamicHtmlName: 'dwfrm_shippingaddress_a98dfa9sd8',
intField: new FormField({
value: 10,
htmlValue: 10,
mandatory: true,
htmlName: 'dwfrm_shippingaddress_intField',
dynamicHtmlName: 'dwfrm_shippingaddress_intField_as8df7asd98',
type: 3,
FIELD_TYPE_INTEGER: 3,
maxValue: 999,
minValue: 1,
valid: true
}),
innerForm: new FormGroup({
valid: true,
error: null,
htmlName: 'dwfrm_address_innerForm',
dynamicHtmlName: 'dwfrm_address_innerForm_a90a9s8fasd',
firstName: new FormField({
value: 'Jon',
htmlValue: 'Jon',
valid: true,
mandatory: true,
htmlName: 'dwfrm_address_innerForm_firstName',
dynamicHtmlName: 'dwfrm_address_innerForm_firstName_asdf8979asd8f',
type: 1,
FIELD_TYPE_STRING: 1,
label: 'hello',
regEx: '/[a-zA-Z]*/',
maxLength: 50,
minLength: 1
}),
innerForm: new FormGroup({
valid: true,
error: null,
htmlName: 'dwfrm_address_innerForm',
dynamicHtmlName: 'dwfrm_address_innerForm_a90a9s8fasd',
firstName: new FormField({
value: 'Jon',
htmlValue: 'Jon',
valid: true,
mandatory: true,
htmlName: 'dwfrm_address_innerForm_firstName',
dynamicHtmlName: 'dwfrm_address_innerForm_firstName_asdf8979asd8f',
type: 1,
FIELD_TYPE_STRING: 1,
label: 'hello',
regEx: '/[a-zA-Z]*/',
maxLength: 50,
minLength: 1
})
})
})
}
}
};
var expectedObject = {
intField: 10,
innerForm: {
firstName: 'Jon',
innerForm: {
firstName: 'Jon'
}
}
};
var forms = formsRequire(session);
var currentForm = forms.getForm('shippingaddress');
var result = currentForm.toObject();
assert.deepEqual(expectedObject, result);
});
it('should copy the values of an object to a form', function () {
var session = {
forms: {
shippingaddress: {
valid: true,
error: null,
htmlName: 'dwfrm_shippingaddress',
dynamicHtmlName: 'dwfrm_shippingaddress_a98dfa9sd8',
intField: new FormField({
value: 10,
htmlValue: 10,
mandatory: true,
htmlName: 'dwfrm_shippingaddress_intField',
dynamicHtmlName: 'dwfrm_shippingaddress_intField_as8df7asd98',
type: 3,
FIELD_TYPE_INTEGER: 3,
maxValue: 999,
minValue: 1,
valid: true
})
}
}
};
var object = { intField: 22 };
var forms = formsRequire(session);
var currentForm = forms.getForm('shippingaddress');
assert.equal(currentForm.intField.value, 10);
currentForm.copyFrom(object);
assert.equal(currentForm.intField.value, 22);
});
it('should copy the values of an object to a nested form', function () {
var session = {
forms: {
address: {
valid: true,
error: null,
htmlName: 'dwfrm_address',
dynamicHtmlName: 'dwfrm_address_a98dfa9sd8',
innerForm: new FormGroup({
valid: true,
error: null,
htmlName: 'dwfrm_address_innerForm',
dynamicHtmlName: 'dwfrm_address_innerForm_a90a9s8fasd',
firstName: new FormField({
value: 'Jon',
htmlValue: 'Jon',
valid: true,
mandatory: true,
htmlName: 'dwfrm_address_innerForm_firstName',
dynamicHtmlName: 'dwfrm_address_innerForm_firstName_asdf8979asd8f',
type: 1,
FIELD_TYPE_STRING: 1,
label: 'hello',
regEx: '/[a-zA-Z]*/',
maxLength: 50,
minLength: 1
})
})
}
}
};
var forms = formsRequire(session);
var currentForm = forms.getForm('address');
var object = { firstName: 'Sally' };
assert.equal(currentForm.innerForm.firstName.value, 'Jon');
currentForm.copyFrom(object);
assert.equal(currentForm.innerForm.firstName.value, 'Sally');
});
});

View File

@@ -0,0 +1,80 @@
'use strict';
var assert = require('chai').assert;
var sinon = require('sinon');
var middleware = require('../../../../cartridges/modules/server/middleware');
describe('middleware', function () {
var next = null;
var req = {};
beforeEach(function () {
next = sinon.spy();
req = {};
});
afterEach(function () {
next.reset();
});
it('should call next for http method', function () {
req.https = false;
middleware.http(req, null, next);
assert.isTrue(next.calledOnce);
});
it('should call next with error for http method', function () {
req.https = true;
middleware.http(req, null, next);
assert.instanceOf(next.firstCall.args[0], Error);
});
it('should call next for https method', function () {
req.https = true;
middleware.https(req, null, next);
assert.isTrue(next.calledOnce);
});
it('should call next with error for https method', function () {
req.https = false;
middleware.https(req, null, next);
assert.instanceOf(next.firstCall.args[0], Error);
});
it('should call next for get method', function () {
req.httpMethod = 'GET';
middleware.get(req, null, next);
assert.isTrue(next.calledOnce);
});
it('should call next with error for get method', function () {
req.httpMethod = 'PUT';
middleware.get(req, null, next);
assert.instanceOf(next.firstCall.args[0], Error);
});
it('should call next for post method', function () {
req.httpMethod = 'POST';
middleware.post(req, null, next);
assert.isTrue(next.calledOnce);
});
it('should call next with error for post method', function () {
req.httpMethod = 'DELETE';
middleware.get(req, null, next);
assert.instanceOf(next.firstCall.args[0], Error);
});
it('should call next for include', function () {
req.includeRequest = true;
middleware.include(req, null, next);
assert.isTrue(next.calledOnce);
});
it('should call next with error for include', function () {
req.includeRequest = false;
middleware.include(req, null, next);
assert.instanceOf(next.firstCall.args[0], Error);
});
});

View File

@@ -0,0 +1,206 @@
'use strict';
var assert = require('chai').assert;
var sinon = require('sinon');
var proxyquire = require('proxyquire').noCallThru().noPreserveCache();
var QueryString;
var logSpy;
describe('querystring', function () {
beforeEach(function () {
logSpy = sinon.spy();
QueryString = proxyquire('../../../../cartridges/modules/server/queryString', {
'dw/system/Logger': {
warn: logSpy
}
});
});
describe('options parsing', function () {
it('should parse product option query parameters', function () {
var params = 'dwopt_microsoft-xbox360-console_consoleWarranty=002&' +
'dwopt_microsoft-xbox360-console_gpsWarranty=003&' +
'dwopt_microsoft-xbox360-console_gps_warranty=003';
var querystring = new QueryString(params);
assert.deepEqual([{
optionId: 'gps_warranty',
productId: 'microsoft-xbox360-console',
selectedValueId: '003'
}, {
optionId: 'gpsWarranty',
productId: 'microsoft-xbox360-console',
selectedValueId: '003'
}, {
optionId: 'consoleWarranty',
productId: 'microsoft-xbox360-console',
selectedValueId: '002'
}], querystring.options);
});
it('should parse product option for product with underscore', function () {
var params = 'dwopt_microsoft__xbox360__console_consoleWarranty=002&' +
'dwopt_microsoft__xbox360__console_gpsWarranty=003&' +
'dwopt_microsoft__xbox360__console_gps_warranty=003';
var querystring = new QueryString(params);
assert.deepEqual([{
optionId: 'gps_warranty',
productId: 'microsoft_xbox360_console',
selectedValueId: '003'
}, {
optionId: 'gpsWarranty',
productId: 'microsoft_xbox360_console',
selectedValueId: '003'
}, {
optionId: 'consoleWarranty',
productId: 'microsoft_xbox360_console',
selectedValueId: '002'
}], querystring.options);
});
it('should output options query params', function () {
var params = 'dwopt_microsoft-xbox360-console_consoleWarranty=002&' +
'dwopt_microsoft-xbox360-console_gpsWarranty=003';
var querystring = new QueryString(params);
var paramsOutput = querystring.toString();
assert.equal(paramsOutput, 'dwopt_microsoft-xbox360-console_consoleWarranty=002&' +
'dwopt_microsoft-xbox360-console_gpsWarranty=003');
});
it('should output options query params for product with underscore', function () {
var params = 'dwopt_microsoft__xbox360__console_console_Warranty=002&' +
'dwopt_microsoft__xbox360__console_gpsWarranty=003';
var querystring = new QueryString(params);
var paramsOutput = querystring.toString();
assert.equal(paramsOutput, 'dwopt_microsoft__xbox360__console_console_Warranty=002&' +
'dwopt_microsoft__xbox360__console_gpsWarranty=003');
});
it('creates a single key "x=y" when options is not an array', function () {
var params = 'dwopt_microsoft__xbox360__console_console_Warranty=002&' +
'dwopt_microsoft__xbox360__console_gpsWarranty=003';
var rangeResult = new QueryString(params);
rangeResult.options = 'a simple string';
var paramsOutput = rangeResult.toString();
assert.equal(paramsOutput, 'options=a%20simple%20string');
});
});
describe('variation attribute parsing', function () {
it('should parse product variation query parameters', function () {
var params = 'dwvar_P12345_color=blue&dwvar_P12345_pv_size=L&pid=P12345';
var querystring = new QueryString(params);
assert.deepEqual({
color: {
id: 'P12345',
value: 'blue'
},
pv_size: {
id: 'P12345',
value: 'L'
}
}, querystring.variables);
});
it('should parse product variation param for product with underscores', function () {
var params = 'dwvar_my__test__product_color=blue&dwvar_my__test__product_pv_size=L&pid=P12345';
var querystring = new QueryString(params);
assert.deepEqual({
color: {
id: 'my_test_product',
value: 'blue'
},
pv_size: {
id: 'my_test_product',
value: 'L'
}
}, querystring.variables);
});
it('creates a single key "x=y" when variables is not an object', function () {
var params = 'dwvar_my__test__product_color=blue&dwvar_my__test__product_pv_size=L';
var rangeResult = new QueryString(params);
rangeResult.variables = 'a simple string';
var paramsOutput = rangeResult.toString();
assert.equal(paramsOutput, 'variables=a%20simple%20string');
});
});
describe('search refinements preferences parsing', function () {
it('should parse search refinement preference query parameters', function () {
var params = 'prefn1=pref1&prefv1=pref1Value&prefn2=pref2&prefv2=pref2Value';
var result = new QueryString(params);
assert.deepEqual(result.preferences, {
pref1: 'pref1Value',
pref2: 'pref2Value'
});
});
it('should output preferences query params', function () {
var params = 'prefn1=pref1&prefv1=pref1Value&prefn2=pref2&prefv2=pref2Value';
var result = new QueryString(params);
var paramsOutput = result.toString();
assert.equal(paramsOutput, 'prefn1=pref1&prefn2=pref2&prefv1=pref1Value&prefv2=pref2Value');
});
it('should parse search refinement preference range query parameters', function () {
var rangeParams = 'prefn1=prefName&prefmin1=0&prefmax1=100';
var rangeResult = new QueryString(rangeParams);
assert.deepEqual(rangeResult.preferences, {
prefName: {
min: '0',
max: '100'
}
});
});
it('should output range preference query params', function () {
var rangeParams = 'prefn1=prefName&prefmin1=0&prefmax1=100';
var rangeResult = new QueryString(rangeParams);
var paramsOutput = rangeResult.toString();
assert.deepEqual(paramsOutput, 'prefmax1=100&prefmin1=0&prefn1=prefName');
});
it('outputs range preference without "undefined" when one or more query params is empty or "undefined"', function () {
var rangeParams = 'prefv1=&prefn1=prefName&prefmin1=0&prefmax1=100';
var rangeResult = new QueryString(rangeParams);
var paramsOutput = rangeResult.toString();
assert.deepEqual(paramsOutput, 'prefmax1=100&prefmin1=0&prefn1=prefName');
});
it('warns via Logger when one or more query params is empty or "undefined"', function () {
var rangeParams = 'prefv1=&prefn1=prefName&prefmin1=0&prefmax1=100';
var rangeResult = new QueryString(rangeParams);
var paramsOutput = rangeResult.toString(); // eslint-disable-line no-unused-vars
assert.equal(logSpy.args[0][0], 'We were passed a key "undefined in the preferences object in queryString.js');
});
it('creates a single key "x=y" when preferences is not an object', function () {
var rangeParams = 'prefv1=&prefn1=prefName&prefmin1=0&prefmax1=100';
var rangeResult = new QueryString(rangeParams);
rangeResult.preferences = 'a simple string';
var paramsOutput = rangeResult.toString();
assert.equal(paramsOutput, 'preferences=a%20simple%20string');
});
});
describe('handling special characters', function () {
it('should handle the \'+\' with a \'%20\' which leads to a \' \'', function () {
var params = '?trackOrderNumber=01&trackOrderPostal=EC1A+1BB';
var result = new QueryString(params);
assert.equal(result.trackOrderPostal, 'EC1A 1BB');
});
});
describe('handling url encoding of querystring', function () {
it('should handle encoding properly', function () {
var params = '?dwvar_P12345_Maat=37%2B&pid=P12345';
var result = new QueryString(params);
assert.equal(result.toString(), 'dwvar_P12345_Maat=37%2B&pid=P12345');
});
});
describe('handling duplicate parameters in querystring', function () {
it('should return an array', function () {
var params = '?one=uno&cheese=1&cheese=2&cheese=3&brand=sony&brand=samsung&cheese=4';
var result = new QueryString(params);
assert.deepEqual(result.one, 'uno');
assert.deepEqual(result.cheese, ['4', '3', '2', '1']);
assert.deepEqual(result.brand, ['samsung', 'sony']);
});
});
});

View File

@@ -0,0 +1,178 @@
'use strict';
var assert = require('chai').assert;
var proxyquire = require('proxyquire').noCallThru().noPreserveCache();
var sinon = require('sinon');
describe('render', function () {
var render = null;
var ismlRender = sinon.spy();
var pageDesignerRender = sinon.spy();
var response = {
base: {
writer: {
print: sinon.spy()
}
},
setContentType: sinon.spy(),
viewData: {},
renderings: [],
view: null
};
beforeEach(function () {
global.XML = function (xmlString) {
var parseString = require('xml2js').parseString;
return parseString(xmlString, 'text/xml', function (error) {
if (error) {
throw new Error(error);
}
});
};
render = proxyquire('../../../../cartridges/modules/server/render', {
'dw/template/ISML': {
renderTemplate: ismlRender
},
'dw/experience/PageMgr': {
renderPage: pageDesignerRender
}
});
});
afterEach(function () {
ismlRender.reset();
pageDesignerRender.reset();
response.base.writer.print.reset();
response.setContentType.reset();
response.viewData = {};
response.renderings = [];
});
it('should correctly render a template', function () {
response.renderings.push({ type: 'render', subType: 'isml', view: 'name' });
render.applyRenderings(response);
assert.isTrue(ismlRender.calledOnce);
});
it('should pass data correctly to the view', function () {
response.renderings.push({ type: 'render', subType: 'isml', view: 'template' });
response.viewData = { name: 'value' };
render.applyRenderings(response);
assert.isTrue(ismlRender.calledWith('template', sinon.match({ name: 'value' })));
});
it('should correctly render a page', function () {
response.renderings.push({ type: 'render', subType: 'page', page: 'page' });
render.applyRenderings(response);
assert.isTrue(pageDesignerRender.calledOnce);
});
it('should pass data correctly to the view of the page being rendered', function () {
response.renderings.push({ type: 'render', subType: 'page', page: 'page2' });
response.viewData = { decorator: 'decorator' };
render.applyRenderings(response);
assert.isTrue(response.base.writer.print.calledOnce);
assert.isTrue(pageDesignerRender.calledWith('page2', '{"decorator":"decorator"}'));
});
it('should render a json output', function () {
response.renderings.push({ type: 'render', subType: 'json' });
response.viewData = { name: 'value' };
render.applyRenderings(response);
assert.isTrue(response.setContentType.calledWith('application/json'));
assert.isTrue(response.base.writer.print.calledOnce);
});
it('should render valid xml output', function () {
response.renderings.push({ type: 'render', subType: 'xml' });
response.viewData = {
key1: 'value1',
key2: 'value2',
xml: '<xmlKey></xmlKey>'
};
render.applyRenderings(response);
assert.isTrue(response.setContentType.calledWith('application/xml'));
assert.isTrue(response.base.writer.print.calledOnce);
});
it('should throw an exception when invalid XML is provided', function () {
response.renderings.push({ type: 'render', subType: 'xml' });
response.viewData = { xml: '<x>I am not valid XML<y>' };
try {
render.applyRenderings(response);
} catch (e) {
assert.isNotNull(e);
}
});
it('should print output', function () {
response.renderings.push({ type: 'print', message: 'crazyMessage' });
render.applyRenderings(response);
assert.isTrue(response.base.writer.print.calledOnce);
assert.isTrue(response.base.writer.print.calledWith('crazyMessage'));
});
it('should render error page when template failed', function () {
var renderMock = proxyquire('../../../../cartridges/modules/server/render', {
'dw/template/ISML': {
renderTemplate: function () {
throw new Error('hello');
}
},
'dw/experience/PageMgr': {
renderPage: function () {
throw new Error('Hello Darkness');
}
}
});
response.renderings.push({ type: 'render', subType: 'isml', view: 'template' });
try {
renderMock.applyRenderings(response);
} catch (e) {
assert.isNotNull(e);
}
});
it('should throw error when no rendering step has been called', function () {
try {
render.applyRenderings(response);
} catch (e) {
assert.isNotNull(e);
}
});
it('should throw error when unidentified Type', function () {
response.renderings.push({ type: 'blah', subType: 'blah', view: 'template' });
try {
render.applyRenderings(response);
} catch (e) {
assert.isNotNull(e);
}
});
it('should throw error when unidentified subType', function () {
response.renderings.push({ type: 'render', subType: 'blah', view: 'template' });
try {
render.applyRenderings(response);
} catch (e) {
assert.isNotNull(e);
}
});
});

View File

@@ -0,0 +1,515 @@
'use strict';
var assert = require('chai').assert;
var proxyquire = require('proxyquire').noCallThru().noPreserveCache();
var sinon = require('sinon');
var ArrayList = require('../../../mocks/dw.util.Collection');
var Request = proxyquire('../../../../cartridges/modules/server/request', {
'dw/util/Locale': {
getLocale: function () {
return { ID: 'en_US', country: 'US' };
}
},
'dw/util/Currency': {
getCurrency: function () {
return 'currency';
}
},
'*/cartridge/config/countries': [
{
'id': 'en_US',
'currencyCode': 'USD',
'alternativeCurrencyCodes': ['CAD']
}, {
'id': 'en_GB',
'currencyCode': 'GBP'
}, {
'id': 'ja_JP',
'currencyCode': 'JPY'
}, {
'id': 'zh_CN',
'currencyCode': 'CNY'
}, {
'id': 'fr_FR',
'currencyCode': 'EUR'
}, {
'id': 'it_IT',
'currencyCode': 'EUR'
}]
});
var session = {
setCurrency: function () { return; }
};
var setCurrencyStub = sinon.stub(session, 'setCurrency');
function createFakeRequest(overrides) {
overrides = overrides || {}; // eslint-disable-line no-param-reassign
var globalRequest = {
httpMethod: 'GET',
httpHost: 'localhost',
httpPath: '/Product-Show',
httpQueryString: '',
httpParameterMap: {
requestBodyAsString: ''
},
isHttpSecure: function () {
return false;
},
getHttpReferer: function () {
return 'https://www.salesforce.com';
},
getHttpRemoteAddress: function () {
return '0.0.0.0';
},
geolocation: {
countryCode: 'US',
latitude: 42.4019,
longitude: -71.1193
},
customer: {
authenticated: true,
profile: {
firstName: 'John',
lastName: 'Snow',
email: 'jsnow@starks.com',
phoneHome: '1234567890',
credentials: {
login: 'jsnow@starks.com'
},
wallet: {
paymentInstruments: new ArrayList([
{
creditCardHolder: 'someName',
maskedCreditCardNumber: 'someMaskedNumber',
creditCardType: 'someCardType',
creditCardExpirationMonth: 'someMonth',
creditCardExpirationYear: 'someYear',
UUID: 'someUUID',
creditCardNumber: 'someNumber'
}
])
}
},
addressBook: {
preferredAddress: {
address1: '15 South Point Drive',
address2: null,
city: 'Boston',
countryCode: {
displayValue: 'United States',
value: 'US'
},
firstName: 'John',
lastName: 'Snow',
ID: 'Home',
postalCode: '02125',
stateCode: 'MA',
postBox: '2134',
salutation: null,
secondName: null,
suffix: null,
suite: '302',
title: 'Dr'
}
}
},
locale: 'ab_YZ',
pageMetaData: {
title: '',
description: '',
keywords: '',
pageMetaTags: [{}],
addPageMetaTags: function (pageMetaTags) {
this.pageMetaTags = pageMetaTags;
},
setTitle: function (title) {
this.title = title;
},
setDescription: function (description) {
this.description = description;
},
setKeywords: function (keywords) {
this.keywords = keywords;
}
},
session: {
currency: {
currencyCode: 'XYZ',
defaultFractionDigits: 10,
name: 'Volodin Dollars',
symbol: '៛'
},
custom: {
rememberMe: true
},
privacyCache: {
get: function (key) { // eslint-disable-line no-unused-vars
return this.key;
},
set: function (value) { // eslint-disable-line no-unused-vars
this.key = value;
},
key: 'value'
},
clickStream: {
clicks: {
toArray: function () {
return [{
host: 'clickObj.host',
locale: 'clickObj.locale',
path: 'clickObj.path',
pipelineName: 'clickObj-pipelineName',
queryString: 'clickObj.queryString',
referer: 'clickObj.referer',
remoteAddress: 'clickObj.remoteAddress',
timestamp: 'clickObj.timestamp',
url: 'clickObj.url',
userAgent: 'clickObj.userAgent'
}];
}
},
partial: false
},
setCurrency: setCurrencyStub
}
};
Object.keys(overrides).forEach(function (key) {
globalRequest[key] = overrides[key];
});
return globalRequest;
}
describe('request', function () {
afterEach(function () {
setCurrencyStub.reset();
});
it('should parse empty query string', function () {
var req = new Request(createFakeRequest(), createFakeRequest().customer, createFakeRequest().session);
assert.isObject(req.querystring);
assert.equal(Object.keys(req.querystring).length, 0);
assert.equal(req.querystring.toString(), '');
});
it('should parse simple query string', function () {
var req = new Request(createFakeRequest({ httpQueryString: 'id=22&name=foo' }), createFakeRequest().customer, createFakeRequest().session);
assert.isObject(req.querystring);
assert.equal(req.querystring.id, 22);
assert.equal(req.querystring.name, 'foo');
assert.equal(req.querystring.toString(), 'id=22&name=foo');
});
it('should parse query string with variables', function () {
var req = new Request(createFakeRequest({
httpQueryString: 'dwvar_bar_size=32&dwvar_foo_color=1111'
}), createFakeRequest().customer, createFakeRequest().session);
assert.equal(req.querystring.variables.color.id, 'foo');
assert.equal(req.querystring.variables.color.value, '1111');
assert.equal(req.querystring.variables.size.id, 'bar');
assert.equal(req.querystring.variables.size.value, '32');
assert.notProperty(req.querystring, 'dwvar_foo_color');
assert.notProperty(req.querystring, 'dwvar_bar_size');
assert.equal(req.querystring.toString(), 'dwvar_bar_size=32&dwvar_foo_color=1111');
});
it('should parse query string with incorrectly formatted variables', function () {
var req = new Request(createFakeRequest({
httpQueryString: 'dwvar_color=1111&dwvar_size=32'
}), createFakeRequest().customer, createFakeRequest().session);
assert.equal(req.querystring.dwvar_color, '1111');
assert.equal(req.querystring.dwvar_size, '32');
assert.notProperty(req.querystring, 'variables');
assert.equal(req.querystring.toString(), 'dwvar_color=1111&dwvar_size=32');
});
it('should contain correct geolocation object and properties', function () {
var req = new Request(createFakeRequest(), createFakeRequest().customer, createFakeRequest().session);
assert.equal(req.geolocation.countryCode, 'US');
assert.equal(req.geolocation.latitude, 42.4019);
assert.equal(req.geolocation.longitude, -71.1193);
});
it('should contain correct current customer profile and properties', function () {
var req = new Request(createFakeRequest(), createFakeRequest().customer, createFakeRequest().session);
assert.equal(req.currentCustomer.profile.firstName, 'John');
assert.equal(req.currentCustomer.profile.lastName, 'Snow');
assert.equal(req.currentCustomer.profile.email, 'jsnow@starks.com');
assert.equal(req.currentCustomer.profile.phone, '1234567890');
});
it('should contain correct customer credentials when customer unauthenticated', function () {
var fakeRequest = createFakeRequest();
fakeRequest.customer.authenticated = false;
var req = new Request(fakeRequest, fakeRequest.customer, createFakeRequest().session);
assert.equal(req.currentCustomer.credentials.username, 'jsnow@starks.com');
});
it('should contain correct current customer address book and properties', function () {
var req = new Request(createFakeRequest(), createFakeRequest().customer, createFakeRequest().session);
var expectedResult = createFakeRequest();
assert.equal(
req.currentCustomer.addressBook.preferredAddress.address1,
'15 South Point Drive'
);
assert.equal(
req.currentCustomer.addressBook.preferredAddress.address2,
null
);
assert.equal(
req.currentCustomer.addressBook.preferredAddress.city,
'Boston'
);
assert.equal(
req.currentCustomer.addressBook.preferredAddress.countryCode.displayValue,
'United States'
);
assert.equal(
req.currentCustomer.addressBook.preferredAddress.countryCode.value,
'US'
);
assert.equal(
req.currentCustomer.addressBook.preferredAddress.firstName,
'John'
);
assert.equal(
req.currentCustomer.addressBook.preferredAddress.lastName,
'Snow'
);
assert.equal(
req.currentCustomer.addressBook.preferredAddress.ID,
'Home'
);
assert.equal(
req.currentCustomer.addressBook.preferredAddress.stateCode,
'MA'
);
assert.equal(
req.currentCustomer.addressBook.preferredAddress.postalCode,
'02125'
);
assert.equal(
req.currentCustomer.addressBook.preferredAddress.postBox,
'2134'
);
assert.equal(
req.currentCustomer.addressBook.preferredAddress.salutation,
null
);
assert.equal(
req.currentCustomer.addressBook.preferredAddress.secondName,
null
);
assert.equal(
req.currentCustomer.addressBook.preferredAddress.suffix,
null
);
assert.equal(
req.currentCustomer.addressBook.preferredAddress.suite,
'302'
);
assert.equal(
req.currentCustomer.addressBook.preferredAddress.title,
'Dr'
);
assert.deepEqual(
req.currentCustomer.addressBook.preferredAddress.raw,
expectedResult.customer.addressBook.preferredAddress
);
});
it('should contain correct current customer wallet and properties', function () {
var req = new Request(createFakeRequest(), createFakeRequest().customer, createFakeRequest().session);
var expectedResult = createFakeRequest();
assert.deepEqual(
req.currentCustomer.wallet.paymentInstrument,
expectedResult.customer.profile.wallet.paymentInstruments[0]
);
});
it('should not fail if customer does not exist', function () {
var req = new Request(createFakeRequest({ customer: null }), null, createFakeRequest().session);
assert.equal(req.host, 'localhost');
});
it('should not fail if customer does not have a profile', function () {
var req = new Request(createFakeRequest({ customer: { profile: null } }), { profile: null }, createFakeRequest().session);
assert.equal(req.currentCustomer.raw.profile, null);
});
it('should retrieve form properties', function () {
var items = {
one: { rawValue: 1 },
two: { rawValue: 2 },
three: { rawValue: 3 },
submitted: { },
id: { rawValue: 22 },
name: { rawValue: 'foo' }
};
var httpParamMap = {
parameterNames: {
iterator: function () {
var index = 0;
return {
hasNext: function () {
return index < Object.keys(items).length - 1;
},
next: function () {
var value = Object.keys(items)[index];
index++;
return value;
}
};
},
length: Object.keys(items).length
},
get: function (name) {
return items[name];
}
};
var req = new Request(
createFakeRequest({ httpParameterMap: httpParamMap, httpQueryString: 'id=22&name=foo' }),
null,
createFakeRequest().session
);
assert.equal(req.form.one, 1);
assert.equal(req.form.two, 2);
assert.equal(req.form.three, 3);
assert.isUndefined(req.form.submitted);
assert.isUndefined(req.form.id);
});
it('should contain locale ID', function () {
var req = new Request(createFakeRequest(), createFakeRequest().customer, createFakeRequest().session);
var expectedResult = createFakeRequest();
assert.deepEqual(
req.locale.id,
expectedResult.locale
);
});
it('should contain session currency', function () {
var req = new Request(createFakeRequest(), createFakeRequest().customer, createFakeRequest().session);
var expectedResult = createFakeRequest();
assert.deepEqual(
req.locale.currency,
expectedResult.session.currency
);
});
it('should contain session privacy', function () {
var req = new Request(createFakeRequest(), createFakeRequest().customer, createFakeRequest().session);
var expectedResult = req.session.raw.privacyCache.get('key');
assert.equal(expectedResult, 'value');
});
it('should contain session clickStream', function () {
var req = new Request(createFakeRequest(), createFakeRequest().customer, createFakeRequest().session);
var expectedClick = {
host: 'clickObj.host',
locale: 'clickObj.locale',
path: 'clickObj.path',
pipelineName: 'clickObj-pipelineName',
queryString: 'clickObj.queryString',
referer: 'clickObj.referer',
remoteAddress: 'clickObj.remoteAddress',
timestamp: 'clickObj.timestamp',
url: 'clickObj.url',
userAgent: 'clickObj.userAgent'
};
var expectedResult = {
clicks: [expectedClick],
first: expectedClick,
last: expectedClick,
partial: false
};
assert.deepEqual(req.session.clickStream, expectedResult);
});
it('should call setCurrency once', function () {
new Request(createFakeRequest(), createFakeRequest().customer, createFakeRequest().session);
assert.isTrue(setCurrencyStub.calledOnce);
});
it('should not call setCurrency when currency is a alternative currency code', function () {
var fakeRequest = createFakeRequest({
locale: 'en_US'
});
fakeRequest.session.currency.currencyCode = 'CAD';
new Request(fakeRequest, fakeRequest.customer, fakeRequest.session);
assert.isFalse(setCurrencyStub.calledOnce);
});
it('should contain correct geolocation object and properties wehn co geolocation exists', function () {
var fakeRequest = createFakeRequest();
delete fakeRequest.geolocation;
var req = new Request(fakeRequest, createFakeRequest().customer, createFakeRequest().session);
assert.equal(req.geolocation.countryCode, 'US');
assert.equal(req.geolocation.latitude, 90.0000);
assert.equal(req.geolocation.longitude, 0.0000);
});
it('should contain the correct referer', function () {
var req = new Request(createFakeRequest(), createFakeRequest().customer, createFakeRequest().session);
assert.equal(req.referer, 'https://www.salesforce.com');
});
it('should contain the correct remote address', function () {
var req = new Request(createFakeRequest(), createFakeRequest().customer, createFakeRequest().session);
assert.equal(req.remoteAddress, '0.0.0.0');
});
it('should not get body as string for a GET request', function () {
var req = new Request(createFakeRequest(), createFakeRequest().customer, createFakeRequest().session);
assert.equal(req.body, null);
});
it('should get body as string for a POST request', function () {
var fakeRequest = createFakeRequest();
fakeRequest.httpMethod = 'POST';
var req = new Request(fakeRequest, createFakeRequest().customer, createFakeRequest().session);
assert.equal(req.body, '');
});
it('should get body as string for a PUT request', function () {
var fakeRequest = createFakeRequest();
fakeRequest.httpMethod = 'PUT';
var req = new Request(fakeRequest, createFakeRequest().customer, createFakeRequest().session);
assert.equal(req.body, '');
});
it('should get pageMetaData title', function () {
var fakeRequest = createFakeRequest();
fakeRequest.pageMetaData.setTitle('TestTitle');
var req = new Request(fakeRequest, createFakeRequest().customer, createFakeRequest().session);
assert.equal(req.pageMetaData.title, 'TestTitle');
});
it('should get pageMetaData description', function () {
var fakeRequest = createFakeRequest();
fakeRequest.pageMetaData.setDescription('TestDescription');
var req = new Request(fakeRequest, createFakeRequest().customer, createFakeRequest().session);
assert.equal(req.pageMetaData.description, 'TestDescription');
});
it('should get pageMetaData keywords', function () {
var fakeRequest = createFakeRequest();
fakeRequest.pageMetaData.setKeywords('TestKeywords');
var req = new Request(fakeRequest, createFakeRequest().customer, createFakeRequest().session);
assert.equal(req.pageMetaData.keywords, 'TestKeywords');
});
it('should get pageMetaData pageMetaTags', function () {
var fakeRequest = createFakeRequest();
fakeRequest.pageMetaData.addPageMetaTags([{ title: true, content: 'TestTitle' }]);
var req = new Request(fakeRequest, createFakeRequest().customer, createFakeRequest().session);
assert.deepEqual(req.pageMetaData.pageMetaTags, [{ title: true, content: 'TestTitle' }]);
});
});

View File

@@ -0,0 +1,187 @@
'use strict';
var assert = require('chai').assert;
var sinon = require('sinon');
var proxyquire = require('proxyquire').noCallThru().noPreserveCache();
var Response = proxyquire('../../../../cartridges/modules/server/response', {
'*/cartridge/config/httpHeadersConf': [
{
'id': 'someName',
'value': 'someValue'
}
]
});
var res = {
redirect: function () {},
setHttpHeader: sinon.spy(),
setContentType: sinon.spy(),
setStatus: sinon.spy()
};
describe('response', function () {
it('should create response object with passed-in base', function () {
var response = new Response(res);
assert.property(response, 'base');
assert.property(response.base, 'redirect');
});
it('should correctly set view and viewData', function () {
var response = new Response(res);
response.render('test', { name: 'value' });
assert.equal(response.view, 'test');
assert.equal(response.viewData.name, 'value');
});
it('should extend viewData', function () {
var response = new Response(res);
response.setViewData({ name: 'value' });
response.setViewData({ foo: 'bar' });
response.render('test', { name: 'test' });
assert.equal(response.viewData.name, 'test');
assert.equal(response.viewData.foo, 'bar');
});
it('should correctly store a page rendering and set viewData', function () {
var response = new Response(res);
response.page('test', { name: 'value' });
assert.equal(response.viewData.name, 'value');
assert.equal(response.renderings.length, 1);
assert.deepEqual(response.renderings[0], {
type: 'render', subType: 'page', page: 'test', aspectAttributes: undefined
});
});
it('should correctly store a page rendering with aspectAttributes and set viewData', function () {
var response = new Response(res);
response.page('test', { name: 'value' }, { test: 'foo' });
assert.equal(response.viewData.name, 'value');
assert.equal(response.renderings.length, 1);
assert.deepEqual(response.renderings[0], {
type: 'render', subType: 'page', page: 'test', aspectAttributes: { test: 'foo' }
});
});
it('should extend viewData for page', function () {
var response = new Response(res);
response.setViewData({ name: 'value' });
response.setViewData({ foo: 'bar' });
response.page('page', { name: 'test' });
assert.equal(response.viewData.name, 'test');
assert.equal(response.viewData.foo, 'bar');
});
it('should not extend viewData with non-objects', function () {
var response = new Response(res);
response.setViewData({ name: 'value' });
response.setViewData(function () {});
assert.equal(response.viewData.name, 'value');
});
it('should correctly set json', function () {
var response = new Response(res);
response.json({ name: 'value' });
assert.isTrue(response.isJson);
assert.equal(response.viewData.name, 'value');
});
it('should correctly set xml', function () {
var response = new Response(res);
response.xml('<?xml version="1.0" encoding="UTF-8" standalone="yes"?>');
assert.isTrue(response.isXml);
assert.equal(response.viewData.xml, '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>');
});
it('should correctly set url', function () {
var response = new Response(res);
response.redirect('hello');
assert.equal(response.redirectUrl, 'hello');
});
it('should correctly set redirect status', function () {
var response = new Response(res);
response.setRedirectStatus('301');
assert.equal(response.redirectStatus, '301');
});
it('should set and retrieve data', function () {
var response = new Response(res);
response.setViewData({ name: 'value' });
assert.equal(response.getViewData().name, 'value');
});
it('should log item', function () {
var response = new Response(res);
response.log('one', 'two', 'three');
assert.equal(response.messageLog.length, 1);
assert.equal(response.messageLog[0], 'one two three');
});
it('should convert log item to json', function () {
var response = new Response(res);
response.log({ name: 'value' });
assert.equal(response.messageLog.length, 1);
assert.equal(response.messageLog[0], '{"name":"value"}');
});
it('should try to print out a message', function () {
var response = new Response(res);
response.print('hello');
assert.equal(response.renderings.length, 1);
assert.equal(response.renderings[0].type, 'print');
assert.equal(response.renderings[0].message, 'hello');
});
it('should set http header', function () {
var response = new Response(res);
response.setHttpHeader('aName', 'aValue');
assert.isTrue(res.setHttpHeader.calledWith('aName', 'aValue'));
});
it('should set content type', function () {
var response = new Response(res);
response.setContentType('text/html');
assert.isTrue(res.setContentType.calledWith('text/html'));
});
it('should set status code', function () {
var response = new Response(res);
response.setStatusCode(500);
assert.isTrue(res.setStatus.calledWith(500));
});
it('should set cache expiration for the page', function (done) {
var response = new Response(res);
response.cacheExpiration(6);
assert.equal(6, response.cachePeriod);
done();
});
it('should loop through and append to renderings array', function () {
var response = new Response(res);
response.renderings.push({ type: 'render', subType: 'isml' });
response.json({ name: 'value' });
assert.isTrue(response.isJson);
assert.equal(response.viewData.name, 'value');
assert.equal(response.renderings.length, 1);
assert.equal(response.renderings[0].type, 'render');
assert.equal(response.renderings[0].subType, 'json');
});
it('should loop through and append to renderings array', function () {
var response = new Response(res);
response.renderings.push({ type: 'print' });
response.json({ name: 'value' });
assert.equal(response.renderings.length, 2);
assert.equal(response.renderings[0].type, 'print');
assert.equal(response.renderings[1].type, 'render');
assert.equal(response.renderings[1].subType, 'json');
});
});

View File

@@ -0,0 +1,170 @@
'use strict';
var proxyquire = require('proxyquire').noCallThru().noPreserveCache();
var Response = proxyquire('../../../../cartridges/modules/server/response', {
'*/cartridge/config/httpHeadersConf': [{ 'id': 'testId', 'value': 'testValue' }]
});
var Route = require('../../../../cartridges/modules/server/route');
var sinon = require('sinon');
var assert = require('chai').assert;
var mockReq = {
path: '',
querystring: {},
locale: ''
};
var mockRes = {
setViewData: function () {}
};
describe('route', function () {
it('should create a new route with a given number of steps', function () {
function tempFunc(req, res, next) { next(); }
var route = new Route('test', [tempFunc, tempFunc], mockReq, mockRes);
assert.equal(route.name, 'test');
assert.equal(route.chain.length, 2);
});
it('should update response after last step', function (done) {
function tempFunc(req, res, next) {
res.test = 'Hello'; // eslint-disable-line no-param-reassign
next();
}
var route = new Route('test', [tempFunc], mockReq, mockRes);
route.on('route:Complete', function (req, res) {
assert.equal(res.test, 'Hello');
done();
});
route.getRoute()();
});
it('should execute two middleware steps', function (done) {
var i = 0;
function tempFunc(req, res, next) {
i += 1;
next();
}
var route = new Route('test', [tempFunc, tempFunc], mockReq, mockRes);
route.on('route:Complete', function () {
assert.equal(i, 2);
done();
});
route.getRoute()();
});
it('should verify that response keeps redirect variable', function (done) {
function tempFunc(req, res, next) {
res.redirect('test');
next();
}
var response = new Response({ redirect: function () {}, setHttpHeader: function () {} });
var route = new Route('test', [tempFunc], mockReq, response);
route.on('route:Redirect', function (req, res) {
assert.equal(res.redirectUrl, 'test');
done();
});
route.getRoute()();
});
it('should verify that redirect with implicit (not set) redirect status works', function (done) {
var baseResponseRedirectMock = sinon.spy();
function tempFunc(req, res, next) {
res.redirect('test');
next();
}
var response = new Response({ redirect: baseResponseRedirectMock, setHttpHeader: function () {} });
var route = new Route('test', [tempFunc], mockReq, response);
route.getRoute()();
assert.isTrue(baseResponseRedirectMock.calledOnce);
assert.isTrue(baseResponseRedirectMock.firstCall.calledWithExactly('test'));
done();
});
it('should verify that redirect with explicit redirect status works', function (done) {
var baseResponseRedirectMock = sinon.spy();
function tempFunc(req, res, next) {
res.setRedirectStatus(301);
res.redirect('test');
next();
}
var response = new Response({ redirect: baseResponseRedirectMock, setHttpHeader: function () {} });
var route = new Route('test', [tempFunc], mockReq, response);
route.getRoute()();
assert.isTrue(baseResponseRedirectMock.calledOnce);
assert.isTrue(baseResponseRedirectMock.firstCall.calledWithExactly('test', 301));
done();
});
it('should throw an error', function () {
function tempFunc(req, res, next) {
next(new Error());
}
var res = {
log: function () {},
setViewData: mockRes.setViewData };
var route = new Route('test', [tempFunc], mockReq, res);
assert.throws(function () { route.getRoute()(); });
});
it('should correct append a step to the route', function () {
function tempFunc(req, res, next) {
next();
}
var route = new Route('test', [tempFunc, tempFunc], mockReq, mockRes);
assert.equal(route.chain.length, 2);
route.append(tempFunc);
assert.equal(route.chain.length, 3);
});
it('should set error object on the response', function () {
var RouteStaging = proxyquire('../../../../cartridges/modules/server/route', {
'dw/system/System': {
getInstanceType: function () {
return false;
},
'PRODUCTION_SYSTEM': true
}
});
function tempFunc(req, res, next) {
next();
}
var req = {
path: mockReq.path,
querystring: mockReq.querystring,
locale: mockReq.locale
};
var route = new RouteStaging('test', [tempFunc], req, mockRes);
route.getRoute()({
ErrorText: 'hello',
ControllerName: 'Foo',
CurrentStartNodeName: 'Bar'
});
assert.isNotNull(req.error);
assert.equal(req.error.errorText, 'hello');
assert.equal(req.error.controllerName, 'Foo');
assert.equal(req.error.startNodeName, 'Bar');
});
it('should set error object on the response to empty string if on production', function () {
var RouteProduction = proxyquire('../../../../cartridges/modules/server/route', {
'dw/system/System': {
getInstanceType: function () {
return true;
},
'PRODUCTION_SYSTEM': true
}
});
function tempFunc(req, res, next) {
next();
}
var req = {
path: mockReq.path,
querystring: mockReq.querystring,
locale: mockReq.locale
};
var route = new RouteProduction('test', [tempFunc], req, mockRes);
route.getRoute()({
ErrorText: 'hello',
ControllerName: 'Foo',
CurrentStartNodeName: 'Bar'
});
assert.isNotNull(req.error);
assert.equal(req.error.errorText, '');
assert.equal(req.error.controllerName, '');
assert.equal(req.error.startNodeName, '');
});
});

View File

@@ -0,0 +1,353 @@
/* eslint "no-underscore-dangle": ["error", { "allow": ["__routes"] }] */
'use strict';
var Route = require('../../../../cartridges/modules/server/route');
var assert = require('chai').assert;
var middleware = require('../../../../cartridges/modules/server/middleware');
var proxyquire = require('proxyquire').noCallThru().noPreserveCache();
var sinon = require('sinon');
var render = {
template: sinon.spy(),
json: sinon.spy(),
xml: sinon.spy(),
applyRenderings: sinon.spy()
};
var server = null;
function request() {
return {
httpMethod: 'GET',
host: 'localhost',
path: 'test',
querystring: '',
locale: {
id: ''
},
https: false,
currentCustomer: {
raw: {},
profile: {},
addressBook: {},
wallet: {}
}
};
}
describe('server', function () {
// this function initializes fields in the response object
// which is created in the server.use method
var initResponse = function (response) {
response.cachePeriod = 0; // eslint-disable-line no-param-reassign
response.cachePeriodUnit = null; // eslint-disable-line no-param-reassign
response.personalized = false; // eslint-disable-line no-param-reassign
response.base = { // eslint-disable-line no-param-reassign
setExpires: function () {},
setVaryBy: function () {},
writer: {
print: function (message) { assert.equal(message, 'test'); }
}
};
response.json = function () {}; // eslint-disable-line no-param-reassign
response.isJson = true; // eslint-disable-line no-param-reassign
response.setViewData = function () { // eslint-disable-line no-param-reassign
return '';
};
response.renderings = [{ type: 'render', subType: 'json' }]; // eslint-disable-line no-param-reassign
return response;
};
beforeEach(function () {
server = proxyquire('../../../../cartridges/modules/server/server', {
'./render': render,
'./request': request,
'./response': require('../../../mocks/modules/responseMock'),
'dw/system/HookMgr': {
hasHook: function (/* extension */) {
return true;
},
callHook: function (/* extensionPoint, functionName , args */) {
}
}
});
});
it('should create a server with one route', function () {
server.use('test', function () {});
var exports = server.exports();
assert.equal(typeof exports.test, 'function');
});
it('should apply default page cache period value', function () {
var mockResp = null;
server.use('test', function (req, res, next) {
mockResp = initResponse(res);
res.cachePeriod = 24; // eslint-disable-line no-param-reassign
res.cachePeriodUnit = 'hours'; // eslint-disable-line no-param-reassign
next();
});
var exports = server.exports();
var route = exports.__routes.test;
var routeStartHit = false;
var routeCompleteHit = false;
route.once('route:Start', function () {
routeStartHit = true;
});
route.on('route:Complete', function () {
routeCompleteHit = true;
assert.equal(typeof mockResp.cachePeriod, 'number');
assert.equal(24, mockResp.cachePeriod);
assert.equal('hours', mockResp.cachePeriodUnit);
assert.equal(false, mockResp.personalized);
});
exports.test();
assert.isTrue(routeStartHit);
assert.isTrue(routeCompleteHit);
});
it('should apply default page cache period value', function () {
var mockResp = null;
server.use('test', function (req, res, next) {
mockResp = initResponse(res);
res.cachePeriod = 30; // eslint-disable-line no-param-reassign
res.cachePeriodUnit = 'minutes'; // eslint-disable-line no-param-reassign
res.personalized = true; // eslint-disable-line no-param-reassign
res.renderings = [{ type: 'render', subType: 'xml' }]; // eslint-disable-line no-param-reassign
next();
});
var exports = server.exports();
var route = exports.__routes.test;
var routeStartHit = false;
var routeCompleteHit = false;
route.once('route:Start', function () {
routeStartHit = true;
});
route.on('route:Complete', function () {
routeCompleteHit = true;
assert.equal(typeof mockResp.cachePeriod, 'number');
assert.equal(30, mockResp.cachePeriod);
assert.equal('minutes', mockResp.cachePeriodUnit);
assert.equal(true, mockResp.personalized);
});
exports.test();
assert.isTrue(routeStartHit);
assert.isTrue(routeCompleteHit);
});
it('should print', function () {
server.use('test', function (req, res, next) {
initResponse(res);
res.cachePeriod = 30; // eslint-disable-line no-param-reassign
res.cachePeriodUnit = 'minutes'; // eslint-disable-line no-param-reassign
res.personalized = true; // eslint-disable-line no-param-reassign
res.renderings = [{ type: 'print', message: 'test' }]; // eslint-disable-line no-param-reassign
next();
});
var exports = server.exports();
exports.test();
});
it('should create a server with a route of two steps', function () {
server.get('test', function () {});
var exports = server.exports();
assert.equal(exports.__routes.test.chain.length, 2);
});
it('should create a server with two routes', function () {
server.get('test', function () {}, function () {});
server.post('test2', function () {});
var exports = server.exports();
assert.equal(typeof exports.test, 'function');
assert.equal(typeof exports.test2, 'function');
assert.equal(exports.__routes.test.chain.length, 3);
assert.equal(exports.__routes.test2.chain.length, 2);
});
it('should extend existing chain with 2 more steps', function () {
server.get('test', function () {});
var exports = server.exports();
assert.equal(exports.__routes.test.chain.length, 2);
server.extend(exports);
server.append('test', function () {}, function () {});
assert.equal(exports.__routes.test.chain.length, 4);
});
it('The extended chain with append should be executed last.', function () {
server.get('test', function () {});
var exports = server.exports();
server.extend(exports);
server.append('test', function () {}, function () { return 'EXECUTED'; });
assert.equal(server.getRoute('test').chain[3](), 'EXECUTED');
});
it('The extended chain with prepend should be executed first.', function () {
server.get('test', function () {});
var exports = server.exports();
server.extend(exports);
server.prepend('test', function () { return 'EXECUTED'; });
assert.equal(server.getRoute('test').chain[0](), 'EXECUTED');
});
it('should replace existing route with a new one', function () {
var spy = sinon.spy();
var spy2 = sinon.spy();
server.get('test', spy);
var exports = server.exports();
server.extend(exports);
server.replace('test', spy2);
var newExports = server.exports();
newExports.test();
assert.isTrue(spy.notCalled);
assert.isTrue(spy2.called);
});
it('should throw when replacing non-existing route', function () {
var testFn = function () {
server.replace('blah', function () {});
};
assert.throws(testFn, 'Route with this name does not exist');
});
it('should throw when trying to create two routes with the same name', function () {
server.get('test', function () {});
assert.throws(function () { server.post('test', function () {}); });
});
it('should throw when route name is not provided', function () {
assert.throws(function () { server.get(function () {}); });
});
it('should throw when route chain contains non-functions', function () {
assert.throws(function () { server.get('test', {}); });
});
it('should throw when trying to append to non-existing route', function () {
server.get('test', function () {});
server.extend(server.exports());
assert.throws(function () { server.append('foo', function () {}); });
});
it('should throw when extending server without routes', function () {
assert.throws(function () { server.extend(server.exports()); });
});
it('should throw when extending server with an object', function () {
assert.throws(function () { server.extend({}); });
});
it('should throw when middleware doesn\'t match route', function () {
server.post('test', middleware.https, function (req, res, next) {
req.render('test', { name: 'value' }); next();
});
assert.throws(function () { server.exports().test(); });
});
it('should verify that whole route passes', function () {
server.get('test', middleware.http, function (req, res, next) {
res.render('test', { name: 'value' });
next();
});
var exports = server.exports();
exports.test();
var result = render.applyRenderings.called;
assert.isTrue(result);
});
it('should verify that all events are emitted', function (done) {
server.get('test', middleware.http, function (req, res, next) {
res.json({ name: 'value' });
next();
});
var exports = server.exports();
var route = exports.__routes.test;
var routeStartHit = false;
var routeStepHits = 0;
route.once('route:Start', function () {
routeStartHit = true;
});
route.on('route:Step', function () {
routeStepHits += 1;
});
route.on('route:Complete', function () {
assert.isTrue(routeStartHit);
assert.equal(routeStepHits, 2);
done();
});
exports.test();
});
it('should maintain events for exported route', function () {
var spy = sinon.spy();
var spy2 = sinon.spy();
server.get('test', spy);
var exports = server.exports();
var route = exports.__routes.test;
route.on('route:Start', spy2);
var exported = server.exports();
assert.equal(exported.__routes.test.listeners('route:Start').length, 1);
});
it('should correctly remove event after export', function () {
var spy = sinon.spy();
var spy2 = sinon.spy();
server.get('test', spy);
var exports = server.exports();
var route = exports.__routes.test;
route.on('route:Start', spy2);
var exported = server.exports();
exported.__routes.test.off('route:Start');
exported.test();
assert.isTrue(spy.called);
assert.isTrue(spy2.notCalled);
});
it('should verify that request is frozen', function (done) {
server.get('test', function (req) {
assert.isFrozen(req);
done();
});
server.exports().test();
});
it('should retrieve a route by name', function () {
server.get('test', function (req, res, next) {
res.json({ name: 'value' });
next();
});
var testRoute = server.getRoute('test');
assert.isNotNull(testRoute);
});
it('should return a route on get call', function () {
var route = server.get('test', function () {});
assert.isTrue(route instanceof Route);
});
it('should redirect if requested in BeforeComplete', function (done) {
server.get('test', function (req, res, next) {
this.on('route:BeforeComplete', function (r, response) {
response.base.redirect = function (text) { // eslint-disable-line no-param-reassign
assert.equal(text, 'test');
done();
};
response.redirect('test');
});
next();
});
var exports = server.exports();
exports.test();
});
});

View File

@@ -0,0 +1,42 @@
'use strict';
var assert = require('chai').assert;
var SimpleCache = require('../../../../cartridges/modules/server/simpleCache');
describe('simpleCache', function () {
beforeEach(function () {
});
afterEach(function () {
});
it('should handle null argument for constructor', function () {
var cache = new SimpleCache(null);
assert.isTrue(cache !== null);
});
it('should accept a pre-filled KV store', function () {
var cache = new SimpleCache({ 'foo': 'bar' });
var value = cache.get('foo');
assert.isTrue(value === 'bar');
});
it('should get a value previously set', function () {
var cache = new SimpleCache({});
cache.set('foo', 'bar');
var value = cache.get('foo');
assert.isTrue(value === 'bar');
});
it('should correctly clear() values previously set', function () {
var cache = new SimpleCache({});
cache.set('foo', 'bar');
cache.clear();
var value = cache.get('foo');
assert.isTrue(value === null);
});
});