fix: Use singular addonType in category search

Fix #1540.
This commit is contained in:
Matthew Riley MacPherson 2016-12-30 13:35:15 +00:00
Родитель 8c0217d8a8
Коммит b706c7182c
36 изменённых файлов: 311 добавлений и 153 удалений

Просмотреть файл

@ -9,7 +9,7 @@ import ScreenShots from 'amo/components/ScreenShots';
import 'amo/css/AddonDetail.scss';
import fallbackIcon from 'amo/img/icons/default-64.png';
import InstallButton from 'core/components/InstallButton';
import { THEME_TYPE } from 'core/constants';
import { ADDON_TYPE_THEME } from 'core/constants';
import { withInstallHelpers } from 'core/installAddon';
import { isAllowedOrigin, nl2br, sanitizeHTML } from 'core/utils';
import translate from 'core/i18n/translate';
@ -77,7 +77,7 @@ export class AddonDetailBase extends React.Component {
const iconUrl = isAllowedOrigin(addon.icon_url) ? addon.icon_url :
fallbackIcon;
if (type === THEME_TYPE) {
if (type === ADDON_TYPE_THEME) {
const label = i18n.gettext('Press to preview');
const imageClassName = 'AddonDetail-theme-header-image';
let headerImage;

Просмотреть файл

@ -2,6 +2,7 @@ import React, { PropTypes } from 'react';
import { compose } from 'redux';
import Link from 'amo/components/Link';
import { visibleAddonType } from 'core/utils';
import translate from 'core/i18n/translate';
import './Categories.scss';
@ -50,7 +51,7 @@ export class CategoriesBase extends React.Component {
{Object.values(categories).map((category) => (
<li className="Categories-list-item">
<Link className="Categories-link"
to={`/${addonType}s/${category.slug}/`}>
to={`/${visibleAddonType(addonType)}/${category.slug}/`}>
{category.name}
</Link>
</li>

Просмотреть файл

@ -6,6 +6,13 @@ import { connect } from 'react-redux';
import LandingAddonsCard from 'amo/components/LandingAddonsCard';
import { loadLandingAddons } from 'amo/utils';
import {
ADDON_TYPE_EXTENSION,
ADDON_TYPE_THEME,
SEARCH_SORT_POPULAR,
SEARCH_SORT_TOP_RATED,
} from 'core/constants';
import { apiAddonType } from 'core/utils';
import translate from 'core/i18n/translate';
import './LandingPage.scss';
@ -24,47 +31,47 @@ export class LandingPageBase extends React.Component {
const { i18n } = this.props;
const contentForTypes = {
extension: {
[ADDON_TYPE_EXTENSION]: {
featuredHeader: i18n.gettext('Featured extensions'),
// TODO: Add this search/route, see:
// https://github.com/mozilla/addons-frontend/issues/1535
featuredFooterLink: {
pathname: '#/extensions/featured',
query: { addonType: 'theme' },
query: { addonType: ADDON_TYPE_EXTENSION },
},
featuredFooterText: i18n.gettext('More featured extensions'),
popularHeader: i18n.gettext('Most popular extensions'),
popularFooterLink: {
pathname: '/search/',
query: { addonType: 'extension', sort: 'hotness' },
query: { sort: SEARCH_SORT_POPULAR, type: ADDON_TYPE_EXTENSION },
},
popularFooterText: i18n.gettext('More popular extensions'),
highlyRatedHeader: i18n.gettext('Top rated extensions'),
highlyRatedFooterLink: {
pathname: '/search/',
query: { addonType: 'extension', sort: 'rating' },
query: { sort: SEARCH_SORT_TOP_RATED, type: ADDON_TYPE_EXTENSION },
},
highlyRatedFooterText: i18n.gettext('More highly rated extensions'),
},
theme: {
[ADDON_TYPE_THEME]: {
featuredHeader: i18n.gettext('Featured themes'),
// TODO: Add this search/route, see:
// https://github.com/mozilla/addons-frontend/issues/1535
featuredFooterLink: {
pathname: '#/themes/featured',
query: { addonType: 'theme' },
query: { addonType: ADDON_TYPE_THEME },
},
featuredFooterText: i18n.gettext('More featured themes'),
popularHeader: i18n.gettext('Most popular themes'),
popularFooterLink: {
pathname: '/search/',
query: { addonType: 'theme', sort: 'hotness' },
query: { sort: SEARCH_SORT_POPULAR, type: ADDON_TYPE_THEME },
},
popularFooterText: i18n.gettext('More popular themes'),
highlyRatedHeader: i18n.gettext('Top rated themes'),
highlyRatedFooterLink: {
pathname: '/search/',
query: { addonType: 'theme', sort: 'rating' },
query: { sort: SEARCH_SORT_TOP_RATED, type: ADDON_TYPE_THEME },
},
highlyRatedFooterText: i18n.gettext('More highly rated themes'),
},
@ -105,12 +112,9 @@ export class LandingPageBase extends React.Component {
}
}
export function singularizeAddonType(state, ownProps) {
return { addonType: ownProps.params.pluralAddonType.replace(/s$/, '') };
}
export function mapStateToProps(state) {
export function mapStateToProps(state, ownProps) {
return {
addonType: apiAddonType(ownProps.params.visibleAddonType),
featuredAddons: state.landing.featured.results,
highlyRatedAddons: state.landing.highlyRated.results,
popularAddons: state.landing.popular.results,
@ -122,6 +126,5 @@ export default compose(
{ deferred: true, promise: loadLandingAddons },
]),
connect(mapStateToProps),
connect(singularizeAddonType),
translate({ withRef: true }),
)(LandingPageBase);

Просмотреть файл

@ -3,11 +3,11 @@ import { asyncConnect } from 'redux-connect';
import { connect } from 'react-redux';
import Categories from 'amo/components/Categories';
import { loadCategoriesIfNeeded } from 'core/utils';
import { loadCategoriesIfNeeded, apiAddonType } from 'core/utils';
export function mapStateToProps(state, ownProps) {
const addonType = ownProps.params.addonType.replace(/s$/, '');
const addonType = apiAddonType(ownProps.params.visibleAddonType);
const clientApp = state.api.clientApp;
const categories = state.categories.categories[clientApp][addonType] ?
state.categories.categories[clientApp][addonType] : {};

Просмотреть файл

@ -5,15 +5,16 @@ import { compose } from 'redux';
import SearchPage from 'amo/components/SearchPage';
import { loadByCategoryIfNeeded, parsePage } from 'core/searchUtils';
import { apiAddonType } from 'core/utils';
export function mapStateToProps(state, ownProps) {
const filters = {
addonType: ownProps.params.addonType,
addonType: apiAddonType(ownProps.params.visibleAddonType),
category: ownProps.params.slug,
clientApp: ownProps.params.application,
};
const pathname = `/${filters.addonType}s/${filters.category}/`;
const pathname = `/${ownProps.params.visibleAddonType}/${filters.category}/`;
const queryParams = { page: parsePage(ownProps.location.query.page) };
const filtersMatchState = deepEqual(

Просмотреть файл

@ -18,10 +18,10 @@ export default (
<IndexRoute component={Home} />
<Route path="addon/:slug/" component={DetailPage} />
<Route path="addon/:slug/review/:reviewId/" component={AddonReview} />
<Route path=":addonType/categories/" component={CategoryList} />
<Route path=":addonType/:slug/" component={CategoryPage} />
<Route path=":visibleAddonType/categories/" component={CategoryList} />
<Route path=":visibleAddonType/:slug/" component={CategoryPage} />
<Route path="fxa-authenticate" component={HandleLogin} />
<Route path="search/" component={SearchPage} />
<Route path=":pluralAddonType/" component={LandingPage} />
<Route path=":visibleAddonType/" component={LandingPage} />
</Route>
);

Просмотреть файл

@ -1,6 +1,8 @@
import { LANDING_PAGE_ADDON_COUNT } from 'amo/constants';
import { getLanding, loadLanding, failLanding } from 'amo/actions/landing';
import { featured as featuredAPI, search } from 'core/api';
import { SEARCH_SORT_POPULAR, SEARCH_SORT_TOP_RATED } from 'core/constants';
import { apiAddonType } from 'core/utils';
export function fetchLandingAddons({ addonType, api, dispatch }) {
@ -9,8 +11,12 @@ export function fetchLandingAddons({ addonType, api, dispatch }) {
const filters = { addonType, page_size: LANDING_PAGE_ADDON_COUNT };
const landingRequests = [
featuredAPI({ api, filters }),
search({ api, filters: { ...filters, sort: 'rating' }, page: 1 }),
search({ api, filters: { ...filters, sort: 'hotness' }, page: 1 }),
search({
api, filters: { ...filters, sort: SEARCH_SORT_TOP_RATED }, page: 1,
}),
search({
api, filters: { ...filters, sort: SEARCH_SORT_POPULAR }, page: 1,
}),
];
return Promise.all(landingRequests)
@ -22,7 +28,7 @@ export function fetchLandingAddons({ addonType, api, dispatch }) {
export function loadLandingAddons({ store: { dispatch, getState }, params }) {
const state = getState();
const addonType = params.pluralAddonType.replace(/s$/, '');
const addonType = apiAddonType(params.visibleAddonType);
return fetchLandingAddons({ addonType, api: state.api, dispatch });
}

Просмотреть файл

@ -3,7 +3,7 @@ import React, { PropTypes } from 'react';
import { compose } from 'redux';
import InstallSwitch from 'core/components/InstallSwitch';
import { THEME_TYPE } from 'core/constants';
import { ADDON_TYPE_THEME } from 'core/constants';
import translate from 'core/i18n/translate';
import { getThemeData } from 'core/themePreview';
import Button from 'ui/components/Button';
@ -32,7 +32,7 @@ export class InstallButtonBase extends React.Component {
const { addon, className, hasAddonManager, i18n, size } = this.props;
const useButton = hasAddonManager !== undefined && !hasAddonManager;
let button;
if (addon.type === THEME_TYPE) {
if (addon.type === ADDON_TYPE_THEME) {
button = (
<Button
data-browsertheme={JSON.stringify(getThemeData(addon))}

Просмотреть файл

@ -8,7 +8,7 @@ import {
ENABLING,
INSTALLING,
INSTALLED,
THEME_TYPE,
ADDON_TYPE_THEME,
UNINSTALLED,
UNINSTALLING,
UNKNOWN,
@ -88,7 +88,7 @@ export class InstallSwitchBase extends React.Component {
const {
addon, guid, enable, install, installURL, name, status, installTheme, type, uninstall,
} = this.props;
if (type === THEME_TYPE && [UNINSTALLED, DISABLED].includes(status)) {
if (type === ADDON_TYPE_THEME && [UNINSTALLED, DISABLED].includes(status)) {
installTheme(this.themeData, { ...addon, status });
} else if (status === UNINSTALLED) {
install();

Просмотреть файл

@ -35,13 +35,36 @@ export const FATAL_UNINSTALL_ERROR = 'FATAL_UNINSTALL_ERROR';
export const FATAL_ERROR = 'FATAL_ERROR';
// Add-on types.
export const API_THEME_TYPE = 'persona';
export const EXTENSION_TYPE = 'extension';
export const THEME_TYPE = 'theme';
export const ADDON_TYPE_EXTENSION = 'extension';
export const ADDON_TYPE_THEME = 'persona';
export const validAddonTypes = [
EXTENSION_TYPE,
THEME_TYPE,
ADDON_TYPE_EXTENSION,
ADDON_TYPE_THEME,
];
// Mapping of the add-on types we show in URLs, etc. and what they map
// to in the API (and how they're represented internally in the app).
//
// Examples:
// * '/extensions/' -> 'extension'
// * '/themes/' -> 'persona'
export const API_ADDON_TYPES_MAPPING = {
extensions: ADDON_TYPE_EXTENSION,
themes: ADDON_TYPE_THEME,
};
export const VISIBLE_ADDON_TYPES_MAPPING = Object.keys(API_ADDON_TYPES_MAPPING)
.reduce((object, key) => ({
...object,
[API_ADDON_TYPES_MAPPING[key]]: key,
}), {});
// Tracking add-on types
export const TRACKING_TYPE_EXTENSION = 'addon';
export const TRACKING_TYPE_THEME = 'theme';
export const TRACKING_TYPE_INVALID = 'invalid';
// Add-on Search Sort Values
export const SEARCH_SORT_POPULAR = 'hotness';
export const SEARCH_SORT_TOP_RATED = 'rating';
// Action types.
export const CATEGORIES_GET = 'CATEGORIES_GET';

Просмотреть файл

@ -15,7 +15,6 @@ import {
DOWNLOAD_PROGRESS,
ENABLED,
ERROR,
EXTENSION_TYPE,
FATAL_ERROR,
FATAL_INSTALL_ERROR,
FATAL_UNINSTALL_ERROR,
@ -29,7 +28,10 @@ import {
THEME_INSTALL,
THEME_PREVIEW,
THEME_RESET_PREVIEW,
THEME_TYPE,
TRACKING_TYPE_EXTENSION,
TRACKING_TYPE_THEME,
ADDON_TYPE_EXTENSION,
ADDON_TYPE_THEME,
UNINSTALL_CATEGORY,
UNINSTALLED,
UNINSTALLING,
@ -37,13 +39,21 @@ import {
} from 'core/constants';
import * as addonManager from 'core/addonManager';
export function installTheme(
node, addon, { _themeAction = themeAction, _tracking = tracking } = {},
) {
const { name, status, type } = addon;
if (type === THEME_TYPE && [DISABLED, UNINSTALLED, UNKNOWN].includes(status)) {
if (
type === ADDON_TYPE_THEME &&
[DISABLED, UNINSTALLED, UNKNOWN].includes(status)
) {
_themeAction(node, THEME_INSTALL);
_tracking.sendEvent({ action: 'theme', category: INSTALL_CATEGORY, label: name });
_tracking.sendEvent({
action: TRACKING_TYPE_THEME,
category: INSTALL_CATEGORY,
label: name,
});
}
}
@ -88,7 +98,7 @@ export function makeMapDispatchToProps({ WrappedComponent, src }) {
return { WrappedComponent };
}
if (ownProps.type === EXTENSION_TYPE && ownProps.installURL === undefined) {
if (ownProps.type === ADDON_TYPE_EXTENSION && ownProps.installURL === undefined) {
throw new Error(oneLine`installURL is required, ensure component props are set before
withInstallHelpers is called`);
}
@ -161,7 +171,7 @@ export function makeMapDispatchToProps({ WrappedComponent, src }) {
return _addonManager.install(installURL, makeProgressHandler(dispatch, guid), { src })
.then(() => {
_tracking.sendEvent({
action: 'addon',
action: TRACKING_TYPE_EXTENSION,
category: INSTALL_CATEGORY,
label: name,
});

Просмотреть файл

@ -1,9 +1,9 @@
import { API_THEME_TYPE, THEME_TYPE } from 'core/constants';
import { ADDON_TYPE_THEME } from 'core/constants';
const initialState = {};
export function getGuid(result) {
if (result.type === API_THEME_TYPE) {
if (result.type === ADDON_TYPE_THEME) {
return `${result.id}@personas.mozilla.org`;
}
return result.guid;
@ -20,7 +20,7 @@ export default function addon(state = initialState, action) {
...thisAddon,
...thisAddon.theme_data,
guid: getGuid(thisAddon),
type: THEME_TYPE,
type: ADDON_TYPE_THEME,
};
delete newState[key].theme_data;
} else if (thisAddon.current_version && thisAddon.current_version.files.length > 0) {

Просмотреть файл

@ -2,6 +2,7 @@ import deepEqual from 'deep-eql';
import { search } from 'core/api';
import { searchStart, searchLoad, searchFail } from 'core/actions/search';
import { apiAddonType } from 'core/utils';
export const paramsToFilter = {
@ -108,7 +109,7 @@ export function loadByCategoryIfNeeded(
) {
const state = getState();
const filters = {
addonType: params.addonType,
addonType: apiAddonType(params.visibleAddonType),
category: params.slug,
clientApp: params.application,
};

Просмотреть файл

@ -5,8 +5,11 @@ import config from 'config';
import { convertBoolean } from 'core/utils';
import log from 'core/logger';
import {
EXTENSION_TYPE,
THEME_TYPE,
TRACKING_TYPE_EXTENSION,
TRACKING_TYPE_INVALID,
TRACKING_TYPE_THEME,
ADDON_TYPE_EXTENSION,
ADDON_TYPE_THEME,
} from 'core/constants';
@ -97,9 +100,9 @@ export class Tracking {
export function getAction(type) {
return {
[EXTENSION_TYPE]: 'addon',
[THEME_TYPE]: 'theme',
}[type] || 'invalid';
[ADDON_TYPE_EXTENSION]: TRACKING_TYPE_EXTENSION,
[ADDON_TYPE_THEME]: TRACKING_TYPE_THEME,
}[type] || TRACKING_TYPE_INVALID;
}
export default new Tracking({

Просмотреть файл

@ -9,9 +9,14 @@ import {
categoriesFail,
} from 'core/actions/categories';
import { categories, fetchAddon } from 'core/api';
import {
API_ADDON_TYPES_MAPPING,
VISIBLE_ADDON_TYPES_MAPPING,
} from 'core/constants';
import log from 'core/logger';
import purify from 'core/purify';
export function gettext(str) {
return str;
}
@ -153,3 +158,21 @@ export function browserBase64Decode(str) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
}
export function apiAddonType(addonType) {
if (!Object.prototype.hasOwnProperty.call(
API_ADDON_TYPES_MAPPING, addonType
)) {
throw new Error(`"${addonType}" not found in API_ADDON_TYPES_MAPPING`);
}
return API_ADDON_TYPES_MAPPING[addonType];
}
export function visibleAddonType(addonType) {
if (!Object.prototype.hasOwnProperty.call(
VISIBLE_ADDON_TYPES_MAPPING, addonType
)) {
throw new Error(`"${addonType}" not found in VISIBLE_ADDON_TYPES_MAPPING`);
}
return VISIBLE_ADDON_TYPES_MAPPING[addonType];
}

Просмотреть файл

@ -16,12 +16,12 @@ import {
CLICK_CATEGORY,
DOWNLOAD_FAILED,
ERROR,
EXTENSION_TYPE,
ADDON_TYPE_EXTENSION,
FATAL_ERROR,
FATAL_INSTALL_ERROR,
FATAL_UNINSTALL_ERROR,
INSTALL_FAILED,
THEME_TYPE,
ADDON_TYPE_THEME,
UNINSTALLING,
validAddonTypes,
validInstallStates,
@ -76,7 +76,7 @@ export class AddonBase extends React.Component {
getLogo() {
const { iconUrl } = this.props;
if (this.props.type === EXTENSION_TYPE) {
if (this.props.type === ADDON_TYPE_EXTENSION) {
return <div className="logo"><img src={iconUrl} alt="" /></div>;
}
return null;
@ -84,7 +84,7 @@ export class AddonBase extends React.Component {
getThemeImage() {
const { getBrowserThemeData, i18n, name, previewURL } = this.props;
if (this.props.type === THEME_TYPE) {
if (this.props.type === ADDON_TYPE_THEME) {
// eslint-disable-next-line jsx-a11y/href-no-hash
return (<a href="#" className="theme-image"
data-browsertheme={getBrowserThemeData()}
@ -102,7 +102,7 @@ export class AddonBase extends React.Component {
getDescription() {
const { i18n, description, type } = this.props;
if (type === THEME_TYPE) {
if (type === ADDON_TYPE_THEME) {
return (
<p className="editorial-description">{i18n.gettext('Hover over the image to preview')}</p>
);
@ -181,8 +181,8 @@ export class AddonBase extends React.Component {
}
const addonClasses = classNames('addon', {
theme: type === THEME_TYPE,
extension: type === EXTENSION_TYPE,
theme: type === ADDON_TYPE_THEME,
extension: type === ADDON_TYPE_EXTENSION,
});
return (

Просмотреть файл

@ -1,15 +1,16 @@
import { getLanding, loadLanding, failLanding } from 'amo/actions/landing';
import { ADDON_TYPE_THEME } from 'core/constants';
describe('LANDING_GET', () => {
const action = getLanding({ addonType: 'theme' });
const action = getLanding({ addonType: ADDON_TYPE_THEME });
it('sets the type', () => {
assert.equal(action.type, 'LANDING_GET');
});
it('sets the filters', () => {
assert.deepEqual(action.payload, { addonType: 'theme' });
assert.deepEqual(action.payload, { addonType: ADDON_TYPE_THEME });
});
it('throws if no addonType is set', () => {
@ -23,14 +24,14 @@ describe('LANDING_LOADED', () => {
highlyRated: sinon.stub(),
popular: sinon.stub(),
};
const action = loadLanding({ addonType: 'theme', ...response });
const action = loadLanding({ addonType: ADDON_TYPE_THEME, ...response });
it('sets the type', () => {
assert.equal(action.type, 'LANDING_LOADED');
});
it('sets the payload', () => {
assert.deepEqual(action.payload, { addonType: 'theme', ...response });
assert.deepEqual(action.payload, { addonType: ADDON_TYPE_THEME, ...response });
});
});

Просмотреть файл

@ -14,7 +14,7 @@ import {
import AddonMeta from 'amo/components/AddonMeta';
import { RatingManagerWithI18n } from 'amo/components/RatingManager';
import createStore from 'amo/store';
import { THEME_TYPE } from 'core/constants';
import { ADDON_TYPE_THEME } from 'core/constants';
import InstallButton from 'core/components/InstallButton';
import I18nProvider from 'core/i18n/Provider';
import { fakeAddon } from 'tests/client/amo/helpers';
@ -233,7 +233,7 @@ describe('AddonDetail', () => {
const root = render({
addon: {
...fakeAddon,
type: THEME_TYPE,
type: ADDON_TYPE_THEME,
previewURL: 'https://amo/preview.png',
},
getBrowserThemeData: () => '{}',
@ -252,7 +252,7 @@ describe('AddonDetail', () => {
const root = render({
addon: {
...fakeAddon,
type: THEME_TYPE,
type: ADDON_TYPE_THEME,
previewURL: 'https://amo/preview.png',
},
getBrowserThemeData: () => '{}',
@ -268,7 +268,7 @@ describe('AddonDetail', () => {
const rootNode = renderAsDOMNode({
addon: {
...fakeAddon,
type: THEME_TYPE,
type: ADDON_TYPE_THEME,
previewURL: 'https://amo/preview.png',
},
getBrowserThemeData: () => '{}',
@ -281,7 +281,7 @@ describe('AddonDetail', () => {
const rootNode = renderAsDOMNode({
addon: {
...fakeAddon,
type: THEME_TYPE,
type: ADDON_TYPE_THEME,
previewURL: 'https://amo/preview.png',
},
getBrowserThemeData: () => '{"the":"themedata"}',
@ -295,7 +295,7 @@ describe('AddonDetail', () => {
const rootNode = renderAsDOMNode({
addon: {
...fakeAddon,
type: THEME_TYPE,
type: ADDON_TYPE_THEME,
},
getBrowserThemeData: () => '{}',
previewTheme,
@ -310,7 +310,7 @@ describe('AddonDetail', () => {
const rootNode = renderAsDOMNode({
addon: {
...fakeAddon,
type: THEME_TYPE,
type: ADDON_TYPE_THEME,
},
getBrowserThemeData: () => '{}',
resetPreviewTheme,

Просмотреть файл

@ -7,12 +7,9 @@ import { findDOMNode } from 'react-dom';
import { Provider } from 'react-redux';
import * as landingActions from 'amo/actions/landing';
import {
LandingPageBase,
mapStateToProps,
singularizeAddonType,
} from 'amo/components/LandingPage';
import { LandingPageBase, mapStateToProps } from 'amo/components/LandingPage';
import createStore from 'amo/store';
import { ADDON_TYPE_EXTENSION, ADDON_TYPE_THEME } from 'core/constants';
import I18nProvider from 'core/i18n/Provider';
import { fakeAddon } from 'tests/client/amo/helpers';
import { getFakeI18nInst } from 'tests/client/helpers';
@ -33,7 +30,7 @@ describe('<LandingPage />', () => {
it('renders a LandingPage with no addons set', () => {
const root = render({
addonType: 'extension',
addonType: ADDON_TYPE_EXTENSION,
});
assert.include(root.textContent, 'Featured extensions');
@ -42,7 +39,7 @@ describe('<LandingPage />', () => {
it('renders a LandingPage with themes HTML', () => {
const root = render({
addonType: 'theme',
addonType: ADDON_TYPE_THEME,
});
assert.include(root.textContent, 'Featured themes');
@ -93,8 +90,8 @@ describe('<LandingPage />', () => {
},
}));
const root = render({
...singularizeAddonType(null, { params: { pluralAddonType: 'themes' } }),
...mapStateToProps(store.getState()),
...mapStateToProps(
store.getState(), { params: { visibleAddonType: 'themes' } }),
});
assert.deepEqual(

Просмотреть файл

@ -1,4 +1,5 @@
import { mapStateToProps } from 'amo/containers/CategoryList';
import { ADDON_TYPE_THEME } from 'core/constants';
describe('<CategoryList />', () => {
@ -8,7 +9,7 @@ describe('<CategoryList />', () => {
categories: {
categories: {
android: {
theme: {
[ADDON_TYPE_THEME]: {
nature: {
name: 'Nature',
slug: 'nature',
@ -21,11 +22,11 @@ describe('<CategoryList />', () => {
loading: true,
},
}, {
params: { addonType: 'themes' },
params: { visibleAddonType: 'themes' },
});
assert.deepEqual(props, {
addonType: 'theme',
addonType: ADDON_TYPE_THEME,
categories: {
nature: {
name: 'Nature',

Просмотреть файл

@ -1,6 +1,7 @@
import { mapStateToProps } from 'amo/containers/CategoryPage';
import createStore from 'amo/store';
import { searchStart } from 'core/actions/search';
import { ADDON_TYPE_THEME } from 'core/constants';
describe('CategoryPage.mapStateToProps()', () => {
@ -9,7 +10,7 @@ describe('CategoryPage.mapStateToProps()', () => {
before(() => {
filters = {
addonType: 'theme',
addonType: ADDON_TYPE_THEME,
category: 'ad-block',
clientApp: 'firefox',
};
@ -17,7 +18,7 @@ describe('CategoryPage.mapStateToProps()', () => {
location: { query: {} },
params: {
application: 'firefox',
addonType: 'theme',
visibleAddonType: 'themes',
slug: 'ad-block',
},
};

Просмотреть файл

@ -1,5 +1,7 @@
import { getLanding } from 'amo/actions/landing';
import landing from 'amo/reducers/landing';
import { ADDON_TYPE_THEME } from 'core/constants';
describe('landing reducer', () => {
let initialData;
@ -48,9 +50,9 @@ describe('landing reducer', () => {
};
const {
addonType, featured, highlyRated, loading, popular,
} = landing(initialState, getLanding({ addonType: 'theme' }));
} = landing(initialState, getLanding({ addonType: ADDON_TYPE_THEME }));
assert.equal(addonType, 'theme');
assert.equal(addonType, ADDON_TYPE_THEME);
assert.equal(loading, true);
assert.deepEqual(featured, { foo: 'bar' });
assert.deepEqual(highlyRated, { count: 0 });
@ -70,7 +72,7 @@ describe('landing reducer', () => {
const { featured, highlyRated, popular } = landing(initialData, {
type: 'LANDING_LOADED',
payload: {
addonType: 'theme',
addonType: ADDON_TYPE_THEME,
featured: {
entities,
result: { count: 2, results: ['foo', 'food'] },
@ -99,7 +101,7 @@ describe('landing reducer', () => {
}, {
type: 'LANDING_LOADED',
payload: {
addonType: 'theme',
addonType: ADDON_TYPE_THEME,
featured: {
entities,
result: { count: 2, results: ['foo', 'food'] },
@ -113,12 +115,12 @@ describe('landing reducer', () => {
describe('LANDING_FAILED', () => {
it('sets loading to false on failure', () => {
const initialState = landing(initialData, { type: 'LANDING_GET', payload: { addonType: 'theme' } });
const initialState = landing(initialData, { type: 'LANDING_GET', payload: { addonType: ADDON_TYPE_THEME } });
const state = landing(initialState,
{ type: 'LANDING_FAILED', payload: { page: 2, addonType: 'theme' } });
{ type: 'LANDING_FAILED', payload: { page: 2, addonType: ADDON_TYPE_THEME } });
assert.deepEqual(state, {
addonType: 'theme',
addonType: ADDON_TYPE_THEME,
featured: { count: 0, results: [] },
highlyRated: { count: 0, results: [] },
loading: false,

Просмотреть файл

@ -1,19 +1,24 @@
import createStore from 'amo/store';
import * as landingActions from 'amo/actions/landing';
import * as api from 'core/api';
import {
ADDON_TYPE_THEME,
SEARCH_SORT_POPULAR,
SEARCH_SORT_TOP_RATED,
} from 'core/constants';
import { loadLandingAddons } from 'amo/utils';
describe('amo/utils', () => {
describe('loadLandingAddons()', () => {
const addonType = 'theme';
const addonType = ADDON_TYPE_THEME;
let ownProps;
beforeEach(() => {
ownProps = {
params: {
application: 'android',
pluralAddonType: 'themes',
visibleAddonType: 'themes',
},
};
});
@ -35,7 +40,7 @@ describe('amo/utils', () => {
.once()
.withArgs({
api: {},
filters: { addonType, page_size: 4, sort: 'rating' },
filters: { addonType, page_size: 4, sort: SEARCH_SORT_TOP_RATED },
page: 1,
})
.returns(Promise.resolve({ entities, result }));
@ -44,7 +49,7 @@ describe('amo/utils', () => {
.once()
.withArgs({
api: {},
filters: { addonType, page_size: 4, sort: 'hotness' },
filters: { addonType, page_size: 4, sort: SEARCH_SORT_POPULAR },
page: 1,
})
.returns(Promise.resolve({ entities, result }));

Просмотреть файл

@ -4,13 +4,14 @@ import { renderIntoDocument } from 'react-addons-test-utils';
import createStore from 'amo/store';
import {
ADDON_TYPE_EXTENSION,
ADDON_TYPE_THEME,
CLOSE_INFO,
DISABLED,
DOWNLOAD_FAILED,
DOWNLOAD_PROGRESS,
ENABLED,
ERROR,
EXTENSION_TYPE,
FATAL_ERROR,
FATAL_INSTALL_ERROR,
FATAL_UNINSTALL_ERROR,
@ -24,7 +25,8 @@ import {
THEME_INSTALL,
THEME_PREVIEW,
THEME_RESET_PREVIEW,
THEME_TYPE,
TRACKING_TYPE_EXTENSION,
TRACKING_TYPE_THEME,
UNINSTALL_CATEGORY,
UNINSTALLED,
UNINSTALLING,
@ -115,7 +117,11 @@ describe('withInstallHelpers inner functions', () => {
const installURL = 'http://the.url';
const { setCurrentStatus } = mapDispatchToProps(dispatch, {
_addonManager: getFakeAddonManagerWrapper({
getAddon: Promise.resolve({ type: EXTENSION_TYPE, isActive: false, isEnabled: false }),
getAddon: Promise.resolve({
isActive: false,
isEnabled: false,
type: ADDON_TYPE_EXTENSION,
}),
}),
guid,
installURL,
@ -135,7 +141,11 @@ describe('withInstallHelpers inner functions', () => {
const installURL = 'http://the.url';
const { setCurrentStatus } = mapDispatchToProps(dispatch, {
_addonManager: getFakeAddonManagerWrapper({
getAddon: Promise.resolve({ type: EXTENSION_TYPE, isActive: false, isEnabled: true }),
getAddon: Promise.resolve({
isActive: false,
isEnabled: true,
type: ADDON_TYPE_EXTENSION,
}),
}),
guid,
installURL,
@ -151,7 +161,7 @@ describe('withInstallHelpers inner functions', () => {
it('sets the status to ENABLED when an enabled theme is found', () => {
const fakeAddonManager = getFakeAddonManagerWrapper({
getAddon: Promise.resolve({ type: THEME_TYPE, isActive: true, isEnabled: true }),
getAddon: Promise.resolve({ type: ADDON_TYPE_THEME, isActive: true, isEnabled: true }),
});
const dispatch = sinon.spy();
const guid = '@foo';
@ -169,7 +179,11 @@ describe('withInstallHelpers inner functions', () => {
it('sets the status to DISABLED when an inactive theme is found', () => {
const fakeAddonManager = getFakeAddonManagerWrapper({
getAddon: Promise.resolve({ type: THEME_TYPE, isActive: false, isEnabled: true }),
getAddon: Promise.resolve({
isActive: false,
isEnabled: true,
type: ADDON_TYPE_THEME,
}),
});
const dispatch = sinon.spy();
const guid = '@foo';
@ -187,7 +201,11 @@ describe('withInstallHelpers inner functions', () => {
it('sets the status to DISABLED when a disabled theme is found', () => {
const fakeAddonManager = getFakeAddonManagerWrapper({
getAddon: Promise.resolve({ type: THEME_TYPE, isActive: true, isEnabled: false }),
getAddon: Promise.resolve({
isActive: true,
isEnabled: false,
type: ADDON_TYPE_THEME,
}),
});
const dispatch = sinon.spy();
const guid = '@foo';
@ -353,7 +371,7 @@ describe('withInstallHelpers inner functions', () => {
it('tracks an addon install', () => {
const fakeAddonManager = getFakeAddonManagerWrapper();
const name = 'hai-addon';
const type = 'extension';
const type = ADDON_TYPE_EXTENSION;
const dispatch = sinon.spy();
const fakeTracking = {
sendEvent: sinon.spy(),
@ -364,7 +382,7 @@ describe('withInstallHelpers inner functions', () => {
return install({ guid, installURL, name, type })
.then(() => {
assert(fakeTracking.sendEvent.calledWith({
action: 'addon',
action: TRACKING_TYPE_EXTENSION,
category: INSTALL_CATEGORY,
label: 'hai-addon',
}));
@ -494,7 +512,7 @@ describe('withInstallHelpers inner functions', () => {
return uninstall({ guid, installURL, name, type })
.then(() => {
assert.ok(fakeTracking.sendEvent.calledWith({
action: 'addon',
action: TRACKING_TYPE_EXTENSION,
category: UNINSTALL_CATEGORY,
label: 'whatevs',
}), 'correctly called');
@ -510,10 +528,10 @@ describe('withInstallHelpers inner functions', () => {
};
const { uninstall } = mapDispatchToProps(dispatch,
{ _tracking: fakeTracking, _addonManager: fakeAddonManager });
return uninstall({ guid, installURL, name, type: THEME_TYPE })
return uninstall({ guid, installURL, name, type: ADDON_TYPE_THEME })
.then(() => {
assert(fakeTracking.sendEvent.calledWith({
action: 'theme',
action: TRACKING_TYPE_THEME,
category: UNINSTALL_CATEGORY,
label: 'whatevs',
}));
@ -551,13 +569,16 @@ describe('withInstallHelpers inner functions', () => {
it('requires an installURL for extensions', () => {
assert.throws(() => {
makeMapDispatchToProps({})(sinon.spy(), { type: EXTENSION_TYPE });
makeMapDispatchToProps({})(sinon.spy(), { type: ADDON_TYPE_EXTENSION });
}, /installURL is required/);
assert.doesNotThrow(() => {
makeMapDispatchToProps({})(sinon.spy(), { type: EXTENSION_TYPE, installURL: 'foo.com' });
makeMapDispatchToProps({})(sinon.spy(), {
installURL: 'foo.com',
type: ADDON_TYPE_EXTENSION,
});
});
assert.doesNotThrow(() => {
makeMapDispatchToProps({})(sinon.spy(), { type: THEME_TYPE });
makeMapDispatchToProps({})(sinon.spy(), { type: ADDON_TYPE_THEME });
});
});
});
@ -567,7 +588,7 @@ describe('withInstallHelpers inner functions', () => {
name: 'hai-theme',
guid: '{install-theme}',
status: UNINSTALLED,
type: THEME_TYPE,
type: ADDON_TYPE_THEME,
};
function installThemeStubs() {
@ -593,7 +614,7 @@ describe('withInstallHelpers inner functions', () => {
const stubs = installThemeStubs();
installTheme(node, addon, stubs);
assert(stubs._tracking.sendEvent.calledWith({
action: 'theme',
action: TRACKING_TYPE_THEME,
category: INSTALL_CATEGORY,
label: 'hai-theme',
}));
@ -609,7 +630,7 @@ describe('withInstallHelpers inner functions', () => {
});
it('does not try to install theme if it is an extension', () => {
const addon = { ...baseAddon, type: EXTENSION_TYPE };
const addon = { ...baseAddon, type: ADDON_TYPE_EXTENSION };
const node = sinon.stub();
const stubs = installThemeStubs();
installTheme(node, addon, stubs);

Просмотреть файл

@ -2,6 +2,7 @@
import config from 'config';
import * as api from 'core/api';
import { ADDON_TYPE_THEME } from 'core/constants';
import { ErrorHandler } from 'core/errorHandler';
import { unexpectedSuccess } from 'tests/client/helpers';
@ -234,12 +235,12 @@ describe('api', () => {
it('sets the app, lang, and type query', () => {
mockWindow.expects('fetch')
.withArgs(`${apiHost}/api/v3/addons/featured/?app=android&type=theme&page=&lang=en-US`)
.withArgs(`${apiHost}/api/v3/addons/featured/?app=android&type=persona&page=&lang=en-US`)
.once()
.returns(mockResponse());
return api.featured({
api: { clientApp: 'android', lang: 'en-US' },
filters: { addonType: 'theme' },
filters: { addonType: ADDON_TYPE_THEME },
})
.then((response) => {
assert.deepEqual(response, {

Просмотреть файл

@ -4,7 +4,7 @@ import { findDOMNode } from 'react-dom';
import { InstallButtonBase } from 'core/components/InstallButton';
import InstallSwitch from 'core/components/InstallSwitch';
import { EXTENSION_TYPE, THEME_TYPE, UNKNOWN } from 'core/constants';
import { ADDON_TYPE_EXTENSION, ADDON_TYPE_THEME, UNKNOWN } from 'core/constants';
import * as themePreview from 'core/themePreview';
import { getFakeI18nInst, shallowRender } from 'tests/client/helpers';
import Button from 'ui/components/Button';
@ -12,7 +12,7 @@ import Button from 'ui/components/Button';
describe('<InstallButton />', () => {
it('renders InstallSwitch when mozAddonManager is available', () => {
const i18n = getFakeI18nInst();
const addon = { type: THEME_TYPE, id: 'foo@personas.mozilla.org' };
const addon = { type: ADDON_TYPE_THEME, id: 'foo@personas.mozilla.org' };
const root = shallowRender(
<InstallButtonBase foo="foo" addon={addon} hasAddonManager i18n={i18n} />);
assert.equal(root.type, 'div');
@ -30,7 +30,7 @@ describe('<InstallButton />', () => {
it('renders a theme button when mozAddonManager is not available', () => {
const i18n = getFakeI18nInst();
const addon = { type: THEME_TYPE, id: 'foo@personas.mozilla.org' };
const addon = { type: ADDON_TYPE_THEME, id: 'foo@personas.mozilla.org' };
const root = shallowRender(
<InstallButtonBase
addon={addon} foo="foo" hasAddonManager={false} i18n={i18n} />);
@ -48,7 +48,7 @@ describe('<InstallButton />', () => {
it('calls installTheme when clicked', () => {
const installTheme = sinon.spy();
const i18n = getFakeI18nInst();
const addon = { type: THEME_TYPE, id: 'foo@personas.mozilla.org' };
const addon = { type: ADDON_TYPE_THEME, id: 'foo@personas.mozilla.org' };
const root = findDOMNode(renderIntoDocument(
<InstallButtonBase
addon={addon} foo="foo" hasAddonManager={false} i18n={i18n}
@ -63,7 +63,7 @@ describe('<InstallButton />', () => {
it('renders an add-on button when mozAddonManager is not available', () => {
const i18n = getFakeI18nInst();
const addon = { type: EXTENSION_TYPE, installURL: 'https://addons.mozilla.org/download' };
const addon = { type: ADDON_TYPE_EXTENSION, installURL: 'https://addons.mozilla.org/download' };
const root = shallowRender(
<InstallButtonBase addon={addon} foo="foo" hasAddonManager={false} i18n={i18n} />);
assert.equal(root.type, 'div');

Просмотреть файл

@ -13,7 +13,7 @@ import {
ENABLING,
INSTALLED,
INSTALLING,
THEME_TYPE,
ADDON_TYPE_THEME,
UNINSTALLED,
UNINSTALLING,
UNKNOWN,
@ -145,7 +145,7 @@ describe('<InstallSwitch />', () => {
const name = 'hai';
const button = renderButton({
installTheme,
type: THEME_TYPE,
type: ADDON_TYPE_THEME,
guid,
name,
status: UNINSTALLED,

Просмотреть файл

@ -1,5 +1,5 @@
import addons from 'core/reducers/addons';
import { API_THEME_TYPE, THEME_TYPE } from 'core/constants';
import { ADDON_TYPE_THEME } from 'core/constants';
describe('addon reducer', () => {
let originalState;
@ -60,7 +60,7 @@ describe('addon reducer', () => {
});
it('flattens theme data', () => {
const type = API_THEME_TYPE;
const type = ADDON_TYPE_THEME;
const state = addons(originalState, {
payload: {
entities: {
@ -80,7 +80,7 @@ describe('addon reducer', () => {
slug: 'baz',
theme_thing: 'some-data',
guid: '42@personas.mozilla.org',
type: THEME_TYPE,
type: ADDON_TYPE_THEME,
},
});
});

Просмотреть файл

@ -1,3 +1,4 @@
import { ADDON_TYPE_EXTENSION, ADDON_TYPE_THEME } from 'core/constants';
import categories, { emptyCategoryList } from 'core/reducers/categories';
@ -62,19 +63,19 @@ describe('categories reducer', () => {
application: 'android',
name: 'Naturé',
slug: 'naturé',
type: 'theme',
type: ADDON_TYPE_THEME,
},
{
application: 'android',
name: 'Painting',
slug: 'painting',
type: 'theme',
type: ADDON_TYPE_THEME,
},
{
application: 'firefox',
name: 'Anime',
slug: 'anime',
type: 'theme',
type: ADDON_TYPE_THEME,
},
{
application: 'firefox',
@ -104,7 +105,7 @@ describe('categories reducer', () => {
it('sets the categories', () => {
assert.deepEqual(state.categories, {
firefox: {
extension: {
[ADDON_TYPE_EXTENSION]: {
'alert-update': {
application: 'firefox',
name: 'Alerts & Update',
@ -118,17 +119,17 @@ describe('categories reducer', () => {
type: 'extension',
},
},
theme: {
[ADDON_TYPE_THEME]: {
anime: {
application: 'firefox',
name: 'Anime',
slug: 'anime',
type: 'theme',
type: ADDON_TYPE_THEME,
},
},
},
android: {
extension: {
[ADDON_TYPE_EXTENSION]: {
'alert-update': {
application: 'android',
name: 'Alerts & Update',
@ -148,18 +149,18 @@ describe('categories reducer', () => {
type: 'extension',
},
},
theme: {
[ADDON_TYPE_THEME]: {
naturé: {
application: 'android',
name: 'Naturé',
slug: 'naturé',
type: 'theme',
type: ADDON_TYPE_THEME,
},
painting: {
application: 'android',
name: 'Painting',
slug: 'painting',
type: 'theme',
type: ADDON_TYPE_THEME,
},
},
},

Просмотреть файл

@ -1,6 +1,7 @@
import createStore from 'amo/store';
import * as searchActions from 'core/actions/search';
import * as api from 'core/api';
import { ADDON_TYPE_THEME } from 'core/constants';
import { loadByCategoryIfNeeded, mapStateToProps } from 'core/searchUtils';
@ -27,15 +28,15 @@ describe('searchUtils loadByCategoryIfNeeded()', () => {
before(() => {
filters = {
addonType: 'theme',
addonType: ADDON_TYPE_THEME,
category: 'anime',
clientApp: 'android',
};
ownProps = {
location: { query: {} },
params: {
addonType: 'theme',
application: 'android',
visibleAddonType: 'themes',
slug: 'anime',
},
};

Просмотреть файл

@ -1,7 +1,12 @@
/* global window */
import { Tracking, getAction } from 'core/tracking';
import { EXTENSION_TYPE, THEME_TYPE } from 'core/constants';
import {
ADDON_TYPE_EXTENSION,
ADDON_TYPE_THEME,
TRACKING_TYPE_EXTENSION,
TRACKING_TYPE_THEME,
} from 'core/constants';
describe('Tracking', () => {
@ -108,12 +113,12 @@ describe('Tracking', () => {
});
describe('getAction', () => {
it('returns addon for EXTENSION_TYPE', () => {
assert.equal(getAction(EXTENSION_TYPE), 'addon');
it('returns addon for TYPE_EXTENSION', () => {
assert.equal(getAction(ADDON_TYPE_EXTENSION), TRACKING_TYPE_EXTENSION);
});
it('returns theme for THEME_TYPE', () => {
assert.equal(getAction(THEME_TYPE), 'theme');
it('returns theme for TYPE_THEME', () => {
assert.equal(getAction(ADDON_TYPE_THEME), TRACKING_TYPE_THEME);
});
it('returns invalid for unknown type', () => {

Просмотреть файл

@ -8,6 +8,7 @@ import * as categoriesActions from 'core/actions/categories';
import * as api from 'core/api';
import {
addQueryParams,
apiAddonType,
convertBoolean,
findAddon,
getClientApp,
@ -18,10 +19,33 @@ import {
loadAddonIfNeeded,
loadCategoriesIfNeeded,
nl2br,
visibleAddonType,
} from 'core/utils';
import { unexpectedSuccess } from 'tests/client/helpers';
describe('apiAddonType', () => {
it('maps plural/visible addonTypes to internal types', () => {
assert.equal(apiAddonType('extensions'), 'extension');
assert.equal(apiAddonType('themes'), 'persona');
});
it('fails on unrecognised plural/visible addonType', () => {
assert.throws(() => {
// "theme" is not a valid pluralAddonType mapping; it should be "themes".
apiAddonType('theme');
}, '"theme" not found in API_ADDON_TYPES_MAPPING');
});
// See:
// https://github.com/mozilla/addons-frontend/pull/1541#discussion_r95861202
it('does not return a false positive on a method', () => {
assert.throws(() => {
apiAddonType('hasOwnProperty');
}, '"hasOwnProperty" not found in API_ADDON_TYPES_MAPPING');
});
});
describe('getClientConfig', () => {
const fakeConfig = new Map();
fakeConfig.set('hai', 'there');
@ -472,3 +496,25 @@ describe('ngettext', () => {
assert.equal('2 files', fileCount(2));
});
});
describe('visibleAddonType', () => {
it('maps internal addonTypes to plural/visible types', () => {
assert.equal(visibleAddonType('extension'), 'extensions');
assert.equal(visibleAddonType('persona'), 'themes');
});
it('fails on unrecognised internal addonType', () => {
assert.throws(() => {
// "theme" is not a valid visible addonType; it should be "themes".
visibleAddonType('personas');
}, '"personas" not found in VISIBLE_ADDON_TYPES_MAPPING');
});
// See:
// https://github.com/mozilla/addons-frontend/pull/1541#discussion_r95861202
it('does not return a false positive on a method', () => {
assert.throws(() => {
visibleAddonType('hasOwnProperty');
}, '"hasOwnProperty" not found in VISIBLE_ADDON_TYPES_MAPPING');
});
});

Просмотреть файл

@ -12,15 +12,16 @@ import {
mapStateToProps,
} from 'disco/components/Addon';
import {
ADDON_TYPE_EXTENSION,
ADDON_TYPE_THEME,
CLICK_CATEGORY,
DOWNLOAD_FAILED,
ERROR,
EXTENSION_TYPE,
FATAL_ERROR,
FATAL_INSTALL_ERROR,
FATAL_UNINSTALL_ERROR,
INSTALL_FAILED,
THEME_TYPE,
TRACKING_TYPE_EXTENSION,
UNINSTALLED,
UNINSTALLING,
} from 'core/constants';
@ -245,7 +246,7 @@ describe('<Addon />', () => {
_tracking: fakeTracking,
name: 'foo',
heading: 'This is <span>an <a href="https://addons.mozilla.org">add-on</a>/span>',
type: EXTENSION_TYPE,
type: ADDON_TYPE_EXTENSION,
};
const root = renderAddon({ addon: data, ...data });
const heading = findDOMNode(root).querySelector('.heading');
@ -253,7 +254,7 @@ describe('<Addon />', () => {
// bubbling.
Simulate.click(heading, { target: { nodeName: 'A' } });
assert.ok(fakeTracking.sendEvent.calledWith({
action: 'addon',
action: TRACKING_TYPE_EXTENSION,
category: CLICK_CATEGORY,
label: 'foo',
}), sinon.format(fakeTracking.sendEvent.firstCall.args));
@ -265,7 +266,7 @@ describe('<Addon />', () => {
let root;
beforeEach(() => {
const data = { ...result, type: THEME_TYPE };
const data = { ...result, type: ADDON_TYPE_THEME };
root = renderAddon({ addon: data, ...data });
});
@ -288,7 +289,7 @@ describe('<Addon />', () => {
beforeEach(() => {
previewTheme = sinon.spy();
resetPreviewTheme = sinon.spy();
const data = { ...result, type: THEME_TYPE, previewTheme, resetPreviewTheme };
const data = { ...result, type: ADDON_TYPE_THEME, previewTheme, resetPreviewTheme };
root = renderAddon({ addon: data, ...data });
themeImage = findDOMNode(root).querySelector('.theme-image');
});
@ -318,7 +319,7 @@ describe('<Addon />', () => {
const data = {
...result,
addon: sinon.stub(),
type: THEME_TYPE,
type: ADDON_TYPE_THEME,
status: UNINSTALLED,
installTheme,
};

Просмотреть файл

@ -4,8 +4,8 @@ import { findDOMNode } from 'react-dom';
import { loadEntities } from 'core/actions';
import {
ADDON_TYPE_EXTENSION,
GLOBAL_EVENTS,
EXTENSION_TYPE,
INSTALL_STATE,
} from 'core/constants';
import * as InfoDialog from 'core/containers/InfoDialog';
@ -29,10 +29,10 @@ describe('AddonPage', () => {
// Stub InfoDialog since it uses the store and is irrelevant.
sinon.stub(InfoDialog, 'default', () => <p>InfoDialog</p>);
const store = createStore({
addons: { foo: { type: EXTENSION_TYPE } },
addons: { foo: { type: ADDON_TYPE_EXTENSION } },
discoResults: [{ addon: 'foo' }],
});
const results = [{ addon: 'foo', type: EXTENSION_TYPE }];
const results = [{ addon: 'foo', type: ADDON_TYPE_EXTENSION }];
const i18n = getFakeI18nInst();
// We need the providers for i18n and since InstallButton will pull data from the store.

Просмотреть файл

@ -4,7 +4,7 @@ import moment from 'moment';
import React from 'react';
import { createRenderer } from 'react-addons-test-utils';
import { EXTENSION_TYPE } from 'core/constants';
import { ADDON_TYPE_EXTENSION } from 'core/constants';
import { ngettext } from 'core/utils';
/*
@ -48,7 +48,11 @@ export function findByTag(root, tag) {
return matches[0];
}
const enabledExtension = Promise.resolve({ type: EXTENSION_TYPE, isActive: true, isEnabled: true });
const enabledExtension = Promise.resolve({
isActive: true,
isEnabled: true,
type: ADDON_TYPE_EXTENSION,
});
export function getFakeAddonManagerWrapper({ getAddon = enabledExtension } = {}) {
return {