Fix broken install button due to circular imports (#3448)
This commit is contained in:
Родитель
d8df872597
Коммит
22a452c770
|
@ -228,6 +228,7 @@
|
|||
"chalk": "^2.0.1",
|
||||
"cheerio": "^1.0.0-rc.2",
|
||||
"chokidar-cli": "^1.2.0",
|
||||
"circular-dependency-plugin": "^4.2.1",
|
||||
"codecov": "^2.3.0",
|
||||
"concurrently": "^3.4.0",
|
||||
"content-security-policy-parser": "^0.1.0",
|
||||
|
|
|
@ -27,10 +27,12 @@ import {
|
|||
} from 'core/constants';
|
||||
import { withInstallHelpers } from 'core/installAddon';
|
||||
import {
|
||||
getClientCompatibility as _getClientCompatibility,
|
||||
sanitizeHTML,
|
||||
sanitizeUserHTML,
|
||||
} from 'core/utils';
|
||||
import {
|
||||
getClientCompatibility as _getClientCompatibility,
|
||||
} from 'core/utils/compatibility';
|
||||
import { getAddonIconUrl } from 'core/imageUtils';
|
||||
import translate from 'core/i18n/translate';
|
||||
import log from 'core/logger';
|
||||
|
|
|
@ -15,7 +15,7 @@ import log from 'core/logger';
|
|||
import { getThemeData } from 'core/themePreview';
|
||||
import {
|
||||
getClientCompatibility as _getClientCompatibility,
|
||||
} from 'core/utils';
|
||||
} from 'core/utils/compatibility';
|
||||
import Button from 'ui/components/Button';
|
||||
|
||||
import './styles.scss';
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
/* global window */
|
||||
import { oneLine } from 'common-tags';
|
||||
import mozCompare from 'mozilla-version-comparator';
|
||||
|
||||
import {
|
||||
ADDON_TYPE_EXTENSION,
|
||||
ADDON_TYPE_OPENSEARCH,
|
||||
INCOMPATIBLE_FIREFOX_FOR_IOS,
|
||||
INCOMPATIBLE_NO_OPENSEARCH,
|
||||
INCOMPATIBLE_NOT_FIREFOX,
|
||||
INCOMPATIBLE_OVER_MAX_VERSION,
|
||||
INCOMPATIBLE_UNDER_MIN_VERSION,
|
||||
INCOMPATIBLE_UNSUPPORTED_PLATFORM,
|
||||
} from 'core/constants';
|
||||
import { findInstallURL } from 'core/installAddon';
|
||||
import log from 'core/logger';
|
||||
|
||||
|
||||
export function getCompatibleVersions({ _log = log, addon, clientApp } = {}) {
|
||||
let maxVersion = null;
|
||||
let minVersion = null;
|
||||
if (
|
||||
addon && addon.current_version && addon.current_version.compatibility
|
||||
) {
|
||||
if (addon.current_version.compatibility[clientApp]) {
|
||||
maxVersion = addon.current_version.compatibility[clientApp].max;
|
||||
minVersion = addon.current_version.compatibility[clientApp].min;
|
||||
} else if (addon.type === ADDON_TYPE_OPENSEARCH) {
|
||||
_log.info(oneLine`addon is type ${ADDON_TYPE_OPENSEARCH}; no
|
||||
compatibility info found but this is expected.`, { addon, clientApp });
|
||||
} else {
|
||||
_log.error(
|
||||
'addon found with no compatibility info for valid clientApp',
|
||||
{ addon, clientApp }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return { maxVersion, minVersion };
|
||||
}
|
||||
|
||||
export function isCompatibleWithUserAgent({
|
||||
_log = log, _window = typeof window !== 'undefined' ? window : {},
|
||||
addon, maxVersion, minVersion, userAgentInfo,
|
||||
} = {}) {
|
||||
// If the userAgent is false there was likely a programming error.
|
||||
if (!userAgentInfo) {
|
||||
throw new Error('userAgentInfo is required');
|
||||
}
|
||||
|
||||
const { browser, os } = userAgentInfo;
|
||||
|
||||
// We need a Firefox browser compatible with add-ons (Firefox for iOS does
|
||||
// not currently support add-ons).
|
||||
if (browser.name === 'Firefox' && os.name === 'iOS') {
|
||||
return { compatible: false, reason: INCOMPATIBLE_FIREFOX_FOR_IOS };
|
||||
}
|
||||
|
||||
if (browser.name === 'Firefox') {
|
||||
// Do version checks, if this add-on has minimum or maximum version
|
||||
// requirements.
|
||||
// The mozilla-version-comparator API is quite strange; a result of
|
||||
// `1` means the first argument is higher in version than the second.
|
||||
//
|
||||
// Being over the maxVersion, oddly, is not actually a reason to
|
||||
// disable the install button or mark the add-on as incompatible
|
||||
// with this version of Firefox. But we log the version mismatch
|
||||
// here so it's not totally silent and a future developer isn't as
|
||||
// confused by this as tofumatt was.
|
||||
// See: https://github.com/mozilla/addons-frontend/issues/2074#issuecomment-286983423
|
||||
if (maxVersion && mozCompare(browser.version, maxVersion) === 1) {
|
||||
if (addon.current_version.is_strict_compatibility_enabled) {
|
||||
return { compatible: false, reason: INCOMPATIBLE_OVER_MAX_VERSION };
|
||||
}
|
||||
|
||||
_log.info(oneLine`maxVersion ${maxVersion} for add-on lower than
|
||||
browser version ${browser.version}, but add-on still marked as
|
||||
compatible because we largely ignore maxVersion. See:
|
||||
https://github.com/mozilla/addons-frontend/issues/2074`);
|
||||
}
|
||||
|
||||
// A result of `-1` means the second argument is a lower version than the
|
||||
// first.
|
||||
if (minVersion && mozCompare(browser.version, minVersion) === -1) {
|
||||
if (minVersion === '*') {
|
||||
_log.error(oneLine`minVersion of "*" was passed to
|
||||
isCompatibleWithUserAgent(); bad add-on version data`,
|
||||
{ browserVersion: browser.version, minVersion }
|
||||
);
|
||||
}
|
||||
|
||||
// `minVersion` is always respected, regardless of
|
||||
// `is_strict_compatibility_enabled`'s value.
|
||||
return { compatible: false, reason: INCOMPATIBLE_UNDER_MIN_VERSION };
|
||||
}
|
||||
|
||||
if (
|
||||
addon.type === ADDON_TYPE_OPENSEARCH &&
|
||||
!(_window.external && 'AddSearchProvider' in _window.external)
|
||||
) {
|
||||
return { compatible: false, reason: INCOMPATIBLE_NO_OPENSEARCH };
|
||||
}
|
||||
|
||||
// Even if an extension's version is marked compatible,
|
||||
// we need to make sure it has a matching platform file
|
||||
// to work around some bugs.
|
||||
// See https://github.com/mozilla/addons-server/issues/6576
|
||||
if (
|
||||
addon.type === ADDON_TYPE_EXTENSION &&
|
||||
!findInstallURL({
|
||||
installURLs: addon.installURLs, userAgentInfo,
|
||||
})
|
||||
) {
|
||||
return {
|
||||
compatible: false,
|
||||
reason: INCOMPATIBLE_UNSUPPORTED_PLATFORM,
|
||||
};
|
||||
}
|
||||
|
||||
// If we made it here we're compatible (yay!)
|
||||
return { compatible: true, reason: null };
|
||||
}
|
||||
|
||||
// This means the client is not Firefox, so it's incompatible.
|
||||
return { compatible: false, reason: INCOMPATIBLE_NOT_FIREFOX };
|
||||
}
|
||||
|
||||
export function getClientCompatibility({
|
||||
addon, clientApp, userAgentInfo,
|
||||
} = {}) {
|
||||
const { maxVersion, minVersion } = getCompatibleVersions({
|
||||
addon, clientApp });
|
||||
const { compatible, reason } = isCompatibleWithUserAgent({
|
||||
addon, maxVersion, minVersion, userAgentInfo });
|
||||
|
||||
return { compatible, maxVersion, minVersion, reason };
|
||||
}
|
|
@ -1,10 +1,8 @@
|
|||
/* global window */
|
||||
/* eslint-disable react/prop-types */
|
||||
import url from 'url';
|
||||
|
||||
import { oneLine } from 'common-tags';
|
||||
import config from 'config';
|
||||
import mozCompare from 'mozilla-version-comparator';
|
||||
import React from 'react';
|
||||
import { asyncConnect as defaultAsyncConnect } from 'redux-connect';
|
||||
|
||||
|
@ -13,23 +11,15 @@ import { fetchAddon } from 'core/api';
|
|||
import GenericError from 'core/components/ErrorPage/GenericError';
|
||||
import NotFound from 'core/components/ErrorPage/NotFound';
|
||||
import {
|
||||
ADDON_TYPE_EXTENSION,
|
||||
ADDON_TYPE_COMPLETE_THEME,
|
||||
ADDON_TYPE_OPENSEARCH,
|
||||
ADDON_TYPE_THEME,
|
||||
API_ADDON_TYPES_MAPPING,
|
||||
CATEGORY_COLORS,
|
||||
VISIBLE_ADDON_TYPES_MAPPING,
|
||||
INCOMPATIBLE_FIREFOX_FOR_IOS,
|
||||
INCOMPATIBLE_NO_OPENSEARCH,
|
||||
INCOMPATIBLE_NOT_FIREFOX,
|
||||
INCOMPATIBLE_OVER_MAX_VERSION,
|
||||
INCOMPATIBLE_UNDER_MIN_VERSION,
|
||||
INCOMPATIBLE_UNSUPPORTED_PLATFORM,
|
||||
} from 'core/constants';
|
||||
import { AddonTypeNotFound } from 'core/errors';
|
||||
import log from 'core/logger';
|
||||
import { findInstallURL } from 'core/installAddon';
|
||||
import purify from 'core/purify';
|
||||
|
||||
|
||||
|
@ -335,126 +325,6 @@ export function render404IfConfigKeyIsFalse(
|
|||
};
|
||||
}
|
||||
|
||||
export function getCompatibleVersions({ _log = log, addon, clientApp } = {}) {
|
||||
let maxVersion = null;
|
||||
let minVersion = null;
|
||||
if (
|
||||
addon && addon.current_version && addon.current_version.compatibility
|
||||
) {
|
||||
if (addon.current_version.compatibility[clientApp]) {
|
||||
maxVersion = addon.current_version.compatibility[clientApp].max;
|
||||
minVersion = addon.current_version.compatibility[clientApp].min;
|
||||
} else if (addon.type === ADDON_TYPE_OPENSEARCH) {
|
||||
_log.info(oneLine`addon is type ${ADDON_TYPE_OPENSEARCH}; no
|
||||
compatibility info found but this is expected.`, { addon, clientApp });
|
||||
} else {
|
||||
_log.error(
|
||||
'addon found with no compatibility info for valid clientApp',
|
||||
{ addon, clientApp }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return { maxVersion, minVersion };
|
||||
}
|
||||
|
||||
export function isCompatibleWithUserAgent({
|
||||
_log = log, _window = typeof window !== 'undefined' ? window : {},
|
||||
addon, maxVersion, minVersion, userAgentInfo,
|
||||
} = {}) {
|
||||
// If the userAgent is false there was likely a programming error.
|
||||
if (!userAgentInfo) {
|
||||
throw new Error('userAgentInfo is required');
|
||||
}
|
||||
|
||||
const { browser, os } = userAgentInfo;
|
||||
|
||||
// We need a Firefox browser compatible with add-ons (Firefox for iOS does
|
||||
// not currently support add-ons).
|
||||
if (browser.name === 'Firefox' && os.name === 'iOS') {
|
||||
return { compatible: false, reason: INCOMPATIBLE_FIREFOX_FOR_IOS };
|
||||
}
|
||||
|
||||
if (browser.name === 'Firefox') {
|
||||
// Do version checks, if this add-on has minimum or maximum version
|
||||
// requirements.
|
||||
// The mozilla-version-comparator API is quite strange; a result of
|
||||
// `1` means the first argument is higher in version than the second.
|
||||
//
|
||||
// Being over the maxVersion, oddly, is not actually a reason to
|
||||
// disable the install button or mark the add-on as incompatible
|
||||
// with this version of Firefox. But we log the version mismatch
|
||||
// here so it's not totally silent and a future developer isn't as
|
||||
// confused by this as tofumatt was.
|
||||
// See: https://github.com/mozilla/addons-frontend/issues/2074#issuecomment-286983423
|
||||
if (maxVersion && mozCompare(browser.version, maxVersion) === 1) {
|
||||
if (addon.current_version.is_strict_compatibility_enabled) {
|
||||
return { compatible: false, reason: INCOMPATIBLE_OVER_MAX_VERSION };
|
||||
}
|
||||
|
||||
_log.info(oneLine`maxVersion ${maxVersion} for add-on lower than
|
||||
browser version ${browser.version}, but add-on still marked as
|
||||
compatible because we largely ignore maxVersion. See:
|
||||
https://github.com/mozilla/addons-frontend/issues/2074`);
|
||||
}
|
||||
|
||||
// A result of `-1` means the second argument is a lower version than the
|
||||
// first.
|
||||
if (minVersion && mozCompare(browser.version, minVersion) === -1) {
|
||||
if (minVersion === '*') {
|
||||
_log.error(oneLine`minVersion of "*" was passed to
|
||||
isCompatibleWithUserAgent(); bad add-on version data`,
|
||||
{ browserVersion: browser.version, minVersion }
|
||||
);
|
||||
}
|
||||
|
||||
// `minVersion` is always respected, regardless of
|
||||
// `is_strict_compatibility_enabled`'s value.
|
||||
return { compatible: false, reason: INCOMPATIBLE_UNDER_MIN_VERSION };
|
||||
}
|
||||
|
||||
if (
|
||||
addon.type === ADDON_TYPE_OPENSEARCH &&
|
||||
!(_window.external && 'AddSearchProvider' in _window.external)
|
||||
) {
|
||||
return { compatible: false, reason: INCOMPATIBLE_NO_OPENSEARCH };
|
||||
}
|
||||
|
||||
// Even if an extension's version is marked compatible,
|
||||
// we need to make sure it has a matching platform file
|
||||
// to work around some bugs.
|
||||
// See https://github.com/mozilla/addons-server/issues/6576
|
||||
if (
|
||||
addon.type === ADDON_TYPE_EXTENSION &&
|
||||
!findInstallURL({
|
||||
installURLs: addon.installURLs, userAgentInfo,
|
||||
})
|
||||
) {
|
||||
return {
|
||||
compatible: false,
|
||||
reason: INCOMPATIBLE_UNSUPPORTED_PLATFORM,
|
||||
};
|
||||
}
|
||||
|
||||
// If we made it here we're compatible (yay!)
|
||||
return { compatible: true, reason: null };
|
||||
}
|
||||
|
||||
// This means the client is not Firefox, so it's incompatible.
|
||||
return { compatible: false, reason: INCOMPATIBLE_NOT_FIREFOX };
|
||||
}
|
||||
|
||||
export function getClientCompatibility({
|
||||
addon, clientApp, userAgentInfo,
|
||||
} = {}) {
|
||||
const { maxVersion, minVersion } = getCompatibleVersions({
|
||||
addon, clientApp });
|
||||
const { compatible, reason } = isCompatibleWithUserAgent({
|
||||
addon, maxVersion, minVersion, userAgentInfo });
|
||||
|
||||
return { compatible, maxVersion, minVersion, reason };
|
||||
}
|
||||
|
||||
export function getCategoryColor(category) {
|
||||
if (!category) {
|
||||
throw new Error('category is required.');
|
|
@ -30,9 +30,11 @@ import { withInstallHelpers } from 'core/installAddon';
|
|||
import themeAction from 'core/themePreview';
|
||||
import tracking, { getAction } from 'core/tracking';
|
||||
import {
|
||||
getClientCompatibility as _getClientCompatibility,
|
||||
sanitizeHTML,
|
||||
} from 'core/utils';
|
||||
import {
|
||||
getClientCompatibility as _getClientCompatibility,
|
||||
} from 'core/utils/compatibility';
|
||||
import LoadingText from 'ui/components/LoadingText';
|
||||
|
||||
import 'disco/css/Addon.scss';
|
||||
|
|
|
@ -0,0 +1,540 @@
|
|||
import { oneLine } from 'common-tags';
|
||||
import UAParser from 'ua-parser-js';
|
||||
|
||||
import {
|
||||
ADDON_TYPE_OPENSEARCH,
|
||||
ADDON_TYPE_THEME,
|
||||
CLIENT_APP_ANDROID,
|
||||
CLIENT_APP_FIREFOX,
|
||||
INCOMPATIBLE_FIREFOX_FOR_IOS,
|
||||
INCOMPATIBLE_NO_OPENSEARCH,
|
||||
INCOMPATIBLE_NOT_FIREFOX,
|
||||
INCOMPATIBLE_OVER_MAX_VERSION,
|
||||
INCOMPATIBLE_UNDER_MIN_VERSION,
|
||||
INCOMPATIBLE_UNSUPPORTED_PLATFORM,
|
||||
OS_MAC,
|
||||
} from 'core/constants';
|
||||
import { createInternalAddon } from 'core/reducers/addons';
|
||||
import {
|
||||
getCompatibleVersions,
|
||||
getClientCompatibility,
|
||||
isCompatibleWithUserAgent,
|
||||
} from 'core/utils/compatibility';
|
||||
import { fakeAddon } from 'tests/unit/amo/helpers';
|
||||
import {
|
||||
userAgents,
|
||||
userAgentsByPlatform,
|
||||
} from 'tests/unit/helpers';
|
||||
|
||||
|
||||
describe(__filename, () => {
|
||||
describe('isCompatibleWithUserAgent', () => {
|
||||
it('should throw if no userAgentInfo supplied', () => {
|
||||
expect(() => {
|
||||
isCompatibleWithUserAgent({ userAgent: null, reason: null });
|
||||
}).toThrowError('userAgentInfo is required');
|
||||
});
|
||||
|
||||
it('is incompatible with Android/webkit', () => {
|
||||
userAgents.androidWebkit.forEach((userAgent) => {
|
||||
expect(isCompatibleWithUserAgent({ userAgentInfo: UAParser(userAgent) }))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_NOT_FIREFOX });
|
||||
});
|
||||
});
|
||||
|
||||
it('is incompatible with Chrome Android', () => {
|
||||
userAgents.chromeAndroid.forEach((userAgent) => {
|
||||
expect(isCompatibleWithUserAgent({ userAgentInfo: UAParser(userAgent) }))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_NOT_FIREFOX });
|
||||
});
|
||||
});
|
||||
|
||||
it('is incompatible with Chrome desktop', () => {
|
||||
userAgents.chrome.forEach((userAgent) => {
|
||||
expect(isCompatibleWithUserAgent({ userAgentInfo: UAParser(userAgent) }))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_NOT_FIREFOX });
|
||||
});
|
||||
});
|
||||
|
||||
it('is compatible with Firefox desktop', () => {
|
||||
userAgents.firefox.forEach((userAgent) => {
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
userAgentInfo: UAParser(userAgent),
|
||||
}))
|
||||
.toEqual({ compatible: true, reason: null });
|
||||
});
|
||||
});
|
||||
|
||||
it('is compatible with Firefox Android', () => {
|
||||
userAgents.firefoxAndroid.forEach((userAgent) => {
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
userAgentInfo: UAParser(userAgent),
|
||||
}))
|
||||
.toEqual({ compatible: true, reason: null });
|
||||
});
|
||||
});
|
||||
|
||||
it('is compatible with Firefox OS', () => {
|
||||
userAgents.firefoxOS.forEach((userAgent) => {
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
userAgentInfo: UAParser(userAgent),
|
||||
}))
|
||||
.toEqual({ compatible: true, reason: null });
|
||||
});
|
||||
});
|
||||
|
||||
it('is incompatible with Firefox iOS', () => {
|
||||
userAgents.firefoxIOS.forEach((userAgent) => {
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
userAgentInfo: UAParser(userAgent),
|
||||
}))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_FIREFOX_FOR_IOS });
|
||||
});
|
||||
});
|
||||
|
||||
it(oneLine`should use a Firefox for iOS reason code even if minVersion is
|
||||
also not met`, () => {
|
||||
const userAgentInfo = {
|
||||
browser: { name: 'Firefox', version: '8.0' },
|
||||
os: { name: 'iOS' },
|
||||
};
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
minVersion: '9.0',
|
||||
userAgentInfo,
|
||||
}))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_FIREFOX_FOR_IOS });
|
||||
});
|
||||
|
||||
it('should mark Firefox without window.external as incompatible', () => {
|
||||
const userAgentInfo = {
|
||||
browser: { name: 'Firefox' },
|
||||
os: { name: 'Windows' },
|
||||
};
|
||||
const fakeOpenSearchAddon = createInternalAddon({
|
||||
...fakeAddon, type: ADDON_TYPE_OPENSEARCH,
|
||||
});
|
||||
const fakeWindow = {};
|
||||
|
||||
expect(isCompatibleWithUserAgent({
|
||||
_window: fakeWindow, addon: fakeOpenSearchAddon, userAgentInfo }))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_NO_OPENSEARCH });
|
||||
});
|
||||
|
||||
it('should mark Firefox without OpenSearch support as incompatible', () => {
|
||||
const userAgentInfo = {
|
||||
browser: { name: 'Firefox' },
|
||||
os: { name: 'Windows' },
|
||||
};
|
||||
const fakeOpenSearchAddon = createInternalAddon({
|
||||
...fakeAddon, type: ADDON_TYPE_OPENSEARCH,
|
||||
});
|
||||
const fakeWindow = { external: {} };
|
||||
|
||||
expect(isCompatibleWithUserAgent({
|
||||
_window: fakeWindow, addon: fakeOpenSearchAddon, userAgentInfo }))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_NO_OPENSEARCH });
|
||||
});
|
||||
|
||||
it('should mark Firefox with OpenSearch support as compatible', () => {
|
||||
const userAgentInfo = {
|
||||
browser: { name: 'Firefox' },
|
||||
os: { name: 'Windows' },
|
||||
};
|
||||
const fakeOpenSearchAddon = createInternalAddon({
|
||||
...fakeAddon, type: ADDON_TYPE_OPENSEARCH,
|
||||
});
|
||||
const fakeWindow = { external: { AddSearchProvider: sinon.stub() } };
|
||||
|
||||
expect(isCompatibleWithUserAgent({
|
||||
_window: fakeWindow, addon: fakeOpenSearchAddon, userAgentInfo }))
|
||||
.toEqual({ compatible: true, reason: null });
|
||||
});
|
||||
|
||||
it('should mark non-Firefox UAs as incompatible', () => {
|
||||
const userAgentInfo = { browser: { name: 'Chrome' } };
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon), userAgentInfo,
|
||||
}))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_NOT_FIREFOX });
|
||||
});
|
||||
|
||||
it('should mark Firefox 10 as incompatible with a minVersion of 10.1', () => {
|
||||
const userAgentInfo = {
|
||||
browser: { name: 'Firefox', version: '10.0' },
|
||||
os: { name: 'Windows' },
|
||||
};
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
minVersion: '10.1',
|
||||
userAgentInfo,
|
||||
}))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_UNDER_MIN_VERSION });
|
||||
});
|
||||
|
||||
it('should mark Firefox 24 as compatible with a maxVersion of 8', () => {
|
||||
// https://github.com/mozilla/addons-frontend/issues/2074
|
||||
const userAgentInfo = {
|
||||
browser: { name: 'Firefox', version: '24.0' },
|
||||
os: { name: 'Windows' },
|
||||
};
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
is_strict_compatibility_enabled: false,
|
||||
},
|
||||
}),
|
||||
maxVersion: '8',
|
||||
userAgentInfo,
|
||||
})).toEqual({ compatible: true, reason: null });
|
||||
});
|
||||
|
||||
it('should mark Firefox as compatible when no min or max version', () => {
|
||||
const userAgentInfo = {
|
||||
browser: { name: 'Firefox', version: '10.0' },
|
||||
os: { name: 'Windows' },
|
||||
};
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon), userAgentInfo,
|
||||
}))
|
||||
.toEqual({ compatible: true, reason: null });
|
||||
});
|
||||
|
||||
it('should mark Firefox as compatible with maxVersion of "*"', () => {
|
||||
// WebExtensions are marked as having a maxVersion of "*" by addons-server
|
||||
// if their manifests don't contain explicit version information.
|
||||
const userAgentInfo = {
|
||||
browser: { name: 'Firefox', version: '54.0' },
|
||||
os: { name: 'Windows' },
|
||||
};
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
maxVersion: '*',
|
||||
userAgentInfo,
|
||||
}))
|
||||
.toEqual({ compatible: true, reason: null });
|
||||
});
|
||||
|
||||
it('should log warning when minVersion is "*"', () => {
|
||||
// Note that this should never happen as addons-server will mark a
|
||||
// WebExtension with no minVersion as having a minVersion of "48".
|
||||
// Still, we accept it (but it will log a warning).
|
||||
const fakeLog = { error: sinon.stub() };
|
||||
const userAgentInfo = {
|
||||
browser: { name: 'Firefox', version: '54.0' },
|
||||
os: { name: 'Windows' },
|
||||
};
|
||||
expect(isCompatibleWithUserAgent({
|
||||
_log: fakeLog,
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
minVersion: '*',
|
||||
userAgentInfo,
|
||||
}))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_UNDER_MIN_VERSION });
|
||||
expect(fakeLog.error.firstCall.args[0])
|
||||
.toContain('minVersion of "*" was passed to isCompatibleWithUserAgent()');
|
||||
});
|
||||
|
||||
it('is incompatible with empty user agent values', () => {
|
||||
const userAgentInfo = { browser: { name: '' } };
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon), userAgentInfo,
|
||||
}))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_NOT_FIREFOX });
|
||||
});
|
||||
|
||||
it('is incompatible with non-string user agent values', () => {
|
||||
const userAgentInfo = { browser: { name: null }, os: { name: null } };
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon), userAgentInfo,
|
||||
}))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_NOT_FIREFOX });
|
||||
});
|
||||
|
||||
it('is incompatible if no matching platform file exists', () => {
|
||||
const addon = createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
files: [{
|
||||
...fakeAddon.current_version.files[0],
|
||||
platform: OS_MAC,
|
||||
}],
|
||||
},
|
||||
});
|
||||
const userAgentInfo =
|
||||
UAParser(userAgentsByPlatform.windows.firefox40);
|
||||
|
||||
expect(isCompatibleWithUserAgent({ addon, userAgentInfo }))
|
||||
.toEqual({
|
||||
compatible: false,
|
||||
reason: INCOMPATIBLE_UNSUPPORTED_PLATFORM,
|
||||
});
|
||||
});
|
||||
|
||||
it('allows non-extensions to have mismatching platform files', () => {
|
||||
const addon = createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
files: [{
|
||||
...fakeAddon.current_version.files[0],
|
||||
platform: OS_MAC,
|
||||
}],
|
||||
},
|
||||
type: ADDON_TYPE_THEME,
|
||||
});
|
||||
const userAgentInfo =
|
||||
UAParser(userAgentsByPlatform.windows.firefox40);
|
||||
|
||||
expect(isCompatibleWithUserAgent({ addon, userAgentInfo }))
|
||||
.toMatchObject({ compatible: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe('getCompatibleVersions', () => {
|
||||
it('gets the min and max versions', () => {
|
||||
const addon = createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
compatibility: {
|
||||
firefox: {
|
||||
max: '20.0.*',
|
||||
min: '11.0.1',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const { maxVersion, minVersion } = getCompatibleVersions({
|
||||
addon, clientApp: CLIENT_APP_FIREFOX });
|
||||
|
||||
expect(maxVersion).toEqual('20.0.*');
|
||||
expect(minVersion).toEqual('11.0.1');
|
||||
});
|
||||
|
||||
it('gets null if the clientApp does not match', () => {
|
||||
const addon = createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
compatibility: {
|
||||
firefox: {
|
||||
max: '20.0.*',
|
||||
min: '11.0.1',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const { maxVersion, minVersion } = getCompatibleVersions({
|
||||
addon, clientApp: CLIENT_APP_ANDROID });
|
||||
|
||||
expect(maxVersion).toEqual(null);
|
||||
expect(minVersion).toEqual(null);
|
||||
});
|
||||
|
||||
it('returns null if clientApp has no compatibility', () => {
|
||||
const addon = createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
compatibility: {},
|
||||
},
|
||||
});
|
||||
const { maxVersion, minVersion } = getCompatibleVersions({
|
||||
addon, clientApp: CLIENT_APP_FIREFOX });
|
||||
|
||||
expect(maxVersion).toEqual(null);
|
||||
expect(minVersion).toEqual(null);
|
||||
});
|
||||
|
||||
it('returns null if current_version does not exist', () => {
|
||||
const addon = createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: null,
|
||||
});
|
||||
const { maxVersion, minVersion } = getCompatibleVersions({
|
||||
addon, clientApp: CLIENT_APP_FIREFOX });
|
||||
|
||||
expect(maxVersion).toEqual(null);
|
||||
expect(minVersion).toEqual(null);
|
||||
});
|
||||
|
||||
it('returns null if addon is null', () => {
|
||||
const { maxVersion, minVersion } = getCompatibleVersions({
|
||||
addon: null, clientApp: CLIENT_APP_FIREFOX });
|
||||
|
||||
expect(maxVersion).toEqual(null);
|
||||
expect(minVersion).toEqual(null);
|
||||
});
|
||||
|
||||
it('should log info when OpenSearch type is found', () => {
|
||||
const fakeLog = { info: sinon.stub() };
|
||||
const openSearchAddon = createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
compatibility: {},
|
||||
},
|
||||
type: ADDON_TYPE_OPENSEARCH,
|
||||
});
|
||||
const { maxVersion, minVersion } = getCompatibleVersions({
|
||||
_log: fakeLog,
|
||||
addon: openSearchAddon,
|
||||
clientApp: CLIENT_APP_FIREFOX,
|
||||
});
|
||||
|
||||
expect(maxVersion).toEqual(null);
|
||||
expect(minVersion).toEqual(null);
|
||||
expect(fakeLog.info.firstCall.args[0])
|
||||
.toContain(`addon is type ${ADDON_TYPE_OPENSEARCH}`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getClientCompatibility', () => {
|
||||
it('returns true for Firefox (reason undefined when compatibile)', () => {
|
||||
const { browser, os } = UAParser(userAgents.firefox[0]);
|
||||
const userAgentInfo = { browser, os };
|
||||
|
||||
expect(getClientCompatibility({
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
clientApp: CLIENT_APP_FIREFOX,
|
||||
userAgentInfo,
|
||||
})).toEqual({
|
||||
compatible: true,
|
||||
maxVersion: null,
|
||||
minVersion: null,
|
||||
reason: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('returns maxVersion when set', () => {
|
||||
const { browser, os } = UAParser(userAgents.firefox[0]);
|
||||
const userAgentInfo = { browser, os };
|
||||
|
||||
expect(getClientCompatibility({
|
||||
addon: createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
compatibility: {
|
||||
firefox: { max: '200.0', min: null },
|
||||
},
|
||||
},
|
||||
}),
|
||||
clientApp: CLIENT_APP_FIREFOX,
|
||||
userAgentInfo,
|
||||
})).toEqual({
|
||||
compatible: true,
|
||||
maxVersion: '200.0',
|
||||
minVersion: null,
|
||||
reason: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('returns minVersion when set', () => {
|
||||
const { browser, os } = UAParser(userAgents.firefox[0]);
|
||||
const userAgentInfo = { browser, os };
|
||||
|
||||
expect(getClientCompatibility({
|
||||
addon: createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
compatibility: {
|
||||
firefox: { max: null, min: '2.0' },
|
||||
},
|
||||
},
|
||||
}),
|
||||
clientApp: CLIENT_APP_FIREFOX,
|
||||
userAgentInfo,
|
||||
})).toEqual({
|
||||
compatible: true,
|
||||
maxVersion: null,
|
||||
minVersion: '2.0',
|
||||
reason: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('returns incompatible for non-Firefox UA', () => {
|
||||
const { browser, os } = UAParser(userAgents.firefox[0]);
|
||||
const userAgentInfo = { browser, os };
|
||||
|
||||
expect(getClientCompatibility({
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
clientApp: CLIENT_APP_FIREFOX,
|
||||
userAgentInfo,
|
||||
})).toEqual({
|
||||
compatible: true,
|
||||
maxVersion: null,
|
||||
minVersion: null,
|
||||
reason: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('returns compatible if strict compatibility is off', () => {
|
||||
const { browser, os } = UAParser(userAgents.firefox[4]);
|
||||
const userAgentInfo = { browser, os };
|
||||
|
||||
expect(getClientCompatibility({
|
||||
addon: createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
compatibility: {
|
||||
...fakeAddon.current_version.compatibility,
|
||||
[CLIENT_APP_FIREFOX]: {
|
||||
max: '56.*',
|
||||
min: '24.0',
|
||||
},
|
||||
},
|
||||
files: [{
|
||||
...fakeAddon.current_version.files[0],
|
||||
is_webextension: true,
|
||||
}],
|
||||
is_strict_compatibility_enabled: false,
|
||||
},
|
||||
}),
|
||||
clientApp: CLIENT_APP_FIREFOX,
|
||||
userAgentInfo,
|
||||
})).toMatchObject({ compatible: true });
|
||||
});
|
||||
|
||||
it('returns incompatible if strict compatibility enabled', () => {
|
||||
const { browser, os } = UAParser(userAgents.firefox[5]);
|
||||
const userAgentInfo = { browser, os };
|
||||
|
||||
expect(getClientCompatibility({
|
||||
addon: createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
compatibility: {
|
||||
...fakeAddon.current_version.compatibility,
|
||||
[CLIENT_APP_FIREFOX]: {
|
||||
max: '56.*',
|
||||
min: '24.0',
|
||||
},
|
||||
},
|
||||
files: [{
|
||||
...fakeAddon.current_version.files[0],
|
||||
is_webextension: false,
|
||||
}],
|
||||
is_strict_compatibility_enabled: true,
|
||||
},
|
||||
}),
|
||||
clientApp: CLIENT_APP_FIREFOX,
|
||||
userAgentInfo,
|
||||
})).toMatchObject({
|
||||
compatible: false,
|
||||
reason: INCOMPATIBLE_OVER_MAX_VERSION,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,6 +1,5 @@
|
|||
import url from 'url';
|
||||
|
||||
import { oneLine } from 'common-tags';
|
||||
import React from 'react';
|
||||
import config from 'config';
|
||||
import { sprintf } from 'jed';
|
||||
|
@ -9,7 +8,6 @@ import {
|
|||
findRenderedComponentWithType,
|
||||
} from 'react-addons-test-utils';
|
||||
import { compose } from 'redux';
|
||||
import UAParser from 'ua-parser-js';
|
||||
|
||||
import * as api from 'core/api';
|
||||
import {
|
||||
|
@ -22,13 +20,6 @@ import {
|
|||
CATEGORY_COLORS,
|
||||
CLIENT_APP_ANDROID,
|
||||
CLIENT_APP_FIREFOX,
|
||||
INCOMPATIBLE_FIREFOX_FOR_IOS,
|
||||
INCOMPATIBLE_NO_OPENSEARCH,
|
||||
INCOMPATIBLE_NOT_FIREFOX,
|
||||
INCOMPATIBLE_OVER_MAX_VERSION,
|
||||
INCOMPATIBLE_UNDER_MIN_VERSION,
|
||||
INCOMPATIBLE_UNSUPPORTED_PLATFORM,
|
||||
OS_MAC,
|
||||
validAddonTypes,
|
||||
} from 'core/constants';
|
||||
import {
|
||||
|
@ -40,12 +31,9 @@ import {
|
|||
findAddon,
|
||||
getCategoryColor,
|
||||
getClientApp,
|
||||
getClientCompatibility,
|
||||
getClientConfig,
|
||||
getCompatibleVersions,
|
||||
isAddonAuthor,
|
||||
isAllowedOrigin,
|
||||
isCompatibleWithUserAgent,
|
||||
isValidClientApp,
|
||||
loadAddonIfNeeded,
|
||||
ngettext,
|
||||
|
@ -71,7 +59,6 @@ import {
|
|||
fakeI18n,
|
||||
unexpectedSuccess,
|
||||
userAgents,
|
||||
userAgentsByPlatform,
|
||||
} from 'tests/unit/helpers';
|
||||
|
||||
|
||||
|
@ -324,276 +311,6 @@ describe('isAddonAuthor', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('isCompatibleWithUserAgent', () => {
|
||||
it('should throw if no userAgentInfo supplied', () => {
|
||||
expect(() => {
|
||||
isCompatibleWithUserAgent({ userAgent: null, reason: null });
|
||||
}).toThrowError('userAgentInfo is required');
|
||||
});
|
||||
|
||||
it('is incompatible with Android/webkit', () => {
|
||||
userAgents.androidWebkit.forEach((userAgent) => {
|
||||
expect(isCompatibleWithUserAgent({ userAgentInfo: UAParser(userAgent) }))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_NOT_FIREFOX });
|
||||
});
|
||||
});
|
||||
|
||||
it('is incompatible with Chrome Android', () => {
|
||||
userAgents.chromeAndroid.forEach((userAgent) => {
|
||||
expect(isCompatibleWithUserAgent({ userAgentInfo: UAParser(userAgent) }))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_NOT_FIREFOX });
|
||||
});
|
||||
});
|
||||
|
||||
it('is incompatible with Chrome desktop', () => {
|
||||
userAgents.chrome.forEach((userAgent) => {
|
||||
expect(isCompatibleWithUserAgent({ userAgentInfo: UAParser(userAgent) }))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_NOT_FIREFOX });
|
||||
});
|
||||
});
|
||||
|
||||
it('is compatible with Firefox desktop', () => {
|
||||
userAgents.firefox.forEach((userAgent) => {
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
userAgentInfo: UAParser(userAgent),
|
||||
}))
|
||||
.toEqual({ compatible: true, reason: null });
|
||||
});
|
||||
});
|
||||
|
||||
it('is compatible with Firefox Android', () => {
|
||||
userAgents.firefoxAndroid.forEach((userAgent) => {
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
userAgentInfo: UAParser(userAgent),
|
||||
}))
|
||||
.toEqual({ compatible: true, reason: null });
|
||||
});
|
||||
});
|
||||
|
||||
it('is compatible with Firefox OS', () => {
|
||||
userAgents.firefoxOS.forEach((userAgent) => {
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
userAgentInfo: UAParser(userAgent),
|
||||
}))
|
||||
.toEqual({ compatible: true, reason: null });
|
||||
});
|
||||
});
|
||||
|
||||
it('is incompatible with Firefox iOS', () => {
|
||||
userAgents.firefoxIOS.forEach((userAgent) => {
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
userAgentInfo: UAParser(userAgent),
|
||||
}))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_FIREFOX_FOR_IOS });
|
||||
});
|
||||
});
|
||||
|
||||
it(oneLine`should use a Firefox for iOS reason code even if minVersion is
|
||||
also not met`, () => {
|
||||
const userAgentInfo = {
|
||||
browser: { name: 'Firefox', version: '8.0' },
|
||||
os: { name: 'iOS' },
|
||||
};
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
minVersion: '9.0',
|
||||
userAgentInfo,
|
||||
}))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_FIREFOX_FOR_IOS });
|
||||
});
|
||||
|
||||
it('should mark Firefox without window.external as incompatible', () => {
|
||||
const userAgentInfo = {
|
||||
browser: { name: 'Firefox' },
|
||||
os: { name: 'Windows' },
|
||||
};
|
||||
const fakeOpenSearchAddon = createInternalAddon({
|
||||
...fakeAddon, type: ADDON_TYPE_OPENSEARCH,
|
||||
});
|
||||
const fakeWindow = {};
|
||||
|
||||
expect(isCompatibleWithUserAgent({
|
||||
_window: fakeWindow, addon: fakeOpenSearchAddon, userAgentInfo }))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_NO_OPENSEARCH });
|
||||
});
|
||||
|
||||
it('should mark Firefox without OpenSearch support as incompatible', () => {
|
||||
const userAgentInfo = {
|
||||
browser: { name: 'Firefox' },
|
||||
os: { name: 'Windows' },
|
||||
};
|
||||
const fakeOpenSearchAddon = createInternalAddon({
|
||||
...fakeAddon, type: ADDON_TYPE_OPENSEARCH,
|
||||
});
|
||||
const fakeWindow = { external: {} };
|
||||
|
||||
expect(isCompatibleWithUserAgent({
|
||||
_window: fakeWindow, addon: fakeOpenSearchAddon, userAgentInfo }))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_NO_OPENSEARCH });
|
||||
});
|
||||
|
||||
it('should mark Firefox with OpenSearch support as compatible', () => {
|
||||
const userAgentInfo = {
|
||||
browser: { name: 'Firefox' },
|
||||
os: { name: 'Windows' },
|
||||
};
|
||||
const fakeOpenSearchAddon = createInternalAddon({
|
||||
...fakeAddon, type: ADDON_TYPE_OPENSEARCH,
|
||||
});
|
||||
const fakeWindow = { external: { AddSearchProvider: sinon.stub() } };
|
||||
|
||||
expect(isCompatibleWithUserAgent({
|
||||
_window: fakeWindow, addon: fakeOpenSearchAddon, userAgentInfo }))
|
||||
.toEqual({ compatible: true, reason: null });
|
||||
});
|
||||
|
||||
it('should mark non-Firefox UAs as incompatible', () => {
|
||||
const userAgentInfo = { browser: { name: 'Chrome' } };
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon), userAgentInfo,
|
||||
}))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_NOT_FIREFOX });
|
||||
});
|
||||
|
||||
it('should mark Firefox 10 as incompatible with a minVersion of 10.1', () => {
|
||||
const userAgentInfo = {
|
||||
browser: { name: 'Firefox', version: '10.0' },
|
||||
os: { name: 'Windows' },
|
||||
};
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
minVersion: '10.1',
|
||||
userAgentInfo,
|
||||
}))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_UNDER_MIN_VERSION });
|
||||
});
|
||||
|
||||
it('should mark Firefox 24 as compatible with a maxVersion of 8', () => {
|
||||
// https://github.com/mozilla/addons-frontend/issues/2074
|
||||
const userAgentInfo = {
|
||||
browser: { name: 'Firefox', version: '24.0' },
|
||||
os: { name: 'Windows' },
|
||||
};
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
is_strict_compatibility_enabled: false,
|
||||
},
|
||||
}),
|
||||
maxVersion: '8',
|
||||
userAgentInfo,
|
||||
})).toEqual({ compatible: true, reason: null });
|
||||
});
|
||||
|
||||
it('should mark Firefox as compatible when no min or max version', () => {
|
||||
const userAgentInfo = {
|
||||
browser: { name: 'Firefox', version: '10.0' },
|
||||
os: { name: 'Windows' },
|
||||
};
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon), userAgentInfo,
|
||||
}))
|
||||
.toEqual({ compatible: true, reason: null });
|
||||
});
|
||||
|
||||
it('should mark Firefox as compatible with maxVersion of "*"', () => {
|
||||
// WebExtensions are marked as having a maxVersion of "*" by addons-server
|
||||
// if their manifests don't contain explicit version information.
|
||||
const userAgentInfo = {
|
||||
browser: { name: 'Firefox', version: '54.0' },
|
||||
os: { name: 'Windows' },
|
||||
};
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
maxVersion: '*',
|
||||
userAgentInfo,
|
||||
}))
|
||||
.toEqual({ compatible: true, reason: null });
|
||||
});
|
||||
|
||||
it('should log warning when minVersion is "*"', () => {
|
||||
// Note that this should never happen as addons-server will mark a
|
||||
// WebExtension with no minVersion as having a minVersion of "48".
|
||||
// Still, we accept it (but it will log a warning).
|
||||
const fakeLog = { error: sinon.stub() };
|
||||
const userAgentInfo = {
|
||||
browser: { name: 'Firefox', version: '54.0' },
|
||||
os: { name: 'Windows' },
|
||||
};
|
||||
expect(isCompatibleWithUserAgent({
|
||||
_log: fakeLog,
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
minVersion: '*',
|
||||
userAgentInfo,
|
||||
}))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_UNDER_MIN_VERSION });
|
||||
expect(fakeLog.error.firstCall.args[0])
|
||||
.toContain('minVersion of "*" was passed to isCompatibleWithUserAgent()');
|
||||
});
|
||||
|
||||
it('is incompatible with empty user agent values', () => {
|
||||
const userAgentInfo = { browser: { name: '' } };
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon), userAgentInfo,
|
||||
}))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_NOT_FIREFOX });
|
||||
});
|
||||
|
||||
it('is incompatible with non-string user agent values', () => {
|
||||
const userAgentInfo = { browser: { name: null }, os: { name: null } };
|
||||
expect(isCompatibleWithUserAgent({
|
||||
addon: createInternalAddon(fakeAddon), userAgentInfo,
|
||||
}))
|
||||
.toEqual({ compatible: false, reason: INCOMPATIBLE_NOT_FIREFOX });
|
||||
});
|
||||
|
||||
it('is incompatible if no matching platform file exists', () => {
|
||||
const addon = createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
files: [{
|
||||
...fakeAddon.current_version.files[0],
|
||||
platform: OS_MAC,
|
||||
}],
|
||||
},
|
||||
});
|
||||
const userAgentInfo =
|
||||
UAParser(userAgentsByPlatform.windows.firefox40);
|
||||
|
||||
expect(isCompatibleWithUserAgent({ addon, userAgentInfo }))
|
||||
.toEqual({
|
||||
compatible: false,
|
||||
reason: INCOMPATIBLE_UNSUPPORTED_PLATFORM,
|
||||
});
|
||||
});
|
||||
|
||||
it('allows non-extensions to have mismatching platform files', () => {
|
||||
const addon = createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
files: [{
|
||||
...fakeAddon.current_version.files[0],
|
||||
platform: OS_MAC,
|
||||
}],
|
||||
},
|
||||
type: ADDON_TYPE_THEME,
|
||||
});
|
||||
const userAgentInfo =
|
||||
UAParser(userAgentsByPlatform.windows.firefox40);
|
||||
|
||||
expect(isCompatibleWithUserAgent({ addon, userAgentInfo }))
|
||||
.toMatchObject({ compatible: true });
|
||||
});
|
||||
});
|
||||
|
||||
describe('isValidClientApp', () => {
|
||||
const _config = new Map();
|
||||
_config.set('validClientApplications', [
|
||||
|
@ -1017,246 +734,6 @@ describe('render404IfConfigKeyIsFalse', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('getCompatibleVersions', () => {
|
||||
it('gets the min and max versions', () => {
|
||||
const addon = createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
compatibility: {
|
||||
firefox: {
|
||||
max: '20.0.*',
|
||||
min: '11.0.1',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const { maxVersion, minVersion } = getCompatibleVersions({
|
||||
addon, clientApp: CLIENT_APP_FIREFOX });
|
||||
|
||||
expect(maxVersion).toEqual('20.0.*');
|
||||
expect(minVersion).toEqual('11.0.1');
|
||||
});
|
||||
|
||||
it('gets null if the clientApp does not match', () => {
|
||||
const addon = createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
compatibility: {
|
||||
firefox: {
|
||||
max: '20.0.*',
|
||||
min: '11.0.1',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
const { maxVersion, minVersion } = getCompatibleVersions({
|
||||
addon, clientApp: CLIENT_APP_ANDROID });
|
||||
|
||||
expect(maxVersion).toEqual(null);
|
||||
expect(minVersion).toEqual(null);
|
||||
});
|
||||
|
||||
it('returns null if clientApp has no compatibility', () => {
|
||||
const addon = createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
compatibility: {},
|
||||
},
|
||||
});
|
||||
const { maxVersion, minVersion } = getCompatibleVersions({
|
||||
addon, clientApp: CLIENT_APP_FIREFOX });
|
||||
|
||||
expect(maxVersion).toEqual(null);
|
||||
expect(minVersion).toEqual(null);
|
||||
});
|
||||
|
||||
it('returns null if current_version does not exist', () => {
|
||||
const addon = createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: null,
|
||||
});
|
||||
const { maxVersion, minVersion } = getCompatibleVersions({
|
||||
addon, clientApp: CLIENT_APP_FIREFOX });
|
||||
|
||||
expect(maxVersion).toEqual(null);
|
||||
expect(minVersion).toEqual(null);
|
||||
});
|
||||
|
||||
it('returns null if addon is null', () => {
|
||||
const { maxVersion, minVersion } = getCompatibleVersions({
|
||||
addon: null, clientApp: CLIENT_APP_FIREFOX });
|
||||
|
||||
expect(maxVersion).toEqual(null);
|
||||
expect(minVersion).toEqual(null);
|
||||
});
|
||||
|
||||
it('should log info when OpenSearch type is found', () => {
|
||||
const fakeLog = { info: sinon.stub() };
|
||||
const openSearchAddon = createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
compatibility: {},
|
||||
},
|
||||
type: ADDON_TYPE_OPENSEARCH,
|
||||
});
|
||||
const { maxVersion, minVersion } = getCompatibleVersions({
|
||||
_log: fakeLog,
|
||||
addon: openSearchAddon,
|
||||
clientApp: CLIENT_APP_FIREFOX,
|
||||
});
|
||||
|
||||
expect(maxVersion).toEqual(null);
|
||||
expect(minVersion).toEqual(null);
|
||||
expect(fakeLog.info.firstCall.args[0])
|
||||
.toContain(`addon is type ${ADDON_TYPE_OPENSEARCH}`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getClientCompatibility', () => {
|
||||
it('returns true for Firefox (reason undefined when compatibile)', () => {
|
||||
const { browser, os } = UAParser(userAgents.firefox[0]);
|
||||
const userAgentInfo = { browser, os };
|
||||
|
||||
expect(getClientCompatibility({
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
clientApp: CLIENT_APP_FIREFOX,
|
||||
userAgentInfo,
|
||||
})).toEqual({
|
||||
compatible: true,
|
||||
maxVersion: null,
|
||||
minVersion: null,
|
||||
reason: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('returns maxVersion when set', () => {
|
||||
const { browser, os } = UAParser(userAgents.firefox[0]);
|
||||
const userAgentInfo = { browser, os };
|
||||
|
||||
expect(getClientCompatibility({
|
||||
addon: createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
compatibility: {
|
||||
firefox: { max: '200.0', min: null },
|
||||
},
|
||||
},
|
||||
}),
|
||||
clientApp: CLIENT_APP_FIREFOX,
|
||||
userAgentInfo,
|
||||
})).toEqual({
|
||||
compatible: true,
|
||||
maxVersion: '200.0',
|
||||
minVersion: null,
|
||||
reason: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('returns minVersion when set', () => {
|
||||
const { browser, os } = UAParser(userAgents.firefox[0]);
|
||||
const userAgentInfo = { browser, os };
|
||||
|
||||
expect(getClientCompatibility({
|
||||
addon: createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
compatibility: {
|
||||
firefox: { max: null, min: '2.0' },
|
||||
},
|
||||
},
|
||||
}),
|
||||
clientApp: CLIENT_APP_FIREFOX,
|
||||
userAgentInfo,
|
||||
})).toEqual({
|
||||
compatible: true,
|
||||
maxVersion: null,
|
||||
minVersion: '2.0',
|
||||
reason: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('returns incompatible for non-Firefox UA', () => {
|
||||
const { browser, os } = UAParser(userAgents.firefox[0]);
|
||||
const userAgentInfo = { browser, os };
|
||||
|
||||
expect(getClientCompatibility({
|
||||
addon: createInternalAddon(fakeAddon),
|
||||
clientApp: CLIENT_APP_FIREFOX,
|
||||
userAgentInfo,
|
||||
})).toEqual({
|
||||
compatible: true,
|
||||
maxVersion: null,
|
||||
minVersion: null,
|
||||
reason: null,
|
||||
});
|
||||
});
|
||||
|
||||
it('returns compatible if strict compatibility is off', () => {
|
||||
const { browser, os } = UAParser(userAgents.firefox[4]);
|
||||
const userAgentInfo = { browser, os };
|
||||
|
||||
expect(getClientCompatibility({
|
||||
addon: createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
compatibility: {
|
||||
...fakeAddon.current_version.compatibility,
|
||||
[CLIENT_APP_FIREFOX]: {
|
||||
max: '56.*',
|
||||
min: '24.0',
|
||||
},
|
||||
},
|
||||
files: [{
|
||||
...fakeAddon.current_version.files[0],
|
||||
is_webextension: true,
|
||||
}],
|
||||
is_strict_compatibility_enabled: false,
|
||||
},
|
||||
}),
|
||||
clientApp: CLIENT_APP_FIREFOX,
|
||||
userAgentInfo,
|
||||
})).toMatchObject({ compatible: true });
|
||||
});
|
||||
|
||||
it('returns incompatible if strict compatibility enabled', () => {
|
||||
const { browser, os } = UAParser(userAgents.firefox[5]);
|
||||
const userAgentInfo = { browser, os };
|
||||
|
||||
expect(getClientCompatibility({
|
||||
addon: createInternalAddon({
|
||||
...fakeAddon,
|
||||
current_version: {
|
||||
...fakeAddon.current_version,
|
||||
compatibility: {
|
||||
...fakeAddon.current_version.compatibility,
|
||||
[CLIENT_APP_FIREFOX]: {
|
||||
max: '56.*',
|
||||
min: '24.0',
|
||||
},
|
||||
},
|
||||
files: [{
|
||||
...fakeAddon.current_version.files[0],
|
||||
is_webextension: false,
|
||||
}],
|
||||
is_strict_compatibility_enabled: true,
|
||||
},
|
||||
}),
|
||||
clientApp: CLIENT_APP_FIREFOX,
|
||||
userAgentInfo,
|
||||
})).toMatchObject({
|
||||
compatible: false,
|
||||
reason: INCOMPATIBLE_OVER_MAX_VERSION,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getCategoryColor', () => {
|
||||
it('throws if category is false-y', () => {
|
||||
expect(() => {
|
|
@ -1,5 +1,6 @@
|
|||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
import autoprefixer from 'autoprefixer';
|
||||
import CircularDependencyPlugin from 'circular-dependency-plugin';
|
||||
import config from 'config';
|
||||
import ExtractTextPlugin from 'extract-text-webpack-plugin';
|
||||
import webpack from 'webpack';
|
||||
|
@ -149,6 +150,10 @@ export function getPlugins({ excludeOtherAppLocales = true } = {}) {
|
|||
// This swaps the server side window object with a standard browser window.
|
||||
new webpack.NormalModuleReplacementPlugin(
|
||||
/core\/window/, 'core/browserWindow.js'),
|
||||
new CircularDependencyPlugin({
|
||||
exclude: /node_modules/,
|
||||
failOnError: true,
|
||||
}),
|
||||
];
|
||||
|
||||
if (excludeOtherAppLocales) {
|
||||
|
|
|
@ -1640,6 +1640,10 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
|
|||
dependencies:
|
||||
inherits "^2.0.1"
|
||||
|
||||
circular-dependency-plugin@4.2.1:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/circular-dependency-plugin/-/circular-dependency-plugin-4.2.1.tgz#d3af66e04b3bb3f47300824740b817cea74e38f1"
|
||||
|
||||
circular-json@^0.3.1:
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d"
|
||||
|
|
Загрузка…
Ссылка в новой задаче