mirror of
https://github.com/wassname/talk.git
synced 2026-08-20 12:50:41 +08:00
Add integration test
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
import sinon, { SinonStub } from "sinon";
|
||||
|
||||
export default function createSinonStub(
|
||||
...callbacks: Array<(s: SinonStub) => void>
|
||||
): SinonStub {
|
||||
const stub = sinon.stub();
|
||||
callbacks.forEach(cb => cb(stub));
|
||||
return stub;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ export {
|
||||
CreateRelayEnvironmentParams,
|
||||
} from "./createRelayEnvironment";
|
||||
export { default as createFluentBundle } from "./createFluentBundle";
|
||||
export { default as createSinonStub } from "./createSinonStub";
|
||||
export {
|
||||
default as removeFragmentRefs,
|
||||
NoFragmentRefs,
|
||||
|
||||
@@ -27,13 +27,21 @@ export interface PostCommentFormProps {
|
||||
const PostCommentForm: StatelessComponent<PostCommentFormProps> = props => (
|
||||
<Form onSubmit={props.onSubmit}>
|
||||
{({ handleSubmit, submitting }) => (
|
||||
<form autoComplete="off" onSubmit={handleSubmit} className={styles.root}>
|
||||
<form
|
||||
autoComplete="off"
|
||||
onSubmit={handleSubmit}
|
||||
className={styles.root}
|
||||
id="comments-postCommentForm-form"
|
||||
>
|
||||
<HorizontalGutter>
|
||||
<Field name="body" validate={required}>
|
||||
{({ input, meta }) => (
|
||||
<div>
|
||||
<Localized id="comments-postCommentForm-rteLabel">
|
||||
<AriaInfo component="label" htmlFor="postCommentField">
|
||||
<AriaInfo
|
||||
component="label"
|
||||
htmlFor="comments-postCommentForm-field"
|
||||
>
|
||||
Post a comment
|
||||
</AriaInfo>
|
||||
</Localized>
|
||||
@@ -42,7 +50,7 @@ const PostCommentForm: StatelessComponent<PostCommentFormProps> = props => (
|
||||
attrs={{ placeholder: true }}
|
||||
>
|
||||
<RTE
|
||||
inputId="postCommentField"
|
||||
inputId="comments-postCommentForm-field"
|
||||
onChange={({ html }) => input.onChange(html)}
|
||||
value={input.value}
|
||||
placeholder="Post a comment"
|
||||
|
||||
@@ -0,0 +1,557 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`post a comment 1`] = `
|
||||
<div
|
||||
className="Flex-root App-root Flex-flex Flex-justifyCenter"
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root Stream-root HorizontalGutter-double"
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-half"
|
||||
>
|
||||
<div
|
||||
className="Flex-root"
|
||||
>
|
||||
<div
|
||||
className="Flex-flex Flex-halfItemGutter Flex-wrap"
|
||||
>
|
||||
<div
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Signed in as
|
||||
<span
|
||||
className="Typography-root Typography-bodyCopyBold Typography-colorTextPrimary"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
.
|
||||
</div>
|
||||
<div
|
||||
className="Flex-root Typography-root Typography-bodyCopy Typography-colorTextPrimary Flex-flex"
|
||||
>
|
||||
<span>
|
||||
Not you?
|
||||
</span>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Sign Out
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form
|
||||
autoComplete="off"
|
||||
className="PostCommentForm-root"
|
||||
id="comments-postCommentForm-form"
|
||||
onSubmit={[Function]}
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div>
|
||||
<label
|
||||
className="AriaInfo-root"
|
||||
htmlFor="comments-postCommentForm-field"
|
||||
>
|
||||
Post a comment
|
||||
</label>
|
||||
<div>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Toolbar-toolbar"
|
||||
>
|
||||
<button
|
||||
className="Button-button"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
title="Bold"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="Icon-root Icon-sm"
|
||||
>
|
||||
format_bold
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="Button-button"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
title="Italic"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="Icon-root Icon-sm"
|
||||
>
|
||||
format_italic
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="Button-button"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
title="Blockquote"
|
||||
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"
|
||||
contentEditable={true}
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "",
|
||||
}
|
||||
}
|
||||
id="comments-postCommentForm-field"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onCut={[Function]}
|
||||
onFocus={[Function]}
|
||||
onInput={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onPaste={[Function]}
|
||||
onSelect={[Function]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-justifySpaceBetween Flex-alignFlexStart Flex-directionRow"
|
||||
>
|
||||
<div
|
||||
className="PostCommentForm-poweredBy"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
|
||||
>
|
||||
Powered by
|
||||
<span
|
||||
className="Typography-root Typography-heading4 Typography-colorTextPrimary"
|
||||
>
|
||||
The Coral Project
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled"
|
||||
disabled={false}
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="submit"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div
|
||||
aria-live="polite"
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
id="talk-comments-stream-log"
|
||||
role="log"
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root TopBar-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "<strong>Hello world</strong>",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Comment-footer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root TopBar-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Comment-footer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root TopBar-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:20:00.000Z"
|
||||
title="2018-07-06T18:20:00.000Z"
|
||||
>
|
||||
2018-07-06T18:20:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Comment-footer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders comment stream 1`] = `
|
||||
<div
|
||||
className="Flex-root App-root Flex-flex Flex-justifyCenter"
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root Stream-root HorizontalGutter-double"
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-half"
|
||||
>
|
||||
<div
|
||||
className="Flex-root"
|
||||
>
|
||||
<div
|
||||
className="Flex-flex Flex-halfItemGutter Flex-wrap"
|
||||
>
|
||||
<div
|
||||
className="Typography-root Typography-bodyCopy Typography-colorTextPrimary"
|
||||
>
|
||||
Signed in as
|
||||
<span
|
||||
className="Typography-root Typography-bodyCopyBold Typography-colorTextPrimary"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
.
|
||||
</div>
|
||||
<div
|
||||
className="Flex-root Typography-root Typography-bodyCopy Typography-colorTextPrimary Flex-flex"
|
||||
>
|
||||
<span>
|
||||
Not you?
|
||||
</span>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantUnderlined"
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="button"
|
||||
>
|
||||
Sign Out
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form
|
||||
autoComplete="off"
|
||||
className="PostCommentForm-root"
|
||||
id="comments-postCommentForm-form"
|
||||
onSubmit={[Function]}
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div>
|
||||
<label
|
||||
className="AriaInfo-root"
|
||||
htmlFor="comments-postCommentForm-field"
|
||||
>
|
||||
Post a comment
|
||||
</label>
|
||||
<div>
|
||||
<div
|
||||
className=""
|
||||
>
|
||||
<div
|
||||
className="Toolbar-toolbar"
|
||||
>
|
||||
<button
|
||||
className="Button-button"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
title="Bold"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="Icon-root Icon-sm"
|
||||
>
|
||||
format_bold
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="Button-button"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
title="Italic"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="Icon-root Icon-sm"
|
||||
>
|
||||
format_italic
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className="Button-button"
|
||||
disabled={false}
|
||||
onClick={[Function]}
|
||||
title="Blockquote"
|
||||
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"
|
||||
contentEditable={true}
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "",
|
||||
}
|
||||
}
|
||||
id="comments-postCommentForm-field"
|
||||
onBlur={[Function]}
|
||||
onChange={[Function]}
|
||||
onCut={[Function]}
|
||||
onFocus={[Function]}
|
||||
onInput={[Function]}
|
||||
onKeyDown={[Function]}
|
||||
onPaste={[Function]}
|
||||
onSelect={[Function]}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="Flex-root Flex-flex Flex-justifySpaceBetween Flex-alignFlexStart Flex-directionRow"
|
||||
>
|
||||
<div
|
||||
className="PostCommentForm-poweredBy"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-inputDescription Typography-colorTextSecondary"
|
||||
>
|
||||
Powered by
|
||||
<span
|
||||
className="Typography-root Typography-heading4 Typography-colorTextPrimary"
|
||||
>
|
||||
The Coral Project
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
className="BaseButton-root Button-root Button-sizeRegular Button-colorPrimary Button-variantFilled"
|
||||
disabled={false}
|
||||
onBlur={[Function]}
|
||||
onFocus={[Function]}
|
||||
onMouseDown={[Function]}
|
||||
onMouseOut={[Function]}
|
||||
onMouseOver={[Function]}
|
||||
onTouchEnd={[Function]}
|
||||
type="submit"
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div
|
||||
aria-live="polite"
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
id="talk-comments-stream-log"
|
||||
role="log"
|
||||
>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root TopBar-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Markus
|
||||
</span>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:24:00.000Z"
|
||||
title="2018-07-06T18:24:00.000Z"
|
||||
>
|
||||
2018-07-06T18:24:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "Joining Too",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Comment-footer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="HorizontalGutter-root HorizontalGutter-full"
|
||||
>
|
||||
<div
|
||||
className="Comment-root"
|
||||
role="article"
|
||||
>
|
||||
<div
|
||||
className="Flex-root TopBar-root Flex-flex Flex-halfItemGutter Flex-alignBaseline Flex-directionColumn"
|
||||
>
|
||||
<span
|
||||
className="Typography-root Typography-heading3 Typography-colorTextPrimary Username-root"
|
||||
>
|
||||
Lukas
|
||||
</span>
|
||||
<time
|
||||
className="Timestamp-root RelativeTime-root"
|
||||
dateTime="2018-07-06T18:20:00.000Z"
|
||||
title="2018-07-06T18:20:00.000Z"
|
||||
>
|
||||
2018-07-06T18:20:00.000Z
|
||||
</time>
|
||||
</div>
|
||||
<div
|
||||
className="HTMLContent-root"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "What's up?",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<div
|
||||
className="Comment-footer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -0,0 +1,104 @@
|
||||
import React from "react";
|
||||
import TestRenderer, { ReactTestRenderer } from "react-test-renderer";
|
||||
import { RecordProxy } from "relay-runtime";
|
||||
|
||||
import { timeout } from "talk-common/utils";
|
||||
import { TalkContext, TalkContextProvider } from "talk-framework/lib/bootstrap";
|
||||
import { PostMessageService } from "talk-framework/lib/postMessage";
|
||||
import { RestClient } from "talk-framework/lib/rest";
|
||||
import { createInMemoryStorage } from "talk-framework/lib/storage";
|
||||
import { createSinonStub } from "talk-framework/testHelpers";
|
||||
import AppContainer from "talk-stream/containers/AppContainer";
|
||||
|
||||
import createEnvironment from "./createEnvironment";
|
||||
import createFluentBundle from "./createFluentBundle";
|
||||
import createNodeMock from "./createNodeMock";
|
||||
import { assets, users } from "./fixtures";
|
||||
|
||||
let testRenderer: ReactTestRenderer;
|
||||
beforeEach(() => {
|
||||
const resolvers = {
|
||||
Query: {
|
||||
asset: createSinonStub(
|
||||
s => s.throws(),
|
||||
s => s.withArgs(undefined, { id: assets[0].id }).returns(assets[0])
|
||||
),
|
||||
me: createSinonStub(
|
||||
s => s.throws(),
|
||||
s => s.withArgs(undefined, { clientAuthRevision: 0 }).returns(users[0])
|
||||
),
|
||||
},
|
||||
Mutation: {
|
||||
createComment: createSinonStub(
|
||||
s => s.throws(),
|
||||
s =>
|
||||
s
|
||||
.withArgs(undefined, {
|
||||
input: {
|
||||
assetID: assets[0].id,
|
||||
body: "<strong>Hello world!</strong>",
|
||||
clientMutationId: "0",
|
||||
},
|
||||
})
|
||||
.returns({
|
||||
commentEdge: {
|
||||
cursor: "2018-07-06T18:24:00.000Z",
|
||||
node: {
|
||||
id: "comment-x",
|
||||
author: users[0],
|
||||
body: "<strong>Hello world</strong>",
|
||||
createdAt: "2018-07-06T18:24:00.000Z",
|
||||
},
|
||||
},
|
||||
clientMutationId: "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 context: TalkContext = {
|
||||
relayEnvironment: environment,
|
||||
localeBundles: [createFluentBundle()],
|
||||
localStorage: createInMemoryStorage(),
|
||||
sessionStorage: createInMemoryStorage(),
|
||||
rest: new RestClient("http://localhost/api"),
|
||||
postMessage: new PostMessageService(),
|
||||
};
|
||||
|
||||
testRenderer = TestRenderer.create(
|
||||
<TalkContextProvider value={context}>
|
||||
<AppContainer />
|
||||
</TalkContextProvider>,
|
||||
{ createNodeMock }
|
||||
);
|
||||
});
|
||||
|
||||
it("renders comment stream", async () => {
|
||||
// Wait for loading.
|
||||
await timeout();
|
||||
expect(testRenderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("post a comment", async () => {
|
||||
testRenderer.root
|
||||
.findByProps({ inputId: "comments-postCommentForm-field" })
|
||||
.props.onChange({ html: "<strong>Hello world!</strong>" });
|
||||
|
||||
testRenderer.root
|
||||
.findByProps({ id: "comments-postCommentForm-form" })
|
||||
.props.onSubmit();
|
||||
|
||||
// Wait for loading.
|
||||
await timeout();
|
||||
expect(testRenderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
@@ -5,6 +5,15 @@ declare var global: any;
|
||||
const jsdom = new JSDOM("<!doctype html><html><body></body></html>");
|
||||
const { window } = jsdom;
|
||||
|
||||
// tiny shim for getSelection for the RTE.
|
||||
// tslint:disable:no-empty
|
||||
window.getSelection = () =>
|
||||
({
|
||||
addRange() {},
|
||||
removeAllRanges() {},
|
||||
} as any);
|
||||
// tslint:enable:no-empty
|
||||
|
||||
function copyProps(src: any, target: any) {
|
||||
const props = Object.getOwnPropertyNames(src)
|
||||
.filter(prop => typeof target[prop] === "undefined")
|
||||
|
||||
Reference in New Issue
Block a user