Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into #13/fix-checkboxgro…
Browse files Browse the repository at this point in the history
…ups-return-value

# Conflicts:
#	dist/clay.js
  • Loading branch information
keegan-lillo committed Mar 1, 2016
2 parents 95c2039 + f7717dc commit 28fa722
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 24 deletions.
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,11 @@ This is the main way of talking to your generated config page.
|----------|------|-------------|
| `.EVENTS.BEFORE_BUILD` | String | Dispatched prior to building the page. |
| `.EVENTS.AFTER_BUILD` | String | Dispatched after building the page. |
| `.config` | Array | Reference to the config passed to the constructer and used for generating the page. |
| `.config` | Array | Reference to the config passed to the constructor and used for generating the page. |
| `.meta` | Object | Contains information about the current user and watch |
| `.meta.activeWatchInfo` | watchinfo\|null | An object containing information on the currently connected Pebble smartwatch or null if unavailable. Read more [here](https://developer.pebble.com/docs/js/Pebble/#getActiveWatchInfo). |
| `.meta.accountToken` | String | A unique account token that is associated with the Pebble account of the current user. Read more [here](https://developer.pebble.com/docs/js/Pebble/#getAccountToken). |
| `.meta.watchToken` | String | A unique token that can be used to identify a Pebble device. Read more [here](https://developer.pebble.com/docs/js/Pebble/#getWatchToken). |


#### Methods
Expand Down Expand Up @@ -637,7 +641,7 @@ This is the main way of talking to your generated config page.
| `.appKey` | String | The ID of the item if provided in the config. |
| `.config` | Object | Reference to the config passed to the constructer. |
| `$element` | $Minified | A Minified list representing the root HTML element of the config item. |
| `$manipulatorTarget` | A Minified list representing the HTML element with **data-manipulator-target** set. This is generally pointing to the main `<input>` element and will be used for binding events. |
| `$manipulatorTarget` | $Minified | A Minified list representing the HTML element with **data-manipulator-target** set. This is generally pointing to the main `<input>` element and will be used for binding events. |


#### Methods
Expand Down
6 changes: 3 additions & 3 deletions dist/clay.js

Large diffs are not rendered by default.

26 changes: 25 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,17 @@ function Clay(config, customFn, options) {
self.config = config;
self.customFn = customFn || function() {};
self.components = {};
self.meta = {
activeWatchInfo: null,
accountToken: '',
watchToken: ''
};

// Let Clay handle all the magic
if (options.autoHandleEvents !== false && typeof Pebble !== 'undefined') {

Pebble.addEventListener('showConfiguration', function() {
_populateMeta();
Pebble.openURL(self.generateUrl());
});

Expand All @@ -49,6 +55,23 @@ function Clay(config, customFn, options) {
console.log(JSON.stringify(error));
});
});
} else if (typeof Pebble !== 'undefined') {
Pebble.addEventListener('ready', function() {
_populateMeta();
});
}

/**
* Populate the meta with data from the Pebble object. Make sure to run this inside
* either the "showConfiguration" or "ready" event handler
* @return {void}
*/
function _populateMeta() {
self.meta = {
activeWatchInfo: Pebble.getActiveWatchInfo && Pebble.getActiveWatchInfo(),
accountToken: Pebble.getAccountToken(),
watchToken: Pebble.getWatchToken()
};
}

/**
Expand Down Expand Up @@ -107,7 +130,8 @@ Clay.prototype.generateUrl = function() {
.replace('$$CUSTOM_FN$$', toSource(this.customFn))
.replace('$$CONFIG$$', toSource(this.config))
.replace('$$SETTINGS$$', toSource(settings))
.replace('$$COMPONENTS$$', toSource(this.components));
.replace('$$COMPONENTS$$', toSource(this.components))
.replace('$$META$$', toSource(this.meta));

// if we are in the emulator then we need to proxy the data via a webpage to
// obtain the return_to.
Expand Down
1 change: 1 addition & 0 deletions src/config-page.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
window.claySettings = $$SETTINGS$$;
window.customFn = $$CUSTOM_FN$$;
window.clayComponents = $$COMPONENTS$$;
window.clayMeta = $$META$$;
</script>
</head>
<body>
Expand Down
3 changes: 2 additions & 1 deletion src/scripts/config-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ var settings = _.extend({}, window.claySettings || {});
var returnTo = window.returnTo || 'pebblejs://close#';
var customFn = window.customFn || function() {};
var clayComponents = window.clayComponents || {};
var clayMeta = window.clayMeta || {};

var platform = window.navigator.userAgent.match(/android/i) ? 'android' : 'ios';
document.documentElement.classList.add('platform-' + platform);
Expand All @@ -21,7 +22,7 @@ _.eachObj(clayComponents, function(key, component) {
});

var $mainForm = $('#main-form');
var clayConfig = new ClayConfig(settings, config, $mainForm);
var clayConfig = new ClayConfig(settings, config, $mainForm, clayMeta);

// add listeners here
$mainForm.on('submit', function() {
Expand Down
6 changes: 4 additions & 2 deletions src/scripts/lib/clay-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ var manipulators = require('./manipulators');
* @param {Object} settings - setting that were set from a previous session
* @param {Array|Object} config
* @param {M} $rootContainer
* @param {Object} meta
* @constructor
*/
function ClayConfig(settings, config, $rootContainer) {
function ClayConfig(settings, config, $rootContainer, meta) {
var self = this;

var _settings = _.copyObj(settings);
Expand Down Expand Up @@ -95,6 +96,8 @@ function ClayConfig(settings, config, $rootContainer) {
return true;
}

self.meta = meta;

self.EVENTS = {
/**
* Called before framework has initialized. This is when you would attach your
Expand Down Expand Up @@ -183,7 +186,6 @@ function ClayConfig(settings, config, $rootContainer) {

// expose the config to allow developers to update it before the build is run
self.config = config;

}

/**
Expand Down
26 changes: 25 additions & 1 deletion test/fixture.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,29 @@ var components = require('../src/scripts/components');
var componentRegistry = require('../src/scripts/lib/component-registry');
var idCounter = 0;

/**
* @returns {{accountToken: string, watchToken: string, activeWatchInfo: {platform:
* string, model: string, language: string, firmware: {major: number, minor:
* number, patch: number, suffix: string}}}}
*/
module.exports.meta = function() {
return {
accountToken: '0123456789abcdef0123456789abcdef',
watchToken: '0123456789abcdef0123456789abcdef',
activeWatchInfo: {
platform: 'chalk',
model: 'qemu_platform_chalk',
language: 'en_US',
firmware: {
major: 3,
minor: 3,
patch: 2,
suffix: ''
}
}
};
};

/**
* @param {string|Object} config
* @param {boolean} [autoRegister=true]
Expand Down Expand Up @@ -70,7 +93,8 @@ module.exports.clayConfig = function(types, build, autoRegister, settings) {
var clayConfig = new ClayConfig(
settings || {},
module.exports.config(types, autoRegister),
$(HTML('<div>'))
$(HTML('<div>')),
module.exports.meta()
);
return build === false ? clayConfig : clayConfig.build();
};
Expand Down
142 changes: 129 additions & 13 deletions test/spec/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,21 @@ var Clay = require('../../index');
var assert = require('chai').assert;
var standardComponents = require('../../src/scripts/components');
var sinon = require('sinon');
var toSource = require('tosource');

var accountToken = '0123456789abcdef0123456789abcdef';
var watchToken = '0123456789abcdef0123456789abcdef';
var activeWatchInfo = {
platform: 'chalk',
model: 'qemu_platform_chalk',
language: 'en_US',
firmware: {
major: 3,
minor: 3,
patch: 2,
suffix: ''
}
};

/**
* @return {void}
Expand All @@ -13,7 +28,10 @@ function stubPebble() {
global.Pebble = {
addEventListener: sinon.stub(),
openURL: sinon.stub(),
sendAppMessage: sinon.stub()
sendAppMessage: sinon.stub(),
getActiveWatchInfo: sinon.stub().returns(activeWatchInfo),
getAccountToken: sinon.stub().returns(accountToken),
getWatchToken: sinon.stub().returns(watchToken)
};
}

Expand Down Expand Up @@ -56,6 +74,8 @@ describe('Clay', function() {

it('handles the "showConfiguration" event if autoHandleEvents is not false',
function() {
this.timeout(10000); // 10 seconds

stubPebble();
var clay = fixture.clay([]);

Expand Down Expand Up @@ -104,7 +124,14 @@ describe('Clay', function() {
'if autoHandleEvents is false', function() {
stubPebble();
fixture.clay([], null, { autoHandleEvents: false });
assert.strictEqual(Pebble.addEventListener.called, false);
assert.strictEqual(
Pebble.addEventListener.withArgs('webviewclosed').called,
false
);
assert.strictEqual(
Pebble.addEventListener.withArgs('showConfiguration').called,
false
);
});
});

Expand All @@ -123,23 +150,66 @@ describe('Clay', function() {

describe('.generateUrl()', function() {

// @todo this test becomes redundant with the work in 94428b1
it('Replaces $$RETURN_TO$$ if in not in the emulator', function() {
var clay = fixture.clay([]);
stubPebble();
Pebble.platform = 'ios';
var decodedUrl =
atob(decodeURIComponent(clay.generateUrl().replace(/^.*?,/, '')));
assert.match(decodedUrl, /pebblejs:\/\/close#/);
/**
* Decode the generated data URI into just the HTML portion
* @param {string} url
* @returns {string}
*/
function decodeUrl(url) {
return atob(decodeURIComponent(url.replace(/^.*?[#,]/, '')));
}

describe('string substitutions', function() {
var customFn = function() { this.getAllItems(); };
var config = fixture.config(['input', 'color']);
var settings = { appKey: 'value' };
var clay;
var html;

before(function() {
stubPebble();
clay = fixture.clay(config, customFn);
Pebble.addEventListener.withArgs('showConfiguration').callArg(1);
localStorage.setItem('clay-settings', JSON.stringify(settings));
html = decodeUrl(clay.generateUrl());
});

it('Substitutes $$RETURN_TO$$ with the pebblejs://close#', function() {
assert.notInclude(html, '$$RETURN_TO$$');
assert.include(html, 'window.returnTo="pebblejs://close#"');
});

it('Substitutes $$CUSTOM_FN$$ with the customFn', function() {
assert.notInclude(html, '$$CUSTOM_FN$$');
assert.include(html, 'window.customFn=' + toSource(customFn));
});

it('Substitutes $$CONFIG$$ with the config', function() {
assert.notInclude(html, '$$CONFIG$$');
assert.include(html, 'window.clayConfig=' + toSource(config));
});

it('Substitutes $$SETTINGS$$ with the config', function() {
assert.notInclude(html, '$$SETTINGS$$');
assert.include(html, 'window.claySettings=' + toSource(settings));
});

it('Substitutes $$COMPONENTS$$ with the config', function() {
assert.notInclude(html, '$$COMPONENTS$$');
assert.include(html, 'window.clayComponents=' + toSource(clay.components));
});

it('Substitutes $$META$$ with the config', function() {
assert.notInclude(html, '$$META$$');
assert.include(html, 'window.clayMeta=' + toSource(clay.meta));
});
});

it('does not replace $$RETURN_TO$$ if in the emulator', function() {
var clay = fixture.clay([]);
stubPebble();
Pebble.platform = 'pypkjs';
var decodedUrl =
atob(decodeURIComponent(clay.generateUrl().replace(/^.*?#/, '')));
assert.match(decodedUrl, /\$\$RETURN_TO\$\$/);
assert.match(decodeUrl(clay.generateUrl()), /\$\$RETURN_TO\$\$/);
});

it('returns the emulator URL if inside emulator', function() {
Expand Down Expand Up @@ -186,6 +256,52 @@ describe('Clay', function() {
});
});

describe('.meta', function() {
var emptyMeta = {
activeWatchInfo: null,
accountToken: '',
watchToken: ''
};

it('populates the meta in the showConfiguration handler', function() {
stubPebble();
var clay = fixture.clay([]);

// meta only gets populated after showConfiguration happens
assert.deepEqual(clay.meta, emptyMeta);
Pebble.addEventListener.withArgs('showConfiguration').callArg(1);

assert.deepEqual(clay.meta, {
activeWatchInfo: activeWatchInfo,
accountToken: accountToken,
watchToken: watchToken
});
});

it('populates the meta in the ready handler', function() {
stubPebble();
var clay = fixture.clay([], null, {autoHandleEvents: false});

// meta only gets populated after ready happens
assert.deepEqual(clay.meta, emptyMeta);
Pebble.addEventListener.withArgs('ready').callArg(1);

assert.deepEqual(clay.meta, {
activeWatchInfo: activeWatchInfo,
accountToken: accountToken,
watchToken: watchToken
});
});

it('populates the meta with with empty values when there is no Pebble global',
function() {
delete global.Pebble;
var clay = fixture.clay([], null, {autoHandleEvents: false});

assert.deepEqual(clay.meta, emptyMeta);
});
});

describe('Clay.encodeDataUri()', function() {

/**
Expand Down
10 changes: 9 additions & 1 deletion test/spec/lib/clay-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,20 @@ describe('ClayConfig', function() {
'build',
'on',
'off',
'trigger'
'trigger',
'meta'
];
var clayConfig = fixtures.clayConfig(['input']);
checkReadOnly(clayConfig, properties);
});

describe('.meta', function() {
it('populates meta', function() {
var clayConfig = fixtures.clayConfig(['input']);
assert.deepEqual(clayConfig.meta, fixtures.meta());
});
});

describe('throws when trying to run methods before being built', function() {
[
'getItemByAppKey',
Expand Down

0 comments on commit 28fa722

Please sign in to comment.