[next] Report Comment + Stream Refactor & Test Improvements (#2144)

* fix: stabilize mutations

* feat: Refactor Stream + Implement Report Comment

* test: add unit tests

* chore: Improve stream integration tests

* test: add integration test for reaction

* test: add feature/integration tests for report comment

* fix: order import

* fix: performance issues + keep active button styling until clicked away
This commit is contained in:
Kiwi
2019-01-16 22:31:43 +00:00
committed by Wyatt Johnson
parent 94eb72a9bf
commit 939152ee81
118 changed files with 7985 additions and 18846 deletions
+8 -2
View File
@@ -13,8 +13,14 @@ export const VALIDATION_REQUIRED = () => (
);
export const VALIDATION_TOO_SHORT = (minLength: number) => (
<Localized id="framework-validation-tooShort">
<span>{"This field must contain at least {$minLength} characters."}</span>
<Localized id="framework-validation-tooShort" $minLength={minLength}>
<span>{"Please enter at least {$minLength} characters."}</span>
</Localized>
);
export const VALIDATION_TOO_LONG = (maxLength: number) => (
<Localized id="framework-validation-tooLong" $maxLength={maxLength}>
<span>{"Please enter at max {$maxLength} characters."}</span>
</Localized>
);
@@ -19,6 +19,8 @@ import {
USERNAME_TOO_LONG,
USERNAME_TOO_SHORT,
VALIDATION_REQUIRED,
VALIDATION_TOO_LONG,
VALIDATION_TOO_SHORT,
} from "./messages";
export type Validator<T = any, V = any> = (v: T, values: V) => ReactNode;
@@ -76,6 +78,24 @@ export const validateURL = createValidator(
INVALID_URL()
);
/**
* validateMinLength is a Validator that checks that the field has a min length of characters
*/
export const validateMinLength = (minLength: number) =>
createValidator(
v => !v || v.length >= minLength,
VALIDATION_TOO_SHORT(minLength)
);
/**
* validateMaxLength is a Validator that checks that the field has max length of characters
*/
export const validateMaxLength = (maxLength: number) =>
createValidator(
v => !v || v.length <= maxLength,
VALIDATION_TOO_LONG(maxLength)
);
/**
* validateUsernameMinLength is a Validator that checks that the username has a min length of characters
*/
@@ -0,0 +1,36 @@
import { ReactTestInstance } from "react-test-renderer";
import matchText, { TextMatchOptions, TextMatchPattern } from "./matchText";
const matcher = (pattern: TextMatchPattern, options?: TextMatchOptions) => (
i: ReactTestInstance
) => {
// Only look at dom components.
if (typeof i.type !== "string" || !i.props.id) {
return false;
}
return matchText(pattern, i.props.id, {
collapseWhitespace: false,
...options,
});
};
export function getByID(
container: ReactTestInstance,
pattern: TextMatchPattern,
options?: TextMatchOptions
) {
return container.find(matcher(pattern, options));
}
export function queryByID(
container: ReactTestInstance,
pattern: TextMatchPattern,
options?: TextMatchOptions
) {
const results = container.findAll(matcher(pattern, options));
if (!results.length) {
return null;
}
return results[0];
}
@@ -62,7 +62,7 @@ export function queryAllByLabelText(
options?: TextMatchOptions
) {
const matches = container.findAll(ariaLabelMatcher(pattern, options));
queryAllByText(container, pattern).forEach(i => {
queryAllByText(container, pattern, options).forEach(i => {
if (typeof i.type !== "string") {
return;
}
@@ -1,6 +1,8 @@
import React from "react";
import { ReactTestInstance } from "react-test-renderer";
import findParentsWithType from "./findParentsWithType";
import findParentWithType from "./findParentWithType";
import matchText, { TextMatchOptions, TextMatchPattern } from "./matchText";
const matcher = (pattern: TextMatchPattern, options?: TextMatchOptions) => (
@@ -10,6 +12,12 @@ const matcher = (pattern: TextMatchPattern, options?: TextMatchOptions) => (
if (typeof i.type !== "string") {
return false;
}
if (
i.props.dangerouslySetInnerHTML &&
matchText(pattern, i.props.dangerouslySetInnerHTML.__html, options)
) {
return true;
}
if (!i.props.children) {
return false;
}
@@ -22,20 +30,34 @@ const matcher = (pattern: TextMatchPattern, options?: TextMatchOptions) => (
return false;
};
interface SelectorOptions {
selector?: string | React.ComponentClass<any> | React.StatelessComponent<any>;
}
export function getByText(
container: ReactTestInstance,
pattern: TextMatchPattern,
options?: TextMatchOptions
options?: TextMatchOptions & SelectorOptions
) {
return container.find(matcher(pattern, options));
const result = findParentWithType(
container.find(matcher(pattern, options)),
options && options.selector
);
if (!result) {
throw new Error(`Couldn't find text ${pattern}`);
}
return result;
}
export function getAllByText(
container: ReactTestInstance,
pattern: TextMatchPattern,
options?: TextMatchOptions
options?: TextMatchOptions & SelectorOptions
) {
const results = container.findAll(matcher(pattern, options));
const results = findParentsWithType(
container.findAll(matcher(pattern, options)),
options && options.selector
);
if (!results.length) {
throw new Error(`Couldn't find text ${pattern}`);
}
@@ -45,9 +67,12 @@ export function getAllByText(
export function queryByText(
container: ReactTestInstance,
pattern: TextMatchPattern,
options?: TextMatchOptions
options?: TextMatchOptions & SelectorOptions
) {
const results = container.findAll(matcher(pattern, options));
const results = findParentsWithType(
container.findAll(matcher(pattern, options)),
options && options.selector
);
if (!results.length) {
return null;
}
@@ -57,7 +82,10 @@ export function queryByText(
export function queryAllByText(
container: ReactTestInstance,
pattern: TextMatchPattern,
options?: TextMatchOptions
options?: TextMatchOptions & SelectorOptions
) {
return container.findAll(matcher(pattern, options));
return findParentsWithType(
container.findAll(matcher(pattern, options)),
options && options.selector
);
}
@@ -0,0 +1,20 @@
import { ReactTestInstance } from "react-test-renderer";
export default function findParentWithType(
instance: ReactTestInstance,
selector:
| string
| React.ComponentClass<any>
| React.StatelessComponent<any> = "*"
): ReactTestInstance | null {
if (selector === "*") {
return instance;
}
if (instance.type === selector) {
return instance;
}
if (instance.parent) {
return findParentWithType(instance.parent, selector);
}
return null;
}
@@ -0,0 +1,15 @@
import { ReactTestInstance } from "react-test-renderer";
import findParentWithType from "./findParentWithType";
export default function findParentsWithType(
instances: ReactTestInstance[],
selector:
| string
| React.ComponentClass<any>
| React.StatelessComponent<any> = "*"
): ReactTestInstance[] {
return instances
.map(i => findParentWithType(i, selector))
.filter(i => i) as ReactTestInstance[];
}
@@ -20,3 +20,5 @@ export { default as matchText } from "./matchText";
export { default as toJSON } from "./toJSON";
export { default as replaceHistoryLocation } from "./replaceHistoryLocation";
export { default as createAuthToken } from "./createAuthToken";
export { default as findParentsWithType } from "./findParentsWithType";
export { default as findParentWithType } from "./findParentWithType";
@@ -1,5 +1,9 @@
import { ReactTestInstance } from "react-test-renderer";
import {
getByID,
queryByID,
} from "./byID";
import {
getAllByLabelText,
getByLabelText,
@@ -47,6 +51,8 @@ export default function within(container: ReactTestInstance) {
getAllByTestID: applyContainer(container, getAllByTestID),
queryByTestID: applyContainer(container, queryByTestID),
queryAllByTestID: applyContainer(container, queryAllByTestID),
getByID: applyContainer(container, getByID),
queryByID: applyContainer(container, queryByID),
getByText: applyContainer(container, getByText),
getAllByText: applyContainer(container, getAllByText),
queryByText: applyContainer(container, queryByText),