diff --git a/dev/config.js b/dev/config.js index 0499478..90c5f7e 100644 --- a/dev/config.js +++ b/dev/config.js @@ -61,6 +61,14 @@ module.exports = [ "type": "date" } }, + { + "type": "input", + "id": "password", + "label": "Password Field", + "attributes": { + "type": "password" + } + }, { "type": "slider", "messageKey": "slider", diff --git a/dev/custom-fn.js b/dev/custom-fn.js index f8d25dc..ff2618b 100644 --- a/dev/custom-fn.js +++ b/dev/custom-fn.js @@ -32,5 +32,10 @@ module.exports = function() { Clay.getItemById('testButton').on('click', handleButtonClick); }); + Clay.on(Clay.EVENTS.BEFORE_SUBMIT, function() { + var password = Clay.getItemById('password').get(); + Clay.meta.userData.password = password; + }); + console.log('userData: ', Clay.meta.userData); }; diff --git a/index.js b/index.js index d02f6d7..4046d3e 100755 --- a/index.js +++ b/index.js @@ -189,16 +189,17 @@ Clay.prototype.generateUrl = function() { */ Clay.prototype.getSettings = function(response, convert) { // Decode and parse config data as JSON - var settings = {}; + var payload = {}; response = response.match(/^\{/) ? response : decodeURIComponent(response); try { - settings = JSON.parse(response); + payload = JSON.parse(response); } catch (e) { throw new Error('The provided response was not valid JSON'); } // flatten the settings for localStorage + var settings = payload.settings; var settingsStorage = {}; Object.keys(settings).forEach(function(key) { if (typeof settings[key] === 'object' && settings[key]) { @@ -213,6 +214,25 @@ Clay.prototype.getSettings = function(response, convert) { return convert === false ? settings : Clay.prepareSettingsForAppMessage(settings); }; +/** + * Parse the response from the webviewclosed event data + * @param {string} response + * @returns {Object} + */ +Clay.prototype.getUserData = function(response) { + // Decode and parse config data as JSON + var payload = {}; + response = response.match(/^\{/) ? response : decodeURIComponent(response); + + try { + payload = JSON.parse(response); + } catch (e) { + throw new Error('The provided response was not valid JSON'); + } + + return payload.userData; +}; + /** * Updates the settings with the given value(s). * diff --git a/src/scripts/lib/clay-config.js b/src/scripts/lib/clay-config.js index 0a31610..eabe794 100644 --- a/src/scripts/lib/clay-config.js +++ b/src/scripts/lib/clay-config.js @@ -129,6 +129,13 @@ function ClayConfig(settings, config, $rootContainer, meta) { */ AFTER_BUILD: 'AFTER_BUILD', + /** + * Called before configuration is returned to app.js. This is when you would set + * properties of of userData to pass back. + * @const + */ + BEFORE_SUBMIT: 'BEFORE_SUBMIT', + /** * Called if .build() is executed after the page has already been built and * before the existing content is destroyed @@ -210,7 +217,13 @@ function ClayConfig(settings, config, $rootContainer, meta) { _settings[messageKey].precision = item.precision; } }); - return _settings; + + self.trigger(self.EVENTS.BEFORE_SUBMIT); + + return { + settings: _settings, + userData: meta.userData + }; }; // @todo maybe don't do this and force the static method diff --git a/test/spec/index.js b/test/spec/index.js index 0088eb9..4f99be9 100644 --- a/test/spec/index.js +++ b/test/spec/index.js @@ -107,14 +107,14 @@ describe('Clay', function() { stubPebble(); fixture.clay([]); var logStub = sinon.stub(console, 'log'); - var expected = {someSetting: 'value'}; + var expected = {settings: {someSetting: 'value'}, userData: {}}; - stubMessageKeys(fixture.messageKeysObjToArray(expected)); + stubMessageKeys(fixture.messageKeysObjToArray(expected.settings)); Pebble.addEventListener .withArgs('webviewclosed') .callArgWith(1, {response: encodeURIComponent(JSON.stringify(expected))}); - var expectedAppMessage = fixture.messageKeysExpected(expected); + var expectedAppMessage = fixture.messageKeysExpected(expected.settings); assert(Pebble.addEventListener.calledWith('webviewclosed')); assert(Pebble.sendAppMessage.calledWith(expectedAppMessage)); @@ -269,13 +269,66 @@ describe('Clay', function() { }); }); + describe('.getUserData', function() { + it('it returns the data when input is encoded', + function() { + var clay = fixture.clay([]); + var payload = encodeURIComponent(JSON.stringify({ + settings: {}, + userData: { + key1: 'value1', + key2: 'value2' + } + })); + var expected = { + key1: 'value1', + key2: 'value2' + }; + + var result = clay.getUserData(payload); + assert.deepEqual(result, expected); + }); + + it('it returns the data when input is not encoded', + function() { + var clay = fixture.clay([]); + var unencodedResponse = JSON.stringify({ + settings: {}, + userData: { + key1: 'value1', + key2: 'value2%7Dbreaks' + } + }); + var expected = { + key1: 'value1', + key2: 'value2%7Dbreaks' + }; + + var result = clay.getUserData(unencodedResponse); + assert.deepEqual(result, expected); + }); + + it('it logs an error if it is invalid JSON', + function() { + var clay = fixture.clay([]); + + assert.throws(function() { + clay.getUserData('not valid JSON'); + }, /Not Valid JSON/i); + }); + + }); + describe('.getSettings', function() { it('it writes to localStorage and returns the data when input is encoded', function() { var clay = fixture.clay([]); - var settings = encodeURIComponent(JSON.stringify({ - key1: 'value1', - key2: {value: 'value2'} + var payload = encodeURIComponent(JSON.stringify({ + settings: { + key1: 'value1', + key2: {value: 'value2'} + }, + userData: {} })); var expected = { key1: 'value1', @@ -284,7 +337,7 @@ describe('Clay', function() { stubMessageKeys(fixture.messageKeysObjToArray(expected)); - var result = clay.getSettings(settings); + var result = clay.getSettings(payload); assert.equal( localStorage.getItem('clay-settings'), JSON.stringify(expected) @@ -295,9 +348,12 @@ describe('Clay', function() { it('it writes to localStorage and returns the data when input is not encoded', function() { var clay = fixture.clay([]); - var settings = JSON.stringify({ - key1: 'value1', - key2: {value: 'value2%7Dbreaks'} + var unencodedResponse = JSON.stringify({ + settings: { + key1: 'value1', + key2: {value: 'value2%7Dbreaks'} + }, + userData: {} }); var expected = { key1: 'value1', @@ -306,7 +362,7 @@ describe('Clay', function() { stubMessageKeys(fixture.messageKeysObjToArray(expected)); - var result = clay.getSettings(settings); + var result = clay.getSettings(unencodedResponse); assert.equal( localStorage.getItem('clay-settings'), JSON.stringify(expected) @@ -328,21 +384,24 @@ describe('Clay', function() { it('Prepares the settings for sendAppMessage', function() { var clay = fixture.clay([]); var response = encodeURIComponent(JSON.stringify({ - test1: false, - test2: 'val-2', - test3: true, - test4: ['cb-1', 'cb-3'], - test5: 12345, - test6: [1, 2, 3, 4], - test7: [true, false, true], - test8: { - precision: 2, - value: 12.34 + settings: { + test1: false, + test2: 'val-2', + test3: true, + test4: ['cb-1', 'cb-3'], + test5: 12345, + test6: [1, 2, 3, 4], + test7: [true, false, true], + test8: { + precision: 2, + value: 12.34 + }, + test9: { + precision: 1, + value: [1, 2, 3, 4] + } }, - test9: { - precision: 1, - value: [1, 2, 3, 4] - } + userData: {} })); var expected = { test1: 0, @@ -367,22 +426,25 @@ describe('Clay', function() { it('does not prepare the settings for sendAppMessage if convert is false', function() { var clay = fixture.clay([]); - var settings = { - test1: false, - test2: 'val-2', - test3: true, - test4: ['cb-1', 'cb-3'], - test5: 12345, - test6: [1, 2, 3, 4], - test7: [true, false, true], - test8: { - precision: 2, - value: 12.34 - } + var payload = { + settings: { + test1: false, + test2: 'val-2', + test3: true, + test4: ['cb-1', 'cb-3'], + test5: 12345, + test6: [1, 2, 3, 4], + test7: [true, false, true], + test8: { + precision: 2, + value: 12.34 + } + }, + userData: {} }; - var response = encodeURIComponent(JSON.stringify(settings)); + var response = encodeURIComponent(JSON.stringify(payload)); - assert.deepEqual(clay.getSettings(response, false), settings); + assert.deepEqual(clay.getSettings(response, false), payload.settings); }); }); diff --git a/test/spec/lib/clay-config.js b/test/spec/lib/clay-config.js index abffc45..4b71e74 100644 --- a/test/spec/lib/clay-config.js +++ b/test/spec/lib/clay-config.js @@ -331,11 +331,14 @@ describe('ClayConfig', function() { var clayConfig = fixtures.clayConfig(config, true, true, settings); assert.deepEqual(clayConfig.serialize(), { - test1: {value: 'default val'}, - test2: {value: 'val-2'}, - test3: {value: false}, - test4: {value: [false, false, false]}, - test5: {value: 12.5, precision: 2} + settings: { + test1: {value: 'default val'}, + test2: {value: 'val-2'}, + test3: {value: false}, + test4: {value: [false, false, false]}, + test5: {value: 12.5, precision: 2} + }, + userData: {} }); clayConfig.getItemByMessageKey('test1').set('val-1'); @@ -343,11 +346,14 @@ describe('ClayConfig', function() { clayConfig.getItemByMessageKey('test4').set([true, false, true]); assert.deepEqual(clayConfig.serialize(), { - test1: {value: 'val-1'}, - test2: {value: 'val-2'}, - test3: {value: true}, - test4: {value: [true, false, true]}, - test5: {value: 12.5, precision: 2} + settings: { + test1: {value: 'val-1'}, + test2: {value: 'val-2'}, + test3: {value: true}, + test4: {value: [true, false, true]}, + test5: {value: 12.5, precision: 2} + }, + userData: {} }); // make sure the result of serialize() can actually be fed back in to @@ -384,8 +390,11 @@ describe('ClayConfig', function() { var clayConfig = fixtures.clayConfig(config, true, true, settings); assert.deepEqual(clayConfig.serialize(), { - test1: {value: 'default val'}, - test2: {value: 'val-2'} + settings: { + test1: {value: 'default val'}, + test2: {value: 'val-2'} + }, + userData: {} }); }); });