Lock file maintenance (#11940)
* Fix some eslint errors * eslint --fix (react/jsx-no-useless-fragment) * Add default value to actions in reducers to avoid triggering default-param-last eslint rule * eslint tests fixes * More eslint * Remove extra backtick * Some testing-library fixes * Revert "Add default value to actions in reducers to avoid triggering default-param-last eslint rule" This reverts commit cfeff97210f27f5259e05942fca83b67bb7d21ed. * disable eslint default-param-last on reducers state param * Add default index * Remove useless regexps * Re-add yarn.lock changes
This commit is contained in:
Родитель
577964e51d
Коммит
6abaafdbe3
|
@ -60,9 +60,15 @@
|
|||
"methods": ["fatal", "info", "error", "warn"]
|
||||
}],
|
||||
"react/default-props-match-prop-types": "off",
|
||||
"react/function-component-definition": "off",
|
||||
"react/jsx-no-useless-fragment" : ["error", { allowExpressions: true }],
|
||||
"react/no-unstable-nested-components": ["error", { allowAsProps: true }],
|
||||
// This rule is disabled because it outputs a lot of false positives, see:
|
||||
// https://github.com/benmosher/eslint-plugin-import/issues/1343
|
||||
"import/no-cycle": "off",
|
||||
// This rule is disabled because it outputs a lot of false positives, see:
|
||||
// https://github.com/import-js/eslint-plugin-import/issues/2181
|
||||
"import/no-import-module-exports": "off",
|
||||
"jest/expect-expect": ["warn", {
|
||||
"assertFunctionNames": [
|
||||
"expect",
|
||||
|
|
|
@ -163,39 +163,37 @@ export const AddonVersionCardBase = (props: InternalProps): React.Node => {
|
|||
return (
|
||||
<li className="AddonVersionCard">
|
||||
<div className="AddonVersionCard-content">
|
||||
<>
|
||||
{headerText && (
|
||||
<h1 className="AddonVersionCard-header">{headerText}</h1>
|
||||
)}
|
||||
{headerText && (
|
||||
<h1 className="AddonVersionCard-header">{headerText}</h1>
|
||||
)}
|
||||
|
||||
{isCurrentVersion && (
|
||||
<>
|
||||
<AddonInstallError error={installError} />
|
||||
<AddonCompatibilityError addon={addon} />
|
||||
</>
|
||||
)}
|
||||
{isCurrentVersion && (
|
||||
<>
|
||||
<AddonInstallError error={installError} />
|
||||
<AddonCompatibilityError addon={addon} />
|
||||
</>
|
||||
)}
|
||||
|
||||
<h2 className="AddonVersionCard-version">{versionNumber}</h2>
|
||||
{getFileInfoText()}
|
||||
<h2 className="AddonVersionCard-version">{versionNumber}</h2>
|
||||
{getFileInfoText()}
|
||||
|
||||
{versionInfo && (
|
||||
<div className="AddonVersionCard-compatibility">
|
||||
{versionInfo.compatibilityString}
|
||||
</div>
|
||||
)}
|
||||
{versionInfo && (
|
||||
<div className="AddonVersionCard-compatibility">
|
||||
{versionInfo.compatibilityString}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{version ? (
|
||||
<div
|
||||
className="AddonVersionCard-releaseNotes"
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={sanitizeUserHTML(version.releaseNotes)}
|
||||
/>
|
||||
) : (
|
||||
<LoadingText />
|
||||
)}
|
||||
{version ? (
|
||||
<div
|
||||
className="AddonVersionCard-releaseNotes"
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={sanitizeUserHTML(version.releaseNotes)}
|
||||
/>
|
||||
) : (
|
||||
<LoadingText />
|
||||
)}
|
||||
|
||||
{licenseSection}
|
||||
</>
|
||||
{licenseSection}
|
||||
</div>
|
||||
|
||||
{addon && <InstallWarning addon={addon} />}
|
||||
|
|
|
@ -66,8 +66,6 @@ type Props = {|
|
|||
|};
|
||||
|
||||
export class AppBase extends React.Component<Props> {
|
||||
scheduledLogout: TimeoutID;
|
||||
|
||||
static defaultProps: DefaultProps = {
|
||||
_addChangeListeners: addChangeListeners,
|
||||
_navigator: typeof navigator !== 'undefined' ? navigator : null,
|
||||
|
|
|
@ -63,6 +63,7 @@ export class DropdownMenuBase extends React.Component<InternalProps, State> {
|
|||
}
|
||||
};
|
||||
|
||||
// eslint-disable-next-line react/no-unused-class-component-methods
|
||||
handleClickOutside: () => void = () => {
|
||||
this.setState({ buttonIsActive: false });
|
||||
};
|
||||
|
|
|
@ -310,11 +310,9 @@ export class HeroRecommendationBase extends React.Component<InternalProps> {
|
|||
</h2>
|
||||
{loading ? (
|
||||
<div className="HeroRecommendation-body">
|
||||
<>
|
||||
<LoadingText width={100} />
|
||||
<br />
|
||||
<LoadingText width={80} />
|
||||
</>
|
||||
<LoadingText width={100} />
|
||||
<br />
|
||||
<LoadingText width={80} />
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
|
|
|
@ -64,8 +64,6 @@ export class HostPermissionsBase extends React.Component<InternalProps> {
|
|||
}
|
||||
}
|
||||
|
||||
i18n: I18nType;
|
||||
|
||||
// Generates Permission components for a list of host permissions. If we have 4 or
|
||||
// fewer, display them all, otherwise display the first 3 followed by an item
|
||||
// that says "...plus N others".
|
||||
|
|
|
@ -17,7 +17,7 @@ const MetadataCard = ({ className, metadata }: Props): React.Node => {
|
|||
|
||||
return (
|
||||
<div className={makeClassName('MetadataCard', className)}>
|
||||
{metadata.map(({ content, title } = {}, index) => {
|
||||
{metadata.map(({ content, title } = {}, index = 0) => {
|
||||
if (content === undefined) {
|
||||
throw new Error('content is required');
|
||||
}
|
||||
|
|
|
@ -153,14 +153,13 @@ export class RatingBase extends React.Component<InternalProps, StateType> {
|
|||
'Rating-selected-star': isSelected,
|
||||
'Rating-half-star': halfStar,
|
||||
}),
|
||||
key: `rating-${thisRating}`,
|
||||
onClick: undefined,
|
||||
onMouseEnter: () => this.onHoverStar(thisRating),
|
||||
title,
|
||||
};
|
||||
|
||||
if (readOnly) {
|
||||
return <div {...props} />;
|
||||
return <div key={`rating-${thisRating}`} {...props} />;
|
||||
}
|
||||
|
||||
if (!this.isLoading()) {
|
||||
|
@ -171,18 +170,16 @@ export class RatingBase extends React.Component<InternalProps, StateType> {
|
|||
|
||||
return (
|
||||
// eslint-disable-next-line react/jsx-key
|
||||
<>
|
||||
<button
|
||||
aria-describedby={id}
|
||||
type="button"
|
||||
value={thisRating}
|
||||
{...props}
|
||||
>
|
||||
<span id={id} className="visually-hidden">
|
||||
{title}
|
||||
</span>
|
||||
</button>
|
||||
</>
|
||||
<button
|
||||
aria-describedby={id}
|
||||
type="button"
|
||||
value={thisRating}
|
||||
{...props}
|
||||
>
|
||||
<span id={id} className="visually-hidden">
|
||||
{title}
|
||||
</span>
|
||||
</button>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -141,7 +141,7 @@ export default class ServerHtml extends Component {
|
|||
// Preload variable font(s) with `subset` in their name.
|
||||
// Note the .* after '.var': this is for the contenthash that is added in
|
||||
// production builds.
|
||||
const subsetFontPattern = new RegExp(`-subset-.*\\.var.*\\.woff2$`, 'i');
|
||||
const subsetFontPattern = /-subset-.*\.var.*\.woff2$/i;
|
||||
|
||||
return Object.keys(assets.assets)
|
||||
.filter((asset) => subsetFontPattern.test(asset))
|
||||
|
|
|
@ -222,9 +222,9 @@ export const withFixedErrorHandler = ({ fileName, extractId }) => {
|
|||
* )(SomeComponent);
|
||||
*/
|
||||
export function withRenderedErrorHandler({ name, id } = {}) {
|
||||
type ErrorBannerProps = {
|
||||
type ErrorBannerProps = {|
|
||||
errorHandler: ErrorHandlerType,
|
||||
};
|
||||
|};
|
||||
|
||||
return (WrappedComponent) => {
|
||||
function ErrorBanner(props: ErrorBannerProps) {
|
||||
|
|
|
@ -226,20 +226,18 @@ export class HomeBase extends React.Component {
|
|||
)}
|
||||
|
||||
{isDesktopSite ? (
|
||||
<>
|
||||
<Card
|
||||
className="Home-SubjectShelf Home-CuratedThemes"
|
||||
header={themesHeader}
|
||||
>
|
||||
<div className="Home-SubjectShelf-text-wrapper">
|
||||
<h2 className="Home-SubjectShelf-subheading">
|
||||
{themesHeader}
|
||||
</h2>
|
||||
</div>
|
||||
<Card
|
||||
className="Home-SubjectShelf Home-CuratedThemes"
|
||||
header={themesHeader}
|
||||
>
|
||||
<div className="Home-SubjectShelf-text-wrapper">
|
||||
<h2 className="Home-SubjectShelf-subheading">
|
||||
{themesHeader}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
{this.renderCuratedThemes()}
|
||||
</Card>
|
||||
</>
|
||||
{this.renderCuratedThemes()}
|
||||
</Card>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -155,6 +155,7 @@ type Action =
|
|||
| ShowAddonAbuseReportUIAction;
|
||||
|
||||
export default function abuseReducer(
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: AbuseState = initialState,
|
||||
action: Action,
|
||||
): AbuseState {
|
||||
|
|
|
@ -348,6 +348,7 @@ type Action =
|
|||
| UpdateRatingCountsAction;
|
||||
|
||||
export default function addonsReducer(
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: AddonsState = initialState,
|
||||
action: Action,
|
||||
): AddonsState {
|
||||
|
|
|
@ -217,6 +217,7 @@ export const getAddonsForAuthorIds = (
|
|||
type Action = FetchAddonsByAuthorsAction | LoadAddonsByAuthorsAction;
|
||||
|
||||
const reducer = (
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: AddonsByAuthorsState = initialState,
|
||||
action: Action,
|
||||
): AddonsByAuthorsState => {
|
||||
|
|
|
@ -142,6 +142,7 @@ type Action =
|
|||
| LogOutUserAction;
|
||||
|
||||
export default function api(
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: Exact<ApiState> = initialApiState,
|
||||
action: Action,
|
||||
): Exact<ApiState> {
|
||||
|
|
|
@ -120,6 +120,7 @@ type Action =
|
|||
| AutocompleteStartAction;
|
||||
|
||||
export default function reducer(
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: AutocompleteState = initialState,
|
||||
action: Action,
|
||||
): AutocompleteState {
|
||||
|
|
|
@ -110,6 +110,7 @@ export const createInternalBlock = (
|
|||
type Action = FetchBlockAction | AbortFetchBlockAction | LoadBlockAction;
|
||||
|
||||
const reducer = (
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: BlocksState = initialState,
|
||||
action: Action,
|
||||
): BlocksState => {
|
||||
|
|
|
@ -97,6 +97,7 @@ export function createEmptyCategoryList(): EmptyCategoryListType {
|
|||
type Action = FetchCategoriesAction | LoadCategoriesAction;
|
||||
|
||||
export default function reducer(
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: CategoriesState = initialState,
|
||||
action: Action,
|
||||
): CategoriesState {
|
||||
|
|
|
@ -1042,6 +1042,7 @@ type Action =
|
|||
| UpdateCollectionAction;
|
||||
|
||||
const reducer = (
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: CollectionsState = initialState,
|
||||
action: Action,
|
||||
): CollectionsState => {
|
||||
|
|
|
@ -48,6 +48,7 @@ export const loadErrorPage = ({
|
|||
type Action = LoadErrorPageAction;
|
||||
|
||||
export default function errorPage(
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: ErrorPageState = initialState,
|
||||
action: Action,
|
||||
): ErrorPageState {
|
||||
|
|
|
@ -29,6 +29,7 @@ export const storeExperimentVariant = ({
|
|||
type Action = StoreExperimentVariantAction;
|
||||
|
||||
export default function experimentsReducer(
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: ExperimentsState = initialState,
|
||||
action: Action,
|
||||
): ExperimentsState {
|
||||
|
|
|
@ -389,6 +389,7 @@ export const createInternalHomeShelves = (
|
|||
};
|
||||
|
||||
const reducer = (
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: HomeState = initialState,
|
||||
action: Action,
|
||||
_config: typeof config = config,
|
||||
|
|
|
@ -84,6 +84,7 @@ export const setInstallError = ({
|
|||
};
|
||||
|
||||
export default function installations(
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: InstallationsState = {},
|
||||
{ type, payload }: InstallationAction,
|
||||
): InstallationsState {
|
||||
|
|
|
@ -104,6 +104,7 @@ export function loadLanding({
|
|||
type Action = GetLandingAction | LoadLandingAction;
|
||||
|
||||
export default function reducer(
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: LandingState = initialState,
|
||||
action: Action,
|
||||
): LandingState {
|
||||
|
|
|
@ -87,6 +87,7 @@ export const createInternalLanguageTool = (
|
|||
type Action = FetchLanguageToolsAction | LoadLanguageToolsAction;
|
||||
|
||||
export default function languageToolsReducer(
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: LanguageToolsState = initialState,
|
||||
action: Action,
|
||||
): LanguageToolsState {
|
||||
|
|
|
@ -136,6 +136,7 @@ type Action =
|
|||
| LoadRecommendationsAction;
|
||||
|
||||
const reducer = (
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: RecommendationsState = initialState,
|
||||
action: Action,
|
||||
): RecommendationsState => {
|
||||
|
|
|
@ -56,6 +56,7 @@ export const sendServerRedirect = ({
|
|||
type Action = SendServerRedirectAction;
|
||||
|
||||
const reducer = (
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: RedirectToState = initialState,
|
||||
action: Action,
|
||||
): RedirectToState => {
|
||||
|
|
|
@ -430,6 +430,7 @@ type ReviewActionType =
|
|||
| UpdateRatingCountsAction;
|
||||
|
||||
export default function reviewsReducer(
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: ReviewsState = initialState,
|
||||
action: ReviewActionType,
|
||||
{
|
||||
|
|
|
@ -93,6 +93,7 @@ export function searchLoad({
|
|||
type Action = AbortSearchAction | SearchStartAction | SearchLoadAction;
|
||||
|
||||
export default function search(
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: SearchState = initialState,
|
||||
action: Action,
|
||||
): SearchState {
|
||||
|
|
|
@ -71,6 +71,7 @@ type Action =
|
|||
| LoadedPageIsAnonymousAction;
|
||||
|
||||
export default function siteReducer(
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: SiteState = initialState,
|
||||
action: Action,
|
||||
): SiteState {
|
||||
|
|
|
@ -42,6 +42,7 @@ export const setUIState = ({
|
|||
type UIStateActions = SetUIStateAction;
|
||||
|
||||
export default function uiStateReducer(
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: UIStateState = initialState,
|
||||
action: UIStateActions,
|
||||
): UIStateState {
|
||||
|
|
|
@ -159,6 +159,7 @@ export const initialState: UserAbuseReportsState = {
|
|||
};
|
||||
|
||||
export default function userAbuseReportReducer(
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: UserAbuseReportsState = initialState,
|
||||
action: UserAbuseReportActionType,
|
||||
): UserAbuseReportsState {
|
||||
|
|
|
@ -648,6 +648,7 @@ type Action =
|
|||
| UpdateUserAccountAction;
|
||||
|
||||
const reducer = (
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: UsersState = initialState,
|
||||
action: Action,
|
||||
_config: typeof config = config,
|
||||
|
|
|
@ -342,6 +342,7 @@ export const getVersionInfo = ({
|
|||
type Action = FetchVersionAction | FetchVersionsAction | LoadVersionsAction;
|
||||
|
||||
const reducer = (
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: VersionsState = initialState,
|
||||
action: Action,
|
||||
): VersionsState => {
|
||||
|
|
|
@ -25,6 +25,7 @@ export type ViewContextActionType = {|
|
|||
export const initialState = { context: VIEW_CONTEXT_HOME };
|
||||
|
||||
export default function viewContext(
|
||||
// eslint-disable-next-line default-param-last
|
||||
state: ViewContextState = initialState,
|
||||
action: ViewContextActionType,
|
||||
): ViewContextState {
|
||||
|
|
|
@ -24,15 +24,13 @@ describe(__filename, () => {
|
|||
it('requires a truthy add-on slug', () => {
|
||||
const params = { ...defaultParams };
|
||||
delete params.addonSlug;
|
||||
expect(() => fetchReviews(params)).toThrowError(
|
||||
/addonSlug cannot be empty/,
|
||||
);
|
||||
expect(() => fetchReviews(params)).toThrow(/addonSlug cannot be empty/);
|
||||
});
|
||||
|
||||
it('requires a truthy error handler ID', () => {
|
||||
const params = { ...defaultParams };
|
||||
delete params.errorHandlerId;
|
||||
expect(() => fetchReviews(params)).toThrowError(
|
||||
expect(() => fetchReviews(params)).toThrow(
|
||||
/errorHandlerId cannot be empty/,
|
||||
);
|
||||
});
|
||||
|
@ -73,7 +71,7 @@ describe(__filename, () => {
|
|||
|
||||
describe('setInternalReview', () => {
|
||||
it('requires a truthy review', () => {
|
||||
expect(() => setInternalReview()).toThrowError(/review cannot be empty/);
|
||||
expect(() => setInternalReview()).toThrow(/review cannot be empty/);
|
||||
});
|
||||
|
||||
it('creates an action with the exact review object', () => {
|
||||
|
|
|
@ -631,7 +631,7 @@ describe(__filename, () => {
|
|||
|
||||
await _fetchAddon({ slug: 'foo' }).then(unexpectedSuccess, (error) => {
|
||||
expect(error.message).toMatch(
|
||||
new RegExp(`Error calling: /api/${apiVersion}/addons/addon/foo/`),
|
||||
`Error calling: /api/${apiVersion}/addons/addon/foo/`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -662,7 +662,7 @@ describe(__filename, () => {
|
|||
apiURL: `${apiHost}/api/${apiVersion}/addons/addon/123/`,
|
||||
});
|
||||
expect(error.message).toMatch(
|
||||
new RegExp(`Error calling: /api/${apiVersion}/addons/addon/123/`),
|
||||
`Error calling: /api/${apiVersion}/addons/addon/123/`,
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -672,7 +672,7 @@ describe(__filename, () => {
|
|||
});
|
||||
// Add a space at the end of the URL to make sure the query string
|
||||
// isn't there.
|
||||
expect(error.message).toMatch(new RegExp('/api/resource/ '));
|
||||
expect(error.message).toMatch('/api/resource/ ');
|
||||
});
|
||||
|
||||
it('copes with a missing API URL', () => {
|
||||
|
|
|
@ -28,7 +28,7 @@ describe(__filename, () => {
|
|||
it('throws if key is missing', () => {
|
||||
expect(() => {
|
||||
config.get('missing-key');
|
||||
}).toThrowError(/Key "missing-key" was not found in clientConfig/);
|
||||
}).toThrow(/Key "missing-key" was not found in clientConfig/);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -416,7 +416,7 @@ describe(__filename, () => {
|
|||
'Select a collection…',
|
||||
);
|
||||
|
||||
expect(dispatch).not.toBeCalled();
|
||||
expect(dispatch).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('lets you create a new collection by navigating to the collection page', async () => {
|
||||
|
|
|
@ -260,7 +260,9 @@ describe(__filename, () => {
|
|||
const openFlagMenu = async ({ isReply = false } = {}) =>
|
||||
userEvent.click(
|
||||
screen.getByRole('button', {
|
||||
name: isReply ? 'Flag this developer response' : 'Flag this review',
|
||||
description: isReply
|
||||
? 'Flag this developer response'
|
||||
: 'Flag this review',
|
||||
}),
|
||||
);
|
||||
|
||||
|
@ -309,7 +311,7 @@ describe(__filename, () => {
|
|||
});
|
||||
|
||||
expect(
|
||||
screen.queryByRole('button', { name: 'Flag this review' }),
|
||||
screen.queryByRole('button', { description: 'Flag this review' }),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
@ -624,7 +626,7 @@ describe(__filename, () => {
|
|||
render({ review: _setReview() });
|
||||
|
||||
expect(
|
||||
screen.getByRole('button', { name: 'Flag this review' }),
|
||||
screen.getByRole('button', { description: 'Flag this review' }),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
@ -632,7 +634,7 @@ describe(__filename, () => {
|
|||
render({ flaggable: false, review: _setReview() });
|
||||
|
||||
expect(
|
||||
screen.queryByRole('button', { name: 'Flag this review' }),
|
||||
screen.queryByRole('button', { description: 'Flag this review' }),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
@ -640,7 +642,7 @@ describe(__filename, () => {
|
|||
render({ review: _setReview(fakeRatingOnly) });
|
||||
|
||||
expect(
|
||||
screen.queryByRole('button', { name: 'Flag this review' }),
|
||||
screen.queryByRole('button', { description: 'Flag this review' }),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
@ -648,7 +650,9 @@ describe(__filename, () => {
|
|||
renderNestedReply();
|
||||
|
||||
expect(
|
||||
screen.getByRole('button', { name: 'Flag this developer response' }),
|
||||
screen.getByRole('button', {
|
||||
description: 'Flag this developer response',
|
||||
}),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
@ -656,10 +660,12 @@ describe(__filename, () => {
|
|||
render({ review: null });
|
||||
|
||||
expect(
|
||||
screen.queryByRole('button', { name: 'Flag this review' }),
|
||||
screen.queryByRole('button', { description: 'Flag this review' }),
|
||||
).not.toBeInTheDocument();
|
||||
expect(
|
||||
screen.queryByRole('button', { name: 'Flag this developer response' }),
|
||||
screen.queryByRole('button', {
|
||||
description: 'Flag this developer response',
|
||||
}),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
@ -672,7 +678,7 @@ describe(__filename, () => {
|
|||
render({ review });
|
||||
|
||||
expect(
|
||||
screen.queryByRole('button', { name: 'Flag this review' }),
|
||||
screen.queryByRole('button', { description: 'Flag this review' }),
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
|
@ -1407,8 +1413,8 @@ describe(__filename, () => {
|
|||
expect(await screen.findByText(postText)).toBeInTheDocument();
|
||||
|
||||
expect(
|
||||
screen.getByRole('button', { name: 'Flag this review' }),
|
||||
).toHaveTextContent('Flagged');
|
||||
screen.getByRole('button', { name: 'Flagged' }),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders loading text while in progress', async () => {
|
||||
|
@ -1459,7 +1465,7 @@ describe(__filename, () => {
|
|||
// AddonReviewCard passes 'AddonReviewCard-control' as the openerClass to
|
||||
// FlagReviewMenu.
|
||||
const flagButton = screen.getByRole('button', {
|
||||
name: 'Flag this review',
|
||||
description: 'Flag this review',
|
||||
});
|
||||
expect(flagButton).toHaveClass('AddonReviewCard-control');
|
||||
|
||||
|
@ -1516,7 +1522,7 @@ describe(__filename, () => {
|
|||
render({ review });
|
||||
|
||||
expect(
|
||||
screen.getByRole('button', { name: 'Flag this review' }),
|
||||
screen.getByRole('button', { description: 'Flag this review' }),
|
||||
).toHaveTextContent('Flag');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -48,6 +48,6 @@ describe(__filename, () => {
|
|||
it('throws an error if invalid type is supplied', () => {
|
||||
expect(() => {
|
||||
render(<Badge type="invalid" label="foo" />);
|
||||
}).toThrowError(/Invalid badge type given: "invalid"/);
|
||||
}).toThrow(/Invalid badge type given: "invalid"/);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -102,7 +102,7 @@ describe(__filename, () => {
|
|||
footerLink: <a href="/some-link">Some link</a>,
|
||||
footerText: 'something else',
|
||||
});
|
||||
}).toThrowError(/can only specify exactly one of these props/);
|
||||
}).toThrow(/can only specify exactly one of these props/);
|
||||
});
|
||||
|
||||
it('throws an error if both footerLink and footer props are passed', () => {
|
||||
|
@ -111,7 +111,7 @@ describe(__filename, () => {
|
|||
footerLink: <a href="/some-link">Some link</a>,
|
||||
footer: 'something else',
|
||||
});
|
||||
}).toThrowError(/can only specify exactly one of these props/);
|
||||
}).toThrow(/can only specify exactly one of these props/);
|
||||
});
|
||||
|
||||
it('throws an error if both footer and footerText props are passed', () => {
|
||||
|
@ -120,7 +120,7 @@ describe(__filename, () => {
|
|||
footer: <a href="/some-link">Some link</a>,
|
||||
footerText: 'something else',
|
||||
});
|
||||
}).toThrowError(/can only specify exactly one of these props/);
|
||||
}).toThrow(/can only specify exactly one of these props/);
|
||||
});
|
||||
|
||||
it('renders children', () => {
|
||||
|
|
|
@ -259,13 +259,14 @@ describe(__filename, () => {
|
|||
it('renders a button with a title', async () => {
|
||||
const onClick = jest.fn();
|
||||
const title = 'some title';
|
||||
const buttonText = 'A button with title';
|
||||
await renderWithItems(
|
||||
<DropdownMenuItem onClick={onClick} title={title}>
|
||||
A button with title
|
||||
{buttonText}
|
||||
</DropdownMenuItem>,
|
||||
);
|
||||
|
||||
expect(screen.getByRole('button', { name: title })).toHaveAttribute(
|
||||
expect(screen.getByRole('button', { name: buttonText })).toHaveAttribute(
|
||||
'title',
|
||||
title,
|
||||
);
|
||||
|
|
|
@ -174,7 +174,7 @@ describe(__filename, () => {
|
|||
it('throws an error if both `href` and `to` are supplied', () => {
|
||||
expect(() => {
|
||||
render({ href: '/test', to: '/test' });
|
||||
}).toThrowError(
|
||||
}).toThrow(
|
||||
'Cannot use "href" prop and "to" prop in the same Link component',
|
||||
);
|
||||
});
|
||||
|
|
|
@ -66,7 +66,7 @@ describe(__filename, () => {
|
|||
});
|
||||
|
||||
it('throws an error for invalid styleSize', () => {
|
||||
expect(() => render({ styleSize: 'x-large' })).toThrowError(
|
||||
expect(() => render({ styleSize: 'x-large' })).toThrow(
|
||||
/styleSize=x-large is not a valid value; possible values: small,/,
|
||||
);
|
||||
});
|
||||
|
|
|
@ -170,13 +170,13 @@ describe(__filename, () => {
|
|||
it('throws for unknown static type', () => {
|
||||
expect(() => {
|
||||
getStatic({ filePath: 'amo-foo', type: 'whatever', includeSri: false });
|
||||
}).toThrowError('Unknown static type');
|
||||
}).toThrow('Unknown static type');
|
||||
});
|
||||
|
||||
it.each(['css', 'js'])('throws for missing SRI data', (type) => {
|
||||
expect(() => {
|
||||
getStatic({ filePath: 'amo-blah', type, includeSri: true, sriData: {} });
|
||||
}).toThrowError(/SRI Data is missing/);
|
||||
}).toThrow(/SRI Data is missing/);
|
||||
});
|
||||
|
||||
it('does not render empty noscript styles', () => {
|
||||
|
|
|
@ -255,7 +255,7 @@ describe(__filename, () => {
|
|||
|
||||
expect(() => {
|
||||
render({ _localStorage });
|
||||
}).toThrowError(/A non-number was stored in VPNPromoImpressionCount/);
|
||||
}).toThrow(/A non-number was stored in VPNPromoImpressionCount/);
|
||||
});
|
||||
|
||||
describe('tracking', () => {
|
||||
|
|
|
@ -401,6 +401,7 @@ describe(__filename, () => {
|
|||
describe('makeI18n', () => {
|
||||
class FakeJed {
|
||||
constructor(i18nData) {
|
||||
// eslint-disable-next-line no-constructor-return
|
||||
return i18nData;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ describe(__filename, () => {
|
|||
jest.useFakeTimers({ legacyFakeTimers: true });
|
||||
renderPage({ initialEntries: ['/en-US/firefox/simulate-async-error/'] });
|
||||
|
||||
expect(() => jest.advanceTimersByTime(51)).toThrowError(
|
||||
expect(() => jest.advanceTimersByTime(51)).toThrow(
|
||||
/simulated asynchronous error/,
|
||||
);
|
||||
});
|
||||
|
|
|
@ -185,15 +185,13 @@ describe(__filename, () => {
|
|||
it('requires an error handler', () => {
|
||||
const params = { ...defaultParams };
|
||||
delete params.errorHandler;
|
||||
expect(() => fetchAddon(params)).toThrowError(
|
||||
/errorHandler cannot be empty/,
|
||||
);
|
||||
expect(() => fetchAddon(params)).toThrow(/errorHandler cannot be empty/);
|
||||
});
|
||||
|
||||
it('requires a slug', () => {
|
||||
const params = { ...defaultParams };
|
||||
delete params.slug;
|
||||
expect(() => fetchAddon(params)).toThrowError(/slug cannot be empty/);
|
||||
expect(() => fetchAddon(params)).toThrow(/slug cannot be empty/);
|
||||
});
|
||||
|
||||
it('stores a loading state for an add-on', () => {
|
||||
|
|
|
@ -150,7 +150,7 @@ describe(__filename, () => {
|
|||
});
|
||||
|
||||
it('requires a clientApp value', () => {
|
||||
expect(() => actions.setClientApp('')).toThrowError(/cannot be falsey/);
|
||||
expect(() => actions.setClientApp('')).toThrow(/cannot be falsey/);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -167,9 +167,7 @@ describe(__filename, () => {
|
|||
|
||||
describe('setAuthToken', () => {
|
||||
it('requires a token', () => {
|
||||
expect(() => actions.setAuthToken()).toThrowError(
|
||||
/token cannot be falsey/,
|
||||
);
|
||||
expect(() => actions.setAuthToken()).toThrow(/token cannot be falsey/);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -304,6 +304,6 @@ describe(__filename, () => {
|
|||
},
|
||||
},
|
||||
),
|
||||
).toThrowError(/no add-on with guid my-addon@me.com found/);
|
||||
).toThrow(/no add-on with guid my-addon@me.com found/);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -91,6 +91,7 @@ describe(__filename, () => {
|
|||
// allowing the `autocompleteCancel()` to be handled. The delay does not
|
||||
// really matter since cancellation is expected as soon as
|
||||
// AUTOCOMPLETE_CANCELLED is fired.
|
||||
// eslint-disable-next-line no-promise-executor-return
|
||||
.returns(new Promise((resolve) => setTimeout(resolve, 500)));
|
||||
|
||||
_autocompleteStart({ filters: {} });
|
||||
|
@ -118,6 +119,7 @@ describe(__filename, () => {
|
|||
// allowing the `autocompleteCancel()` to be handled. The delay does not
|
||||
// really matter since cancellation is expected as soon as
|
||||
// AUTOCOMPLETE_CANCELLED is fired.
|
||||
// eslint-disable-next-line no-promise-executor-return
|
||||
.returns(new Promise((resolve) => setTimeout(resolve, 500)));
|
||||
|
||||
// This configures the API for the second autocomplete start.
|
||||
|
|
|
@ -4,6 +4,6 @@ describe(__filename, () => {
|
|||
it('should run all sagas without an error', () => {
|
||||
expect(() => {
|
||||
rootSagas().next();
|
||||
}).not.toThrowError();
|
||||
}).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -117,7 +117,7 @@ describe(__filename, () => {
|
|||
});
|
||||
|
||||
it('requires a webpackAssetsFileName parameter', () => {
|
||||
expect(() => new WebpackAssetsFontsPlugin()).toThrowError(
|
||||
expect(() => new WebpackAssetsFontsPlugin()).toThrow(
|
||||
/options misses the property 'webpackAssetsFileName'/,
|
||||
);
|
||||
});
|
||||
|
|
|
@ -57,6 +57,7 @@ describe(__filename, () => {
|
|||
});
|
||||
|
||||
return new Promise((resolve, reject) =>
|
||||
// eslint-disable-next-line no-promise-executor-return
|
||||
compiler.run((error, stats) => {
|
||||
if (error) {
|
||||
return reject(error);
|
||||
|
@ -124,7 +125,7 @@ describe(__filename, () => {
|
|||
});
|
||||
|
||||
it('requires a saveAs parameter', () => {
|
||||
expect(() => new SriDataPlugin()).toThrowError(
|
||||
expect(() => new SriDataPlugin()).toThrow(
|
||||
/saveAs parameter cannot be empty/,
|
||||
);
|
||||
});
|
||||
|
|
|
@ -359,7 +359,7 @@ describe(__filename, () => {
|
|||
|
||||
expect(() => {
|
||||
handleChangeEvent({ type: 'whatevs' });
|
||||
}).toThrowError(/Unknown global event/);
|
||||
}).toThrow(/Unknown global event/);
|
||||
});
|
||||
|
||||
it('listens to onOperationCancelled', () => {
|
||||
|
|
|
@ -133,7 +133,7 @@ describe(__filename, () => {
|
|||
const tracking = createTracking();
|
||||
expect(() => {
|
||||
tracking.setPage();
|
||||
}).toThrowError(/page is required/);
|
||||
}).toThrow(/page is required/);
|
||||
});
|
||||
|
||||
it('should call ga with setPage', () => {
|
||||
|
@ -224,7 +224,7 @@ describe(__filename, () => {
|
|||
tracking.sendEvent({
|
||||
action: 'whatever',
|
||||
});
|
||||
}).toThrowError(/category is required/);
|
||||
}).toThrow(/category is required/);
|
||||
});
|
||||
|
||||
it('should throw if action not set', () => {
|
||||
|
@ -233,7 +233,7 @@ describe(__filename, () => {
|
|||
tracking.sendEvent({
|
||||
category: 'whatever',
|
||||
});
|
||||
}).toThrowError(/action is required/);
|
||||
}).toThrow(/action is required/);
|
||||
});
|
||||
|
||||
// This is a way to check how many times window.ga was called with the
|
||||
|
|
|
@ -20,7 +20,7 @@ describe(__filename, () => {
|
|||
};
|
||||
|
||||
it('requires a config key', () => {
|
||||
expect(() => render404IfConfigKeyIsFalse()).toThrowError(
|
||||
expect(() => render404IfConfigKeyIsFalse()).toThrow(
|
||||
/configKey cannot be empty/,
|
||||
);
|
||||
});
|
||||
|
|
|
@ -314,7 +314,7 @@ describe(__filename, () => {
|
|||
// "theme" is not a valid pluralAddonType mapping; it should
|
||||
// be "themes".
|
||||
apiAddonType('theme');
|
||||
}).toThrowError('"theme" not found in API_ADDON_TYPES_MAPPING');
|
||||
}).toThrow('"theme" not found in API_ADDON_TYPES_MAPPING');
|
||||
});
|
||||
|
||||
// See:
|
||||
|
@ -322,7 +322,7 @@ describe(__filename, () => {
|
|||
it('does not return a false positive on a method', () => {
|
||||
expect(() => {
|
||||
apiAddonType('hasOwnProperty');
|
||||
}).toThrowError('"hasownproperty" not found in API_ADDON_TYPES_MAPPING');
|
||||
}).toThrow('"hasownproperty" not found in API_ADDON_TYPES_MAPPING');
|
||||
});
|
||||
|
||||
// See https://github.com/mozilla/addons-frontend/issues/11788
|
||||
|
@ -609,7 +609,7 @@ describe(__filename, () => {
|
|||
expect(() => {
|
||||
// "theme" is not a valid visible addonType; it should be "themes".
|
||||
visibleAddonType('theme');
|
||||
}).toThrowError('"theme" not found in VISIBLE_ADDON_TYPES_MAPPING');
|
||||
}).toThrow('"theme" not found in VISIBLE_ADDON_TYPES_MAPPING');
|
||||
});
|
||||
|
||||
// See:
|
||||
|
@ -617,9 +617,7 @@ describe(__filename, () => {
|
|||
it('does not return a false positive on a method', () => {
|
||||
expect(() => {
|
||||
visibleAddonType('hasOwnProperty');
|
||||
}).toThrowError(
|
||||
'"hasownproperty" not found in VISIBLE_ADDON_TYPES_MAPPING',
|
||||
);
|
||||
}).toThrow('"hasownproperty" not found in VISIBLE_ADDON_TYPES_MAPPING');
|
||||
});
|
||||
|
||||
// See https://github.com/mozilla/addons-frontend/issues/11788
|
||||
|
|
|
@ -1217,6 +1217,7 @@ export async function matchingSagaAction(
|
|||
}
|
||||
|
||||
// Yield a tick to the saga.
|
||||
// eslint-disable-next-line no-promise-executor-return
|
||||
await new Promise((resolve) => globalSetTimeout(resolve, 1));
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ describe(__filename, () => {
|
|||
if (!skipDevDeps.includes(key)) {
|
||||
// eslint-disable-next-line jest/no-conditional-expect
|
||||
expect(packageJson.devDependencies[key]).toEqual(
|
||||
// eslint-disable-next-line jest/no-conditional-expect
|
||||
expect.stringMatching(/^(\^|git)/),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -7,13 +7,13 @@ describe(__filename, () => {
|
|||
it('should throw an error', () => {
|
||||
expect(() => {
|
||||
fetch(url);
|
||||
}).toThrowError(`API calls MUST be mocked. URL fetched: ${url}`);
|
||||
}).toThrow(`API calls MUST be mocked. URL fetched: ${url}`);
|
||||
});
|
||||
|
||||
it('should throw an error when using a Request', () => {
|
||||
expect(() => {
|
||||
fetch(new Request(url));
|
||||
}).toThrowError(`API calls MUST be mocked. URL fetched: ${url}`);
|
||||
}).toThrow(`API calls MUST be mocked. URL fetched: ${url}`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -129,10 +129,7 @@ export function getPlugins({ withBrowserWindow = true } = {}) {
|
|||
failOnError: true,
|
||||
}),
|
||||
// This allow us to exclude locales for other apps being built.
|
||||
new webpack.ContextReplacementPlugin(
|
||||
/locale$/,
|
||||
new RegExp(`^\\.\\/.*?\\/amo\\.js$`),
|
||||
),
|
||||
new webpack.ContextReplacementPlugin(/locale$/, /^\.\/.*?\/amo\.js$/),
|
||||
];
|
||||
|
||||
if (withBrowserWindow) {
|
||||
|
|
|
@ -68,7 +68,7 @@ export default {
|
|||
plugins: [
|
||||
// Don't generate modules for locale files.
|
||||
new webpack.IgnorePlugin({
|
||||
resourceRegExp: new RegExp(`locale\\/.*\\/amo\\.js$`),
|
||||
resourceRegExp: /locale\/.*\/amo\.js$/,
|
||||
}),
|
||||
...webpackConfig.plugins,
|
||||
],
|
||||
|
|
2919
yarn.lock
2919
yarn.lock
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Загрузка…
Ссылка в новой задаче