diff --git a/src/disco/api.js b/src/disco/api.js
index 073aed9f019..05c7aa76b33 100644
--- a/src/disco/api.js
+++ b/src/disco/api.js
@@ -1,10 +1,18 @@
import { Schema, arrayOf } from 'normalizr';
-import { addon, callApi } from 'core/api';
+import { callApi } from 'core/api';
-export const discoResult = new Schema('discoResults', {idAttribute: (result) => result.addon.slug});
-discoResult.addon = addon;
+export function getGuid(result) {
+ if (result.type === 'persona') {
+ return `${result.id}@personas.mozilla.org`;
+ }
+ return result.guid;
+}
+export const discoResult =
+ new Schema('discoResults', {idAttribute: (result) => getGuid(result.addon)});
+export const addon = new Schema('addons', {idAttribute: getGuid});
+discoResult.addon = addon;
export function getDiscoveryAddons({ api }) {
return callApi({
diff --git a/src/disco/components/Addon.js b/src/disco/components/Addon.js
index d89ade0d1de..8bd873fea2d 100644
--- a/src/disco/components/Addon.js
+++ b/src/disco/components/Addon.js
@@ -34,6 +34,7 @@ export class Addon extends React.Component {
editorialDescription: PropTypes.string.isRequired,
errorMessage: PropTypes.string,
footerURL: PropTypes.string,
+ guid: PropTypes.string.isRequired,
headerURL: PropTypes.string,
heading: PropTypes.string.isRequired,
i18n: PropTypes.string.isRequired,
@@ -41,7 +42,6 @@ export class Addon extends React.Component {
id: PropTypes.string.isRequired,
previewURL: PropTypes.string,
name: PropTypes.string.isRequired,
- slug: PropTypes.string.isRequired,
status: PropTypes.oneOf(validInstallStates).isRequired,
textcolor: PropTypes.string,
themeAction: PropTypes.func,
@@ -117,7 +117,7 @@ export class Addon extends React.Component {
}
render() {
- const { heading, slug, type } = this.props;
+ const { guid, heading, type } = this.props;
if (!validAddonTypes.includes(type)) {
throw new Error(`Invalid addon type "${type}"`);
@@ -141,7 +141,7 @@ export class Addon extends React.Component {
{this.getDescription()}
-
+
diff --git a/src/disco/containers/InstallButton.js b/src/disco/containers/InstallButton.js
index 9bf996fece8..7de8e9e1475 100644
--- a/src/disco/containers/InstallButton.js
+++ b/src/disco/containers/InstallButton.js
@@ -24,7 +24,7 @@ import 'disco/css/InstallButton.scss';
export class InstallButton extends React.Component {
static propTypes = {
handleChange: PropTypes.func,
- guid: PropTypes.string,
+ guid: PropTypes.string.isRequired,
install: PropTypes.func.isRequired,
installTheme: PropTypes.func.isRequired,
i18n: PropTypes.object.isRequired,
@@ -45,20 +45,19 @@ export class InstallButton extends React.Component {
}
componentDidMount() {
- const { guid, installURL, setInitialStatus, slug } = this.props;
- setInitialStatus({guid, installURL, slug});
+ const { guid, installURL, setInitialStatus } = this.props;
+ setInitialStatus({guid, installURL});
}
handleClick = (e) => {
e.preventDefault();
- const { guid, install, installURL, name, slug,
- status, installTheme, type, uninstall } = this.props;
+ const { guid, install, installURL, name, status, installTheme, type, uninstall } = this.props;
if (type === THEME_TYPE && status === UNINSTALLED) {
- installTheme(this.refs.themeData, slug, name);
+ installTheme(this.refs.themeData, guid, name);
} else if (status === UNINSTALLED) {
- install({ guid, installURL, slug, name });
+ install({ guid, installURL, name });
} else if (status === INSTALLED) {
- uninstall({ guid, installURL, slug, name, type });
+ uninstall({ guid, installURL, name, type });
}
}
@@ -97,21 +96,21 @@ export class InstallButton extends React.Component {
}
export function mapStateToProps(state, ownProps) {
- const installation = state.installations[ownProps.slug] || {};
- const addon = state.addons[ownProps.slug] || {};
+ const installation = state.installations[ownProps.guid] || {};
+ const addon = state.addons[ownProps.guid] || {};
return {...installation, ...addon};
}
-export function makeProgressHandler(dispatch, slug) {
+export function makeProgressHandler(dispatch, guid) {
return (addonInstall) => {
if (addonInstall.state === 'STATE_DOWNLOADING') {
const downloadProgress = parseInt(
100 * addonInstall.progress / addonInstall.maxProgress, 10);
- dispatch({type: 'DOWNLOAD_PROGRESS', payload: {slug, downloadProgress}});
+ dispatch({type: 'DOWNLOAD_PROGRESS', payload: {guid, downloadProgress}});
} else if (addonInstall.state === 'STATE_INSTALLING') {
- dispatch({type: 'START_INSTALL', payload: {slug}});
+ dispatch({type: 'START_INSTALL', payload: {guid}});
} else if (addonInstall.state === 'STATE_INSTALLED') {
- dispatch({type: 'INSTALL_COMPLETE', payload: {slug}});
+ dispatch({type: 'INSTALL_COMPLETE', payload: {guid}});
}
};
}
@@ -121,9 +120,9 @@ export function mapDispatchToProps(dispatch) {
return {};
}
return {
- setInitialStatus({ guid, installURL, slug }) {
+ setInitialStatus({ guid, installURL }) {
const addonManager = new AddonManager(guid, installURL);
- const payload = {guid, slug, url: installURL};
+ const payload = {guid, url: installURL};
return addonManager.getAddon()
.then(
(addon) => {
@@ -133,34 +132,34 @@ export function mapDispatchToProps(dispatch) {
() => dispatch({type: 'INSTALL_STATE', payload: {...payload, status: UNINSTALLED}}));
},
- install({ guid, installURL, slug, name }) {
- const addonManager = new AddonManager(guid, installURL, makeProgressHandler(dispatch, slug));
- dispatch({type: 'START_DOWNLOAD', payload: {slug}});
+ install({ guid, installURL, name }) {
+ const addonManager = new AddonManager(guid, installURL, makeProgressHandler(dispatch, guid));
+ dispatch({type: 'START_DOWNLOAD', payload: {guid}});
tracking.sendEvent({action: 'addon', category: INSTALL_CATEGORY, label: name});
return addonManager.install();
},
- installTheme(node, slug, name, _themeAction = themeAction) {
+ installTheme(node, guid, name, _themeAction = themeAction) {
_themeAction(node, THEME_INSTALL);
tracking.sendEvent({action: 'theme', category: INSTALL_CATEGORY, label: name});
return new Promise((resolve) => {
setTimeout(() => {
- dispatch({type: 'INSTALL_STATE', payload: {slug, status: INSTALLED}});
+ dispatch({type: 'INSTALL_STATE', payload: {guid, status: INSTALLED}});
resolve();
}, 250);
});
},
- uninstall({ guid, installURL, slug, name, type }) {
+ uninstall({ guid, installURL, name, type }) {
const addonManager = new AddonManager(guid, installURL);
- dispatch({type: 'START_UNINSTALL', payload: {slug}});
+ dispatch({type: 'START_UNINSTALL', payload: {guid}});
const action = {
ADDON_TYPE: 'addon',
THEME_TYPE: 'theme',
}[type] || 'invalid';
tracking.sendEvent({action, category: UNINSTALL_CATEGORY, label: name});
return addonManager.uninstall()
- .then(() => dispatch({type: 'UNINSTALL_COMPLETE', payload: {slug}}));
+ .then(() => dispatch({type: 'UNINSTALL_COMPLETE', payload: {guid}}));
},
};
}
diff --git a/src/disco/reducers/installations.js b/src/disco/reducers/installations.js
index 7c2922ea922..93c2c904e37 100644
--- a/src/disco/reducers/installations.js
+++ b/src/disco/reducers/installations.js
@@ -23,12 +23,11 @@ export default function installations(state = {}, { type, payload }) {
return state;
}
let addon;
- if (state[payload.slug]) {
- addon = {...state[payload.slug]};
+ if (state[payload.guid]) {
+ addon = {...state[payload.guid]};
}
if (type === 'INSTALL_STATE') {
addon = {
- slug: payload.slug,
guid: payload.guid,
url: payload.url,
downloadProgress: 0,
@@ -56,6 +55,6 @@ export default function installations(state = {}, { type, payload }) {
}
return {
...state,
- [payload.slug]: addon,
+ [payload.guid]: addon,
};
}
diff --git a/tests/client/disco/containers/TestInstallButton.js b/tests/client/disco/containers/TestInstallButton.js
index bcfadade83d..e8e9b663275 100644
--- a/tests/client/disco/containers/TestInstallButton.js
+++ b/tests/client/disco/containers/TestInstallButton.js
@@ -109,94 +109,92 @@ describe('', () => {
it('should call installTheme function on click when uninstalled theme', () => {
const installTheme = sinon.spy();
- const slug = 'my-theme';
- const button = renderButton({installTheme, type: THEME_TYPE, slug, status: UNINSTALLED});
+ const guid = 'test-guid';
+ const name = 'hai';
+ const button = renderButton({installTheme, type: THEME_TYPE, guid, name, status: UNINSTALLED});
const themeData = button.refs.themeData;
const root = findDOMNode(button);
Simulate.click(root);
- assert(installTheme.calledWith(themeData, slug));
+ assert(installTheme.calledWith(themeData, guid, name));
});
it('should call install function on click when uninstalled', () => {
const guid = '@foo';
+ const name = 'hai';
const install = sinon.spy();
const installURL = 'https://my.url/download';
- const name = 'hai';
- const slug = 'foo';
- const button = renderButton({guid, install, installURL, name, slug, status: UNINSTALLED});
+ const button = renderButton({guid, install, installURL, name, status: UNINSTALLED});
const root = findDOMNode(button);
Simulate.click(root);
- assert(install.calledWith({guid, installURL, slug, name}));
+ assert(install.calledWith({guid, installURL, name}));
});
it('should call uninstall function on click when installed', () => {
const guid = '@foo';
const installURL = 'https://my.url/download';
const name = 'hai';
- const slug = 'foo';
const type = 'whatevs';
const uninstall = sinon.spy();
- const button = renderButton({guid, installURL, name, slug, status: INSTALLED, type, uninstall});
+ const button = renderButton({guid, installURL, name, status: INSTALLED, type, uninstall});
const root = findDOMNode(button);
Simulate.click(root);
- assert(uninstall.calledWith({guid, installURL, slug, name, type}));
+ assert(uninstall.calledWith({guid, installURL, name, type}));
});
it('should call setInitialStatus in componentDidMount', () => {
const guid = '@foo';
const installURL = 'http://the.url';
const setInitialStatus = sinon.spy();
- const slug = 'foo';
- renderButton({guid, installURL, setInitialStatus, slug, status: UNKNOWN});
- assert(setInitialStatus.calledWith({guid, installURL, slug}));
+ renderButton({guid, installURL, setInitialStatus, status: UNKNOWN});
+ assert(setInitialStatus.calledWith({guid, installURL}));
});
describe('mapStateToProps', () => {
it('pulls the installation data from the state', () => {
const addon = {
- slug: 'addon',
+ guid: 'foo@addon',
downloadProgress: 75,
};
assert.deepEqual(
mapStateToProps({
- installations: {foo: {some: 'data'}, addon},
- addons: {addon: {addonProp: 'addonValue'}},
- }, {slug: 'addon'}),
- {slug: 'addon', downloadProgress: 75, addonProp: 'addonValue'});
+ installations: {foo: {some: 'data'}, 'foo@addon': addon},
+ addons: {'foo@addon': {addonProp: 'addonValue'}},
+ }, {guid: 'foo@addon'}),
+ {guid: 'foo@addon', downloadProgress: 75, addonProp: 'addonValue'});
});
});
describe('makeProgressHandler', () => {
it('sets the download progress on STATE_DOWNLOADING', () => {
const dispatch = sinon.spy();
- const slug = 'my-addon';
- const handler = makeProgressHandler(dispatch, slug);
+ const guid = 'foo@addon';
+ const handler = makeProgressHandler(dispatch, guid);
handler({state: 'STATE_DOWNLOADING', progress: 300, maxProgress: 990});
assert(dispatch.calledWith({
type: 'DOWNLOAD_PROGRESS',
- payload: {downloadProgress: 30, slug},
+ payload: {downloadProgress: 30, guid},
}));
});
it('sets status to installing on STATE_INSTALLING', () => {
const dispatch = sinon.spy();
- const slug = 'my-addon';
- const handler = makeProgressHandler(dispatch, slug);
+ const guid = 'foo@my-addon';
+ const handler = makeProgressHandler(dispatch, guid);
handler({state: 'STATE_INSTALLING'});
assert(dispatch.calledWith({
type: 'START_INSTALL',
- payload: {slug},
+ payload: {guid},
}));
});
it('sets status to installed on STATE_INSTALLED', () => {
const dispatch = sinon.spy();
- const slug = 'my-addon';
- const handler = makeProgressHandler(dispatch, slug);
+ const guid = '{my-addon}';
+ const handler = makeProgressHandler(dispatch, guid);
handler({state: 'STATE_INSTALLED'});
assert(dispatch.calledWith({
type: 'INSTALL_COMPLETE',
- payload: {slug},
+ payload: {guid},
}));
});
});
@@ -206,14 +204,13 @@ describe('', () => {
stubAddonManager();
const dispatch = sinon.spy();
const guid = '@foo';
- const slug = 'foo';
const installURL = 'http://the.url';
const { setInitialStatus } = mapDispatchToProps(dispatch);
- return setInitialStatus({guid, installURL, slug})
+ return setInitialStatus({guid, installURL})
.then(() => {
assert(dispatch.calledWith({
type: 'INSTALL_STATE',
- payload: {guid, slug, status: INSTALLED, url: installURL},
+ payload: {guid, status: INSTALLED, url: installURL},
}));
});
});
@@ -222,14 +219,13 @@ describe('', () => {
stubAddonManager({getAddon: Promise.resolve({type: THEME_TYPE, isEnabled: true})});
const dispatch = sinon.spy();
const guid = '@foo';
- const slug = 'foo';
const installURL = 'http://the.url';
const { setInitialStatus } = mapDispatchToProps(dispatch);
- return setInitialStatus({guid, installURL, slug})
+ return setInitialStatus({guid, installURL})
.then(() => {
assert(dispatch.calledWith({
type: 'INSTALL_STATE',
- payload: {guid, slug, status: INSTALLED, url: installURL},
+ payload: {guid, status: INSTALLED, url: installURL},
}));
});
});
@@ -238,14 +234,13 @@ describe('', () => {
stubAddonManager({getAddon: Promise.resolve({type: THEME_TYPE, isEnabled: false})});
const dispatch = sinon.spy();
const guid = '@foo';
- const slug = 'foo';
const installURL = 'http://the.url';
const { setInitialStatus } = mapDispatchToProps(dispatch);
- return setInitialStatus({guid, installURL, slug})
+ return setInitialStatus({guid, installURL})
.then(() => {
assert(dispatch.calledWith({
type: 'INSTALL_STATE',
- payload: {guid, slug, status: UNINSTALLED, url: installURL},
+ payload: {guid, status: UNINSTALLED, url: installURL},
}));
});
});
@@ -254,14 +249,13 @@ describe('', () => {
stubAddonManager({getAddon: Promise.reject()});
const dispatch = sinon.spy();
const guid = '@foo';
- const slug = 'foo';
const installURL = 'http://the.url';
const { setInitialStatus } = mapDispatchToProps(dispatch);
- return setInitialStatus({guid, installURL, slug})
+ return setInitialStatus({guid, installURL})
.then(() => {
assert(dispatch.calledWith({
type: 'INSTALL_STATE',
- payload: {guid, slug, status: UNINSTALLED, url: installURL},
+ payload: {guid, status: UNINSTALLED, url: installURL},
}));
});
});
@@ -270,13 +264,12 @@ describe('', () => {
describe('install', () => {
const guid = '@install';
const installURL = 'https://mysite.com/download.xpi';
- const slug = 'install';
it('installs the addon on a new AddonManager', () => {
stubAddonManager();
const dispatch = sinon.spy();
const { install } = mapDispatchToProps(dispatch);
- return install({guid, installURL, slug})
+ return install({guid, installURL})
.then(() => {
assert(addonManager.AddonManager.calledWithNew, 'new AddonManager() called');
assert(addonManager.AddonManager.calledWith(guid, installURL, sinon.match.func));
@@ -287,10 +280,10 @@ describe('', () => {
stubAddonManager();
const dispatch = sinon.spy();
const { install } = mapDispatchToProps(dispatch);
- return install({guid, installURL, slug})
+ return install({guid, installURL})
.then(() => assert(dispatch.calledWith({
type: 'START_DOWNLOAD',
- payload: {slug},
+ payload: {guid},
})));
});
});
@@ -298,13 +291,12 @@ describe('', () => {
describe('uninstall', () => {
const guid = '@uninstall';
const installURL = 'https://mysite.com/download.xpi';
- const slug = 'uninstall';
it('prepares the addon on a new AddonManager', () => {
stubAddonManager();
const dispatch = sinon.spy();
const { uninstall } = mapDispatchToProps(dispatch);
- return uninstall({guid, installURL, slug})
+ return uninstall({guid, installURL})
.then(() => {
assert(addonManager.AddonManager.calledWithNew, 'new AddonManager() called');
assert(addonManager.AddonManager.calledWith(guid, installURL));
@@ -315,10 +307,10 @@ describe('', () => {
stubAddonManager();
const dispatch = sinon.spy();
const { uninstall } = mapDispatchToProps(dispatch);
- return uninstall({guid, installURL, slug})
+ return uninstall({guid, installURL})
.then(() => assert(dispatch.calledWith({
type: 'START_UNINSTALL',
- payload: {slug},
+ payload: {guid},
})));
});
});
@@ -326,17 +318,17 @@ describe('', () => {
describe('installTheme', () => {
it('installs the theme', () => {
const name = 'hai-theme';
+ const guid = '{install-theme}';
const node = sinon.stub();
- const slug = 'install-theme';
const spyThemeAction = sinon.spy();
const dispatch = sinon.spy();
const { installTheme } = mapDispatchToProps(dispatch);
- return installTheme(node, slug, name, spyThemeAction)
+ return installTheme(node, guid, name, spyThemeAction)
.then(() => {
assert(spyThemeAction.calledWith(node, THEME_INSTALL));
assert(dispatch.calledWith({
type: 'INSTALL_STATE',
- payload: {slug, status: INSTALLED},
+ payload: {guid, status: INSTALLED},
}));
});
});
diff --git a/tests/client/disco/reducers/test_installations.js b/tests/client/disco/reducers/test_installations.js
index 823d4a5ce54..ed93552c2e3 100644
--- a/tests/client/disco/reducers/test_installations.js
+++ b/tests/client/disco/reducers/test_installations.js
@@ -23,15 +23,13 @@ describe('installations reducer', () => {
installations(undefined, {
type: 'INSTALL_STATE',
payload: {
- slug: 'my-addon',
guid: 'my-addon@me.com',
url: 'https://cdn.amo/download/my-addon.xpi',
status: UNINSTALLED,
},
}),
{
- 'my-addon': {
- slug: 'my-addon',
+ 'my-addon@me.com': {
guid: 'my-addon@me.com',
url: 'https://cdn.amo/download/my-addon.xpi',
downloadProgress: 0,
@@ -45,15 +43,13 @@ describe('installations reducer', () => {
installations(undefined, {
type: 'INSTALL_STATE',
payload: {
- slug: 'an-addon',
guid: 'an-addon@me.com',
url: 'https://cdn.amo/download/an-addon.xpi',
status: INSTALLED,
},
}),
{
- 'an-addon': {
- slug: 'an-addon',
+ 'an-addon@me.com': {
guid: 'an-addon@me.com',
url: 'https://cdn.amo/download/an-addon.xpi',
downloadProgress: 0,
@@ -64,8 +60,7 @@ describe('installations reducer', () => {
it('marks an add-on as installing on START_DOWNLOAD', () => {
const state = {
- 'my-addon': {
- slug: 'my-addon',
+ 'my-addon@me.com': {
guid: 'my-addon@me.com',
url: 'https://cdn.amo/download/my-addon.xpi',
downloadProgress: 0,
@@ -76,12 +71,11 @@ describe('installations reducer', () => {
installations(state, {
type: 'START_DOWNLOAD',
payload: {
- slug: 'my-addon',
+ guid: 'my-addon@me.com',
},
}),
{
- 'my-addon': {
- slug: 'my-addon',
+ 'my-addon@me.com': {
guid: 'my-addon@me.com',
url: 'https://cdn.amo/download/my-addon.xpi',
downloadProgress: 0,
@@ -92,8 +86,7 @@ describe('installations reducer', () => {
it('updates the downloadProgress on DOWNLOAD_PROGRESS', () => {
const state = {
- 'my-addon': {
- slug: 'my-addon',
+ 'my-addon@me.com': {
guid: 'my-addon@me.com',
url: 'https://cdn.amo/download/my-addon.xpi',
downloadProgress: 0,
@@ -104,13 +97,12 @@ describe('installations reducer', () => {
installations(state, {
type: 'DOWNLOAD_PROGRESS',
payload: {
- slug: 'my-addon',
+ guid: 'my-addon@me.com',
downloadProgress: 25,
},
}),
{
- 'my-addon': {
- slug: 'my-addon',
+ 'my-addon@me.com': {
guid: 'my-addon@me.com',
url: 'https://cdn.amo/download/my-addon.xpi',
downloadProgress: 25,
@@ -121,8 +113,7 @@ describe('installations reducer', () => {
it('updates the status and downloadProgress on START_INSTALL', () => {
const state = {
- 'my-addon': {
- slug: 'my-addon',
+ 'my-addon@me.com': {
guid: 'my-addon@me.com',
url: 'https://cdn.amo/download/my-addon.xpi',
downloadProgress: 75,
@@ -133,12 +124,11 @@ describe('installations reducer', () => {
installations(state, {
type: 'START_INSTALL',
payload: {
- slug: 'my-addon',
+ guid: 'my-addon@me.com',
},
}),
{
- 'my-addon': {
- slug: 'my-addon',
+ 'my-addon@me.com': {
guid: 'my-addon@me.com',
url: 'https://cdn.amo/download/my-addon.xpi',
downloadProgress: 100,
@@ -149,8 +139,7 @@ describe('installations reducer', () => {
it('updates the status on INSTALL_COMPLETE', () => {
const state = {
- 'my-addon': {
- slug: 'my-addon',
+ 'my-addon@me.com': {
guid: 'my-addon@me.com',
url: 'https://cdn.amo/download/my-addon.xpi',
downloadProgress: 100,
@@ -161,12 +150,11 @@ describe('installations reducer', () => {
installations(state, {
type: 'INSTALL_COMPLETE',
payload: {
- slug: 'my-addon',
+ guid: 'my-addon@me.com',
},
}),
{
- 'my-addon': {
- slug: 'my-addon',
+ 'my-addon@me.com': {
guid: 'my-addon@me.com',
url: 'https://cdn.amo/download/my-addon.xpi',
downloadProgress: 100,
@@ -177,8 +165,7 @@ describe('installations reducer', () => {
it('updates the status on START_UNINSTALL', () => {
const state = {
- 'my-addon': {
- slug: 'my-addon',
+ 'my-addon@me.com': {
guid: 'my-addon@me.com',
url: 'https://cdn.amo/download/my-addon.xpi',
downloadProgress: 100,
@@ -189,12 +176,11 @@ describe('installations reducer', () => {
installations(state, {
type: 'START_UNINSTALL',
payload: {
- slug: 'my-addon',
+ guid: 'my-addon@me.com',
},
}),
{
- 'my-addon': {
- slug: 'my-addon',
+ 'my-addon@me.com': {
guid: 'my-addon@me.com',
url: 'https://cdn.amo/download/my-addon.xpi',
downloadProgress: 0,
@@ -205,8 +191,7 @@ describe('installations reducer', () => {
it('updates the status on UNINSTALL_COMPLETE', () => {
const state = {
- 'my-addon': {
- slug: 'my-addon',
+ 'my-addon@me.com': {
guid: 'my-addon@me.com',
url: 'https://cdn.amo/download/my-addon.xpi',
downloadProgress: 0,
@@ -217,12 +202,11 @@ describe('installations reducer', () => {
installations(state, {
type: 'UNINSTALL_COMPLETE',
payload: {
- slug: 'my-addon',
+ guid: 'my-addon@me.com',
},
}),
{
- 'my-addon': {
- slug: 'my-addon',
+ 'my-addon@me.com': {
guid: 'my-addon@me.com',
url: 'https://cdn.amo/download/my-addon.xpi',
downloadProgress: 0,
@@ -233,8 +217,7 @@ describe('installations reducer', () => {
it('sets an error on INSTALL_ERROR', () => {
const state = {
- 'my-addon': {
- slug: 'my-addon',
+ 'my-addon@me.com': {
guid: 'my-addon@me.com',
url: 'https://cdn.amo/download/my-addon.xpi',
downloadProgress: 55,
@@ -245,13 +228,12 @@ describe('installations reducer', () => {
installations(state, {
type: 'INSTALL_ERROR',
payload: {
- slug: 'my-addon',
+ guid: 'my-addon@me.com',
error: 'Download interrupted, check your network connection.',
},
}),
{
- 'my-addon': {
- slug: 'my-addon',
+ 'my-addon@me.com': {
guid: 'my-addon@me.com',
url: 'https://cdn.amo/download/my-addon.xpi',
downloadProgress: 0,
diff --git a/tests/client/disco/test_api.js b/tests/client/disco/test_api.js
index cbeea45f3c7..8357c4ac7f8 100644
--- a/tests/client/disco/test_api.js
+++ b/tests/client/disco/test_api.js
@@ -1,6 +1,6 @@
import { arrayOf, normalize } from 'normalizr';
-import { discoResult, getDiscoveryAddons } from 'disco/api';
+import { discoResult, getDiscoveryAddons, getGuid } from 'disco/api';
import * as coreApi from 'core/api';
describe('disco api', () => {
@@ -18,18 +18,28 @@ describe('disco api', () => {
});
describe('discoResult', () => {
- it("uses the addon's slug as an id", () => {
- const normalized = normalize({addon: {slug: 'foo'}}, discoResult);
+ it("uses the addon's guid as an id", () => {
+ const normalized = normalize({addon: {guid: '{foo}'}}, discoResult);
assert.deepEqual(
normalized,
{
entities: {
- addons: {foo: {slug: 'foo'}},
- discoResults: {foo: {addon: 'foo'}},
+ addons: {'{foo}': {guid: '{foo}'}},
+ discoResults: {'{foo}': {addon: '{foo}'}},
},
- result: 'foo',
+ result: '{foo}',
},
sinon.format(normalized.entities));
});
});
+
+ describe('getGuid', () => {
+ it('provides a theme guid for a theme', () => {
+ const fakeResult = {
+ type: 'persona',
+ id: 'awooga',
+ };
+ assert.equal(getGuid(fakeResult), 'awooga@personas.mozilla.org');
+ });
+ });
});