Merge pull request #1829 from coralproject/rte-next

[next] Support for Rich Text
This commit is contained in:
Kim Gardner
2018-08-29 16:01:11 -04:00
committed by GitHub
50 changed files with 2117 additions and 648 deletions
+46 -7
View File
@@ -1341,6 +1341,17 @@
"to-fast-properties": "^2.0.0"
}
},
"@coralproject/rte": {
"version": "0.10.6",
"resolved": "https://registry.npmjs.org/@coralproject/rte/-/rte-0.10.6.tgz",
"integrity": "sha512-oUK/KSw28AkmpX5D8v1IkQT0iIxKxPmSG0euTFgqEthSgnAUQgoOmQengaR/nsS9zE31KPbbWMIAzH0aN/YwNA==",
"dev": true,
"requires": {
"bowser": "^1.0.0",
"classnames": "^2.2.6",
"react-contenteditable": "^2.1.5"
}
},
"@csstools/convert-colors": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz",
@@ -1703,6 +1714,12 @@
"@types/node": "*"
}
},
"@types/dompurify": {
"version": "0.0.31",
"resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-0.0.31.tgz",
"integrity": "sha512-Vi2VBl262MjJuxpROjQU3AuBv1NgA7oaL9jqLJRgF60tps4GR/9qzXN0P4pRYPXsBA0b10AF1M6wO74uwGqtmw==",
"dev": true
},
"@types/dotenv": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/@types/dotenv/-/dotenv-4.0.3.tgz",
@@ -5359,6 +5376,12 @@
}
}
},
"bowser": {
"version": "1.9.4",
"resolved": "https://registry.npmjs.org/bowser/-/bowser-1.9.4.tgz",
"integrity": "sha512-9IdMmj2KjigRq6oWhmwv1W36pDuA4STQZ8q6YO9um+x07xgYNCD3Oou+WP/3L1HNz7iqythGet3/p4wvc8AAwQ==",
"dev": true
},
"boxen": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz",
@@ -8751,6 +8774,12 @@
"domelementtype": "1"
}
},
"dompurify": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-1.0.7.tgz",
"integrity": "sha512-1xK0JEda/jvIm3SgqHXKvRCh3AbEKCyBbUAGpNCMVIljBD145cPvBR66JSj3O4SdscFUx5NXsDkJpz6vDT8KLg==",
"dev": true
},
"domutils": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
@@ -20474,6 +20503,16 @@
"integrity": "sha512-9Fv10F6rrzFDIT04aoRsw3dbN6l6onNXbBvCpt4OjXZFGDz/P65laNIujHVTlVjcqErut9d4BL0aplVByyGcJw==",
"dev": true
},
"react-contenteditable": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/react-contenteditable/-/react-contenteditable-2.1.5.tgz",
"integrity": "sha512-mjaxwybOX7Om8Cx/0mVCUpgvAyheP48JXoABMTvzWENluFTpwAhlsLfKN4xNZk3Y7DsiidA7mUZibh0sTMly2w==",
"dev": true,
"requires": {
"@types/prop-types": "^15.5.4",
"fast-deep-equal": "^2.0.1"
}
},
"react-copy-to-clipboard": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/react-copy-to-clipboard/-/react-copy-to-clipboard-5.0.1.tgz",
@@ -20774,9 +20813,9 @@
}
},
"react-is": {
"version": "16.4.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.4.1.tgz",
"integrity": "sha512-xpb0PpALlFWNw/q13A+1aHeyJyLYCg0/cCHPUA43zYluZuIPHaHL3k8OBsTgQtxqW0FhyDEMvi8fZ/+7+r4OSQ==",
"version": "16.4.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.4.2.tgz",
"integrity": "sha512-rI3cGFj/obHbBz156PvErrS5xc6f1eWyTwyV4mo0vF2lGgXgS+mm7EKD5buLJq6jNgIagQescGSVG2YzgXt8Yg==",
"dev": true
},
"react-lifecycles-compat": {
@@ -20926,15 +20965,15 @@
}
},
"react-test-renderer": {
"version": "16.4.1",
"resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.4.1.tgz",
"integrity": "sha512-wyyiPxRZOTpKnNIgUBOB6xPLTpIzwcQMIURhZvzUqZzezvHjaGNsDPBhMac5fIY3Jf5NuKxoGvV64zDSOECPPQ==",
"version": "16.4.2",
"resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.4.2.tgz",
"integrity": "sha512-vdTPnRMDbxfv4wL4lzN4EkVGXyYs7LE2uImOsqh1FKiP6L5o1oJl8nore5sFi9vxrP9PK3l4rgb/fZ4PVUaWSA==",
"dev": true,
"requires": {
"fbjs": "^0.8.16",
"object-assign": "^4.1.1",
"prop-types": "^15.6.0",
"react-is": "^16.4.1"
"react-is": "^16.4.2"
}
},
"react-timeago": {
+4 -1
View File
@@ -76,6 +76,7 @@
"@babel/polyfill": "7.0.0-beta.49",
"@babel/preset-env": "7.0.0-beta.49",
"@babel/preset-react": "7.0.0-beta.49",
"@coralproject/rte": "^0.10.6",
"@types/bcryptjs": "^2.4.1",
"@types/bunyan": "^1.8.4",
"@types/case-sensitive-paths-webpack-plugin": "^2.1.2",
@@ -85,6 +86,7 @@
"@types/consolidate": "0.0.34",
"@types/convict": "^4.2.0",
"@types/cross-spawn": "^6.0.0",
"@types/dompurify": "0.0.31",
"@types/dotenv": "^4.0.3",
"@types/enzyme": "^3.1.11",
"@types/enzyme-adapter-react-16": "^1.0.2",
@@ -145,6 +147,7 @@
"css-loader": "^0.28.11",
"del": "^3.0.0",
"docz": "^0.5.8",
"dompurify": "^1.0.7",
"enzyme": "^3.3.0",
"enzyme-adapter-react-16": "^1.1.1",
"enzyme-to-json": "^3.3.4",
@@ -193,7 +196,7 @@
"react-popper": "^1.0.0",
"react-relay": "github:coralproject/patched#react-relay",
"react-responsive": "^5.0.0",
"react-test-renderer": "^16.4.1",
"react-test-renderer": "^16.4.2",
"react-timeago": "^4.1.9",
"react-with-state-props": "^2.0.4",
"recompose": "^0.27.1",
+1 -1
View File
@@ -37,7 +37,7 @@ const mediaQueryVariables = mapValues(
// with the smallest screen and gradually add styling for the
// next bigger screen. This is realized using `min-width` without
// ever using `max-width`.
v => `${Number.parseInt(v) + 1}px`
v => `${Number.parseInt(v, 10) + 1}px`
);
module.exports = {
@@ -17,8 +17,8 @@ interface SignUpContainerProps {
class SignUpContainer extends Component<SignUpContainerProps> {
private onSubmit: SignUpForm["onSubmit"] = async (input, form) => {
try {
return await this.props.signUp(input);
form.reset();
await this.props.signUp(input);
return form.reset();
} catch (error) {
return { [FORM_ERROR]: error.message };
}
@@ -25,14 +25,27 @@ exports[`accepts correct password 1`] = `
Email Address
</label>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="email"
onChange={[Function]}
placeholder="Email Address"
type="text"
value="hans@test.com"
value=""
/>
<div
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
</span>
<span>
This field is required.
</span>
</div>
</div>
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
@@ -155,6 +168,7 @@ exports[`accepts valid email 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -249,6 +263,7 @@ exports[`checks for invalid email 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -279,6 +294,7 @@ exports[`checks for invalid email 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -473,6 +489,7 @@ exports[`shows error when submitting empty form 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -503,6 +520,7 @@ exports[`shows error when submitting empty form 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -781,11 +799,6 @@ exports[`submits form successfully 1`] = `
>
Sign in to join the conversation
</h1>
<div
className="CallOut-root CallOut-colorError CallOut-fullWidth"
>
Server Error
</div>
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
>
@@ -25,14 +25,27 @@ exports[`accepts correct password 1`] = `
Email Address
</label>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="email"
onChange={[Function]}
placeholder="Email Address"
type="text"
value="hans@test.com"
value=""
/>
<div
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
</span>
<span>
This field is required.
</span>
</div>
</div>
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
@@ -48,14 +61,27 @@ exports[`accepts correct password 1`] = `
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="username"
onChange={[Function]}
placeholder="Username"
type="text"
value="hans"
value=""
/>
<div
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
</span>
<span>
This field is required.
</span>
</div>
</div>
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
@@ -101,6 +127,7 @@ exports[`accepts correct password 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -164,14 +191,27 @@ exports[`accepts correct password confirmation 1`] = `
Email Address
</label>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="email"
onChange={[Function]}
placeholder="Email Address"
type="text"
value="hans@test.com"
value=""
/>
<div
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
</span>
<span>
This field is required.
</span>
</div>
</div>
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
@@ -187,14 +227,27 @@ exports[`accepts correct password confirmation 1`] = `
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="username"
onChange={[Function]}
placeholder="Username"
type="text"
value="hans"
value=""
/>
<div
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
</span>
<span>
This field is required.
</span>
</div>
</div>
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
@@ -210,14 +263,27 @@ exports[`accepts correct password confirmation 1`] = `
Must be at least {$minLength} characters
</p>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value="testtest"
value=""
/>
<div
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
</span>
<span>
This field is required.
</span>
</div>
</div>
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
@@ -228,7 +294,7 @@ exports[`accepts correct password confirmation 1`] = `
Confirm Password
</label>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="confirmPassword"
onChange={[Function]}
@@ -236,6 +302,19 @@ exports[`accepts correct password confirmation 1`] = `
type="password"
value="testtest"
/>
<div
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
</span>
<span>
Passwords do not match. Try again.
</span>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeLarge Button-colorPrimary Button-variantFilled Button-fullWidth"
@@ -326,6 +405,7 @@ exports[`accepts valid email 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -361,6 +441,7 @@ exports[`accepts valid email 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -391,6 +472,7 @@ exports[`accepts valid email 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -454,14 +536,27 @@ exports[`accepts valid username 1`] = `
Email Address
</label>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="email"
onChange={[Function]}
placeholder="Email Address"
type="text"
value="hans@test.com"
value=""
/>
<div
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
</span>
<span>
This field is required.
</span>
</div>
</div>
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
@@ -512,6 +607,7 @@ exports[`accepts valid username 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -542,6 +638,7 @@ exports[`accepts valid username 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -605,14 +702,27 @@ exports[`checks for invalid characters in username 1`] = `
Email Address
</label>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="email"
onChange={[Function]}
placeholder="Email Address"
type="text"
value="hans@test.com"
value=""
/>
<div
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
</span>
<span>
This field is required.
</span>
</div>
</div>
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
@@ -640,6 +750,7 @@ exports[`checks for invalid characters in username 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -675,6 +786,7 @@ exports[`checks for invalid characters in username 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -705,6 +817,7 @@ exports[`checks for invalid characters in username 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -780,6 +893,7 @@ exports[`checks for invalid email 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -815,6 +929,7 @@ exports[`checks for invalid email 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -850,6 +965,7 @@ exports[`checks for invalid email 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -880,6 +996,7 @@ exports[`checks for invalid email 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -943,14 +1060,27 @@ exports[`checks for too long username 1`] = `
Email Address
</label>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="email"
onChange={[Function]}
placeholder="Email Address"
type="text"
value="hans@test.com"
value=""
/>
<div
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
</span>
<span>
This field is required.
</span>
</div>
</div>
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
@@ -978,6 +1108,7 @@ exports[`checks for too long username 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -1013,6 +1144,7 @@ exports[`checks for too long username 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -1043,6 +1175,7 @@ exports[`checks for too long username 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -1106,14 +1239,27 @@ exports[`checks for too short password 1`] = `
Email Address
</label>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="email"
onChange={[Function]}
placeholder="Email Address"
type="text"
value="hans@test.com"
value=""
/>
<div
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
</span>
<span>
This field is required.
</span>
</div>
</div>
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
@@ -1129,14 +1275,27 @@ exports[`checks for too short password 1`] = `
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="username"
onChange={[Function]}
placeholder="Username"
type="text"
value="hans"
value=""
/>
<div
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
</span>
<span>
This field is required.
</span>
</div>
</div>
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
@@ -1164,6 +1323,7 @@ exports[`checks for too short password 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -1194,6 +1354,7 @@ exports[`checks for too short password 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -1257,14 +1418,27 @@ exports[`checks for too short username 1`] = `
Email Address
</label>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="email"
onChange={[Function]}
placeholder="Email Address"
type="text"
value="hans@test.com"
value=""
/>
<div
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
</span>
<span>
This field is required.
</span>
</div>
</div>
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
@@ -1292,6 +1466,7 @@ exports[`checks for too short username 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -1327,6 +1502,7 @@ exports[`checks for too short username 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -1357,6 +1533,7 @@ exports[`checks for too short username 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -1420,14 +1597,27 @@ exports[`checks for wrong password confirmation 1`] = `
Email Address
</label>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="email"
onChange={[Function]}
placeholder="Email Address"
type="text"
value="hans@test.com"
value=""
/>
<div
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
</span>
<span>
This field is required.
</span>
</div>
</div>
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
@@ -1443,14 +1633,27 @@ exports[`checks for wrong password confirmation 1`] = `
A unique identifier displayed on your comments. You may use “_” and “.”
</p>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="username"
onChange={[Function]}
placeholder="Username"
type="text"
value="hans"
value=""
/>
<div
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
</span>
<span>
This field is required.
</span>
</div>
</div>
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
@@ -1466,14 +1669,27 @@ exports[`checks for wrong password confirmation 1`] = `
Must be at least {$minLength} characters
</p>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value="testtest"
value=""
/>
<div
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
</span>
<span>
This field is required.
</span>
</div>
</div>
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
@@ -1496,6 +1712,7 @@ exports[`checks for wrong password confirmation 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -1698,6 +1915,7 @@ exports[`shows error when submitting empty form 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -1733,6 +1951,7 @@ exports[`shows error when submitting empty form 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -1768,6 +1987,7 @@ exports[`shows error when submitting empty form 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -1798,6 +2018,7 @@ exports[`shows error when submitting empty form 1`] = `
className="ValidationMessage-root ValidationMessage-colorError ValidationMessage-fullWidth"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
@@ -2111,11 +2332,6 @@ exports[`submits form successfully 1`] = `
>
Sign up to join the conversation
</h1>
<div
className="CallOut-root CallOut-colorError CallOut-fullWidth"
>
Server Error
</div>
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
>
@@ -2258,7 +2474,7 @@ exports[`submits form successfully 2`] = `
onChange={[Function]}
placeholder="Email Address"
type="text"
value="hans@test.com"
value=""
/>
</div>
<div
@@ -2281,7 +2497,7 @@ exports[`submits form successfully 2`] = `
onChange={[Function]}
placeholder="Username"
type="text"
value="hans"
value=""
/>
</div>
<div
@@ -2304,7 +2520,7 @@ exports[`submits form successfully 2`] = `
onChange={[Function]}
placeholder="Password"
type="password"
value="testtest"
value=""
/>
</div>
<div
@@ -2322,7 +2538,7 @@ exports[`submits form successfully 2`] = `
onChange={[Function]}
placeholder="Confirm Password"
type="password"
value="testtest"
value=""
/>
</div>
<button
+47 -23
View File
@@ -1,5 +1,8 @@
import React from "react";
import TestRenderer, { ReactTestInstance } from "react-test-renderer";
import TestRenderer, {
ReactTestInstance,
ReactTestRenderer,
} from "react-test-renderer";
import { RecordProxy } from "relay-runtime";
import sinon from "sinon";
@@ -12,32 +15,36 @@ import { createInMemoryStorage } from "talk-framework/lib/storage";
import createEnvironment from "./createEnvironment";
const environment = createEnvironment({
initLocalState: (localRecord: RecordProxy) => {
localRecord.setValue("SIGN_IN", "view");
},
});
const context: TalkContext = {
relayEnvironment: environment,
localeBundles: [],
localStorage: createInMemoryStorage(),
sessionStorage: createInMemoryStorage(),
rest: new RestClient("http://localhost/api"),
postMessage: new PostMessageService(),
};
const testRenderer = TestRenderer.create(
<TalkContextProvider value={context}>
<AppContainer />
</TalkContextProvider>
);
const inputPredicate = (name: string) => (n: ReactTestInstance) => {
return n.props.name === name && n.props.onChange;
};
const form = testRenderer.root.findByType("form");
let context: TalkContext;
let testRenderer: ReactTestRenderer;
let form: ReactTestInstance;
beforeEach(() => {
const environment = createEnvironment({
initLocalState: (localRecord: RecordProxy) => {
localRecord.setValue("SIGN_IN", "view");
},
});
context = {
relayEnvironment: environment,
localeBundles: [],
localStorage: createInMemoryStorage(),
sessionStorage: createInMemoryStorage(),
rest: new RestClient("http://localhost/api"),
postMessage: new PostMessageService(),
};
testRenderer = TestRenderer.create(
<TalkContextProvider value={context}>
<AppContainer />
</TalkContextProvider>
);
form = testRenderer.root.findByType("form");
});
it("renders sign in form", async () => {
expect(testRenderer.toJSON()).toMatchSnapshot();
@@ -52,6 +59,7 @@ it("checks for invalid email", async () => {
form
.find(inputPredicate("email"))
.props.onChange({ target: { value: "invalid-email" } });
form.props.onSubmit();
expect(testRenderer.toJSON()).toMatchSnapshot();
});
@@ -59,6 +67,7 @@ it("accepts valid email", async () => {
form
.find(inputPredicate("email"))
.props.onChange({ target: { value: "hans@test.com" } });
form.props.onSubmit();
expect(testRenderer.toJSON()).toMatchSnapshot();
});
@@ -66,10 +75,18 @@ it("accepts correct password", async () => {
form
.find(inputPredicate("password"))
.props.onChange({ target: { value: "testtest" } });
form.props.onSubmit();
expect(testRenderer.toJSON()).toMatchSnapshot();
});
it("shows server error", async () => {
form
.find(inputPredicate("email"))
.props.onChange({ target: { value: "hans@test.com" } });
form
.find(inputPredicate("password"))
.props.onChange({ target: { value: "testtest" } });
const windowMock = sinon.mock(window);
windowMock.expects("resizeTo");
@@ -105,6 +122,13 @@ it("shows server error", async () => {
});
it("submits form successfully", async () => {
form
.find(inputPredicate("email"))
.props.onChange({ target: { value: "hans@test.com" } });
form
.find(inputPredicate("password"))
.props.onChange({ target: { value: "testtest" } });
const windowMock = sinon.mock(window);
windowMock.expects("close").once();
windowMock.expects("resizeTo");
+67 -23
View File
@@ -1,5 +1,8 @@
import React from "react";
import TestRenderer, { ReactTestInstance } from "react-test-renderer";
import TestRenderer, {
ReactTestInstance,
ReactTestRenderer,
} from "react-test-renderer";
import { RecordProxy } from "relay-runtime";
import sinon from "sinon";
@@ -12,32 +15,37 @@ import { createInMemoryStorage } from "talk-framework/lib/storage";
import createEnvironment from "./createEnvironment";
const environment = createEnvironment({
initLocalState: (localRecord: RecordProxy) => {
localRecord.setValue("SIGN_UP", "view");
},
});
const context: TalkContext = {
relayEnvironment: environment,
localeBundles: [],
localStorage: createInMemoryStorage(),
sessionStorage: createInMemoryStorage(),
rest: new RestClient("http://localhost/api"),
postMessage: new PostMessageService(),
};
const testRenderer = TestRenderer.create(
<TalkContextProvider value={context}>
<AppContainer />
</TalkContextProvider>
);
const inputPredicate = (name: string) => (n: ReactTestInstance) => {
return n.props.name === name && n.props.onChange;
};
const form = testRenderer.root.findByType("form");
let context: TalkContext;
let testRenderer: ReactTestRenderer;
let form: ReactTestInstance;
beforeEach(() => {
const environment = createEnvironment({
initLocalState: (localRecord: RecordProxy) => {
localRecord.setValue("SIGN_UP", "view");
},
});
context = {
relayEnvironment: environment,
localeBundles: [],
localStorage: createInMemoryStorage(),
sessionStorage: createInMemoryStorage(),
rest: new RestClient("http://localhost/api"),
postMessage: new PostMessageService(),
};
testRenderer = TestRenderer.create(
<TalkContextProvider value={context}>
<AppContainer />
</TalkContextProvider>
);
form = testRenderer.root.findByType("form");
});
it("renders sign up form", async () => {
expect(testRenderer.toJSON()).toMatchSnapshot();
@@ -52,6 +60,7 @@ it("checks for invalid email", async () => {
form
.find(inputPredicate("email"))
.props.onChange({ target: { value: "invalid-email" } });
form.props.onSubmit();
expect(testRenderer.toJSON()).toMatchSnapshot();
});
@@ -59,6 +68,7 @@ it("accepts valid email", async () => {
form
.find(inputPredicate("email"))
.props.onChange({ target: { value: "hans@test.com" } });
form.props.onSubmit();
expect(testRenderer.toJSON()).toMatchSnapshot();
});
@@ -66,6 +76,7 @@ it("checks for too short username", async () => {
form
.find(inputPredicate("username"))
.props.onChange({ target: { value: "u" } });
form.props.onSubmit();
expect(testRenderer.toJSON()).toMatchSnapshot();
});
@@ -73,6 +84,7 @@ it("checks for too long username", async () => {
form
.find(inputPredicate("username"))
.props.onChange({ target: { value: "a".repeat(100) } });
form.props.onSubmit();
expect(testRenderer.toJSON()).toMatchSnapshot();
});
@@ -80,6 +92,7 @@ it("checks for invalid characters in username", async () => {
form
.find(inputPredicate("username"))
.props.onChange({ target: { value: "$%$§$%$§%" } });
form.props.onSubmit();
expect(testRenderer.toJSON()).toMatchSnapshot();
});
@@ -87,6 +100,7 @@ it("accepts valid username", async () => {
form
.find(inputPredicate("username"))
.props.onChange({ target: { value: "hans" } });
form.props.onSubmit();
expect(testRenderer.toJSON()).toMatchSnapshot();
});
@@ -94,6 +108,7 @@ it("checks for too short password", async () => {
form
.find(inputPredicate("password"))
.props.onChange({ target: { value: "pass" } });
form.props.onSubmit();
expect(testRenderer.toJSON()).toMatchSnapshot();
});
@@ -101,6 +116,7 @@ it("accepts correct password", async () => {
form
.find(inputPredicate("password"))
.props.onChange({ target: { value: "testtest" } });
form.props.onSubmit();
expect(testRenderer.toJSON()).toMatchSnapshot();
});
@@ -108,6 +124,7 @@ it("checks for wrong password confirmation", async () => {
form
.find(inputPredicate("confirmPassword"))
.props.onChange({ target: { value: "not-matching" } });
form.props.onSubmit();
expect(testRenderer.toJSON()).toMatchSnapshot();
});
@@ -115,10 +132,24 @@ it("accepts correct password confirmation", async () => {
form
.find(inputPredicate("confirmPassword"))
.props.onChange({ target: { value: "testtest" } });
form.props.onSubmit();
expect(testRenderer.toJSON()).toMatchSnapshot();
});
it("shows server error", async () => {
form
.find(inputPredicate("email"))
.props.onChange({ target: { value: "hans@test.com" } });
form
.find(inputPredicate("username"))
.props.onChange({ target: { value: "hans" } });
form
.find(inputPredicate("password"))
.props.onChange({ target: { value: "testtest" } });
form
.find(inputPredicate("confirmPassword"))
.props.onChange({ target: { value: "testtest" } });
const windowMock = sinon.mock(window);
windowMock.expects("resizeTo");
@@ -155,6 +186,19 @@ it("shows server error", async () => {
});
it("submits form successfully", async () => {
form
.find(inputPredicate("email"))
.props.onChange({ target: { value: "hans@test.com" } });
form
.find(inputPredicate("username"))
.props.onChange({ target: { value: "hans" } });
form
.find(inputPredicate("password"))
.props.onChange({ target: { value: "testtest" } });
form
.find(inputPredicate("confirmPassword"))
.props.onChange({ target: { value: "testtest" } });
const windowMock = sinon.mock(window);
windowMock.expects("close").once();
windowMock.expects("resizeTo");
@@ -1,9 +1,9 @@
import React from "react";
import { StatelessComponent } from "react";
import { Typography } from "talk-ui/components";
import * as styles from "./Comment.css";
import PermalinkButtonContainer from "../../containers/PermalinkButtonContainer";
import HTMLContent from "./HTMLContent";
import Timestamp from "./Timestamp";
import TopBar from "./TopBar";
import Username from "./Username";
@@ -26,7 +26,7 @@ const Comment: StatelessComponent<CommentProps> = props => {
props.author.username && <Username>{props.author.username}</Username>}
<Timestamp>{props.createdAt}</Timestamp>
</TopBar>
<Typography>{props.body}</Typography>
<HTMLContent>{props.body || ""}</HTMLContent>
<div className={styles.footer}>
<PermalinkButtonContainer commentID={props.id} />
</div>
@@ -0,0 +1,3 @@
.root {
composes: root from "talk-stream/shared/htmlContent.css";
}
@@ -0,0 +1,23 @@
import React from "react";
import TestRenderer from "react-test-renderer";
import HTMLContent from "./HTMLContent";
it("renders correctly", () => {
const renderer = TestRenderer.create(
<HTMLContent>{"<span>Hello world</span>"}</HTMLContent>
);
expect(renderer.toJSON()).toMatchSnapshot();
});
it("sanitizes evil html", () => {
const renderer = TestRenderer.create(
<HTMLContent>
{`
<script>alert('I am evil')</script>
<span onClick=\"javascript:alert('haha')\" title="test">Hello world</span>
`}
</HTMLContent>
);
expect(renderer.toJSON()).toMatchSnapshot();
});
@@ -0,0 +1,22 @@
import React from "react";
import dompurify from "dompurify";
import styles from "./HTMLContent.css";
interface ContentProps {
children: string;
}
class HTMLContent extends React.Component<ContentProps> {
public render() {
const { children } = this.props;
return (
<div
className={styles.root}
dangerouslySetInnerHTML={{ __html: dompurify.sanitize(children) }}
/>
);
}
}
export default HTMLContent;
@@ -13,9 +13,9 @@ exports[`renders username and body 1`] = `
1995-12-17T03:24:00.000Z
</Timestamp>
</TopBar>
<withPropsOnChange(Typography)>
<HTMLContent>
Woof
</withPropsOnChange(Typography)>
</HTMLContent>
<div
className="Comment-footer"
>
@@ -0,0 +1,24 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "<span>Hello world</span>",
}
}
/>
`;
exports[`sanitizes evil html 1`] = `
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "<span title=\\"test\\">Hello world</span>
",
}
}
/>
`;
@@ -28,7 +28,7 @@ class Permalink extends React.Component<PermalinkProps> {
public render() {
const { commentID, assetURL } = this.props;
const popoverID = "permalink-popover";
const popoverID = `permalink-popover-${commentID}`;
return (
<Popover
id={popoverID}
@@ -1,11 +1,20 @@
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import { Field, Form } from "react-final-form";
import { OnSubmit } from "talk-framework/lib/form";
import { required } from "talk-framework/lib/validation";
import { Button, Flex, HorizontalGutter, Typography } from "talk-ui/components";
import {
AriaInfo,
Button,
Flex,
HorizontalGutter,
Typography,
} from "talk-ui/components";
import * as styles from "./PostCommentForm.css";
import PoweredBy from "./PoweredBy";
import RTE from "./RTE";
interface FormProps {
body: string;
@@ -23,13 +32,22 @@ const PostCommentForm: StatelessComponent<PostCommentFormProps> = props => (
<Field name="body" validate={required}>
{({ input, meta }) => (
<div>
<textarea
className={styles.textarea}
name={input.name}
onChange={input.onChange}
value={input.value}
placeholder="Post a comment"
/>
<Localized id="comments-postCommentForm-rteLabel">
<AriaInfo component="label" htmlFor="postCommentField">
Post a comment
</AriaInfo>
</Localized>
<Localized
id="comments-postCommentForm-rte"
attrs={{ placeholder: true }}
>
<RTE
inputId="postCommentField"
onChange={({ html }) => input.onChange(html)}
value={input.value}
placeholder="Post a comment"
/>
</Localized>
{meta.touched &&
(meta.error || meta.submitError) && (
<Typography align="right" color="error" gutterBottom>
@@ -2,15 +2,19 @@ import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import { Button, HorizontalGutter } from "talk-ui/components";
import * as styles from "./PostCommentFormFake.css";
import RTE from "./RTE";
const PostCommentFormFake: StatelessComponent = props => (
<HorizontalGutter className={styles.root}>
<textarea
className={styles.textarea}
placeholder="Post a comment"
disabled
/>
<Localized id="comments-PostCommentFormFake-signInAndJoin">
<div aria-hidden="true">
<Localized
id="comments-postCommentFormFake-rte"
attrs={{ placeholder: true }}
>
<RTE placeholder="Post a comment" disabled />
</Localized>
</div>
<Localized id="comments-postCommentFormFake-signInAndJoin">
<Button color="primary" variant="filled" disabled type="submit" fullWidth>
Sign in and join the conversation
</Button>
@@ -1,4 +1,5 @@
import cn from "classnames";
import { Localized } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import { Typography } from "talk-ui/components";
@@ -9,16 +10,18 @@ interface Props {
const PoweredBy: StatelessComponent<Props> = props => {
return (
<div className={cn(props.className)}>
<Typography
variant="inputDescription"
container="span"
color="textSecondary"
<Localized
id="comments-poweredBy"
logo={<Typography variant="heading4" container="span" />}
>
Powered by
</Typography>{" "}
<Typography variant="heading4" container="span">
The Coral Project
</Typography>
<Typography
variant="inputDescription"
container="span"
color="textSecondary"
>
{"Powered by <logo>The Coral Project</logo>"}
</Typography>
</Localized>
</div>
);
};
@@ -0,0 +1,8 @@
.content {
composes: root from "talk-stream/shared/htmlContent.css";
}
.placeholder {
composes: placeholder from "talk-ui/shared/typography.css";
margin: var(--spacing-unit) 0 0 calc(1px + var(--spacing-unit));
}
@@ -0,0 +1,16 @@
import { shallow } from "enzyme";
import React from "react";
import { PropTypesOf } from "talk-framework/types";
import RTE from "./RTE";
it("renders correctly", () => {
const props: PropTypesOf<typeof RTE> = {
className: "custom",
placeholder: "Post a comment",
value: "Hello world",
};
const wrapper = shallow(<RTE {...props} />);
expect(wrapper).toMatchSnapshot();
});
+106
View File
@@ -0,0 +1,106 @@
import { Blockquote, Bold, CoralRTE, Italic } from "@coralproject/rte";
import { Localized as LocalizedOriginal } from "fluent-react/compat";
import React, { StatelessComponent } from "react";
import { Icon } from "talk-ui/components";
import { PropTypesOf } from "talk-ui/types";
import * as styles from "./RTE.css";
// Use a special Localized version that forwards
// ref and passes the api prop to the children.
// This is currently required in order for the RTE
// to detect and setup the features.
const Localized = React.forwardRef<any, PropTypesOf<typeof LocalizedOriginal>>(
({ api, ...props }, ref) => (
<LocalizedOriginal {...props}>
{React.cloneElement(React.Children.only(props.children), { api, ref })}
</LocalizedOriginal>
)
);
export interface RTEProps {
inputId?: string;
/**
* The content value of the component.
*/
defaultValue?: string;
/**
* The content value of the component.
*/
value?: string;
/**
* Convenient prop to override the root styling.
*/
className?: string;
/*
* If set renders a full width button
*/
fullWidth?: boolean;
/**
* Placeholder
*/
placeholder?: string;
/**
* onChange
*/
onChange?: (data: { html: string; text: string }) => void;
disabled?: boolean;
}
// tslint:disable:jsx-wrap-multiline
const features = [
<Localized key="bold" id="comments-rte-bold" attrs={{ title: true }}>
<Bold>
<Icon>format_bold</Icon>
</Bold>
</Localized>,
<Localized key="italic" id="comments-rte-italic" attrs={{ title: true }}>
<Italic>
<Icon>format_italic</Icon>
</Italic>
</Localized>,
<Localized
key="blockquote"
id="comments-rte-blockquote"
attrs={{ title: true }}
>
<Blockquote key="blockquote">
<Icon>format_quote</Icon>
</Blockquote>
</Localized>,
];
// tslint:enable:jsx-wrap-multiline
const RTE: StatelessComponent<RTEProps> = props => {
const {
className,
fullWidth,
value,
inputId,
placeholder,
onChange,
disabled,
defaultValue,
...rest
} = props;
return (
<div>
<CoralRTE
inputId={inputId}
className={className}
contentClassName={styles.content}
placeholderClassName={styles.placeholder}
onChange={onChange}
value={value || defaultValue}
disabled={disabled}
placeholder={placeholder}
features={features}
{...rest}
/>
</div>
);
};
export default RTE;
@@ -15,11 +15,28 @@ it("renders correctly", () => {
onLoadMore: noop,
disableLoadMore: false,
hasMore: false,
user: null,
};
const wrapper = shallow(<Stream {...props} />);
expect(wrapper).toMatchSnapshot();
});
describe("when use is logged in", () => {
it("renders correctly", () => {
const props: PropTypesOf<typeof Stream> = {
assetID: "asset-id",
isClosed: false,
comments: [{ id: "comment-1" }, { id: "comment-2" }],
onLoadMore: noop,
disableLoadMore: false,
hasMore: false,
user: {},
};
const wrapper = shallow(<Stream {...props} />);
expect(wrapper).toMatchSnapshot();
});
});
describe("when there is more", () => {
const props: PropTypesOf<typeof Stream> = {
assetID: "asset-id",
@@ -28,6 +45,7 @@ describe("when there is more", () => {
onLoadMore: sinon.spy(),
disableLoadMore: false,
hasMore: true,
user: null,
};
const wrapper = shallow(<Stream {...props} />);
@@ -4,13 +4,25 @@ exports[`renders correctly 1`] = `
<withPropsOnChange(HorizontalGutter)
className="PostCommentFormFake-root"
>
<textarea
className="PostCommentFormFake-textarea"
disabled={true}
placeholder="Post a comment"
/>
<div
aria-hidden="true"
>
<Localized
attrs={
Object {
"placeholder": true,
}
}
id="comments-postCommentFormFake-rte"
>
<RTE
disabled={true}
placeholder="Post a comment"
/>
</Localized>
</div>
<Localized
id="comments-PostCommentFormFake-signInAndJoin"
id="comments-postCommentFormFake-signInAndJoin"
>
<withPropsOnChange(Button)
color="primary"
@@ -4,19 +4,22 @@ exports[`renders correctly 1`] = `
<div
className="custom"
>
<withPropsOnChange(Typography)
color="textSecondary"
container="span"
variant="inputDescription"
<Localized
id="comments-poweredBy"
logo={
<withPropsOnChange(Typography)
container="span"
variant="heading4"
/>
}
>
Powered by
</withPropsOnChange(Typography)>
<withPropsOnChange(Typography)
container="span"
variant="heading4"
>
The Coral Project
</withPropsOnChange(Typography)>
<withPropsOnChange(Typography)
color="textSecondary"
container="span"
variant="inputDescription"
>
Powered by &lt;logo&gt;The Coral Project&lt;/logo&gt;
</withPropsOnChange(Typography)>
</Localized>
</div>
`;
@@ -0,0 +1,64 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<div>
<RTE
className="custom"
classNameDisabled=""
contentClassName="RTE-content"
contentClassNameDisabled=""
features={
Array [
<ForwardRef
attrs={
Object {
"title": true,
}
}
id="comments-rte-bold"
>
<Toggle>
<withPropsOnChange(Icon)>
format_bold
</withPropsOnChange(Icon)>
</Toggle>
</ForwardRef>,
<ForwardRef
attrs={
Object {
"title": true,
}
}
id="comments-rte-italic"
>
<Toggle>
<withPropsOnChange(Icon)>
format_italic
</withPropsOnChange(Icon)>
</Toggle>
</ForwardRef>,
<ForwardRef
attrs={
Object {
"title": true,
}
}
id="comments-rte-blockquote"
>
<Toggle>
<withPropsOnChange(Icon)>
format_quote
</withPropsOnChange(Icon)>
</Toggle>
</ForwardRef>,
]
}
placeholder="Post a comment"
placeholderClassName="RTE-placeholder"
placeholderClassNameDisabled=""
toolbarClassName=""
toolbarClassNameDisabled=""
value="Hello world"
/>
</div>
`;
@@ -8,7 +8,9 @@ exports[`renders correctly 1`] = `
<withPropsOnChange(HorizontalGutter)
size="half"
>
<withContext(createMutationContainer(withContext(createMutationContainer(withContext(createMutationContainer(withContext(withLocalStateContainer(Relay(UserBoxContainer))))))))) />
<withContext(createMutationContainer(withContext(createMutationContainer(withContext(createMutationContainer(withContext(withLocalStateContainer(Relay(UserBoxContainer)))))))))
user={null}
/>
<PostCommentFormFake />
</withPropsOnChange(HorizontalGutter)>
<withPropsOnChange(HorizontalGutter)
@@ -64,7 +66,9 @@ exports[`when there is more disables load more button 1`] = `
<withPropsOnChange(HorizontalGutter)
size="half"
>
<withContext(createMutationContainer(withContext(createMutationContainer(withContext(createMutationContainer(withContext(withLocalStateContainer(Relay(UserBoxContainer))))))))) />
<withContext(createMutationContainer(withContext(createMutationContainer(withContext(createMutationContainer(withContext(withLocalStateContainer(Relay(UserBoxContainer)))))))))
user={null}
/>
<PostCommentFormFake />
</withPropsOnChange(HorizontalGutter)>
<withPropsOnChange(HorizontalGutter)
@@ -134,7 +138,9 @@ exports[`when there is more renders a load more button 1`] = `
<withPropsOnChange(HorizontalGutter)
size="half"
>
<withContext(createMutationContainer(withContext(createMutationContainer(withContext(createMutationContainer(withContext(withLocalStateContainer(Relay(UserBoxContainer))))))))) />
<withContext(createMutationContainer(withContext(createMutationContainer(withContext(createMutationContainer(withContext(withLocalStateContainer(Relay(UserBoxContainer)))))))))
user={null}
/>
<PostCommentFormFake />
</withPropsOnChange(HorizontalGutter)>
<withPropsOnChange(HorizontalGutter)
@@ -195,3 +201,63 @@ exports[`when there is more renders a load more button 1`] = `
</withPropsOnChange(HorizontalGutter)>
</withPropsOnChange(HorizontalGutter)>
`;
exports[`when use is logged in renders correctly 1`] = `
<withPropsOnChange(HorizontalGutter)
className="Stream-root"
size="double"
>
<withPropsOnChange(HorizontalGutter)
size="half"
>
<withContext(createMutationContainer(withContext(createMutationContainer(withContext(createMutationContainer(withContext(withLocalStateContainer(Relay(UserBoxContainer)))))))))
user={Object {}}
/>
<withContext(createMutationContainer(PostCommentFormContainer))
assetID="asset-id"
/>
</withPropsOnChange(HorizontalGutter)>
<withPropsOnChange(HorizontalGutter)
aria-live="polite"
id="talk-comments-stream-log"
role="log"
>
<withPropsOnChange(HorizontalGutter)
key="comment-1"
>
<Relay(CommentContainer)
data={
Object {
"id": "comment-1",
}
}
/>
<Relay(ReplyListContainer)
comment={
Object {
"id": "comment-1",
}
}
/>
</withPropsOnChange(HorizontalGutter)>
<withPropsOnChange(HorizontalGutter)
key="comment-2"
>
<Relay(CommentContainer)
data={
Object {
"id": "comment-2",
}
}
/>
<Relay(ReplyListContainer)
comment={
Object {
"id": "comment-2",
}
}
/>
</withPropsOnChange(HorizontalGutter)>
</withPropsOnChange(HorizontalGutter)>
</withPropsOnChange(HorizontalGutter)>
`;
@@ -0,0 +1,25 @@
.root {
composes: bodyCopy from "talk-ui/shared/typography.css";
& * bold,
& * strong {
font-weight: var(--font-weight-medium);
}
& * italic,
& * em {
font-style: italic;
}
blockquote {
background-color: var(--palette-grey-lightest);
padding: var(--spacing-unit);
margin: calc(2 * var(--spacing-unit)) 0 calc(2 * var(--spacing-unit))
var(--spacing-unit);
border-radius: var(--round-corners);
&::after {
content: none;
}
&::before {
content: none;
}
}
}
@@ -43,11 +43,84 @@ exports[`loads more comments 1`] = `
<div
className="HorizontalGutter-root PostCommentFormFake-root HorizontalGutter-full"
>
<textarea
className="PostCommentFormFake-textarea"
disabled={true}
placeholder="Post a comment"
/>
<div
aria-hidden="true"
>
<div>
<div
className=""
>
<div
className=" RTE-toolbarDisabled Toolbar-toolbar"
>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_bold
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_italic
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_quote
</span>
</button>
</div>
<div
aria-hidden="true"
className="RTE-placeholder RTE-placeholder "
>
Post a comment
</div>
<div
aria-placeholder="Post a comment"
className="RTE-contentEditable RTE-content RTE-contentEditableDisabled"
contentEditable={false}
dangerouslySetInnerHTML={
Object {
"__html": "",
}
}
disabled={true}
onBlur={[Function]}
onChange={[Function]}
onCut={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onPaste={[Function]}
onSelect={[Function]}
/>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-fullWidth Button-disabled"
disabled={true}
@@ -92,11 +165,14 @@ exports[`loads more comments 1`] = `
2018-07-06T18:24:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
Joining Too
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Comment-footer"
/>
@@ -125,11 +201,14 @@ exports[`loads more comments 1`] = `
2018-07-06T18:20:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
What's up?
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "What's up?",
}
}
/>
<div
className="Comment-footer"
/>
@@ -158,11 +237,14 @@ exports[`loads more comments 1`] = `
2018-07-06T18:14:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
Hey!
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Hey!",
}
}
/>
<div
className="Comment-footer"
/>
@@ -216,11 +298,84 @@ exports[`renders comment stream 1`] = `
<div
className="HorizontalGutter-root PostCommentFormFake-root HorizontalGutter-full"
>
<textarea
className="PostCommentFormFake-textarea"
disabled={true}
placeholder="Post a comment"
/>
<div
aria-hidden="true"
>
<div>
<div
className=""
>
<div
className=" RTE-toolbarDisabled Toolbar-toolbar"
>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_bold
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_italic
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_quote
</span>
</button>
</div>
<div
aria-hidden="true"
className="RTE-placeholder RTE-placeholder "
>
Post a comment
</div>
<div
aria-placeholder="Post a comment"
className="RTE-contentEditable RTE-content RTE-contentEditableDisabled"
contentEditable={false}
dangerouslySetInnerHTML={
Object {
"__html": "",
}
}
disabled={true}
onBlur={[Function]}
onChange={[Function]}
onCut={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onPaste={[Function]}
onSelect={[Function]}
/>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-fullWidth Button-disabled"
disabled={true}
@@ -265,11 +420,14 @@ exports[`renders comment stream 1`] = `
2018-07-06T18:24:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
Joining Too
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Comment-footer"
/>
@@ -298,11 +456,14 @@ exports[`renders comment stream 1`] = `
2018-07-06T18:20:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
What's up?
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "What's up?",
}
}
/>
<div
className="Comment-footer"
/>
@@ -43,11 +43,14 @@ exports[`renders permalink view 1`] = `
2018-07-06T18:24:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
Joining Too
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Comment-footer"
/>
@@ -99,11 +102,84 @@ exports[`show all comments 1`] = `
<div
className="HorizontalGutter-root PostCommentFormFake-root HorizontalGutter-full"
>
<textarea
className="PostCommentFormFake-textarea"
disabled={true}
placeholder="Post a comment"
/>
<div
aria-hidden="true"
>
<div>
<div
className=""
>
<div
className=" RTE-toolbarDisabled Toolbar-toolbar"
>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_bold
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_italic
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_quote
</span>
</button>
</div>
<div
aria-hidden="true"
className="RTE-placeholder RTE-placeholder "
>
Post a comment
</div>
<div
aria-placeholder="Post a comment"
className="RTE-contentEditable RTE-content RTE-contentEditableDisabled"
contentEditable={false}
dangerouslySetInnerHTML={
Object {
"__html": "",
}
}
disabled={true}
onBlur={[Function]}
onChange={[Function]}
onCut={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onPaste={[Function]}
onSelect={[Function]}
/>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-fullWidth Button-disabled"
disabled={true}
@@ -148,11 +224,14 @@ exports[`show all comments 1`] = `
2018-07-06T18:24:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
Joining Too
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Comment-footer"
/>
@@ -75,11 +75,84 @@ exports[`show all comments 1`] = `
<div
className="HorizontalGutter-root PostCommentFormFake-root HorizontalGutter-full"
>
<textarea
className="PostCommentFormFake-textarea"
disabled={true}
placeholder="Post a comment"
/>
<div
aria-hidden="true"
>
<div>
<div
className=""
>
<div
className=" RTE-toolbarDisabled Toolbar-toolbar"
>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_bold
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_italic
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_quote
</span>
</button>
</div>
<div
aria-hidden="true"
className="RTE-placeholder RTE-placeholder "
>
Post a comment
</div>
<div
aria-placeholder="Post a comment"
className="RTE-contentEditable RTE-content RTE-contentEditableDisabled"
contentEditable={false}
dangerouslySetInnerHTML={
Object {
"__html": "",
}
}
disabled={true}
onBlur={[Function]}
onChange={[Function]}
onCut={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onPaste={[Function]}
onSelect={[Function]}
/>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-fullWidth Button-disabled"
disabled={true}
@@ -124,11 +197,14 @@ exports[`show all comments 1`] = `
2018-07-06T18:24:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
Joining Too
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Comment-footer"
/>
@@ -43,11 +43,84 @@ exports[`renders comment stream 1`] = `
<div
className="HorizontalGutter-root PostCommentFormFake-root HorizontalGutter-full"
>
<textarea
className="PostCommentFormFake-textarea"
disabled={true}
placeholder="Post a comment"
/>
<div
aria-hidden="true"
>
<div>
<div
className=""
>
<div
className=" RTE-toolbarDisabled Toolbar-toolbar"
>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_bold
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_italic
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_quote
</span>
</button>
</div>
<div
aria-hidden="true"
className="RTE-placeholder RTE-placeholder "
>
Post a comment
</div>
<div
aria-placeholder="Post a comment"
className="RTE-contentEditable RTE-content RTE-contentEditableDisabled"
contentEditable={false}
dangerouslySetInnerHTML={
Object {
"__html": "",
}
}
disabled={true}
onBlur={[Function]}
onChange={[Function]}
onCut={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onPaste={[Function]}
onSelect={[Function]}
/>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-fullWidth Button-disabled"
disabled={true}
@@ -92,11 +165,14 @@ exports[`renders comment stream 1`] = `
2018-07-06T18:24:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
Joining Too
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Comment-footer"
/>
@@ -125,11 +201,14 @@ exports[`renders comment stream 1`] = `
2018-07-06T18:24:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
I like yoghurt
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "I like yoghurt",
}
}
/>
<div
className="Comment-footer"
/>
@@ -162,11 +241,14 @@ exports[`renders comment stream 1`] = `
2018-07-06T18:24:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
Joining Too
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Comment-footer"
/>
@@ -191,11 +273,14 @@ exports[`renders comment stream 1`] = `
2018-07-06T18:20:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
What's up?
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "What's up?",
}
}
/>
<div
className="Comment-footer"
/>
@@ -43,11 +43,84 @@ exports[`renders comment stream 1`] = `
<div
className="HorizontalGutter-root PostCommentFormFake-root HorizontalGutter-full"
>
<textarea
className="PostCommentFormFake-textarea"
disabled={true}
placeholder="Post a comment"
/>
<div
aria-hidden="true"
>
<div>
<div
className=""
>
<div
className=" RTE-toolbarDisabled Toolbar-toolbar"
>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_bold
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_italic
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_quote
</span>
</button>
</div>
<div
aria-hidden="true"
className="RTE-placeholder RTE-placeholder "
>
Post a comment
</div>
<div
aria-placeholder="Post a comment"
className="RTE-contentEditable RTE-content RTE-contentEditableDisabled"
contentEditable={false}
dangerouslySetInnerHTML={
Object {
"__html": "",
}
}
disabled={true}
onBlur={[Function]}
onChange={[Function]}
onCut={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onPaste={[Function]}
onSelect={[Function]}
/>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-fullWidth Button-disabled"
disabled={true}
@@ -92,11 +165,14 @@ exports[`renders comment stream 1`] = `
2018-07-06T18:24:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
Joining Too
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Comment-footer"
/>
@@ -125,11 +201,14 @@ exports[`renders comment stream 1`] = `
2018-07-06T18:20:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
What's up?
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "What's up?",
}
}
/>
<div
className="Comment-footer"
/>
@@ -43,11 +43,84 @@ exports[`renders comment stream 1`] = `
<div
className="HorizontalGutter-root PostCommentFormFake-root HorizontalGutter-full"
>
<textarea
className="PostCommentFormFake-textarea"
disabled={true}
placeholder="Post a comment"
/>
<div
aria-hidden="true"
>
<div>
<div
className=""
>
<div
className=" RTE-toolbarDisabled Toolbar-toolbar"
>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_bold
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_italic
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_quote
</span>
</button>
</div>
<div
aria-hidden="true"
className="RTE-placeholder RTE-placeholder "
>
Post a comment
</div>
<div
aria-placeholder="Post a comment"
className="RTE-contentEditable RTE-content RTE-contentEditableDisabled"
contentEditable={false}
dangerouslySetInnerHTML={
Object {
"__html": "",
}
}
disabled={true}
onBlur={[Function]}
onChange={[Function]}
onCut={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onPaste={[Function]}
onSelect={[Function]}
/>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-fullWidth Button-disabled"
disabled={true}
@@ -92,11 +165,14 @@ exports[`renders comment stream 1`] = `
2018-07-06T18:24:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
Joining Too
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Comment-footer"
/>
@@ -129,11 +205,14 @@ exports[`renders comment stream 1`] = `
2018-07-06T18:20:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
What's up?
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "What's up?",
}
}
/>
<div
className="Comment-footer"
/>
@@ -205,11 +284,84 @@ exports[`show all replies 1`] = `
<div
className="HorizontalGutter-root PostCommentFormFake-root HorizontalGutter-full"
>
<textarea
className="PostCommentFormFake-textarea"
disabled={true}
placeholder="Post a comment"
/>
<div
aria-hidden="true"
>
<div>
<div
className=""
>
<div
className=" RTE-toolbarDisabled Toolbar-toolbar"
>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_bold
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_italic
</span>
</button>
<button
className="Button-button"
disabled={false}
onClick={[Function]}
type="button"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
format_quote
</span>
</button>
</div>
<div
aria-hidden="true"
className="RTE-placeholder RTE-placeholder "
>
Post a comment
</div>
<div
aria-placeholder="Post a comment"
className="RTE-contentEditable RTE-content RTE-contentEditableDisabled"
contentEditable={false}
dangerouslySetInnerHTML={
Object {
"__html": "",
}
}
disabled={true}
onBlur={[Function]}
onChange={[Function]}
onCut={[Function]}
onFocus={[Function]}
onInput={[Function]}
onKeyDown={[Function]}
onPaste={[Function]}
onSelect={[Function]}
/>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled Button-fullWidth Button-disabled"
disabled={true}
@@ -254,11 +406,14 @@ exports[`show all replies 1`] = `
2018-07-06T18:24:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
Joining Too
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Joining Too",
}
}
/>
<div
className="Comment-footer"
/>
@@ -291,11 +446,14 @@ exports[`show all replies 1`] = `
2018-07-06T18:20:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
What's up?
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "What's up?",
}
}
/>
<div
className="Comment-footer"
/>
@@ -320,11 +478,14 @@ exports[`show all replies 1`] = `
2018-07-06T18:14:00.000Z
</time>
</div>
<p
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
>
Hey!
</p>
<div
className="HTMLContent-root"
dangerouslySetInnerHTML={
Object {
"__html": "Hey!",
}
}
/>
<div
className="Comment-footer"
/>
@@ -0,0 +1,10 @@
import { ReactElement } from "react";
export default function createNodeMock(element: ReactElement<any>) {
if (element.type === "div") {
return {
innerHtml: "",
};
}
return null;
}
+71 -66
View File
@@ -1,5 +1,5 @@
import React from "react";
import TestRenderer from "react-test-renderer";
import TestRenderer, { ReactTestRenderer } from "react-test-renderer";
import sinon from "sinon";
import { timeout } from "talk-common/utils";
@@ -10,84 +10,89 @@ import { createInMemoryStorage } from "talk-framework/lib/storage";
import AppContainer from "talk-stream/containers/AppContainer";
import createEnvironment from "./createEnvironment";
import createNodeMock from "./createNodeMock";
import { assets, comments } from "./fixtures";
const connectionStub = sinon.stub().throws();
connectionStub.withArgs({ first: 5, orderBy: "CREATED_AT_DESC" }).returns({
edges: [
{
node: comments[0],
cursor: comments[0].createdAt,
},
{
node: comments[1],
cursor: comments[1].createdAt,
},
],
pageInfo: {
endCursor: comments[1].createdAt,
hasNextPage: true,
},
});
connectionStub
.withArgs({
first: 10,
orderBy: "CREATED_AT_DESC",
after: comments[1].createdAt,
})
.returns({
let testRenderer: ReactTestRenderer;
beforeEach(() => {
const connectionStub = sinon.stub().throws();
connectionStub.withArgs({ first: 5, orderBy: "CREATED_AT_DESC" }).returns({
edges: [
{
node: comments[2],
cursor: comments[2].createdAt,
node: comments[0],
cursor: comments[0].createdAt,
},
{
node: comments[1],
cursor: comments[1].createdAt,
},
],
pageInfo: {
endCursor: comments[2].createdAt,
hasNextPage: false,
endCursor: comments[1].createdAt,
hasNextPage: true,
},
});
connectionStub
.withArgs({
first: 10,
orderBy: "CREATED_AT_DESC",
after: comments[1].createdAt,
})
.returns({
edges: [
{
node: comments[2],
cursor: comments[2].createdAt,
},
],
pageInfo: {
endCursor: comments[2].createdAt,
hasNextPage: false,
},
});
const assetStub = {
...assets[0],
comments: connectionStub,
};
const resolvers = {
Query: {
asset: sinon
.stub()
.throws()
.withArgs(undefined, { id: assetStub.id })
.returns(assetStub),
},
};
const environment = createEnvironment({
// Set this to true, to see graphql responses.
logNetwork: false,
resolvers,
initLocalState: (localRecord, source) => {
localRecord.setValue(0, "authRevision");
localRecord.setValue(assetStub.id, "assetID");
},
});
const assetStub = {
...assets[0],
comments: connectionStub,
};
const context: TalkContext = {
relayEnvironment: environment,
localeBundles: [],
localStorage: createInMemoryStorage(),
sessionStorage: createInMemoryStorage(),
rest: new RestClient("http://localhost/api"),
postMessage: new PostMessageService(),
};
const resolvers = {
Query: {
asset: sinon
.stub()
.throws()
.withArgs(undefined, { id: assetStub.id })
.returns(assetStub),
},
};
const environment = createEnvironment({
// Set this to true, to see graphql responses.
logNetwork: false,
resolvers,
initLocalState: (localRecord, source) => {
localRecord.setValue(0, "authRevision");
localRecord.setValue(assetStub.id, "assetID");
},
testRenderer = TestRenderer.create(
<TalkContextProvider value={context}>
<AppContainer />
</TalkContextProvider>,
{ createNodeMock }
);
});
const context: TalkContext = {
relayEnvironment: environment,
localeBundles: [],
localStorage: createInMemoryStorage(),
sessionStorage: createInMemoryStorage(),
rest: new RestClient("http://localhost/api"),
postMessage: new PostMessageService(),
};
const testRenderer = TestRenderer.create(
<TalkContextProvider value={context}>
<AppContainer />
</TalkContextProvider>
);
it("renders comment stream", async () => {
// Wait for loading.
await timeout();
@@ -1,5 +1,5 @@
import React from "react";
import TestRenderer from "react-test-renderer";
import TestRenderer, { ReactTestRenderer } from "react-test-renderer";
import { RecordProxy } from "relay-runtime";
import sinon from "sinon";
@@ -11,68 +11,73 @@ import { createInMemoryStorage } from "talk-framework/lib/storage";
import AppContainer from "talk-stream/containers/AppContainer";
import createEnvironment from "./createEnvironment";
import createNodeMock from "./createNodeMock";
import { assets, comments } from "./fixtures";
const commentStub = {
...comments[0],
};
let testRenderer: ReactTestRenderer;
beforeEach(() => {
const commentStub = {
...comments[0],
};
const assetStub = {
...assets[0],
comments: {
pageInfo: {
hasNextPage: false,
},
edges: [
{
node: commentStub,
cursor: commentStub.createdAt,
const assetStub = {
...assets[0],
comments: {
pageInfo: {
hasNextPage: false,
},
],
},
};
edges: [
{
node: commentStub,
cursor: commentStub.createdAt,
},
],
},
};
const resolvers = {
Query: {
comment: sinon
.stub()
.throws()
.withArgs(undefined, { id: commentStub.id })
.returns(commentStub),
asset: sinon
.stub()
.throws()
.withArgs(undefined, { id: assetStub.id })
.returns(assetStub),
},
};
const resolvers = {
Query: {
comment: sinon
.stub()
.throws()
.withArgs(undefined, { id: commentStub.id })
.returns(commentStub),
asset: sinon
.stub()
.throws()
.withArgs(undefined, { id: assetStub.id })
.returns(assetStub),
},
};
const environment = createEnvironment({
// Set this to true, to see graphql responses.
logNetwork: false,
resolvers,
initLocalState: (localRecord: RecordProxy) => {
localRecord.setValue(0, "authRevision");
localRecord.setValue(assetStub.id, "assetID");
localRecord.setValue(commentStub.id, "commentID");
},
const environment = createEnvironment({
// Set this to true, to see graphql responses.
logNetwork: false,
resolvers,
initLocalState: (localRecord: RecordProxy) => {
localRecord.setValue(0, "authRevision");
localRecord.setValue(assetStub.id, "assetID");
localRecord.setValue(commentStub.id, "commentID");
},
});
const context: TalkContext = {
relayEnvironment: environment,
localeBundles: [],
localStorage: createInMemoryStorage(),
sessionStorage: createInMemoryStorage(),
rest: new RestClient("http://localhost/api"),
postMessage: new PostMessageService(),
};
testRenderer = TestRenderer.create(
<TalkContextProvider value={context}>
<AppContainer />
</TalkContextProvider>,
{ createNodeMock }
);
});
const context: TalkContext = {
relayEnvironment: environment,
localeBundles: [],
localStorage: createInMemoryStorage(),
sessionStorage: createInMemoryStorage(),
rest: new RestClient("http://localhost/api"),
postMessage: new PostMessageService(),
};
const testRenderer = TestRenderer.create(
<TalkContextProvider value={context}>
<AppContainer />
</TalkContextProvider>
);
it("renders permalink view", async () => {
// Wait for loading.
await timeout();
@@ -1,5 +1,5 @@
import React from "react";
import TestRenderer from "react-test-renderer";
import TestRenderer, { ReactTestRenderer } from "react-test-renderer";
import { RecordProxy } from "relay-runtime";
import { timeout } from "talk-common/utils";
@@ -10,40 +10,45 @@ import { createInMemoryStorage } from "talk-framework/lib/storage";
import AppContainer from "talk-stream/containers/AppContainer";
import createEnvironment from "./createEnvironment";
import createNodeMock from "./createNodeMock";
const resolvers = {
Query: {
comment: () => null,
asset: () => null,
},
};
let testRenderer: ReactTestRenderer;
beforeEach(() => {
const resolvers = {
Query: {
comment: () => null,
asset: () => null,
},
};
const environment = createEnvironment({
// Set this to true, to see graphql responses.
logNetwork: false,
resolvers,
initLocalState: (localRecord: RecordProxy) => {
localRecord.setValue(0, "authRevision");
localRecord.setValue("unknown-asset-id", "assetID");
localRecord.setValue("unknown-comment-id", "commentID");
},
const environment = createEnvironment({
// Set this to true, to see graphql responses.
logNetwork: false,
resolvers,
initLocalState: (localRecord: RecordProxy) => {
localRecord.setValue(0, "authRevision");
localRecord.setValue("unknown-asset-id", "assetID");
localRecord.setValue("unknown-comment-id", "commentID");
},
});
const context: TalkContext = {
relayEnvironment: environment,
localeBundles: [],
localStorage: createInMemoryStorage(),
sessionStorage: createInMemoryStorage(),
rest: new RestClient("http://localhost/api"),
postMessage: new PostMessageService(),
};
testRenderer = TestRenderer.create(
<TalkContextProvider value={context}>
<AppContainer />
</TalkContextProvider>,
{ createNodeMock }
);
});
const context: TalkContext = {
relayEnvironment: environment,
localeBundles: [],
localStorage: createInMemoryStorage(),
sessionStorage: createInMemoryStorage(),
rest: new RestClient("http://localhost/api"),
postMessage: new PostMessageService(),
};
const testRenderer = TestRenderer.create(
<TalkContextProvider value={context}>
<AppContainer />
</TalkContextProvider>
);
it("renders permalink view with unknown asset", async () => {
// Wait for loading.
await timeout();
@@ -1,5 +1,5 @@
import React from "react";
import TestRenderer from "react-test-renderer";
import TestRenderer, { ReactTestRenderer } from "react-test-renderer";
import { RecordProxy } from "relay-runtime";
import sinon from "sinon";
@@ -11,64 +11,69 @@ import { createInMemoryStorage } from "talk-framework/lib/storage";
import AppContainer from "talk-stream/containers/AppContainer";
import createEnvironment from "./createEnvironment";
import createNodeMock from "./createNodeMock";
import { assets, comments } from "./fixtures";
const commentStub = {
...comments[0],
};
let testRenderer: ReactTestRenderer;
beforeEach(() => {
const commentStub = {
...comments[0],
};
const assetStub = {
...assets[0],
comments: {
pageInfo: {
hasNextPage: false,
},
edges: [
{
node: commentStub,
cursor: commentStub.createdAt,
const assetStub = {
...assets[0],
comments: {
pageInfo: {
hasNextPage: false,
},
],
},
};
edges: [
{
node: commentStub,
cursor: commentStub.createdAt,
},
],
},
};
const resolvers = {
Query: {
comment: () => null,
asset: sinon
.stub()
.throws()
.withArgs(undefined, { id: assetStub.id })
.returns(assetStub),
},
};
const resolvers = {
Query: {
comment: () => null,
asset: sinon
.stub()
.throws()
.withArgs(undefined, { id: assetStub.id })
.returns(assetStub),
},
};
const environment = createEnvironment({
// Set this to true, to see graphql responses.
logNetwork: false,
resolvers,
initLocalState: (localRecord: RecordProxy) => {
localRecord.setValue(assetStub.id, "assetID");
localRecord.setValue("unknown-comment-id", "commentID");
localRecord.setValue(0, "authRevision");
},
const environment = createEnvironment({
// Set this to true, to see graphql responses.
logNetwork: false,
resolvers,
initLocalState: (localRecord: RecordProxy) => {
localRecord.setValue(assetStub.id, "assetID");
localRecord.setValue("unknown-comment-id", "commentID");
localRecord.setValue(0, "authRevision");
},
});
const context: TalkContext = {
relayEnvironment: environment,
localeBundles: [],
localStorage: createInMemoryStorage(),
sessionStorage: createInMemoryStorage(),
rest: new RestClient("http://localhost/api"),
postMessage: new PostMessageService(),
};
testRenderer = TestRenderer.create(
<TalkContextProvider value={context}>
<AppContainer />
</TalkContextProvider>,
{ createNodeMock }
);
});
const context: TalkContext = {
relayEnvironment: environment,
localeBundles: [],
localStorage: createInMemoryStorage(),
sessionStorage: createInMemoryStorage(),
rest: new RestClient("http://localhost/api"),
postMessage: new PostMessageService(),
};
const testRenderer = TestRenderer.create(
<TalkContextProvider value={context}>
<AppContainer />
</TalkContextProvider>
);
it("renders permalink view with unknown comment", async () => {
// Wait for loading.
await timeout();
@@ -1,5 +1,5 @@
import React from "react";
import TestRenderer from "react-test-renderer";
import TestRenderer, { ReactTestRenderer } from "react-test-renderer";
import { RecordProxy } from "relay-runtime";
import sinon from "sinon";
@@ -11,43 +11,48 @@ import { createInMemoryStorage } from "talk-framework/lib/storage";
import AppContainer from "talk-stream/containers/AppContainer";
import createEnvironment from "./createEnvironment";
import createNodeMock from "./createNodeMock";
import { assetWithReplies } from "./fixtures";
const resolvers = {
Query: {
asset: sinon
.stub()
.throws()
.withArgs(undefined, { id: assetWithReplies.id })
.returns(assetWithReplies),
},
};
let testRenderer: ReactTestRenderer;
beforeEach(() => {
const resolvers = {
Query: {
asset: sinon
.stub()
.throws()
.withArgs(undefined, { id: assetWithReplies.id })
.returns(assetWithReplies),
},
};
const environment = createEnvironment({
// Set this to true, to see graphql responses.
logNetwork: false,
resolvers,
initLocalState: (localRecord: RecordProxy) => {
localRecord.setValue(assetWithReplies.id, "assetID");
localRecord.setValue(0, "authRevision");
},
const environment = createEnvironment({
// Set this to true, to see graphql responses.
logNetwork: false,
resolvers,
initLocalState: (localRecord: RecordProxy) => {
localRecord.setValue(assetWithReplies.id, "assetID");
localRecord.setValue(0, "authRevision");
},
});
const context: TalkContext = {
relayEnvironment: environment,
localeBundles: [],
localStorage: createInMemoryStorage(),
sessionStorage: createInMemoryStorage(),
rest: new RestClient("http://localhost/api"),
postMessage: new PostMessageService(),
};
testRenderer = TestRenderer.create(
<TalkContextProvider value={context}>
<AppContainer />
</TalkContextProvider>,
{ createNodeMock }
);
});
const context: TalkContext = {
relayEnvironment: environment,
localeBundles: [],
localStorage: createInMemoryStorage(),
sessionStorage: createInMemoryStorage(),
rest: new RestClient("http://localhost/api"),
postMessage: new PostMessageService(),
};
const testRenderer = TestRenderer.create(
<TalkContextProvider value={context}>
<AppContainer />
</TalkContextProvider>
);
it("renders comment stream", async () => {
// Wait for loading.
await timeout();
@@ -1,5 +1,5 @@
import React from "react";
import TestRenderer from "react-test-renderer";
import TestRenderer, { ReactTestRenderer } from "react-test-renderer";
import { RecordProxy } from "relay-runtime";
import sinon from "sinon";
@@ -11,43 +11,48 @@ import { createInMemoryStorage } from "talk-framework/lib/storage";
import AppContainer from "talk-stream/containers/AppContainer";
import createEnvironment from "./createEnvironment";
import createNodeMock from "./createNodeMock";
import { assets } from "./fixtures";
const resolvers = {
Query: {
asset: sinon
.stub()
.throws()
.withArgs(undefined, { id: assets[0].id })
.returns(assets[0]),
},
};
let testRenderer: ReactTestRenderer;
beforeEach(() => {
const resolvers = {
Query: {
asset: sinon
.stub()
.throws()
.withArgs(undefined, { id: assets[0].id })
.returns(assets[0]),
},
};
const environment = createEnvironment({
// Set this to true, to see graphql responses.
logNetwork: false,
resolvers,
initLocalState: (localRecord: RecordProxy) => {
localRecord.setValue(assets[0].id, "assetID");
localRecord.setValue(0, "authRevision");
},
const environment = createEnvironment({
// Set this to true, to see graphql responses.
logNetwork: false,
resolvers,
initLocalState: (localRecord: RecordProxy) => {
localRecord.setValue(assets[0].id, "assetID");
localRecord.setValue(0, "authRevision");
},
});
const context: TalkContext = {
relayEnvironment: environment,
localeBundles: [],
localStorage: createInMemoryStorage(),
sessionStorage: createInMemoryStorage(),
rest: new RestClient("http://localhost/api"),
postMessage: new PostMessageService(),
};
testRenderer = TestRenderer.create(
<TalkContextProvider value={context}>
<AppContainer />
</TalkContextProvider>,
{ createNodeMock }
);
});
const context: TalkContext = {
relayEnvironment: environment,
localeBundles: [],
localStorage: createInMemoryStorage(),
sessionStorage: createInMemoryStorage(),
rest: new RestClient("http://localhost/api"),
postMessage: new PostMessageService(),
};
const testRenderer = TestRenderer.create(
<TalkContextProvider value={context}>
<AppContainer />
</TalkContextProvider>
);
it("renders comment stream", async () => {
// Wait for loading.
await timeout();
@@ -1,5 +1,5 @@
import React from "react";
import TestRenderer from "react-test-renderer";
import TestRenderer, { ReactTestRenderer } from "react-test-renderer";
import { RecordProxy } from "relay-runtime";
import sinon from "sinon";
@@ -11,100 +11,105 @@ import { createInMemoryStorage } from "talk-framework/lib/storage";
import AppContainer from "talk-stream/containers/AppContainer";
import createEnvironment from "./createEnvironment";
import createNodeMock from "./createNodeMock";
import { assets, comments } from "./fixtures";
const connectionStub = sinon.stub().throws();
connectionStub.withArgs({ first: 5, orderBy: "CREATED_AT_ASC" }).returns({
edges: [
{
node: comments[1],
cursor: comments[1].createdAt,
},
],
pageInfo: {
endCursor: comments[1].createdAt,
hasNextPage: true,
},
});
connectionStub
.withArgs({
first: sinon.match(n => n > 10000),
orderBy: "CREATED_AT_ASC",
after: comments[1].createdAt,
})
.returns({
let testRenderer: ReactTestRenderer;
beforeEach(() => {
const connectionStub = sinon.stub().throws();
connectionStub.withArgs({ first: 5, orderBy: "CREATED_AT_ASC" }).returns({
edges: [
{
node: comments[2],
cursor: comments[2].createdAt,
node: comments[1],
cursor: comments[1].createdAt,
},
],
pageInfo: {
endCursor: comments[2].createdAt,
hasNextPage: false,
endCursor: comments[1].createdAt,
hasNextPage: true,
},
});
connectionStub
.withArgs({
first: sinon.match(n => n > 10000),
orderBy: "CREATED_AT_ASC",
after: comments[1].createdAt,
})
.returns({
edges: [
{
node: comments[2],
cursor: comments[2].createdAt,
},
],
pageInfo: {
endCursor: comments[2].createdAt,
hasNextPage: false,
},
});
const commentStub = {
...comments[0],
replies: connectionStub,
};
const assetStub = {
...assets[0],
comments: {
pageInfo: {
hasNextPage: false,
},
edges: [
{
node: commentStub,
cursor: commentStub.createdAt,
},
],
},
};
const resolvers = {
Query: {
comment: sinon
.stub()
.throws()
.withArgs(undefined, { id: commentStub.id })
.returns(commentStub),
asset: sinon
.stub()
.throws()
.withArgs(undefined, { id: assetStub.id })
.returns(assetStub),
},
};
const environment = createEnvironment({
// Set this to true, to see graphql responses.
logNetwork: false,
resolvers,
initLocalState: (localRecord: RecordProxy) => {
localRecord.setValue(assetStub.id, "assetID");
localRecord.setValue(0, "authRevision");
},
});
const commentStub = {
...comments[0],
replies: connectionStub,
};
const context: TalkContext = {
relayEnvironment: environment,
localeBundles: [],
localStorage: createInMemoryStorage(),
sessionStorage: createInMemoryStorage(),
rest: new RestClient("http://localhost/api"),
postMessage: new PostMessageService(),
};
const assetStub = {
...assets[0],
comments: {
pageInfo: {
hasNextPage: false,
},
edges: [
{
node: commentStub,
cursor: commentStub.createdAt,
},
],
},
};
const resolvers = {
Query: {
comment: sinon
.stub()
.throws()
.withArgs(undefined, { id: commentStub.id })
.returns(commentStub),
asset: sinon
.stub()
.throws()
.withArgs(undefined, { id: assetStub.id })
.returns(assetStub),
},
};
const environment = createEnvironment({
// Set this to true, to see graphql responses.
logNetwork: false,
resolvers,
initLocalState: (localRecord: RecordProxy) => {
localRecord.setValue(assetStub.id, "assetID");
localRecord.setValue(0, "authRevision");
},
testRenderer = TestRenderer.create(
<TalkContextProvider value={context}>
<AppContainer />
</TalkContextProvider>,
{ createNodeMock }
);
});
const context: TalkContext = {
relayEnvironment: environment,
localeBundles: [],
localStorage: createInMemoryStorage(),
sessionStorage: createInMemoryStorage(),
rest: new RestClient("http://localhost/api"),
postMessage: new PostMessageService(),
};
const testRenderer = TestRenderer.create(
<TalkContextProvider value={context}>
<AppContainer />
</TalkContextProvider>
);
it("renders comment stream", async () => {
// Wait for loading.
await timeout();
@@ -1,12 +1,12 @@
import cn from "classnames";
import React, { HTMLAttributes, StatelessComponent } from "react";
import React, { AllHTMLAttributes, StatelessComponent } from "react";
import { withForwardRef, withStyles } from "talk-ui/hocs";
import { PropTypesOf } from "talk-ui/types";
import * as styles from "./AriaInfo.css";
interface InnerProps extends HTMLAttributes<HTMLElement> {
interface InnerProps extends AllHTMLAttributes<HTMLElement> {
/**
* This prop can be used to add custom classnames.
* It is handled by the `withStyles `HOC.
+8 -1
View File
@@ -25,7 +25,14 @@ interface InnerProps extends HTMLAttributes<HTMLSpanElement> {
const Icon: StatelessComponent<InnerProps> = props => {
const { classes, className, size, forwardRef, ...rest } = props;
const rootClassName = cn(classes.root, className, classes[size!]);
return <span className={rootClassName} {...rest} ref={forwardRef} />;
return (
<span
className={rootClassName}
aria-hidden="true"
{...rest}
ref={forwardRef}
/>
);
};
Icon.defaultProps = {
@@ -2,6 +2,7 @@
exports[`renders correctly 1`] = `
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
face
@@ -10,6 +11,7 @@ exports[`renders correctly 1`] = `
exports[`renders correctly with specified size 1`] = `
<span
aria-hidden="true"
className="Icon-root Icon-lg"
>
bookmark
@@ -24,7 +24,8 @@
}
.bodyCopyBold {
composes: bodyCopyBold from "talk-ui/shared/typography.css";
composes: bodyCopy from "talk-ui/shared/typography.css";
font-weight: var(--font-weight-medium);
}
.button {
@@ -5,6 +5,7 @@ exports[`renders correctly 1`] = `
className="ValidationMessage-root ValidationMessage-colorError custom"
>
<span
aria-hidden="true"
className="Icon-root ValidationMessage-icon Icon-sm"
>
warning
+2
View File
@@ -18,3 +18,5 @@ export { default as FormField } from "./FormField";
export { default as InputDescription } from "./InputDescription";
export { default as Spinner } from "./Spinner";
export { default as HorizontalGutter } from "./HorizontalGutter";
export { default as Icon } from "./Icon";
export { default as AriaInfo } from "./AriaInfo";
-5
View File
@@ -101,11 +101,6 @@
color: var(--palette-text-primary);
}
.bodyCopyBold {
composes: bodyCopy;
font-weight: var(--font-weight-medium);
}
.button {
color: var(--palette-text-secondary);
font-family: var(--font-family-sans-serif);
+1 -1
View File
@@ -1 +1 @@
-brand-name = The Coral Project
+21
View File
@@ -21,3 +21,24 @@ comments-userBoxAuthenticated-signedInAs =
comments-userBoxAuthenticated-notYou =
Not you? <button>Sign Out</button>
comments-rte-bold =
.title = Bold
comments-rte-italic =
.title = Italic
comments-rte-blockquote =
.title = Blockquote
comments-poweredBy = Powered by <logo>{ -brand-name }</logo>
comments-postCommentFormFake-signInAndJoin = Sign in and join the conversation
comments-postCommentForm-rteLabel = Post a comment
comments-postCommentForm-rte =
.placeholder = { comments-postCommentForm-rteLabel }
comments-postCommentFormFake-rte =
.placeholder = { comments-postCommentForm-rteLabel }