[CORL-678] Transition to eslint (#2634)

* chore: setup eslint

* chore: tslint checks with types & check for import order

* chore: complete eslint transition

* fix: tests

* fix: linting after rebase, faster lint for lint-staged

* chore: remove line

* fix: lint rules

* feat: add a11y linter and fix errors

* fix: tests
This commit is contained in:
Vinh
2019-10-15 22:56:38 +00:00
committed by Wyatt Johnson
parent b0e0ba6633
commit 3bfcc509d2
569 changed files with 2592 additions and 1925 deletions
@@ -4,11 +4,10 @@ import React, { FunctionComponent } from "react";
import { Omit, PropTypesOf } from "coral-framework/types";
import { PasswordField as PasswordFieldUI } from "coral-ui/components";
export interface Props
extends Omit<
PropTypesOf<typeof PasswordFieldUI>,
"showPasswordTitle" | "hidePasswordTitle"
> {}
type Props = Omit<
PropTypesOf<typeof PasswordFieldUI>,
"showPasswordTitle" | "hidePasswordTitle"
>;
const PasswordField: FunctionComponent<Props> = props => (
<Localized
@@ -152,7 +152,7 @@ class MarkdownEditor extends Component<Props> {
this.editor.codemirror.on("change", this.onChange);
}
public componentWillReceiveProps(nextProps: Props) {
public UNSAFE_componentWillReceiveProps(nextProps: Props) {
if (
this.props.value !== nextProps.value &&
nextProps.value !== this.editor!.value()
@@ -198,18 +198,20 @@ let enhanced = withGetMessage(MarkdownEditor);
if (process.env.NODE_ENV === "test") {
// Replace with simple texteditor because it won't work in a jsdom environment.
enhanced = ({ onChange, ...rest }) => (
<div className={styles.wrapper}>
<textarea
{...rest}
onChange={(e: ChangeEvent<HTMLTextAreaElement> | string) => {
if (onChange) {
onChange(typeof e === "string" ? e : e.target.value);
}
}}
/>
</div>
);
enhanced = function MarkdownEditorTest({ onChange, ...rest }) {
return (
<div className={styles.wrapper}>
<textarea
{...rest}
onChange={(e: ChangeEvent<HTMLTextAreaElement> | string) => {
if (onChange) {
onChange(typeof e === "string" ? e : e.target.value);
}
}}
/>
</div>
);
};
}
export default enhanced;
@@ -1,6 +1,7 @@
import { Environment } from "relay-runtime";
import { lookup } from "coral-framework/lib/relay";
import { GQLUser } from "coral-framework/schema";
import { Environment } from "relay-runtime";
import getViewerSourceID from "./getViewerSourceID";
@@ -8,7 +8,7 @@ function resolveStoryURL() {
return canonical.href;
}
// tslint:disable-next-line:no-console
// eslint-disable-next-line no-console
console.warn(
"This page does not include a canonical link tag. Coral has inferred this story_url from the window object. Query params have been stripped, which may cause a single thread to be present across multiple pages."
);
@@ -1,5 +1,6 @@
import { Child } from "pym.js";
import React from "react";
import withContext from "./withContext";
interface Props {
@@ -132,7 +132,7 @@ function createManagedCoralContextProvider(
initLocalState: InitLocalState,
localesData: LocalesData
) {
const ManagedCoralContextProvider = class extends Component<
const ManagedCoralContextProvider = class ManagedCoralContextProvider extends Component<
{},
{ context: CoralContext }
> {
@@ -294,7 +294,7 @@ export default async function createManaged({
}
if (process.env.NODE_ENV !== "production") {
// tslint:disable:next-line: no-console
// eslint-disable-next-line no-console
console.log(`Using locales ${JSON.stringify(locales)}`);
}
@@ -1,4 +1,5 @@
import { createContextHOC } from "coral-framework/helpers";
import { CoralContext, CoralContextConsumer } from "./CoralContext";
const withContext = createContextHOC<CoralContext>(
@@ -1,6 +1,7 @@
import { ERROR_CODES } from "coral-common/errors";
import { FORM_ERROR } from "final-form";
import { ERROR_CODES } from "coral-common/errors";
/**
* Shape of the `InvalidRequest` extension as
* the client requires. Note: the only crucial
@@ -41,7 +42,7 @@ export default class InvalidRequestError extends Error
this.message = extension.message || extension.code;
}
get invalidArgs() {
public get invalidArgs() {
if (this.param) {
return {
[this.param.substr("input.".length)]: this.message,
@@ -1,6 +1,7 @@
import { areWeInIframe } from "coral-framework/utils";
import { Child as PymChild } from "pym.js";
import { areWeInIframe } from "coral-framework/utils";
export interface ExternalConfig {
accessToken?: string;
}
@@ -54,7 +54,7 @@ class SubmitHookContainer extends React.Component<Props> {
if (error instanceof InvalidRequestError) {
return error.invalidArgs;
}
// tslint:disable-next-line:no-console
// eslint-disable-next-line no-console
console.error(error);
}
return;
@@ -1,4 +1,5 @@
import { createContextHOC } from "coral-framework/helpers";
import {
SubmitHookContext,
SubmitHookContextConsumer,
@@ -1,9 +1,10 @@
import "fluent-intl-polyfill/compat";
import { FluentBundle } from "fluent/compat";
import * as functions from "./functions";
import { LocalesData } from "./locales";
import "fluent-intl-polyfill/compat";
// Don't warn in production.
let decorateWarnMissing = (bundle: FluentBundle) => bundle;
@@ -16,11 +17,9 @@ if (process.env.NODE_ENV !== "production") {
bundle.hasMessage = (id: string) => {
const result = original.apply(bundle, [id]);
if (!result) {
const warn = `${
bundle.locales
} translation for key "${id}" not found`;
const warn = `${bundle.locales} translation for key "${id}" not found`;
if (!warnings.includes(warn)) {
// tslint:disable:next-line: no-console
// eslint-disable-next-line no-console
console.warn(warn);
warnings.push(warn);
}
@@ -9,7 +9,7 @@ export default function getMessage<T extends {}>(
const res = bundles.reduce((val, bundle) => {
const message = bundle.getMessage(key);
if (!message && process.env.NODE_ENV !== "production") {
// tslint:disable-next-line:no-console
// eslint-disable-next-line no-console
console.warn(`Translation ${key} was not found for ${bundle.locales}`);
}
if (!args) {
@@ -1,4 +1,5 @@
import { toPairs } from "lodash";
import { getShortNumberCode, validateFormat } from "./FluentShortNumber";
describe("getShortNumberCode", () => {
@@ -1,6 +1,6 @@
import { FluentBundle, FluentNumber, FluentType } from "fluent/compat";
const formatRegExp = /^(0+|0+\.0+)[^\d\.]+$/;
const formatRegExp = /^(0+|0+\.0+)[^\d.]+$/;
export function validateFormat(fmt: string) {
return formatRegExp.test(fmt);
@@ -48,7 +48,7 @@ export default class FluentShortNumber extends FluentNumber {
if (!fmt) {
const message = `Missing translation key for ${key} for languages ${bundle.locales.toString()}`;
if (process.env.NODE_ENV === "production") {
// tslint:disable-next-line:no-console
// eslint-disable-next-line no-console
console.warn(message);
} else {
throw new Error(message);
@@ -60,7 +60,7 @@ export default class FluentShortNumber extends FluentNumber {
if (!validateFormat(fmt)) {
const message = `Invalid Short Number Format ${fmt}`;
if (process.env.NODE_ENV === "production") {
// tslint:disable-next-line:no-console
// eslint-disable-next-line no-console
console.warn(message);
} else {
throw new Error(message);
@@ -52,6 +52,7 @@ export interface ManagedSubscriptionClient {
/**
* Creates a ManagedSubscriptionClient
*
* @param url url of the graphql live server
* @param clientID a clientID that is provided to the graphql live server
*/
@@ -18,7 +18,7 @@ function isCoralError(err: any): err is CoralError {
export default function extractError(
err: CoralError,
unknownErrorMessage: string = "Unknown error"
unknownErrorMessage = "Unknown error"
): Error {
if (!isCoralError(err)) {
return new UnknownServerError(unknownErrorMessage, err);
+4 -2
View File
@@ -9,7 +9,7 @@ export class PostMessageService {
constructor(
scope = "coral",
origin: string = `${location.protocol}//${location.host}`
origin = `${location.protocol}//${location.host}`
) {
this.origin = origin;
this.scope = scope;
@@ -17,6 +17,7 @@ export class PostMessageService {
/**
* Send a message over the postMessage API
*
* @param name string name of the message
* @param value string value of the message
* @param target Window target window, e.g. window.opener
@@ -36,6 +37,7 @@ export class PostMessageService {
/**
* Subscribe to messages
*
* @param name string Name of the message
* @param handler PostMessageHandler
*/
@@ -43,7 +45,7 @@ export class PostMessageService {
const listener = (event: MessageEvent) => {
if (!event.origin) {
if (process.env.NODE_ENV !== "test") {
// tslint:disable-next-line:no-console
// eslint-disable-next-line no-console
console.warn("empty origin received in postMessage", name);
}
} else if (event.origin !== this.origin) {
@@ -10,7 +10,7 @@ type RecordSourceProxy<T> = T extends object
? ReadonlyArray<RecordSourceProxy<U>>
: T[P] extends ReadonlyArray<infer V>
? ReadonlyArray<RecordSourceProxy<V>>
: RecordSourceProxy<T[P]>
: RecordSourceProxy<T[P]>;
}
: T;
@@ -1,4 +1,4 @@
import { useCallback } from "react";
import React, { useCallback } from "react";
import { InferableComponentEnhancer } from "recompose";
import { Disposable, Environment } from "relay-runtime";
@@ -75,7 +75,7 @@ export function withSubscription<N extends string, V, R>(
return (BaseComponent: React.ComponentType<any>) => {
{
const sub = useSubscription(subscription);
return props => {
return function WithSubscription(props) {
const finalProps = {
...props,
[subscription.name]: sub,
+1 -1
View File
@@ -1,7 +1,7 @@
import { _RefType } from "react-relay";
export type FragmentKeys<T> = {
[P in keyof T]: T[P] extends _RefType<any> | null ? P : never
[P in keyof T]: T[P] extends _RefType<any> | null ? P : never;
}[keyof T];
export type FragmentKeysNoLocal<T> = Exclude<FragmentKeys<T>, "local">;
@@ -18,7 +18,7 @@ export default function useLoadMore(
relay.loadMore(count, error => {
setIsLoadingMore(false);
if (error) {
// tslint:disable-next-line:no-console
// eslint-disable-next-line no-console
console.error(error);
}
});
@@ -8,7 +8,6 @@ import {
import { OmitFragments } from "coral-framework/testHelpers/removeFragmentRefs";
import { DeepPartial } from "coral-framework/types";
import { _RefType } from "react-relay";
import { useCoralContext } from "../bootstrap";
import { LOCAL_ID, LOCAL_TYPE } from "./localState";
@@ -31,6 +30,7 @@ function isAdvancedUpdater(t: LocalUpdater<any>): t is AdvancedUpdater {
/**
* applySimplified takes selections defined in a fragment, an object
* containing data changes and smartly applies it to the record proxy.
*
* @param record Record Proxy poing to Local Record
* @param selections Selections of the fragment
* @param data Data you want to set
@@ -25,7 +25,7 @@ export default function useRefetch<V = Variables>(
error => {
setRefetching(false);
if (error) {
// tslint:disable-next-line:no-console
// eslint-disable-next-line no-console
console.error(error);
}
},
@@ -1,11 +1,12 @@
import {
_RefType,
createFragmentContainer,
FragmentOrRegularProp,
GraphQLTaggedNode,
} from "react-relay";
import { InferableComponentEnhancerWithProps } from "recompose";
import { wrapDisplayName } from "recompose";
import {
InferableComponentEnhancerWithProps,
wrapDisplayName,
} from "recompose";
import hideForwardRef from "./hideForwardRef";
import { FragmentKeysNoLocal } from "./types";
@@ -76,6 +76,7 @@ function withLocalStateContainer(
const nextState = { data: snapshot.data };
// State has not been initialized yet.
if (!this.state) {
// eslint-disable-next-line react/no-direct-mutation-state
this.state = nextState;
return;
}
@@ -86,7 +87,7 @@ function withLocalStateContainer(
this.subscription.dispose();
}
public componentWillReceiveProps(next: Props) {
public UNSAFE_componentWillReceiveProps(next: Props) {
if (this.props.relayEnvironment !== next.relayEnvironment) {
this.unsubscribe();
this.subscribe(next.relayEnvironment);
@@ -12,13 +12,13 @@ export default function wrapFetchWithLogger(
try {
const result = await (fetch as any)(...args);
if (options.logResult) {
// tslint:disable-next-line:no-console
// eslint-disable-next-line no-console
console.log(JSON.stringify(result));
}
return result;
} catch (err) {
if (!options.muteErrors) {
// tslint:disable-next-line:no-console
// eslint-disable-next-line no-console
console.error(err);
}
throw err;
@@ -31,7 +31,13 @@ function withRouteConfig<
(component as any).routeConfig = {
...config,
Component: component,
render: ({ error, props: data, retry, match, Component }: any) => {
render: function WitRouteConfig({
error,
props: data,
retry,
match,
Component,
}: any) {
if (config.render) {
return config.render({ error, data, retry, match, Component });
}
@@ -11,7 +11,7 @@ class InMemoryStorage implements Storage {
this.data = data;
}
get length() {
public get length() {
return Object.keys(this.data).length;
}
@@ -31,7 +31,7 @@ class BackedPromisifedStorage implements PromisifiedStorage {
this.storage = storage;
}
get length() {
public get length() {
return Promise.resolve(this.storage.length);
}
@@ -1,5 +1,6 @@
import { Child, Parent } from "pym.js";
import uuid from "uuid/v1";
import { PromisifiedStorage } from "./PromisifiedStorage";
type Pym = Child | Parent;
@@ -55,7 +56,7 @@ class PymStorage implements PromisifiedStorage {
this.listen();
}
get length() {
public get length() {
return this.call<number>("length");
}
public key(n: number) {
@@ -78,8 +79,9 @@ class PymStorage implements PromisifiedStorage {
/**
* Creates a storage that put requests onto pym.
* This is the counterpart of `connectStorageToPym`.
*
* @param {string} pym pym
* @return {Object} storage
* @returns {object} storage
*/
export default function createPymStorage(
pym: Pym,
@@ -1,4 +1,5 @@
import sinon from "sinon";
import createInMemoryStorage from "./InMemoryStorage";
import prefixStorage from "./prefixStorage";
@@ -11,7 +11,7 @@ class PrefixedStorage implements Storage {
this.prefix = prefix;
}
get length() {
public get length() {
let count = 0;
for (let i = 0; i < this.storage.length; i++) {
const key = this.storage.key(i);
@@ -1,6 +1,8 @@
import { Environment } from "relay-runtime";
import { CoralContext } from "coral-framework/lib/bootstrap";
import { createMutationContainer } from "coral-framework/lib/relay";
import { Environment } from "relay-runtime";
import signOut from "../rest/signOut";
import SetAccessTokenMutation from "./SetAccessTokenMutation";
+2 -1
View File
@@ -3,7 +3,6 @@
* This should be generated by `graphql-schema-typescript`.
*/
import { RelayEnumLiteral } from "../types";
import {
GQLCOMMENT_FLAG_DETECTED_REASON,
GQLCOMMENT_FLAG_REASON,
@@ -18,6 +17,8 @@ import {
GQLUSER_STATUS,
} from "./__generated__/types";
import { RelayEnumLiteral } from "../types";
export type GQLMODERATION_QUEUE_RL = RelayEnumLiteral<
typeof GQLMODERATION_QUEUE
>;
@@ -1,7 +1,8 @@
import { withContext } from "coral-framework/lib/bootstrap";
import { Location, Match, Router, withRouter } from "found";
import React, { useEffect } from "react";
import { withContext } from "coral-framework/lib/bootstrap";
interface Props {
/** router is injected by `withRouter` HOC */
router: Router;
@@ -77,7 +77,7 @@ export function queryAllByLabelText(
x.props["aria-labelledby"] === i.props.id
)
);
} catch {} // tslint:disable-line:no-empty
} catch {} // eslint-disable-line no-empty
}
});
// Find matching labels.
@@ -90,7 +90,7 @@ export function queryAllByLabelText(
x => typeof x.type === "string" && x.props.id === i.props.htmlFor
)
);
} catch {} // tslint:disable-line:no-empty
} catch {} // eslint-disable-line no-empty
}
}
);
@@ -7,6 +7,7 @@ import matchText, { TextMatchOptions, TextMatchPattern } from "./matchText";
/**
* Turns list of children of a dom element into a string.
* This will also handle React Fragments.
*
* @param children list of children
*/
const childrenToString = (children: ReactTestInstance["children"]) => {
@@ -12,14 +12,14 @@ export type Callbackify<T> = T extends object
? Array<Callbackify<U>>
: T[P] extends (ReadonlyArray<infer V> | undefined)
? ReadonlyArray<Callbackify<V>>
: Callbackify<T[P]>
: Callbackify<T[P]>;
}
| (() => {
[P in keyof T]: T[P] extends (Array<infer U> | undefined)
? Array<Callbackify<U>>
: T[P] extends (ReadonlyArray<infer V> | undefined)
? ReadonlyArray<Callbackify<V>>
: Callbackify<T[P]>
: Callbackify<T[P]>;
})
: T | (() => T);
@@ -32,7 +32,7 @@ export type WithTypename<T> = T extends object
? Array<WithTypename<U>>
: T[P] extends (ReadonlyArray<infer V> | undefined)
? ReadonlyArray<WithTypename<V>>
: WithTypename<T[P]>
: WithTypename<T[P]>;
} & { __typename?: string }
: T;
@@ -1,10 +1,10 @@
import "fluent-intl-polyfill/compat";
import { FluentBundle } from "fluent/compat";
import fs from "fs";
import path from "path";
import * as functions from "coral-framework/lib/i18n/functions";
import fs from "fs";
import path from "path";
import "fluent-intl-polyfill/compat";
// These locale prefixes are always loaded.
const commonPrefixes = ["ui", "common", "framework"];
@@ -17,7 +17,7 @@ function decorateErrorWhenMissing(bundle: FluentBundle) {
const result = originalHasMessage.apply(bundle, [id]);
if (!result) {
const msg = `${bundle.locales} translation for key "${id}" not found`;
// tslint:disable-next-line:no-console
// eslint-disable-next-line no-console
console.error(msg);
missing.push(id);
}
@@ -26,7 +26,7 @@ function decorateErrorWhenMissing(bundle: FluentBundle) {
return true;
};
bundle.getMessage = (id: string) => {
if (missing.indexOf(id) !== -1) {
if (missing.includes(id)) {
return `Missing translation "${id}"`;
}
return originalGetMessage.apply(bundle, [id]);
@@ -47,6 +47,7 @@ function createFluentBundle(
files.forEach(f => {
prefixes.forEach(prefix => {
if (f.startsWith(prefix)) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
bundle.addMessages(require(path.resolve(pathToLocale, f)));
}
});
@@ -1,7 +1,8 @@
import { Omit } from "coral-framework/types";
import { identity, omit } from "lodash";
import sinon from "sinon";
import { Omit } from "coral-framework/types";
import { Fixture } from "./createFixture";
import { Resolver } from "./createTestRenderer";
@@ -38,7 +39,7 @@ export default function createMutationResolverStub<
expectAndFail(clientMutationId).toBeTruthy();
expectAndFail(lastClientMutationIds).not.toContain(clientMutationId);
lastClientMutationIds.push(clientMutationId);
const result = await callback({
const result = callback({
variables: omit(data.input, "clientMutationId"),
callCount: callCount++,
typecheck: identity,
@@ -11,6 +11,11 @@ import {
Store,
} from "relay-runtime";
import { loadSchema } from "coral-common/graphql";
import {
InvalidRequestError,
ModerationNudgeError,
} from "coral-framework/lib/errors";
import {
createAndRetain,
LOCAL_ID,
@@ -18,12 +23,6 @@ import {
wrapFetchWithLogger,
} from "coral-framework/lib/relay";
import { loadSchema } from "coral-common/graphql";
import {
InvalidRequestError,
ModerationNudgeError,
} from "coral-framework/lib/errors";
import { SubscriptionHandler } from "./createSubscriptionHandler";
export interface CreateRelayEnvironmentNetworkParams {
@@ -180,7 +179,7 @@ export default function createRelayEnvironment(
);
root.setLinkedRecord(localRecord, "local");
if (typeof params.initLocalState === "function") {
params.initLocalState!(localRecord, sourceProxy, environment);
params.initLocalState(localRecord, sourceProxy, environment);
}
});
}
@@ -13,12 +13,12 @@ export interface ResolversTemplate<T extends Resolvers = any> {
Query?: {
[P in keyof Required<T>["Query"]]: QueryResolverCallback<
Required<T>["Query"][P]
>
>;
};
Mutation?: {
[P in keyof Required<T>["Mutation"]]: MutationResolverCallback<
Required<T>["Mutation"][P]
>
>;
};
}
@@ -1,5 +1,4 @@
import { GQLSubscription } from "coral-framework/schema";
import { DeepPartial } from "coral-framework/types";
export type SubscriptionVariables<
@@ -42,6 +41,7 @@ export interface SubscriptionHandlerReadOnly {
* dispatch will look for subscriptions of the field `field` and
* calls the `callback` for each of them. If `callback` returns data,
* it'll be dispatched to that subscription.
*
* @param field name of subscription field to look for.
* @param callback callback is called for every subscription on this field.
*/
@@ -70,7 +70,7 @@ export default function createSubscriptionHandler(): SubscriptionHandler {
dispatch: (field, callback) => {
subscriptions.forEach(s => {
if (s.field === field) {
const data = callback(s.variables as any);
const data = callback(s.variables);
if (data) {
s.dispatch(data);
}
@@ -5,6 +5,7 @@ import path from "path";
import React from "react";
import TestRenderer, { ReactTestRenderer } from "react-test-renderer";
import { Environment, RecordProxy, RecordSourceProxy } from "relay-runtime";
import sinon from "sinon";
import { RequireProperty } from "coral-common/types";
import {
@@ -16,7 +17,6 @@ import { RestClient } from "coral-framework/lib/rest";
import { createPromisifiedStorage } from "coral-framework/lib/storage";
import { createUUIDGenerator } from "coral-framework/testHelpers";
import sinon from "sinon";
import createFluentBundle from "./createFluentBundle";
import createRelayEnvironment from "./createRelayEnvironment";
import createSubscriptionHandler, {
@@ -4,7 +4,7 @@ import createQueryResolverStub, {
import { Resolver, Resolvers, TestResolvers } from "./createTestRenderer";
type ValueOrCallbackRecursive<T> = {
[P in keyof T]?: ValueOrCallbackRecursive<T[P]> | (() => void)
[P in keyof T]?: ValueOrCallbackRecursive<T[P]> | (() => void);
};
type ResolverResult<T extends Resolver<any, any>> = T extends Resolver<
@@ -17,7 +17,7 @@ type ResolverResult<T extends Resolver<any, any>> = T extends Resolver<
type OverwriteQueryResolverTemplate<T extends Resolvers = any> = {
[P in keyof Required<T>["Query"]]: ValueOrCallbackRecursive<
ResolverResult<Required<T>["Query"][P]>
>
>;
};
/**
@@ -47,7 +47,7 @@ function overwriteRecursive(original: any, overwrite: any) {
if (typeof overwrite[k] === "function") {
// Resolve overwrite resolver and return it's value
// or if undefined the original resolved value.
const result = (overwrite as any)[k](...args);
const result = overwrite[k](...args);
return result !== undefined ? result : resolve();
}
// The overwrite is an Object, so we will recurse into it,
@@ -72,6 +72,7 @@ function overwriteRecursive(original: any, overwrite: any) {
* but allows you to return `void` which would then fallback to the original resolver.
*
* Given a `ResolverType` from the Schema it'll provide types as well!.
*
* @param callback resolver callback
*/
export function createQueryResolverOverwrite<T extends Resolver<any, any>>(
@@ -4,7 +4,7 @@ import { ComponentType } from "react";
export type OmitFragments<T> = Pick<
T,
{
[P in keyof T]: P extends " $fragmentRefs" | " $refType" ? never : P
[P in keyof T]: P extends " $fragmentRefs" | " $refType" ? never : P;
}[keyof T]
>;
@@ -32,12 +32,12 @@ type RemoveFirstArgument<T, R> = T extends [any, any, any, any?]
? Func0<R>
: unknown;
// tslint:disable
// @TODO: currently tslint fails to parse this: `...any[]`.
function applyContainer<T extends [ReactTestInstance, ...any[]], R>(container: ReactTestInstance, fn: (...args: T) => R): RemoveFirstArgument<T, R> {
return ((...args: any[]) => fn(...[container, ...args] as any)) as any;
function applyContainer<T extends [ReactTestInstance, ...any[]], R>(
container: ReactTestInstance,
fn: (...args: T) => R
): RemoveFirstArgument<T, R> {
return ((...args: any[]) => fn(...([container, ...args] as any))) as any;
}
// tslint:enable
export default function within(container: ReactTestInstance) {
return {
+1 -1
View File
@@ -6,7 +6,7 @@ export default function buildURL({
search = window.location.search,
hash = window.location.hash,
} = {}) {
if (search && search[0] !== "?") {
if (search && !search.startsWith("?")) {
search = `?${search}`;
} else if (search === "?") {
search = "";
+4 -3
View File
@@ -1,8 +1,9 @@
/**
* Initiate a jsonp request.
* @argument endpoint jsonp endpoint
* @argument callback name of global callback to receive response
* @argument args args to send along the jsonp request.
*
* @param endpoint jsonp endpoint
* @param callback name of global callback to receive response
* @param args args to send along the jsonp request.
*/
function jsonp(
endpoint: string,
@@ -4,7 +4,7 @@ export default function parseQueryHash(
hash: string
): Record<string, string | undefined> {
let normalized = hash;
if (normalized[0] === "#") {
if (normalized.startsWith("#")) {
normalized = normalized.substr(1);
}
return parseQuery(normalized);