[next] Auth Popup v2 (#2101)

* feat: Implement new Sign In view

* feat: Move forgot + resetPassword to new design

* feat: Implement sign up with new design

* fix: narrow gutter

* test: add unit tests

* test: integration tests

* feat: support show / hide password

* feat: support oauth2 flow

* feat: add views for user completion

* feat: implement oauth2 sign up

* test: fix snapshots

* fix: lint

* fix: get more complete mutation response

* fix: removed array of OIDC integrations

* fix: renamed resolver function

* fix: adapt oidc client implementation

* fix: targetFilter should be stream on signup

* fix: removed unneeded message

* fix: moved password into local profile

* fix: made username optional, removed valid null value

* fix: linting

* fix: respect targetFilter

* feat: support user registration mutations

- Added `setUsername`
- Added `setEmail`
- Added `setPassword`
- Added `permit` to `@auth`
- Added `email` to `User`

* fix: fixed issue with query

* feat: added user password update

* feat: complete sign in mutation

* fix: adapt some rebasing gitches

* test: improve tests

* test: unittest for setting auth token

* fix: failing tests

* test: move most tests from enzyme to react-test-renderer

* fix: remove schema warnings in tests

* test: improve window mock

* test: test different social login configurations

* test: test social logins for sign up

* fix: use htmlFor instead of for

* test: more feature tests

* feat: always go through account completion

* test: feature test account completion

* feat: addtional account completion test

* Update start.ts

* chore: refactor auth token retrieval logic
This commit is contained in:
Kiwi
2018-12-20 22:32:04 +01:00
committed by GitHub
parent 326a10dc5d
commit 065cb4b03a
331 changed files with 12476 additions and 7163 deletions
+1 -1
View File
@@ -37,7 +37,7 @@
"lint:server": "tslint --project ./src/tsconfig.json",
"lint:client": "tslint --project ./src/core/client/tsconfig.json",
"lint:scripts": "tslint --project ./tsconfig.json",
"lint-fix": "npm run lint:server -- --fix && npm run lint:client -- --fix && npm run lint:client-embed -- --fix && npm run lint:scripts -- --fix",
"lint-fix": "npm run lint:server -- --fix && npm run lint:client -- --fix && npm run lint:scripts -- --fix",
"test": "node scripts/test.js --env=jsdom",
"tscheck": "npm-run-all --parallel tscheck:*",
"tscheck:server": "tsc --project ./src/tsconfig.json --noEmit",
+24 -42
View File
@@ -7,7 +7,6 @@ dotenv.config();
import chalk from "chalk";
import {
choosePort,
createCompiler,
prepareUrls,
} from "react-dev-utils/WebpackDevServerUtils";
@@ -34,7 +33,7 @@ process.on("unhandledRejection", err => {
throw err;
});
const PORT = parseInt(process.env.DEV_SERVER_PORT!, 10) || 8080;
const PORT = config.get("dev_port");
const HOST = "0.0.0.0";
if (process.env.HOST) {
@@ -52,45 +51,28 @@ if (process.env.HOST) {
console.log();
}
// We attempt to use the default port but if it is busy, we offer the user to
// run on a different port. `choosePort()` Promise resolves to the next free port.
choosePort(HOST, PORT)
.then((port: number) => {
if (port == null) {
// We have not found a port.
return;
}
const protocol = "http";
const appName = "Talk";
const urls = prepareUrls(protocol, HOST, port);
const webpackConfig = createWebpackConfig(config);
// Create a webpack compiler that is configured with custom messages.
const compiler = createCompiler(webpack, webpackConfig, appName, urls);
// Serve webpack assets generated by the compiler over a web sever.
const serverConfig = createDevServerConfig({
allowedHost: urls.lanUrlForConfig,
serverPort: config.get("port"),
publicPath: webpackConfig[0].output!.publicPath!,
});
const devServer = new WebpackDevServer(compiler, serverConfig);
// Launch WebpackDevServer.
devServer.listen(port, HOST, (err: Error) => {
if (err) {
return console.log(err);
}
console.log(chalk.cyan("Starting the development server...\n"));
});
const urls = prepareUrls("http", HOST, PORT);
const webpackConfig = createWebpackConfig(config);
// Create a webpack compiler that is configured with custom messages.
const compiler = createCompiler(webpack, webpackConfig, "Talk", urls);
// Serve webpack assets generated by the compiler over a web sever.
const serverConfig = createDevServerConfig({
allowedHost: urls.lanUrlForConfig,
serverPort: config.get("port"),
publicPath: webpackConfig[0].output!.publicPath!,
});
const devServer = new WebpackDevServer(compiler, serverConfig);
// Launch WebpackDevServer.
devServer.listen(PORT, HOST, (err: Error) => {
if (err) {
return console.log(err);
}
console.log(chalk.cyan("Starting the development server...\n"));
});
["SIGINT", "SIGTERM"].forEach((sig: any) => {
process.once(sig, () => {
devServer.close();
process.exit();
});
});
})
.catch((err: Error) => {
if (err.message) {
console.log(err.message);
}
process.exit(1);
["SIGINT", "SIGTERM"].forEach((sig: any) => {
process.once(sig, () => {
devServer.close();
process.exit();
});
});
+7
View File
@@ -14,6 +14,13 @@ const config = convict({
env: "PORT",
arg: "port",
},
dev_port: {
doc: "The port to bind for the Webpack Dev Server.",
format: "port",
default: 8080,
env: "DEV_PORT",
arg: "dev-port",
},
generateReport: {
doc: "Generate a report using webpack-bundle-analyzer",
format: Boolean,
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -9,6 +9,8 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof App> = {
children: "child",
};
const wrapper = shallow(<App {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<App {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -20,7 +20,7 @@ class DecisionHistoryButton extends React.Component {
const popoverID = `decision-history-popover`;
return (
<Popover
data-test="decisionHistory-popover"
data-testid="decisionHistory-popover"
id={popoverID}
placement="bottom-end"
description="A dialog showing a permalink to the comment"
@@ -43,7 +43,7 @@ class DecisionHistoryButton extends React.Component {
aria-controls={popoverID}
forwardRef={forwardRef}
className={styles.historyIcon}
data-test="decisionHistory-toggle"
data-testid="decisionHistory-toggle"
>
<Icon size="lg">history</Icon>
</BaseButton>
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -9,6 +9,8 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof MainLayout> = {
children: "content",
};
const wrapper = shallow(<MainLayout {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<MainLayout {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,9 +1,10 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import Navigation from "./Navigation";
it("renders correctly", () => {
const wrapper = shallow(<Navigation />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Navigation />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -10,6 +10,7 @@ it("renders correctly", () => {
to: "/moderate",
children: "link",
};
const wrapper = shallow(<NavigationLink {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<NavigationLink {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,6 +1,6 @@
import { shallow } from "enzyme";
import { noop } from "lodash";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -11,6 +11,7 @@ it("renders correctly", () => {
id: "id",
onClick: noop,
};
const wrapper = shallow(<SignOutButton {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<SignOutButton {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,56 +0,0 @@
import { graphql } from "react-relay";
import { Environment } from "relay-runtime";
import {
commitMutationPromiseNormalized,
createMutationContainer,
} from "talk-framework/lib/relay";
import { Omit } from "talk-framework/types";
import { CreateOIDCAuthIntegrationMutation as MutationTypes } from "talk-admin/__generated__/CreateOIDCAuthIntegrationMutation.graphql";
export type CreateOIDCAuthIntegrationInput = Omit<
MutationTypes["variables"]["input"],
"clientMutationId"
>;
const mutation = graphql`
mutation CreateOIDCAuthIntegrationMutation(
$input: CreateOIDCAuthIntegrationInput!
) {
createOIDCAuthIntegration(input: $input) {
settings {
auth {
...OIDCConfigListContainer_authReadOnly
}
}
clientMutationId
}
}
`;
let clientMutationId = 0;
function commit(
environment: Environment,
input: CreateOIDCAuthIntegrationInput
) {
return commitMutationPromiseNormalized<MutationTypes>(environment, {
mutation,
variables: {
input: {
...input,
clientMutationId: (clientMutationId++).toString(),
},
},
});
}
export const withCreateOIDCAuthIntegrationMutation = createMutationContainer(
"createOIDCAuthIntegration",
commit
);
export type CreateOIDCAuthIntegrationMutation = (
input: CreateOIDCAuthIntegrationInput
) => Promise<MutationTypes["response"]["createOIDCAuthIntegration"]>;
@@ -1,56 +0,0 @@
import { graphql } from "react-relay";
import { Environment } from "relay-runtime";
import {
commitMutationPromiseNormalized,
createMutationContainer,
} from "talk-framework/lib/relay";
import { Omit } from "talk-framework/types";
import { UpdateOIDCAuthIntegrationMutation as MutationTypes } from "talk-admin/__generated__/UpdateOIDCAuthIntegrationMutation.graphql";
export type UpdateOIDCAuthIntegrationInput = Omit<
MutationTypes["variables"]["input"],
"clientMutationId"
>;
const mutation = graphql`
mutation UpdateOIDCAuthIntegrationMutation(
$input: UpdateOIDCAuthIntegrationInput!
) {
updateOIDCAuthIntegration(input: $input) {
settings {
auth {
...OIDCConfigListContainer_authReadOnly
}
}
clientMutationId
}
}
`;
let clientMutationId = 0;
function commit(
environment: Environment,
input: UpdateOIDCAuthIntegrationInput
) {
return commitMutationPromiseNormalized<MutationTypes>(environment, {
mutation,
variables: {
input: {
...input,
clientMutationId: (clientMutationId++).toString(),
},
},
});
}
export const withUpdateOIDCAuthIntegrationMutation = createMutationContainer(
"updateOIDCAuthIntegration",
commit
);
export type UpdateOIDCAuthIntegrationMutation = (
input: UpdateOIDCAuthIntegrationInput
) => Promise<MutationTypes["response"]["updateOIDCAuthIntegration"]>;
@@ -25,8 +25,8 @@ const mutation = graphql`
...GoogleConfigContainer_authReadOnly
...SSOConfigContainer_auth
...SSOConfigContainer_authReadOnly
...OIDCConfigListContainer_auth
...OIDCConfigListContainer_authReadOnly
...OIDCConfigContainer_auth
...OIDCConfigContainer_authReadOnly
...DisplayNamesConfigContainer_auth
}
}
-8
View File
@@ -20,11 +20,3 @@ export {
withRegenerateSSOKeyMutation,
RegenerateSSOKeyMutation,
} from "./RegenerateSSOKeyMutation";
export {
withCreateOIDCAuthIntegrationMutation,
CreateOIDCAuthIntegrationMutation,
} from "./CreateOIDCAuthIntegrationMutation";
export {
withUpdateOIDCAuthIntegrationMutation,
UpdateOIDCAuthIntegrationMutation,
} from "./UpdateOIDCAuthIntegrationMutation";
@@ -1,9 +1,10 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import Community from "./Community";
it("renders correctly", () => {
const wrapper = shallow(<Community />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Community />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -11,6 +11,7 @@ it("renders correctly", () => {
title: <span>title</span>,
children: "child",
};
const wrapper = shallow(<ConfigBox {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<ConfigBox {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,6 +1,6 @@
import { shallow } from "enzyme";
import { noop } from "lodash";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -11,6 +11,7 @@ it("renders correctly", () => {
onSave: noop,
onChange: noop,
};
const wrapper = shallow(<Configure {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Configure {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -21,7 +21,7 @@ const Configure: StatelessComponent<Props> = ({
onChange,
children,
}) => (
<MainLayout data-test="configure-container">
<MainLayout data-testid="configure-container">
<Form onSubmit={onSave}>
{({ handleSubmit, submitting, pristine, form, submitError }) => (
<form autoComplete="off" onSubmit={handleSubmit} id="configure-form">
@@ -39,7 +39,7 @@ const Configure: StatelessComponent<Props> = ({
<HorizontalGutter size="double">
<Localized id="configure-sideBar-saveChanges">
<Button
data-test="configure-sideBar-saveChanges"
data-testid="configure-sideBar-saveChanges"
color="success"
variant="filled"
type="submit"
@@ -52,7 +52,7 @@ const Configure: StatelessComponent<Props> = ({
<CallOut
color="error"
fullWidth
data-test="configure-auth-submitError"
data-testid="configure-auth-submitError"
>
{submitError}
</CallOut>
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -9,6 +9,7 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof Header> = {
children: "child",
};
const wrapper = shallow(<Header {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Header {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,9 +1,10 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import HorizontalRule from "./HorizontalRule";
it("renders correctly", () => {
const wrapper = shallow(<HorizontalRule />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<HorizontalRule />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -9,6 +9,7 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof Layout> = {
children: "child",
};
const wrapper = shallow(<Layout {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Layout {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -9,6 +9,7 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof Main> = {
children: "child",
};
const wrapper = shallow(<Main {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Main {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -9,6 +9,7 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof Moderation> = {
children: "child",
};
const wrapper = shallow(<Moderation {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Moderation {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -22,6 +22,6 @@
.linkActive {
font-weight: var(--font-weight-bold);
margin-left: 0px;
border-left: calc(0.5 * var(--spacing-unit)) solid var(--palette-brand);
border-left: calc(0.5 * var(--spacing-unit)) solid var(--palette-brand-main);
padding-left: var(--spacing-unit);
}
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -11,6 +11,7 @@ it("renders correctly", () => {
to: "/admin",
children: "child",
};
const wrapper = shallow(<Link {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Link {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -9,6 +9,7 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof Navigation> = {
children: "child",
};
const wrapper = shallow(<Navigation {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Navigation {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -9,6 +9,7 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof SideBar> = {
children: "child",
};
const wrapper = shallow(<SideBar {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<SideBar {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -2,12 +2,12 @@
exports[`renders correctly 1`] = `
<MainLayout
data-test="configure-container"
data-testid="configure-container"
>
<ReactFinalForm
onSubmit={[Function]}
>
<Component />
[Function]
</ReactFinalForm>
</MainLayout>
`;
@@ -81,7 +81,9 @@ class ConfigureContainer extends React.Component<Props> {
executeCallbacks.push(() =>
this.props.updateSettings({ settings: nextData })
);
await Promise.all(executeCallbacks.map(cb => cb()));
for (const c of executeCallbacks.map(cb => cb())) {
await c;
}
form.initialize(data);
} catch (error) {
if (error instanceof BadUserInputError) {
@@ -8,7 +8,7 @@ import Header from "../../../components/Header";
import FacebookConfigContainer from "../containers/FacebookConfigContainer";
import GoogleConfigContainer from "../containers/GoogleConfigContainer";
import LocalAuthConfigContainer from "../containers/LocalAuthConfigContainer";
import OIDCConfigListContainer from "../containers/OIDCConfigListContainer";
import OIDCConfigContainer from "../containers/OIDCConfigContainer";
import SSOConfigContainer from "../containers/SSOConfigContainer";
interface Props {
@@ -20,8 +20,8 @@ interface Props {
PropTypesOf<typeof SSOConfigContainer>["auth"] &
PropTypesOf<typeof SSOConfigContainer>["authReadOnly"] &
PropTypesOf<typeof LocalAuthConfigContainer>["auth"] &
PropTypesOf<typeof OIDCConfigListContainer>["auth"] &
PropTypesOf<typeof OIDCConfigListContainer>["authReadOnly"];
PropTypesOf<typeof OIDCConfigContainer>["auth"] &
PropTypesOf<typeof OIDCConfigContainer>["authReadOnly"];
onInitValues: (values: any) => void;
}
@@ -39,7 +39,7 @@ const AuthIntegrationsConfig: StatelessComponent<Props> = ({
auth={auth}
onInitValues={onInitValues}
/>
<OIDCConfigListContainer
<OIDCConfigContainer
disabled={disabled}
auth={auth}
authReadOnly={auth}
@@ -38,7 +38,7 @@ const FacebookConfig: StatelessComponent<Props> = ({
callbackURL,
}) => (
<ConfigBoxWithToggleField
data-test="configure-auth-facebook-container"
data-testid="configure-auth-facebook-container"
title={
<Localized id="configure-auth-facebook-loginWith">
<span>Login with Facebook</span>
@@ -1,4 +0,0 @@
.redirectDescriptionIcon {
color: var(--palette-text-secondary);
flex-shrink: 0;
}
@@ -14,7 +14,6 @@ import {
Flex,
FormField,
HorizontalGutter,
Icon,
InputLabel,
TextField,
TextLink,
@@ -31,10 +30,7 @@ import RegistrationField from "./RegistrationField";
import TargetFilterField from "./TargetFilterField";
import ValidationMessage from "./ValidationMessage";
import styles from "./OIDCConfig.css";
interface Props {
index: number;
disabled?: boolean;
callbackURL: string;
disableForDiscover?: boolean;
@@ -48,7 +44,6 @@ const OIDCLink = () => (
const OIDCConfig: StatelessComponent<Props> = ({
disabled,
callbackURL,
index,
onDiscover,
disableForDiscover,
}) => {
@@ -56,20 +51,20 @@ const OIDCConfig: StatelessComponent<Props> = ({
v,
values
) => {
if (values.auth.integrations.oidc[0].enabled) {
if (values.auth.integrations.oidc.enabled) {
return validator(v, values);
}
return "";
};
return (
<ConfigBoxWithToggleField
data-test={`configure-auth-oidc-container-${index}`}
data-testid={`configure-auth-oidc-container`}
title={
<Localized id="configure-auth-oidc-loginWith">
<span>Login with OIDC</span>
</Localized>
}
name={`auth.integrations.oidc.${index}.enabled`}
name={`auth.integrations.oidc.enabled`}
disabled={disabled}
>
{disabledInside => (
@@ -80,22 +75,7 @@ const OIDCConfig: StatelessComponent<Props> = ({
</Typography>
</Localized>
<HorizontalRule />
<RedirectField
url={callbackURL}
description={
<ConfigDescription container="div">
<Flex itemGutter="half">
<Icon className={styles.redirectDescriptionIcon}>error</Icon>
<Localized id="configure-auth-oidc-redirectDescription">
<div>
For OpenID Connect, your Redirect URI will not appear
until you after you save this integration
</div>
</Localized>
</Flex>
</ConfigDescription>
}
/>
<RedirectField url={callbackURL} />
<HorizontalRule />
<FormField>
<Localized id="configure-auth-oidc-providerName">
@@ -109,7 +89,7 @@ const OIDCConfig: StatelessComponent<Props> = ({
</ConfigDescription>
</Localized>
<Field
name={`auth.integrations.oidc.${index}.name`}
name={`auth.integrations.oidc.name`}
validate={validateWhenEnabled(required)}
parse={identity}
>
@@ -137,12 +117,12 @@ const OIDCConfig: StatelessComponent<Props> = ({
</FormField>
<ClientIDField
validate={validateWhenEnabled(required)}
name={`auth.integrations.oidc.${index}.clientID`}
name={`auth.integrations.oidc.clientID`}
disabled={disabledInside}
/>
<ClientSecretField
validate={validateWhenEnabled(required)}
name={`auth.integrations.oidc.${index}.clientSecret`}
name={`auth.integrations.oidc.clientSecret`}
disabled={disabledInside}
/>
<FormField>
@@ -157,7 +137,7 @@ const OIDCConfig: StatelessComponent<Props> = ({
</ConfigDescription>
</Localized>
<Field
name={`auth.integrations.oidc.${index}.issuer`}
name={`auth.integrations.oidc.issuer`}
validate={validateWhenEnabled(
composeValidators(required, validateURL)
)}
@@ -177,7 +157,7 @@ const OIDCConfig: StatelessComponent<Props> = ({
spellCheck={false}
/>
<Button
id="configure-auth-oidc-discover-0"
id="configure-auth-oidc-discover"
variant="filled"
color="primary"
size="small"
@@ -202,7 +182,7 @@ const OIDCConfig: StatelessComponent<Props> = ({
<InputLabel>authorizationURL</InputLabel>
</Localized>
<Field
name={`auth.integrations.oidc.${index}.authorizationURL`}
name={`auth.integrations.oidc.authorizationURL`}
validate={validateWhenEnabled(
composeValidators(required, validateURL)
)}
@@ -235,7 +215,7 @@ const OIDCConfig: StatelessComponent<Props> = ({
<InputLabel>tokenURL</InputLabel>
</Localized>
<Field
name={`auth.integrations.oidc.${index}.tokenURL`}
name={`auth.integrations.oidc.tokenURL`}
validate={validateWhenEnabled(
composeValidators(required, validateURL)
)}
@@ -268,7 +248,7 @@ const OIDCConfig: StatelessComponent<Props> = ({
<InputLabel>jwksURI</InputLabel>
</Localized>
<Field
name={`auth.integrations.oidc.${index}.jwksURI`}
name={`auth.integrations.oidc.jwksURI`}
validate={validateWhenEnabled(
composeValidators(required, validateURL)
)}
@@ -302,11 +282,11 @@ const OIDCConfig: StatelessComponent<Props> = ({
<span>Use OIDC login on</span>
</Localized>
}
name={`auth.integrations.oidc.${index}.targetFilter`}
name={`auth.integrations.oidc.targetFilter`}
disabled={disabledInside}
/>
<RegistrationField
name={`auth.integrations.oidc.${index}.allowRegistration`}
name={`auth.integrations.oidc.allowRegistration`}
disabled={disabledInside}
/>
</HorizontalGutter>
@@ -26,7 +26,7 @@ const SSOKeyField: StatelessComponent<Props> = ({
disabled,
onRegenerate,
}) => (
<FormField data-test="configure-auth-sso-key">
<FormField data-testid="configure-auth-sso-key">
<Localized id="configure-auth-sso-key">
<InputLabel>Key</InputLabel>
</Localized>
@@ -49,7 +49,7 @@ export default class AuthContainer extends React.Component<Props> {
get(data, "auth.integrations.facebook"),
get(data, "auth.integrations.sso"),
get(data, "auth.integrations.local"),
...(get(data, "auth.integrations.oidc") || []),
get(data, "auth.integrations.oidc"),
];
if (!integrations.some((i: any) => i.enabled && i.targetFilter.admin)) {
cancel({
@@ -111,8 +111,8 @@ AuthContainer.routeConfig = {
...SSOConfigContainer_authReadOnly
...LocalAuthConfigContainer_auth
...DisplayNamesConfigContainer_auth
...OIDCConfigListContainer_auth
...OIDCConfigListContainer_authReadOnly
...OIDCConfigContainer_auth
...OIDCConfigContainer_authReadOnly
}
}
}
@@ -1,17 +1,22 @@
import { FormApi } from "final-form";
import PropTypes from "prop-types";
import React from "react";
import { graphql } from "react-relay";
import { OIDCConfigContainer_auth as AuthData } from "talk-admin/__generated__/OIDCConfigContainer_auth.graphql";
import { OIDCConfigContainer_authReadOnly as AuthReadOnlyData } from "talk-admin/__generated__/OIDCConfigContainer_authReadOnly.graphql";
import {
DiscoverOIDCConfigurationFetch,
withDiscoverOIDCConfigurationFetch,
} from "talk-admin/fetches";
import { withFragmentContainer } from "talk-framework/lib/relay";
import OIDCConfig from "../components/OIDCConfig";
interface Props {
index: number;
callbackURL: string;
auth: AuthData;
authReadOnly: AuthReadOnlyData;
onInitValues: (values: AuthData) => void;
disabled?: boolean;
discoverOIDCConfiguration: DiscoverOIDCConfigurationFetch;
}
@@ -34,15 +39,15 @@ class OIDCConfigContainer extends React.Component<Props, State> {
this.setState({ awaitingResponse: true });
try {
const config = await this.props.discoverOIDCConfiguration({
issuer: form.getState().values.auth.integrations.oidc[0].issuer,
issuer: form.getState().values.auth.integrations.oidc.issuer,
});
if (config) {
form.change(
"auth.integrations.oidc.0.authorizationURL",
"auth.integrations.oidc.authorizationURL",
config.authorizationURL
);
form.change("auth.integrations.oidc.0.jwksURI", config.jwksURI);
form.change("auth.integrations.oidc.0.tokenURL", config.tokenURL);
form.change("auth.integrations.oidc.jwksURI", config.jwksURI);
form.change("auth.integrations.oidc.tokenURL", config.tokenURL);
}
} catch (error) {
// tslint:disable-next-line:no-console
@@ -51,13 +56,17 @@ class OIDCConfigContainer extends React.Component<Props, State> {
this.setState({ awaitingResponse: false });
};
constructor(props: Props) {
super(props);
props.onInitValues(props.auth);
}
public render() {
const { disabled, index, callbackURL } = this.props;
const { disabled, authReadOnly } = this.props;
return (
<OIDCConfig
disabled={disabled}
index={index}
callbackURL={callbackURL}
callbackURL={authReadOnly.integrations.oidc.callbackURL}
onDiscover={this.handleDiscover}
disableForDiscover={this.state.awaitingResponse}
/>
@@ -65,6 +74,39 @@ class OIDCConfigContainer extends React.Component<Props, State> {
}
}
const enhanced = withDiscoverOIDCConfigurationFetch(OIDCConfigContainer);
const enhanced = withDiscoverOIDCConfigurationFetch(
withFragmentContainer<Props>({
auth: graphql`
fragment OIDCConfigContainer_auth on Auth {
integrations {
oidc {
enabled
allowRegistration
targetFilter {
admin
stream
}
name
clientID
clientSecret
authorizationURL
tokenURL
jwksURI
issuer
}
}
}
`,
authReadOnly: graphql`
fragment OIDCConfigContainer_authReadOnly on Auth {
integrations {
oidc {
callbackURL
}
}
}
`,
})(OIDCConfigContainer)
);
export default enhanced;
@@ -1,154 +0,0 @@
import { cloneDeep } from "lodash";
import React from "react";
import { graphql } from "react-relay";
import { OIDCConfigListContainer_auth as AuthData } from "talk-admin/__generated__/OIDCConfigListContainer_auth.graphql";
import { OIDCConfigListContainer_authReadOnly as AuthReadOnlyData } from "talk-admin/__generated__/OIDCConfigListContainer_authReadOnly.graphql";
import {
CreateOIDCAuthIntegrationMutation,
UpdateOIDCAuthIntegrationMutation,
withCreateOIDCAuthIntegrationMutation,
withUpdateOIDCAuthIntegrationMutation,
} from "talk-admin/mutations";
import { withFragmentContainer } from "talk-framework/lib/relay";
import {
AddSubmitHook,
RemoveSubmitHook,
SubmitHook,
withSubmitHookContext,
} from "../../../submitHook";
import OIDCConfigContainer from "./OIDCConfigContainer";
interface Props {
auth: AuthData;
authReadOnly: AuthReadOnlyData;
disabled?: boolean;
addSubmitHook: AddSubmitHook;
onInitValues: (values: AuthData) => void;
createOIDCAuthIntegration: CreateOIDCAuthIntegrationMutation;
updateOIDCAuthIntegration: UpdateOIDCAuthIntegrationMutation;
}
class OIDCConfigListContainer extends React.Component<Props> {
private removeSubmitHook: RemoveSubmitHook;
constructor(props: Props) {
super(props);
props.onInitValues(this.getAuthWithDefault());
this.removeSubmitHook = this.props.addSubmitHook(this.submitHook);
}
public componentWillUnmount() {
this.removeSubmitHook();
}
private submitHook: SubmitHook = async (data: any, { onExecute }) => {
const cloned = cloneDeep(data);
const oidc = cloned.auth.integrations.oidc;
delete cloned.auth.integrations.oidc;
if (this.props.auth.integrations.oidc.length === 0) {
if (oidc[0].enabled) {
onExecute(() =>
this.props.createOIDCAuthIntegration({ configuration: oidc[0] })
);
}
} else {
onExecute(() =>
this.props.updateOIDCAuthIntegration({
configuration: oidc[0],
id: this.props.authReadOnly.integrations.oidc[0].id,
})
);
}
return cloned;
};
private getAuthWithDefault(): AuthData {
return this.props.auth.integrations.oidc.length === 0
? ({
integrations: {
oidc: [
{
clientID: "",
clientSecret: "",
allowRegistration: false,
targetFilter: {
admin: true,
stream: true,
},
name: "",
authorizationURL: "",
tokenURL: "",
jwksURI: "",
issuer: "",
},
],
},
} as any)
: this.props.auth;
}
public render() {
const { disabled, authReadOnly } = this.props;
const integrations = this.getAuthWithDefault().integrations.oidc.map(
(data, i) => (
<OIDCConfigContainer
key={i}
disabled={disabled}
index={i}
callbackURL={
(authReadOnly.integrations.oidc[i] &&
authReadOnly.integrations.oidc[i].callbackURL) ||
""
}
/>
)
);
return <>{integrations}</>;
}
}
const enhanced = withFragmentContainer<Props>({
auth: graphql`
fragment OIDCConfigListContainer_auth on Auth {
integrations {
oidc {
enabled
allowRegistration
targetFilter {
admin
stream
}
name
clientID
clientSecret
authorizationURL
tokenURL
jwksURI
issuer
}
}
}
`,
authReadOnly: graphql`
fragment OIDCConfigListContainer_authReadOnly on Auth {
integrations {
oidc {
id
callbackURL
}
}
}
`,
})(
withCreateOIDCAuthIntegrationMutation(
withUpdateOIDCAuthIntegrationMutation(
withSubmitHookContext(addSubmitHook => ({ addSubmitHook }))(
OIDCConfigListContainer
)
)
)
);
export default enhanced;
@@ -1,9 +1,10 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import Login from "./Login";
it("renders correctly", () => {
const wrapper = shallow(<Login />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Login />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -4,12 +4,12 @@ import { Field, Form } from "react-final-form";
import { OnSubmit } from "talk-framework/lib/form";
import { PasswordField } from "talk-framework/components";
import {
composeValidators,
required,
validateEmail,
} from "talk-framework/lib/validation";
import {
Button,
CallOut,
@@ -87,12 +87,11 @@ const SignIn: StatelessComponent<Props> = props => (
id="login-signIn-passwordTextField"
attrs={{ placeholder: true }}
>
<TextField
<PasswordField
name={input.name}
onChange={input.onChange}
value={input.value}
placeholder="Password"
type="password"
color={
meta.touched && (meta.error || meta.submitError)
? "error"
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import AcceptButton from "./AcceptButton";
@@ -9,14 +9,16 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof AcceptButton> = {
invert: false,
};
const wrapper = shallow(<AcceptButton {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<AcceptButton {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders correctly inverted", () => {
const props: PropTypesOf<typeof AcceptButton> = {
invert: true,
};
const wrapper = shallow(<AcceptButton {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<AcceptButton {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import CommentContent from "./CommentContent";
@@ -12,8 +12,9 @@ it("renders correctly", () => {
className: "custom",
children: "Hello <strong>idiot</strong>, you fucking bastard",
};
const wrapper = shallow(<CommentContent {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<CommentContent {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders empty words correctly", () => {
@@ -23,6 +24,7 @@ it("renders empty words correctly", () => {
className: "custom",
children: "Hello <strong>idiot</strong>, you fucking bastard",
};
const wrapper = shallow(<CommentContent {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<CommentContent {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -9,6 +9,7 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof InReplyTo> = {
children: "Username",
};
const wrapper = shallow(<InReplyTo {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<InReplyTo {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -3,7 +3,7 @@ import React, { StatelessComponent } from "react";
import { Flex, Spinner } from "talk-ui/components";
const LoadingQueue: StatelessComponent = () => (
<Flex justifyContent="center" data-test="loading-moderate-container">
<Flex justifyContent="center" data-testid="loading-moderate-container">
<Spinner />
</Flex>
);
@@ -1,12 +1,13 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import Moderate from "./Moderate";
import { PropTypesOf } from "talk-framework/types";
it("renders correctly", () => {
const wrapper = shallow(<Moderate />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Moderate />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders correctly with counts", () => {
@@ -15,6 +16,7 @@ it("renders correctly with counts", () => {
reportedCount: 4,
pendingCount: 0,
};
const wrapper = shallow(<Moderate {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Moderate {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -20,8 +20,8 @@ const Moderate: StatelessComponent<Props> = ({
pendingCount,
children,
}) => (
<div data-test="moderate-container">
<SubBar data-test="moderate-subBar-container">
<div data-testid="moderate-container">
<SubBar data-testid="moderate-subBar-container">
<Navigation
unmoderatedCount={unmoderatedCount}
reportedCount={reportedCount}
@@ -29,7 +29,7 @@ const Moderate: StatelessComponent<Props> = ({
/>
</SubBar>
<div className={styles.background} />
<MainLayout data-test="moderate-main-container">
<MainLayout data-testid="moderate-main-container">
<main className={styles.main}>{children}</main>
</MainLayout>
</div>
@@ -1,6 +1,6 @@
import { shallow } from "enzyme";
import { noop } from "lodash";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { removeFragmentRefs } from "talk-framework/testHelpers";
import { PropTypesOf } from "talk-framework/types";
@@ -28,8 +28,9 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof ModerateCardN> = {
...baseProps,
};
const wrapper = shallow(<ModerateCardN {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<ModerateCardN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders reply correctly", () => {
@@ -37,8 +38,9 @@ it("renders reply correctly", () => {
...baseProps,
inReplyTo: "Julian",
};
const wrapper = shallow(<ModerateCardN {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<ModerateCardN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders accepted correctly", () => {
@@ -46,8 +48,9 @@ it("renders accepted correctly", () => {
...baseProps,
status: "accepted",
};
const wrapper = shallow(<ModerateCardN {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<ModerateCardN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders rejected correctly", () => {
@@ -55,8 +58,9 @@ it("renders rejected correctly", () => {
...baseProps,
status: "rejected",
};
const wrapper = shallow(<ModerateCardN {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<ModerateCardN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders dangling correctly", () => {
@@ -64,6 +68,7 @@ it("renders dangling correctly", () => {
...baseProps,
dangling: true,
};
const wrapper = shallow(<ModerateCardN {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<ModerateCardN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -53,7 +53,7 @@ const ModerateCard: StatelessComponent<Props> = ({
}) => (
<Card
className={cn(styles.root, { [styles.dangling]: dangling })}
data-test={`moderate-comment-${id}`}
data-testid={`moderate-comment-${id}`}
>
<Flex>
<div className={styles.mainContainer}>
@@ -1,12 +1,13 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import Navigation from "./Navigation";
import { PropTypesOf } from "talk-framework/types";
it("renders correctly", () => {
const wrapper = shallow(<Navigation />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Navigation />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders correctly with counts", () => {
@@ -15,6 +16,7 @@ it("renders correctly with counts", () => {
reportedCount: 4,
pendingCount: 0,
};
const wrapper = shallow(<Navigation {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Navigation {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -24,7 +24,7 @@ const Navigation: StatelessComponent<Props> = ({
<span>Reported</span>
</Localized>
{reportedCount !== undefined && (
<Counter data-test="moderate-navigation-reported-count">
<Counter data-testid="moderate-navigation-reported-count">
{reportedCount}
</Counter>
)}
@@ -35,7 +35,7 @@ const Navigation: StatelessComponent<Props> = ({
<span>Pending</span>
</Localized>
{pendingCount !== undefined && (
<Counter data-test="moderate-navigation-pending-count">
<Counter data-testid="moderate-navigation-pending-count">
{pendingCount}
</Counter>
)}
@@ -46,7 +46,7 @@ const Navigation: StatelessComponent<Props> = ({
<span>Unmoderated</span>
</Localized>
{unmoderatedCount !== undefined && (
<Counter data-test="moderate-navigation-unmoderated-count">
<Counter data-testid="moderate-navigation-unmoderated-count">
{unmoderatedCount}
</Counter>
)}
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -10,6 +10,7 @@ it("renders correctly", () => {
to: "/moderate",
children: "link",
};
const wrapper = shallow(<NavigationLink {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<NavigationLink {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,6 +1,6 @@
import { shallow } from "enzyme";
import { noop } from "lodash";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { removeFragmentRefs } from "talk-framework/testHelpers";
import { PropTypesOf } from "talk-framework/types";
@@ -18,8 +18,9 @@ it("renders correctly with load more", () => {
disableLoadMore: false,
danglingLogic: () => true,
};
const wrapper = shallow(<QueueN {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<QueueN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders correctly without load more", () => {
@@ -31,6 +32,7 @@ it("renders correctly without load more", () => {
disableLoadMore: false,
danglingLogic: () => true,
};
const wrapper = shallow(<QueueN {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<QueueN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import RejectButton from "./RejectButton";
@@ -9,14 +9,16 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof RejectButton> = {
invert: false,
};
const wrapper = shallow(<RejectButton {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<RejectButton {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders correctly inverted", () => {
const props: PropTypesOf<typeof RejectButton> = {
invert: true,
};
const wrapper = shallow(<RejectButton {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<RejectButton {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -9,6 +9,7 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof SingleModerate> = {
children: "singe comment queue",
};
const wrapper = shallow(<SingleModerate {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<SingleModerate {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -12,7 +12,7 @@ interface Props {
}
const Moderate: StatelessComponent<Props> = ({ children }) => (
<div data-test="single-moderate-container">
<div data-testid="single-moderate-container">
<SubBar className={styles.subBar} gutterBegin gutterEnd>
<Localized id="moderate-single-goToModerationQueues">
<Link className={styles.subBarBegin} to="/admin/moderate/">
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -9,6 +9,7 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof Timestamp> = {
children: "1995-12-17T03:24:00.000Z",
};
const wrapper = shallow(<Timestamp {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Timestamp {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -2,10 +2,10 @@
exports[`renders correctly 1`] = `
<div
data-test="moderate-container"
data-testid="moderate-container"
>
<withPropsOnChange(SubBar)
data-test="moderate-subBar-container"
data-testid="moderate-subBar-container"
>
<Navigation />
</withPropsOnChange(SubBar)>
@@ -13,7 +13,7 @@ exports[`renders correctly 1`] = `
className="Moderate-background"
/>
<MainLayout
data-test="moderate-main-container"
data-testid="moderate-main-container"
>
<main
className="Moderate-main"
@@ -24,10 +24,10 @@ exports[`renders correctly 1`] = `
exports[`renders correctly with counts 1`] = `
<div
data-test="moderate-container"
data-testid="moderate-container"
>
<withPropsOnChange(SubBar)
data-test="moderate-subBar-container"
data-testid="moderate-subBar-container"
>
<Navigation
pendingCount={0}
@@ -39,7 +39,7 @@ exports[`renders correctly with counts 1`] = `
className="Moderate-background"
/>
<MainLayout
data-test="moderate-main-container"
data-testid="moderate-main-container"
>
<main
className="Moderate-main"
@@ -3,7 +3,7 @@
exports[`renders accepted correctly 1`] = `
<withPropsOnChange(Card)
className="ModerateCard-root"
data-test="moderate-comment-comment-id"
data-testid="moderate-comment-comment-id"
>
<withPropsOnChange(Flex)>
<div
@@ -112,7 +112,7 @@ exports[`renders accepted correctly 1`] = `
exports[`renders correctly 1`] = `
<withPropsOnChange(Card)
className="ModerateCard-root"
data-test="moderate-comment-comment-id"
data-testid="moderate-comment-comment-id"
>
<withPropsOnChange(Flex)>
<div
@@ -220,7 +220,7 @@ exports[`renders correctly 1`] = `
exports[`renders dangling correctly 1`] = `
<withPropsOnChange(Card)
className="ModerateCard-root ModerateCard-dangling"
data-test="moderate-comment-comment-id"
data-testid="moderate-comment-comment-id"
>
<withPropsOnChange(Flex)>
<div
@@ -330,7 +330,7 @@ exports[`renders dangling correctly 1`] = `
exports[`renders rejected correctly 1`] = `
<withPropsOnChange(Card)
className="ModerateCard-root"
data-test="moderate-comment-comment-id"
data-testid="moderate-comment-comment-id"
>
<withPropsOnChange(Flex)>
<div
@@ -439,7 +439,7 @@ exports[`renders rejected correctly 1`] = `
exports[`renders reply correctly 1`] = `
<withPropsOnChange(Card)
className="ModerateCard-root"
data-test="moderate-comment-comment-id"
data-testid="moderate-comment-comment-id"
>
<withPropsOnChange(Flex)>
<div
@@ -77,7 +77,7 @@ exports[`renders correctly with counts 1`] = `
</span>
</Localized>
<withPropsOnChange(Counter)
data-test="moderate-navigation-reported-count"
data-testid="moderate-navigation-reported-count"
>
4
</withPropsOnChange(Counter)>
@@ -96,7 +96,7 @@ exports[`renders correctly with counts 1`] = `
</span>
</Localized>
<withPropsOnChange(Counter)
data-test="moderate-navigation-pending-count"
data-testid="moderate-navigation-pending-count"
>
0
</withPropsOnChange(Counter)>
@@ -115,7 +115,7 @@ exports[`renders correctly with counts 1`] = `
</span>
</Localized>
<withPropsOnChange(Counter)
data-test="moderate-navigation-unmoderated-count"
data-testid="moderate-navigation-unmoderated-count"
>
3
</withPropsOnChange(Counter)>
@@ -2,7 +2,7 @@
exports[`renders correctly 1`] = `
<div
data-test="single-moderate-container"
data-testid="single-moderate-container"
>
<withPropsOnChange(SubBar)
className="SingleModerate-subBar"
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { removeFragmentRefs } from "talk-framework/testHelpers";
import { PropTypesOf } from "talk-framework/types";
@@ -28,8 +28,9 @@ it("renders all markers", () => {
},
},
};
const wrapper = shallow(<MarkersContainerN {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<MarkersContainerN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders some markers", () => {
@@ -52,6 +53,7 @@ it("renders some markers", () => {
},
},
};
const wrapper = shallow(<MarkersContainerN {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<MarkersContainerN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -4,7 +4,6 @@ exports[`renders all markers 1`] = `
Array [
<Localized
id="moderate-marker-preMod"
key="0"
>
<withPropsOnChange(Marker)
color="primary"
@@ -14,7 +13,6 @@ Array [
</Localized>,
<Localized
id="moderate-marker-link"
key="1"
>
<withPropsOnChange(Marker)
color="primary"
@@ -24,7 +22,6 @@ Array [
</Localized>,
<Localized
id="moderate-marker-bannedWord"
key="2"
>
<withPropsOnChange(Marker)
color="error"
@@ -34,7 +31,6 @@ Array [
</Localized>,
<Localized
id="moderate-marker-suspectWord"
key="3"
>
<withPropsOnChange(Marker)
color="error"
@@ -45,7 +41,6 @@ Array [
</Localized>,
<Localized
id="moderate-marker-spam"
key="4"
>
<withPropsOnChange(Marker)
color="error"
@@ -55,7 +50,6 @@ Array [
</Localized>,
<Localized
id="moderate-marker-toxic"
key="5"
>
<withPropsOnChange(Marker)
color="error"
@@ -65,7 +59,6 @@ Array [
</Localized>,
<Localized
id="moderate-marker-karma"
key="6"
>
<withPropsOnChange(Marker)
color="error"
@@ -75,7 +68,6 @@ Array [
</Localized>,
<withPropsOnChange(Marker)
color="error"
key="7"
>
<Localized
id="moderate-marker-offensive"
@@ -91,7 +83,6 @@ Array [
</withPropsOnChange(Marker)>,
<withPropsOnChange(Marker)
color="error"
key="8"
>
<Localized
id="moderate-marker-spam"
@@ -112,7 +103,6 @@ exports[`renders some markers 1`] = `
Array [
<Localized
id="moderate-marker-preMod"
key="9"
>
<withPropsOnChange(Marker)
color="primary"
@@ -120,10 +110,9 @@ Array [
Pre-Mod
</withPropsOnChange(Marker)>
</Localized>,
"",
null,
<Localized
id="moderate-marker-bannedWord"
key="10"
>
<withPropsOnChange(Marker)
color="error"
@@ -131,11 +120,10 @@ Array [
Banned Word
</withPropsOnChange(Marker)>
</Localized>,
"",
"",
null,
null,
<Localized
id="moderate-marker-toxic"
key="11"
>
<withPropsOnChange(Marker)
color="error"
@@ -145,7 +133,6 @@ Array [
</Localized>,
<Localized
id="moderate-marker-karma"
key="12"
>
<withPropsOnChange(Marker)
color="error"
@@ -155,7 +142,6 @@ Array [
</Localized>,
<withPropsOnChange(Marker)
color="error"
key="13"
>
<Localized
id="moderate-marker-offensive"
@@ -169,6 +155,6 @@ Array [
2
</withPropsOnChange(Count)>
</withPropsOnChange(Marker)>,
"",
null,
]
`;
@@ -1,9 +1,10 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import Stories from "./Stories";
it("renders correctly", () => {
const wrapper = shallow(<Stories />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Stories />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -121,15 +121,37 @@ exports[`accepts correct password 1`] = `
>
Password
</label>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
disabled={false}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value="testtest"
/>
<div
className="PasswordField-fullWidth PasswordField-root"
>
<div
className="PasswordField-wrapper"
>
<input
className="PasswordField-colorRegular PasswordField-fullWidth PasswordField-input"
disabled={false}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value="testtest"
/>
<div
className="PasswordField-icon"
onClick={[Function]}
role="button"
tabIndex={0}
title="Show password"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
visibility
</span>
</div>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeLarge Button-colorPrimary Button-variantFilled Button-fullWidth"
@@ -258,15 +280,37 @@ exports[`accepts valid email 1`] = `
>
Password
</label>
<input
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value=""
/>
<div
className="PasswordField-fullWidth PasswordField-root"
>
<div
className="PasswordField-wrapper"
>
<input
className="PasswordField-colorError PasswordField-fullWidth PasswordField-input"
disabled={false}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value=""
/>
<div
className="PasswordField-icon"
onClick={[Function]}
role="button"
tabIndex={0}
title="Show password"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
visibility
</span>
</div>
</div>
</div>
<div
className="Message-root Message-colorError Message-fullWidth"
>
@@ -421,15 +465,37 @@ exports[`checks for invalid email 1`] = `
>
Password
</label>
<input
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value=""
/>
<div
className="PasswordField-fullWidth PasswordField-root"
>
<div
className="PasswordField-wrapper"
>
<input
className="PasswordField-colorError PasswordField-fullWidth PasswordField-input"
disabled={false}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value=""
/>
<div
className="PasswordField-icon"
onClick={[Function]}
role="button"
tabIndex={0}
title="Show password"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
visibility
</span>
</div>
</div>
</div>
<div
className="Message-root Message-colorError Message-fullWidth"
>
@@ -571,15 +637,37 @@ exports[`renders sign in form 1`] = `
>
Password
</label>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
disabled={false}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value=""
/>
<div
className="PasswordField-fullWidth PasswordField-root"
>
<div
className="PasswordField-wrapper"
>
<input
className="PasswordField-colorRegular PasswordField-fullWidth PasswordField-input"
disabled={false}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value=""
/>
<div
className="PasswordField-icon"
onClick={[Function]}
role="button"
tabIndex={0}
title="Show password"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
visibility
</span>
</div>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeLarge Button-colorPrimary Button-variantFilled Button-fullWidth"
@@ -721,15 +809,37 @@ exports[`shows error when submitting empty form 1`] = `
>
Password
</label>
<input
className="TextField-root TextField-colorError TextField-fullWidth"
disabled={false}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value=""
/>
<div
className="PasswordField-fullWidth PasswordField-root"
>
<div
className="PasswordField-wrapper"
>
<input
className="PasswordField-colorError PasswordField-fullWidth PasswordField-input"
disabled={false}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value=""
/>
<div
className="PasswordField-icon"
onClick={[Function]}
role="button"
tabIndex={0}
title="Show password"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
visibility
</span>
</div>
</div>
</div>
<div
className="Message-root Message-colorError Message-fullWidth"
>
@@ -871,15 +981,37 @@ exports[`shows server error 1`] = `
>
Password
</label>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
disabled={true}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value="testtest"
/>
<div
className="PasswordField-fullWidth PasswordField-root"
>
<div
className="PasswordField-wrapper"
>
<input
className="PasswordField-colorRegular PasswordField-fullWidth PasswordField-input"
disabled={true}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value="testtest"
/>
<div
className="PasswordField-icon"
onClick={[Function]}
role="button"
tabIndex={0}
title="Show password"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
visibility
</span>
</div>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeLarge Button-colorPrimary Button-variantFilled Button-fullWidth Button-disabled"
@@ -1013,15 +1145,37 @@ exports[`shows server error 2`] = `
>
Password
</label>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
disabled={false}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value="testtest"
/>
<div
className="PasswordField-fullWidth PasswordField-root"
>
<div
className="PasswordField-wrapper"
>
<input
className="PasswordField-colorRegular PasswordField-fullWidth PasswordField-input"
disabled={false}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value="testtest"
/>
<div
className="PasswordField-icon"
onClick={[Function]}
role="button"
tabIndex={0}
title="Show password"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
visibility
</span>
</div>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeLarge Button-colorPrimary Button-variantFilled Button-fullWidth"
@@ -1150,15 +1304,37 @@ exports[`submits form successfully 1`] = `
>
Password
</label>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
disabled={true}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value="testtest"
/>
<div
className="PasswordField-fullWidth PasswordField-root"
>
<div
className="PasswordField-wrapper"
>
<input
className="PasswordField-colorRegular PasswordField-fullWidth PasswordField-input"
disabled={true}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value="testtest"
/>
<div
className="PasswordField-icon"
onClick={[Function]}
role="button"
tabIndex={0}
title="Show password"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
visibility
</span>
</div>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeLarge Button-colorPrimary Button-variantFilled Button-fullWidth Button-disabled"
@@ -1287,15 +1463,37 @@ exports[`submits form successfully 2`] = `
>
Password
</label>
<input
className="TextField-root TextField-colorRegular TextField-fullWidth"
disabled={false}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value=""
/>
<div
className="PasswordField-fullWidth PasswordField-root"
>
<div
className="PasswordField-wrapper"
>
<input
className="PasswordField-colorRegular PasswordField-fullWidth PasswordField-input"
disabled={false}
name="password"
onChange={[Function]}
placeholder="Password"
type="password"
value=""
/>
<div
className="PasswordField-icon"
onClick={[Function]}
role="button"
tabIndex={0}
title="Show password"
>
<span
aria-hidden="true"
className="Icon-root Icon-sm"
>
visibility
</span>
</div>
</div>
</div>
</div>
<button
className="BaseButton-root Button-root Button-sizeLarge Button-colorPrimary Button-variantFilled Button-fullWidth"
@@ -3,7 +3,7 @@
exports[`change settings: during submit: oidc without errors 1`] = `
<div
className="ConfigBox-root"
data-test="configure-auth-oidc-container-0"
data-testid="configure-auth-oidc-container"
>
<div
className="Flex-root ConfigBox-title Flex-flex Flex-justifySpaceBetween"
@@ -24,8 +24,8 @@ exports[`change settings: during submit: oidc without errors 1`] = `
checked={true}
className="CheckBox-input"
disabled={true}
id="auth.integrations.oidc.0.enabled"
name="auth.integrations.oidc.0.enabled"
id="auth.integrations.oidc.enabled"
name="auth.integrations.oidc.enabled"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
@@ -33,7 +33,7 @@ exports[`change settings: during submit: oidc without errors 1`] = `
/>
<label
className="CheckBox-label CheckBox-labelLight"
htmlFor="auth.integrations.oidc.0.enabled"
htmlFor="auth.integrations.oidc.enabled"
>
<span
className="CheckBox-labelSpan"
@@ -74,23 +74,6 @@ exports[`change settings: during submit: oidc without errors 1`] = `
>
Redirect URI
</label>
<div
className="Typography-root Typography-detail Typography-colorTextSecondary ConfigDescription-description"
>
<div
className="Flex-root Flex-flex Flex-halfItemGutter"
>
<span
aria-hidden="true"
className="Icon-root OIDCConfig-redirectDescriptionIcon Icon-sm"
>
error
</span>
<div>
For OpenID Connect, your Redirect URI will not appear until you after you save this integration.
</div>
</div>
</div>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
@@ -100,7 +83,7 @@ exports[`change settings: during submit: oidc without errors 1`] = `
placeholder=""
readOnly={true}
type="text"
value=""
value="http://localhost/oidc/callback"
/>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantFilled"
@@ -141,7 +124,7 @@ needs to be displayed, e.g. “Log in with &lt;Facebook&gt;”.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={true}
name="auth.integrations.oidc.0.name"
name="auth.integrations.oidc.name"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -163,7 +146,7 @@ needs to be displayed, e.g. “Log in with &lt;Facebook&gt;”.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={true}
name="auth.integrations.oidc.0.clientID"
name="auth.integrations.oidc.clientID"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -185,7 +168,7 @@ needs to be displayed, e.g. “Log in with &lt;Facebook&gt;”.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={true}
name="auth.integrations.oidc.0.clientSecret"
name="auth.integrations.oidc.clientSecret"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -216,7 +199,7 @@ the remaining fields. You may also enter the information manually.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={true}
name="auth.integrations.oidc.0.issuer"
name="auth.integrations.oidc.issuer"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -226,7 +209,7 @@ the remaining fields. You may also enter the information manually.
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantFilled Button-disabled"
disabled={true}
id="configure-auth-oidc-discover-0"
id="configure-auth-oidc-discover"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
@@ -253,7 +236,7 @@ the remaining fields. You may also enter the information manually.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={true}
name="auth.integrations.oidc.0.authorizationURL"
name="auth.integrations.oidc.authorizationURL"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -275,7 +258,7 @@ the remaining fields. You may also enter the information manually.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={true}
name="auth.integrations.oidc.0.tokenURL"
name="auth.integrations.oidc.tokenURL"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -297,7 +280,7 @@ the remaining fields. You may also enter the information manually.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={true}
name="auth.integrations.oidc.0.jwksURI"
name="auth.integrations.oidc.jwksURI"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -325,8 +308,8 @@ the remaining fields. You may also enter the information manually.
checked={true}
className="CheckBox-input"
disabled={true}
id="auth.integrations.oidc.0.targetFilter.admin"
name="auth.integrations.oidc.0.targetFilter.admin"
id="auth.integrations.oidc.targetFilter.admin"
name="auth.integrations.oidc.targetFilter.admin"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
@@ -334,7 +317,7 @@ the remaining fields. You may also enter the information manually.
/>
<label
className="CheckBox-label"
htmlFor="auth.integrations.oidc.0.targetFilter.admin"
htmlFor="auth.integrations.oidc.targetFilter.admin"
>
<span
className="CheckBox-labelSpan"
@@ -350,8 +333,8 @@ the remaining fields. You may also enter the information manually.
checked={true}
className="CheckBox-input"
disabled={true}
id="auth.integrations.oidc.0.targetFilter.stream"
name="auth.integrations.oidc.0.targetFilter.stream"
id="auth.integrations.oidc.targetFilter.stream"
name="auth.integrations.oidc.targetFilter.stream"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
@@ -359,7 +342,7 @@ the remaining fields. You may also enter the information manually.
/>
<label
className="CheckBox-label"
htmlFor="auth.integrations.oidc.0.targetFilter.stream"
htmlFor="auth.integrations.oidc.targetFilter.stream"
>
<span
className="CheckBox-labelSpan"
@@ -394,8 +377,8 @@ integration to register for a new account.
checked={false}
className="CheckBox-input"
disabled={true}
id="auth.integrations.oidc.0.allowRegistration"
name="auth.integrations.oidc.0.allowRegistration"
id="auth.integrations.oidc.allowRegistration"
name="auth.integrations.oidc.allowRegistration"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
@@ -403,7 +386,7 @@ integration to register for a new account.
/>
<label
className="CheckBox-label"
htmlFor="auth.integrations.oidc.0.allowRegistration"
htmlFor="auth.integrations.oidc.allowRegistration"
>
<span
className="CheckBox-labelSpan"
@@ -422,7 +405,7 @@ integration to register for a new account.
exports[`change settings: enable facebook configure box 1`] = `
<div
className="ConfigBox-root"
data-test="configure-auth-facebook-container"
data-testid="configure-auth-facebook-container"
>
<div
className="Flex-root ConfigBox-title Flex-flex Flex-justifySpaceBetween"
@@ -687,7 +670,7 @@ integration to register for a new account.
exports[`change settings: enable oidc configure box 1`] = `
<div
className="ConfigBox-root"
data-test="configure-auth-oidc-container-0"
data-testid="configure-auth-oidc-container"
>
<div
className="Flex-root ConfigBox-title Flex-flex Flex-justifySpaceBetween"
@@ -708,8 +691,8 @@ exports[`change settings: enable oidc configure box 1`] = `
checked={true}
className="CheckBox-input"
disabled={false}
id="auth.integrations.oidc.0.enabled"
name="auth.integrations.oidc.0.enabled"
id="auth.integrations.oidc.enabled"
name="auth.integrations.oidc.enabled"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
@@ -717,7 +700,7 @@ exports[`change settings: enable oidc configure box 1`] = `
/>
<label
className="CheckBox-label CheckBox-labelLight"
htmlFor="auth.integrations.oidc.0.enabled"
htmlFor="auth.integrations.oidc.enabled"
>
<span
className="CheckBox-labelSpan"
@@ -758,23 +741,6 @@ exports[`change settings: enable oidc configure box 1`] = `
>
Redirect URI
</label>
<div
className="Typography-root Typography-detail Typography-colorTextSecondary ConfigDescription-description"
>
<div
className="Flex-root Flex-flex Flex-halfItemGutter"
>
<span
aria-hidden="true"
className="Icon-root OIDCConfig-redirectDescriptionIcon Icon-sm"
>
error
</span>
<div>
For OpenID Connect, your Redirect URI will not appear until you after you save this integration.
</div>
</div>
</div>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
@@ -784,7 +750,7 @@ exports[`change settings: enable oidc configure box 1`] = `
placeholder=""
readOnly={true}
type="text"
value=""
value="http://localhost/oidc/callback"
/>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantFilled"
@@ -825,7 +791,7 @@ needs to be displayed, e.g. “Log in with &lt;Facebook&gt;”.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={false}
name="auth.integrations.oidc.0.name"
name="auth.integrations.oidc.name"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -847,7 +813,7 @@ needs to be displayed, e.g. “Log in with &lt;Facebook&gt;”.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={false}
name="auth.integrations.oidc.0.clientID"
name="auth.integrations.oidc.clientID"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -869,7 +835,7 @@ needs to be displayed, e.g. “Log in with &lt;Facebook&gt;”.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={false}
name="auth.integrations.oidc.0.clientSecret"
name="auth.integrations.oidc.clientSecret"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -900,7 +866,7 @@ the remaining fields. You may also enter the information manually.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={false}
name="auth.integrations.oidc.0.issuer"
name="auth.integrations.oidc.issuer"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -910,7 +876,7 @@ the remaining fields. You may also enter the information manually.
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantFilled"
disabled={false}
id="configure-auth-oidc-discover-0"
id="configure-auth-oidc-discover"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
@@ -937,7 +903,7 @@ the remaining fields. You may also enter the information manually.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={false}
name="auth.integrations.oidc.0.authorizationURL"
name="auth.integrations.oidc.authorizationURL"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -959,7 +925,7 @@ the remaining fields. You may also enter the information manually.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={false}
name="auth.integrations.oidc.0.tokenURL"
name="auth.integrations.oidc.tokenURL"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -981,7 +947,7 @@ the remaining fields. You may also enter the information manually.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={false}
name="auth.integrations.oidc.0.jwksURI"
name="auth.integrations.oidc.jwksURI"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -1009,8 +975,8 @@ the remaining fields. You may also enter the information manually.
checked={true}
className="CheckBox-input"
disabled={false}
id="auth.integrations.oidc.0.targetFilter.admin"
name="auth.integrations.oidc.0.targetFilter.admin"
id="auth.integrations.oidc.targetFilter.admin"
name="auth.integrations.oidc.targetFilter.admin"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
@@ -1018,7 +984,7 @@ the remaining fields. You may also enter the information manually.
/>
<label
className="CheckBox-label"
htmlFor="auth.integrations.oidc.0.targetFilter.admin"
htmlFor="auth.integrations.oidc.targetFilter.admin"
>
<span
className="CheckBox-labelSpan"
@@ -1034,8 +1000,8 @@ the remaining fields. You may also enter the information manually.
checked={true}
className="CheckBox-input"
disabled={false}
id="auth.integrations.oidc.0.targetFilter.stream"
name="auth.integrations.oidc.0.targetFilter.stream"
id="auth.integrations.oidc.targetFilter.stream"
name="auth.integrations.oidc.targetFilter.stream"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
@@ -1043,7 +1009,7 @@ the remaining fields. You may also enter the information manually.
/>
<label
className="CheckBox-label"
htmlFor="auth.integrations.oidc.0.targetFilter.stream"
htmlFor="auth.integrations.oidc.targetFilter.stream"
>
<span
className="CheckBox-labelSpan"
@@ -1078,8 +1044,8 @@ integration to register for a new account.
checked={false}
className="CheckBox-input"
disabled={false}
id="auth.integrations.oidc.0.allowRegistration"
name="auth.integrations.oidc.0.allowRegistration"
id="auth.integrations.oidc.allowRegistration"
name="auth.integrations.oidc.allowRegistration"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
@@ -1087,7 +1053,7 @@ integration to register for a new account.
/>
<label
className="CheckBox-label"
htmlFor="auth.integrations.oidc.0.allowRegistration"
htmlFor="auth.integrations.oidc.allowRegistration"
>
<span
className="CheckBox-labelSpan"
@@ -1106,7 +1072,7 @@ integration to register for a new account.
exports[`change settings: oidc validation errors 1`] = `
<div
className="ConfigBox-root"
data-test="configure-auth-oidc-container-0"
data-testid="configure-auth-oidc-container"
>
<div
className="Flex-root ConfigBox-title Flex-flex Flex-justifySpaceBetween"
@@ -1127,8 +1093,8 @@ exports[`change settings: oidc validation errors 1`] = `
checked={true}
className="CheckBox-input"
disabled={false}
id="auth.integrations.oidc.0.enabled"
name="auth.integrations.oidc.0.enabled"
id="auth.integrations.oidc.enabled"
name="auth.integrations.oidc.enabled"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
@@ -1136,7 +1102,7 @@ exports[`change settings: oidc validation errors 1`] = `
/>
<label
className="CheckBox-label CheckBox-labelLight"
htmlFor="auth.integrations.oidc.0.enabled"
htmlFor="auth.integrations.oidc.enabled"
>
<span
className="CheckBox-labelSpan"
@@ -1177,23 +1143,6 @@ exports[`change settings: oidc validation errors 1`] = `
>
Redirect URI
</label>
<div
className="Typography-root Typography-detail Typography-colorTextSecondary ConfigDescription-description"
>
<div
className="Flex-root Flex-flex Flex-halfItemGutter"
>
<span
aria-hidden="true"
className="Icon-root OIDCConfig-redirectDescriptionIcon Icon-sm"
>
error
</span>
<div>
For OpenID Connect, your Redirect URI will not appear until you after you save this integration.
</div>
</div>
</div>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
@@ -1203,7 +1152,7 @@ exports[`change settings: oidc validation errors 1`] = `
placeholder=""
readOnly={true}
type="text"
value=""
value="http://localhost/oidc/callback"
/>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantFilled"
@@ -1244,7 +1193,7 @@ needs to be displayed, e.g. “Log in with &lt;Facebook&gt;”.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={false}
name="auth.integrations.oidc.0.name"
name="auth.integrations.oidc.name"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -1279,7 +1228,7 @@ needs to be displayed, e.g. “Log in with &lt;Facebook&gt;”.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={false}
name="auth.integrations.oidc.0.clientID"
name="auth.integrations.oidc.clientID"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -1314,7 +1263,7 @@ needs to be displayed, e.g. “Log in with &lt;Facebook&gt;”.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={false}
name="auth.integrations.oidc.0.clientSecret"
name="auth.integrations.oidc.clientSecret"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -1358,7 +1307,7 @@ the remaining fields. You may also enter the information manually.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={false}
name="auth.integrations.oidc.0.issuer"
name="auth.integrations.oidc.issuer"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -1368,7 +1317,7 @@ the remaining fields. You may also enter the information manually.
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantFilled"
disabled={false}
id="configure-auth-oidc-discover-0"
id="configure-auth-oidc-discover"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
@@ -1408,7 +1357,7 @@ the remaining fields. You may also enter the information manually.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={false}
name="auth.integrations.oidc.0.authorizationURL"
name="auth.integrations.oidc.authorizationURL"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -1443,7 +1392,7 @@ the remaining fields. You may also enter the information manually.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={false}
name="auth.integrations.oidc.0.tokenURL"
name="auth.integrations.oidc.tokenURL"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -1478,7 +1427,7 @@ the remaining fields. You may also enter the information manually.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={false}
name="auth.integrations.oidc.0.jwksURI"
name="auth.integrations.oidc.jwksURI"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -1519,8 +1468,8 @@ the remaining fields. You may also enter the information manually.
checked={true}
className="CheckBox-input"
disabled={false}
id="auth.integrations.oidc.0.targetFilter.admin"
name="auth.integrations.oidc.0.targetFilter.admin"
id="auth.integrations.oidc.targetFilter.admin"
name="auth.integrations.oidc.targetFilter.admin"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
@@ -1528,7 +1477,7 @@ the remaining fields. You may also enter the information manually.
/>
<label
className="CheckBox-label"
htmlFor="auth.integrations.oidc.0.targetFilter.admin"
htmlFor="auth.integrations.oidc.targetFilter.admin"
>
<span
className="CheckBox-labelSpan"
@@ -1544,8 +1493,8 @@ the remaining fields. You may also enter the information manually.
checked={true}
className="CheckBox-input"
disabled={false}
id="auth.integrations.oidc.0.targetFilter.stream"
name="auth.integrations.oidc.0.targetFilter.stream"
id="auth.integrations.oidc.targetFilter.stream"
name="auth.integrations.oidc.targetFilter.stream"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
@@ -1553,7 +1502,7 @@ the remaining fields. You may also enter the information manually.
/>
<label
className="CheckBox-label"
htmlFor="auth.integrations.oidc.0.targetFilter.stream"
htmlFor="auth.integrations.oidc.targetFilter.stream"
>
<span
className="CheckBox-labelSpan"
@@ -1588,8 +1537,8 @@ integration to register for a new account.
checked={false}
className="CheckBox-input"
disabled={false}
id="auth.integrations.oidc.0.allowRegistration"
name="auth.integrations.oidc.0.allowRegistration"
id="auth.integrations.oidc.allowRegistration"
name="auth.integrations.oidc.allowRegistration"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
@@ -1597,7 +1546,7 @@ integration to register for a new account.
/>
<label
className="CheckBox-label"
htmlFor="auth.integrations.oidc.0.allowRegistration"
htmlFor="auth.integrations.oidc.allowRegistration"
>
<span
className="CheckBox-labelSpan"
@@ -1616,7 +1565,7 @@ integration to register for a new account.
exports[`prevents admin lock out 1`] = `
<div
className="CallOut-root CallOut-colorError CallOut-fullWidth"
data-test="configure-auth-submitError"
data-testid="configure-auth-submitError"
>
<span>
Please enable at least one authentication integration for Talk Admin
@@ -1627,7 +1576,7 @@ exports[`prevents admin lock out 1`] = `
exports[`regenerate sso key 1`] = `
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
data-test="configure-auth-sso-key"
data-testid="configure-auth-sso-key"
>
<label
className="Typography-root Typography-inputLabel Typography-colorTextPrimary InputLabel-root"
@@ -1688,7 +1637,7 @@ and all signed-in users will be signed out.
exports[`renders configure auth 1`] = `
<div
className="MainLayout-root"
data-test="configure-container"
data-testid="configure-container"
>
<form
autoComplete="off"
@@ -1736,7 +1685,7 @@ exports[`renders configure auth 1`] = `
>
<button
className="BaseButton-root Button-root Button-sizeRegular Button-colorSuccess Button-variantFilled Button-disabled"
data-test="configure-sideBar-saveChanges"
data-testid="configure-sideBar-saveChanges"
disabled={true}
onBlur={[Function]}
onFocus={[Function]}
@@ -2000,7 +1949,7 @@ integration to register for a new account.
</div>
<div
className="ConfigBox-root"
data-test="configure-auth-oidc-container-0"
data-testid="configure-auth-oidc-container"
>
<div
className="Flex-root ConfigBox-title Flex-flex Flex-justifySpaceBetween"
@@ -2018,11 +1967,11 @@ integration to register for a new account.
className="CheckBox-root"
>
<input
checked=""
checked={false}
className="CheckBox-input"
disabled={false}
id="auth.integrations.oidc.0.enabled"
name="auth.integrations.oidc.0.enabled"
id="auth.integrations.oidc.enabled"
name="auth.integrations.oidc.enabled"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
@@ -2030,7 +1979,7 @@ integration to register for a new account.
/>
<label
className="CheckBox-label CheckBox-labelLight"
htmlFor="auth.integrations.oidc.0.enabled"
htmlFor="auth.integrations.oidc.enabled"
>
<span
className="CheckBox-labelSpan"
@@ -2071,23 +2020,6 @@ integration to register for a new account.
>
Redirect URI
</label>
<div
className="Typography-root Typography-detail Typography-colorTextSecondary ConfigDescription-description"
>
<div
className="Flex-root Flex-flex Flex-halfItemGutter"
>
<span
aria-hidden="true"
className="Icon-root OIDCConfig-redirectDescriptionIcon Icon-sm"
>
error
</span>
<div>
For OpenID Connect, your Redirect URI will not appear until you after you save this integration.
</div>
</div>
</div>
<div
className="Flex-root Flex-flex Flex-halfItemGutter Flex-alignCenter Flex-directionRow"
>
@@ -2097,7 +2029,7 @@ integration to register for a new account.
placeholder=""
readOnly={true}
type="text"
value=""
value="http://localhost/oidc/callback"
/>
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantFilled"
@@ -2138,7 +2070,7 @@ needs to be displayed, e.g. “Log in with &lt;Facebook&gt;”.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={true}
name="auth.integrations.oidc.0.name"
name="auth.integrations.oidc.name"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -2160,7 +2092,7 @@ needs to be displayed, e.g. “Log in with &lt;Facebook&gt;”.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={true}
name="auth.integrations.oidc.0.clientID"
name="auth.integrations.oidc.clientID"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -2182,7 +2114,7 @@ needs to be displayed, e.g. “Log in with &lt;Facebook&gt;”.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={true}
name="auth.integrations.oidc.0.clientSecret"
name="auth.integrations.oidc.clientSecret"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -2213,7 +2145,7 @@ the remaining fields. You may also enter the information manually.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={true}
name="auth.integrations.oidc.0.issuer"
name="auth.integrations.oidc.issuer"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -2223,7 +2155,7 @@ the remaining fields. You may also enter the information manually.
<button
className="BaseButton-root Button-root Button-sizeSmall Button-colorPrimary Button-variantFilled Button-disabled"
disabled={true}
id="configure-auth-oidc-discover-0"
id="configure-auth-oidc-discover"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
@@ -2250,7 +2182,7 @@ the remaining fields. You may also enter the information manually.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={true}
name="auth.integrations.oidc.0.authorizationURL"
name="auth.integrations.oidc.authorizationURL"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -2272,7 +2204,7 @@ the remaining fields. You may also enter the information manually.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={true}
name="auth.integrations.oidc.0.tokenURL"
name="auth.integrations.oidc.tokenURL"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -2294,7 +2226,7 @@ the remaining fields. You may also enter the information manually.
autoCorrect="off"
className="TextField-root TextField-colorRegular"
disabled={true}
name="auth.integrations.oidc.0.jwksURI"
name="auth.integrations.oidc.jwksURI"
onChange={[Function]}
placeholder=""
spellCheck={false}
@@ -2322,8 +2254,8 @@ the remaining fields. You may also enter the information manually.
checked={true}
className="CheckBox-input"
disabled={true}
id="auth.integrations.oidc.0.targetFilter.admin"
name="auth.integrations.oidc.0.targetFilter.admin"
id="auth.integrations.oidc.targetFilter.admin"
name="auth.integrations.oidc.targetFilter.admin"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
@@ -2331,7 +2263,7 @@ the remaining fields. You may also enter the information manually.
/>
<label
className="CheckBox-label"
htmlFor="auth.integrations.oidc.0.targetFilter.admin"
htmlFor="auth.integrations.oidc.targetFilter.admin"
>
<span
className="CheckBox-labelSpan"
@@ -2347,8 +2279,8 @@ the remaining fields. You may also enter the information manually.
checked={true}
className="CheckBox-input"
disabled={true}
id="auth.integrations.oidc.0.targetFilter.stream"
name="auth.integrations.oidc.0.targetFilter.stream"
id="auth.integrations.oidc.targetFilter.stream"
name="auth.integrations.oidc.targetFilter.stream"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
@@ -2356,7 +2288,7 @@ the remaining fields. You may also enter the information manually.
/>
<label
className="CheckBox-label"
htmlFor="auth.integrations.oidc.0.targetFilter.stream"
htmlFor="auth.integrations.oidc.targetFilter.stream"
>
<span
className="CheckBox-labelSpan"
@@ -2391,8 +2323,8 @@ integration to register for a new account.
checked={false}
className="CheckBox-input"
disabled={true}
id="auth.integrations.oidc.0.allowRegistration"
name="auth.integrations.oidc.0.allowRegistration"
id="auth.integrations.oidc.allowRegistration"
name="auth.integrations.oidc.allowRegistration"
onBlur={[Function]}
onChange={[Function]}
onFocus={[Function]}
@@ -2400,7 +2332,7 @@ integration to register for a new account.
/>
<label
className="CheckBox-label"
htmlFor="auth.integrations.oidc.0.allowRegistration"
htmlFor="auth.integrations.oidc.allowRegistration"
>
<span
className="CheckBox-labelSpan"
@@ -2465,7 +2397,7 @@ integration to register for a new account.
>
<div
className="HorizontalGutter-root FormField-root HorizontalGutter-half"
data-test="configure-auth-sso-key"
data-testid="configure-auth-sso-key"
>
<label
className="Typography-root Typography-inputLabel Typography-colorTextPrimary InputLabel-root"
@@ -2895,7 +2827,7 @@ integration to register for a new account.
</div>
<div
className="ConfigBox-root"
data-test="configure-auth-facebook-container"
data-testid="configure-auth-facebook-container"
>
<div
className="Flex-root ConfigBox-title Flex-flex Flex-justifySpaceBetween"
@@ -138,7 +138,7 @@ it("prevents stream lock out", async () => {
// Submit button should not be disabled because we canceled the submit.
expect(
testRenderer.root.findByProps({
"data-test": "configure-sideBar-saveChanges",
"data-testid": "configure-sideBar-saveChanges",
}).props.disabled
).toBe(true);
expect(stubCancel.calledOnce).toBe(true);
@@ -175,82 +175,52 @@ it("change settings", async () => {
),
},
Mutation: {
updateSettings: createSinonStub(s =>
s.callsFake((_: any, data: any) => {
expect(data.input.settings.auth.integrations.facebook).toEqual({
enabled: true,
allowRegistration: true,
targetFilter: {
admin: true,
stream: true,
},
clientID: "myClientID",
clientSecret: "myClientSecret",
});
settingsRecord = merge({}, settingsRecord, data.input.settings);
return {
settings: settingsRecord,
clientMutationId: data.input.clientMutationId,
};
})
),
createOIDCAuthIntegration: createSinonStub(s =>
s.callsFake((_: any, data: any) => {
expect(data.input.configuration).toEqual({
enabled: true,
allowRegistration: false,
targetFilter: {
admin: true,
stream: true,
},
name: "name",
clientID: "clientID",
clientSecret: "clientSecret",
issuer: "http://issuer.com",
jwksURI: "http://issuer.com/jwksURI",
authorizationURL: "http://issuer.com/authorizationURL",
tokenURL: "http://issuer.com/tokenURL",
});
(settingsRecord.auth.integrations.oidc as any).push({
id: "generatedID",
enabled: false,
callbackURL: "http://localhost/oidc/callback",
...data.input.configuration,
});
return {
settings: settingsRecord,
clientMutationId: data.input.clientMutationId,
};
})
),
updateOIDCAuthIntegration: createSinonStub(s =>
s.callsFake((_: any, data: any) => {
expect(data.input.configuration).toEqual({
enabled: true,
allowRegistration: false,
targetFilter: {
admin: true,
stream: true,
},
name: "name",
clientID: "clientID",
clientSecret: "clientSecret2",
issuer: "http://issuer.com",
jwksURI: "http://issuer.com/jwksURI",
authorizationURL: "http://issuer.com/authorizationURL",
tokenURL: "http://issuer.com/tokenURL",
});
(settingsRecord.auth.integrations.oidc[0] as any) = merge(
{},
settingsRecord.auth.integrations.oidc[0],
data.input.configuration
);
return {
integration: settingsRecord.auth.integrations.oidc[0],
settings: settingsRecord,
clientMutationId: data.input.clientMutationId,
};
})
updateSettings: createSinonStub(
s =>
s.onFirstCall().callsFake((_: any, data: any) => {
expect(data.input.settings.auth.integrations.facebook).toEqual({
enabled: true,
allowRegistration: true,
targetFilter: {
admin: true,
stream: true,
},
clientID: "myClientID",
clientSecret: "myClientSecret",
});
settingsRecord = merge(settingsRecord, data.input.settings);
return {
settings: settingsRecord,
clientMutationId: data.input.clientMutationId,
};
}),
s =>
s.onSecondCall().callsFake((_: any, data: any) => {
expect(data.input.settings.auth.integrations.oidc).toEqual({
enabled: true,
allowRegistration: false,
targetFilter: {
admin: true,
stream: true,
},
name: "name",
clientID: "clientID",
clientSecret: "clientSecret",
issuer: "http://issuer.com",
jwksURI: "http://issuer.com/jwksURI",
authorizationURL: "http://issuer.com/authorizationURL",
tokenURL: "http://issuer.com/tokenURL",
});
(settingsRecord.auth.integrations.oidc as any) = merge(
settingsRecord.auth.integrations.oidc,
data.input.configuration
);
return {
integration: settingsRecord.auth.integrations.oidc,
settings: settingsRecord,
clientMutationId: data.input.clientMutationId,
};
})
),
},
});
@@ -269,13 +239,13 @@ it("change settings", async () => {
limitSnapshotTo("configure-auth-facebook-container", testRenderer.toJSON())
).toMatchSnapshot("enable facebook configure box");
// Send form, this will perform creating an initial oidc record and update settings.
// Send form
testRenderer.root.findByProps({ id: "configure-form" }).props.onSubmit();
// Submit button should be disabled.
expect(
testRenderer.root.findByProps({
"data-test": "configure-sideBar-saveChanges",
"data-testid": "configure-sideBar-saveChanges",
}).props.disabled
).toBe(true);
@@ -293,73 +263,54 @@ it("change settings", async () => {
// Now let's enable oidc
testRenderer.root
.find(inputPredicate("auth.integrations.oidc.0.enabled"))
.find(inputPredicate("auth.integrations.oidc.enabled"))
.props.onChange({});
expect(
limitSnapshotTo("configure-auth-oidc-container-0", testRenderer.toJSON())
limitSnapshotTo("configure-auth-oidc-container", testRenderer.toJSON())
).toMatchSnapshot("enable oidc configure box");
// Try to submit form, this will give validation error messages.
testRenderer.root.findByProps({ id: "configure-form" }).props.onSubmit();
expect(
limitSnapshotTo("configure-auth-oidc-container-0", testRenderer.toJSON())
limitSnapshotTo("configure-auth-oidc-container", testRenderer.toJSON())
).toMatchSnapshot("oidc validation errors");
// Fill form
testRenderer.root
.find(inputPredicate("auth.integrations.oidc.0.name"))
.find(inputPredicate("auth.integrations.oidc.name"))
.props.onChange("name");
testRenderer.root
.find(inputPredicate("auth.integrations.oidc.0.clientID"))
.find(inputPredicate("auth.integrations.oidc.clientID"))
.props.onChange("clientID");
testRenderer.root
.find(inputPredicate("auth.integrations.oidc.0.clientSecret"))
.find(inputPredicate("auth.integrations.oidc.clientSecret"))
.props.onChange("clientSecret");
testRenderer.root
.find(inputPredicate("auth.integrations.oidc.0.issuer"))
.find(inputPredicate("auth.integrations.oidc.issuer"))
.props.onChange("http://issuer.com");
// Discover the rest.
testRenderer.root
.find(inputPredicate("configure-auth-oidc-discover-0"))
.find(inputPredicate("configure-auth-oidc-discover"))
.props.onClick();
await timeout();
// Try to submit again, this should work now.
testRenderer.root.findByProps({ id: "configure-form" }).props.onSubmit();
expect(
limitSnapshotTo("configure-auth-oidc-container-0", testRenderer.toJSON())
limitSnapshotTo("configure-auth-oidc-container", testRenderer.toJSON())
).toMatchSnapshot("during submit: oidc without errors");
// Disable other fields while submitting
// We are only testing for one here right now..
expect(
testRenderer.root.find(inputPredicate("auth.integrations.oidc.0.enabled"))
testRenderer.root.find(inputPredicate("auth.integrations.oidc.enabled"))
.props.disabled
).toBe(true);
await timeout();
expect(
testRenderer.root.find(inputPredicate("auth.integrations.oidc.0.enabled"))
.props.disabled
).toBe(false);
// Change clientSecret
testRenderer.root
.find(inputPredicate("auth.integrations.oidc.0.clientSecret"))
.props.onChange("clientSecret2");
testRenderer.root.findByProps({ id: "configure-form" }).props.onSubmit();
// Disable other fields while submitting
// We are only testing for one here right now..
expect(
testRenderer.root.find(inputPredicate("auth.integrations.oidc.0.enabled"))
.props.disabled
).toBe(true);
await timeout();
expect(
testRenderer.root.find(inputPredicate("auth.integrations.oidc.0.enabled"))
testRenderer.root.find(inputPredicate("auth.integrations.oidc.enabled"))
.props.disabled
).toBe(false);
});
@@ -2,7 +2,7 @@
exports[`loads more 1`] = `
<div
data-test="decisionHistory-container"
data-testid="decisionHistory-container"
>
<div
className="Flex-root Title-root Flex-flex Flex-alignCenter"
@@ -227,7 +227,7 @@ exports[`loads more 1`] = `
exports[`opens popover when clicked on button showing loading state 1`] = `
<div
data-test="decisionHistory-loading-container"
data-testid="decisionHistory-loading-container"
>
<div
className="Flex-root Title-root Flex-flex Flex-alignCenter"
@@ -259,7 +259,7 @@ exports[`opens popover when clicked on button showing loading state 1`] = `
exports[`render popover content 1`] = `
<div
data-test="decisionHistory-container"
data-testid="decisionHistory-container"
>
<div
className="Flex-root Title-root Flex-flex Flex-alignCenter"
@@ -434,12 +434,12 @@ exports[`render popover content 1`] = `
exports[`renders decision history popover button 1`] = `
<div
className="Popover-root"
data-test="decisionHistory-popover"
data-testid="decisionHistory-popover"
>
<button
aria-controls="decision-history-popover"
className="BaseButton-root DecisionHistoryButton-historyIcon"
data-test="decisionHistory-toggle"
data-testid="decisionHistory-toggle"
onBlur={[Function]}
onClick={[Function]}
onFocus={[Function]}
@@ -86,7 +86,7 @@ const createTestRenderer = async (resolver: any = {}) => {
async function createTestRendererAndOpenPopover() {
const testRenderer = await createTestRenderer();
const toggle = testRenderer.root.findByProps({
"data-test": "decisionHistory-toggle",
"data-testid": "decisionHistory-toggle",
})!;
toggle.props.onClick();
return testRenderer;
+9 -1
View File
@@ -11,7 +11,6 @@ export const settings = {
enabled: false,
},
integrations: {
oidc: [],
local: {
enabled: true,
allowRegistration: true,
@@ -52,6 +51,15 @@ export const settings = {
clientSecret: "",
callbackURL: "http://localhost/facebook/callback",
},
oidc: {
enabled: false,
allowRegistration: false,
targetFilter: {
admin: true,
stream: true,
},
callbackURL: "http://localhost/oidc/callback",
},
},
},
};
+5 -11
View File
@@ -5,7 +5,10 @@ import { timeout } from "talk-common/utils";
import { TalkContext } from "talk-framework/lib/bootstrap";
import { LOCAL_ID } from "talk-framework/lib/relay";
import { replaceHistoryLocation } from "talk-framework/testHelpers";
import {
createAuthToken,
replaceHistoryLocation,
} from "talk-framework/testHelpers";
import create from "./create";
import {
@@ -116,16 +119,7 @@ it("submits form successfully", async () => {
.find(inputPredicate("password"))
.props.onChange({ target: { value: "testtest" } });
const authToken = `${btoa(
JSON.stringify({
alg: "HS256",
typ: "JWT",
})
)}.${btoa(
JSON.stringify({
jti: "31b26591-4e9a-4388-a7ff-e1bdc5d97cce",
})
)}`;
const authToken = createAuthToken();
const restMock = sinon.mock(context.rest);
restMock
@@ -3,7 +3,7 @@
exports[`navigation bar renders navigation bar (empty queues) 1`] = `
<div
className="SubBar-root"
data-test="moderate-subBar-container"
data-testid="moderate-subBar-container"
>
<div
className="Flex-root SubBar-container Flex-flex Flex-justifyCenter Flex-alignCenter"
@@ -33,7 +33,7 @@ exports[`navigation bar renders navigation bar (empty queues) 1`] = `
</span>
<span
className="Counter-root Counter-colorInherit"
data-test="moderate-navigation-reported-count"
data-testid="moderate-navigation-reported-count"
>
<span
className="Counter-text"
@@ -62,7 +62,7 @@ exports[`navigation bar renders navigation bar (empty queues) 1`] = `
</span>
<span
className="Counter-root Counter-colorInherit"
data-test="moderate-navigation-pending-count"
data-testid="moderate-navigation-pending-count"
>
<span
className="Counter-text"
@@ -91,7 +91,7 @@ exports[`navigation bar renders navigation bar (empty queues) 1`] = `
</span>
<span
className="Counter-root Counter-colorInherit"
data-test="moderate-navigation-unmoderated-count"
data-testid="moderate-navigation-unmoderated-count"
>
<span
className="Counter-text"
@@ -129,7 +129,7 @@ exports[`navigation bar renders navigation bar (empty queues) 1`] = `
exports[`rejected queue accepts comment in rejected queue: count should be 1 1`] = `
<span
className="Counter-root Counter-colorInherit"
data-test="moderate-navigation-reported-count"
data-testid="moderate-navigation-reported-count"
>
<span
className="Counter-text"
@@ -142,7 +142,7 @@ exports[`rejected queue accepts comment in rejected queue: count should be 1 1`]
exports[`rejected queue accepts comment in rejected queue: dangling 1`] = `
<div
className="Card-root ModerateCard-root ModerateCard-dangling"
data-test="moderate-comment-comment-0"
data-testid="moderate-comment-comment-0"
>
<div
className="Flex-root Flex-flex"
@@ -285,7 +285,7 @@ exports[`rejected queue accepts comment in rejected queue: dangling 1`] = `
exports[`rejected queue renders rejected queue with comments 1`] = `
<div
className="MainLayout-root"
data-test="moderate-main-container"
data-testid="moderate-main-container"
>
<main
className="Moderate-main"
@@ -295,7 +295,7 @@ exports[`rejected queue renders rejected queue with comments 1`] = `
>
<div
className="Card-root ModerateCard-root"
data-test="moderate-comment-comment-0"
data-testid="moderate-comment-comment-0"
>
<div
className="Flex-root Flex-flex"
@@ -435,7 +435,7 @@ exports[`rejected queue renders rejected queue with comments 1`] = `
</div>
<div
className="Card-root ModerateCard-root"
data-test="moderate-comment-comment-1"
data-testid="moderate-comment-comment-1"
>
<div
className="Flex-root Flex-flex"
@@ -582,7 +582,7 @@ exports[`rejected queue renders rejected queue with comments 1`] = `
exports[`rejected queue renders rejected queue with comments and load more 1`] = `
<div
className="Card-root ModerateCard-root"
data-test="moderate-comment-comment-2"
data-testid="moderate-comment-comment-2"
>
<div
className="Flex-root Flex-flex"
@@ -738,7 +738,7 @@ exports[`rejected queue renders rejected queue with comments and load more 1`] =
exports[`reported queue accepts comment in reported queue: count should be 1 1`] = `
<span
className="Counter-root Counter-colorInherit"
data-test="moderate-navigation-reported-count"
data-testid="moderate-navigation-reported-count"
>
<span
className="Counter-text"
@@ -751,7 +751,7 @@ exports[`reported queue accepts comment in reported queue: count should be 1 1`]
exports[`reported queue accepts comment in reported queue: dangling 1`] = `
<div
className="Card-root ModerateCard-root ModerateCard-dangling"
data-test="moderate-comment-comment-0"
data-testid="moderate-comment-comment-0"
>
<div
className="Flex-root Flex-flex"
@@ -894,7 +894,7 @@ exports[`reported queue accepts comment in reported queue: dangling 1`] = `
exports[`reported queue rejects comment in reported queue: count should be 1 1`] = `
<span
className="Counter-root Counter-colorInherit"
data-test="moderate-navigation-reported-count"
data-testid="moderate-navigation-reported-count"
>
<span
className="Counter-text"
@@ -907,7 +907,7 @@ exports[`reported queue rejects comment in reported queue: count should be 1 1`]
exports[`reported queue rejects comment in reported queue: dangling 1`] = `
<div
className="Card-root ModerateCard-root ModerateCard-dangling"
data-test="moderate-comment-comment-0"
data-testid="moderate-comment-comment-0"
>
<div
className="Flex-root Flex-flex"
@@ -1050,7 +1050,7 @@ exports[`reported queue rejects comment in reported queue: dangling 1`] = `
exports[`reported queue renders empty reported queue 1`] = `
<div
className="MainLayout-root"
data-test="moderate-main-container"
data-testid="moderate-main-container"
>
<main
className="Moderate-main"
@@ -1065,7 +1065,7 @@ exports[`reported queue renders empty reported queue 1`] = `
exports[`reported queue renders reported queue with comments 1`] = `
<div
className="MainLayout-root"
data-test="moderate-main-container"
data-testid="moderate-main-container"
>
<main
className="Moderate-main"
@@ -1075,7 +1075,7 @@ exports[`reported queue renders reported queue with comments 1`] = `
>
<div
className="Card-root ModerateCard-root"
data-test="moderate-comment-comment-0"
data-testid="moderate-comment-comment-0"
>
<div
className="Flex-root Flex-flex"
@@ -1215,7 +1215,7 @@ exports[`reported queue renders reported queue with comments 1`] = `
</div>
<div
className="Card-root ModerateCard-root"
data-test="moderate-comment-comment-1"
data-testid="moderate-comment-comment-1"
>
<div
className="Flex-root Flex-flex"
@@ -1361,7 +1361,7 @@ exports[`reported queue renders reported queue with comments 1`] = `
exports[`reported queue renders reported queue with comments and load more 1`] = `
<div
className="Card-root ModerateCard-root"
data-test="moderate-comment-comment-2"
data-testid="moderate-comment-comment-2"
>
<div
className="Flex-root Flex-flex"
@@ -1522,7 +1522,7 @@ exports[`reported queue renders reported queue with comments and load more 1`] =
exports[`single comment view accepts single comment 1`] = `
<div
className="Card-root ModerateCard-root"
data-test="moderate-comment-comment-0"
data-testid="moderate-comment-comment-0"
>
<div
className="Flex-root Flex-flex"
@@ -1665,7 +1665,7 @@ exports[`single comment view accepts single comment 1`] = `
exports[`single comment view rejects single comment 1`] = `
<div
className="Card-root ModerateCard-root"
data-test="moderate-comment-comment-0"
data-testid="moderate-comment-comment-0"
>
<div
className="Flex-root Flex-flex"
@@ -1807,7 +1807,7 @@ exports[`single comment view rejects single comment 1`] = `
exports[`single comment view renders single comment view 1`] = `
<div
data-test="single-moderate-container"
data-testid="single-moderate-container"
>
<div
className="SubBar-root SingleModerate-subBar SubBar-gutterBegin SubBar-gutterEnd"
@@ -1843,7 +1843,7 @@ exports[`single comment view renders single comment view 1`] = `
>
<div
className="Card-root ModerateCard-root"
data-test="moderate-comment-comment-0"
data-testid="moderate-comment-comment-0"
>
<div
className="Flex-root Flex-flex"
@@ -181,7 +181,7 @@ describe("reported queue", () => {
expect(comments.length).toBe(previousCount + 1);
// Verify last one added was our new one
expect(comments[comments.length - 1].props["data-test"]).toBe(
expect(comments[comments.length - 1].props["data-testid"]).toBe(
`moderate-comment-${reportedComments[2].id}`
);
@@ -453,7 +453,7 @@ describe("rejected queue", () => {
expect(comments.length).toBe(previousCount + 1);
// Verify last one added was our new one
expect(comments[comments.length - 1].props["data-test"]).toBe(
expect(comments[comments.length - 1].props["data-testid"]).toBe(
`moderate-comment-${rejectedComments[2].id}`
);
@@ -1,6 +1,6 @@
import { shallow } from "enzyme";
import { noop } from "lodash";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -13,6 +13,7 @@ it("renders correctly", () => {
date: "2018-07-06T18:24:00.000Z",
onGotoComment: noop,
};
const wrapper = shallow(<AcceptedComment {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<AcceptedComment {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,9 +1,10 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import AcceptedIcon from "./AcceptedIcon";
it("renders correctly", () => {
const wrapper = shallow(<AcceptedIcon />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<AcceptedIcon />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,6 +1,6 @@
import { shallow } from "enzyme";
import { noop } from "lodash";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { removeFragmentRefs } from "talk-framework/testHelpers";
import { PropTypesOf } from "talk-framework/types";
@@ -22,16 +22,18 @@ it("renders correctly", () => {
...baseProps,
actions: [{ id: "1" }, { id: "2" }, { id: "3" }],
};
const wrapper = shallow(<DecisionHistoryN {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<DecisionHistoryN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders empty state", () => {
const props: PropTypesOf<typeof DecisionHistoryN> = {
...baseProps,
};
const wrapper = shallow(<DecisionHistoryN {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<DecisionHistoryN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders hasMore", () => {
@@ -40,8 +42,9 @@ it("renders hasMore", () => {
actions: [{ id: "1" }, { id: "2" }, { id: "3" }],
hasMore: true,
};
const wrapper = shallow(<DecisionHistoryN {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<DecisionHistoryN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
it("renders disable load more", () => {
@@ -51,6 +54,7 @@ it("renders disable load more", () => {
hasMore: true,
disableLoadMore: true,
};
const wrapper = shallow(<DecisionHistoryN {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<DecisionHistoryN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -20,7 +20,7 @@ interface Props {
}
const DecisionHistory: StatelessComponent<Props> = props => (
<div data-test="decisionHistory-container">
<div data-testid="decisionHistory-container">
<Title />
<Main>
<DecisionList>
@@ -1,9 +1,10 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import DecisionHistoryLoading from "./DecisionHistoryLoading";
it("renders correctly", () => {
const wrapper = shallow(<DecisionHistoryLoading />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<DecisionHistoryLoading />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -8,7 +8,7 @@ import Title from "./Title";
import styles from "./DecisionHistoryLoading.css";
const DecisionHistoryLoading: StatelessComponent = () => (
<div data-test="decisionHistory-loading-container">
<div data-testid="decisionHistory-loading-container">
<Title />
<Main>
<Flex
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -10,6 +10,7 @@ it("renders correctly", () => {
icon: "icon",
children: "children",
};
const wrapper = shallow(<DecisionItem {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<DecisionItem {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -9,6 +9,7 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof DecisionList> = {
children: "children",
};
const wrapper = shallow(<DecisionList {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<DecisionList {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,9 +1,10 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import DotDivider from "./DotDivider";
it("renders correctly", () => {
const wrapper = shallow(<DotDivider />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<DotDivider />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,9 +1,10 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import Empty from "./Empty";
it("renders correctly", () => {
const wrapper = shallow(<Empty />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Empty />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -9,6 +9,7 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof Footer> = {
children: "children",
};
const wrapper = shallow(<Footer {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Footer {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,6 +1,6 @@
import { shallow } from "enzyme";
import { noop } from "lodash";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -11,6 +11,7 @@ it("renders correctly", () => {
href: "#",
onClick: noop,
};
const wrapper = shallow(<GoToCommentLink {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<GoToCommentLink {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -9,6 +9,7 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof Info> = {
children: "children",
};
const wrapper = shallow(<Info {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Info {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -9,6 +9,7 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof Main> = {
children: "children",
};
const wrapper = shallow(<Main {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Main {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,6 +1,6 @@
import { shallow } from "enzyme";
import { noop } from "lodash";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -13,6 +13,7 @@ it("renders correctly", () => {
date: "2018-07-06T18:24:00.000Z",
onGotoComment: noop,
};
const wrapper = shallow(<RejectedComment {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<RejectedComment {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,9 +1,10 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import RejectedIcon from "./RejectedIcon";
it("renders correctly", () => {
const wrapper = shallow(<RejectedIcon />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<RejectedIcon />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,6 +1,6 @@
import { shallow } from "enzyme";
import { noop } from "lodash";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -11,6 +11,7 @@ it("renders correctly", () => {
disabled: false,
onClick: noop,
};
const wrapper = shallow(<ShowMoreButton {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<ShowMoreButton {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,5 +1,5 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
@@ -9,6 +9,7 @@ it("renders correctly", () => {
const props: PropTypesOf<typeof Timestamp> = {
children: "2018-07-06T18:24:00.000Z",
};
const wrapper = shallow(<Timestamp {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Timestamp {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -1,9 +1,10 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import Title from "./Title";
it("renders correctly", () => {
const wrapper = shallow(<Title />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<Title />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -2,7 +2,7 @@
exports[`renders correctly 1`] = `
<div
data-test="decisionHistory-container"
data-testid="decisionHistory-container"
>
<Title />
<Main>
@@ -13,7 +13,6 @@ exports[`renders correctly 1`] = `
"id": "1",
}
}
key="1"
onClosePopover={[Function]}
/>
<Relay(DecisionHistoryItemContainer)
@@ -22,7 +21,6 @@ exports[`renders correctly 1`] = `
"id": "2",
}
}
key="2"
onClosePopover={[Function]}
/>
<Relay(DecisionHistoryItemContainer)
@@ -31,7 +29,6 @@ exports[`renders correctly 1`] = `
"id": "3",
}
}
key="3"
onClosePopover={[Function]}
/>
</DecisionList>
@@ -41,7 +38,7 @@ exports[`renders correctly 1`] = `
exports[`renders disable load more 1`] = `
<div
data-test="decisionHistory-container"
data-testid="decisionHistory-container"
>
<Title />
<Main>
@@ -52,7 +49,6 @@ exports[`renders disable load more 1`] = `
"id": "1",
}
}
key="1"
onClosePopover={[Function]}
/>
<Relay(DecisionHistoryItemContainer)
@@ -61,7 +57,6 @@ exports[`renders disable load more 1`] = `
"id": "2",
}
}
key="2"
onClosePopover={[Function]}
/>
<Relay(DecisionHistoryItemContainer)
@@ -70,7 +65,6 @@ exports[`renders disable load more 1`] = `
"id": "3",
}
}
key="3"
onClosePopover={[Function]}
/>
</DecisionList>
@@ -84,7 +78,7 @@ exports[`renders disable load more 1`] = `
exports[`renders empty state 1`] = `
<div
data-test="decisionHistory-container"
data-testid="decisionHistory-container"
>
<Title />
<Main>
@@ -97,7 +91,7 @@ exports[`renders empty state 1`] = `
exports[`renders hasMore 1`] = `
<div
data-test="decisionHistory-container"
data-testid="decisionHistory-container"
>
<Title />
<Main>
@@ -108,7 +102,6 @@ exports[`renders hasMore 1`] = `
"id": "1",
}
}
key="1"
onClosePopover={[Function]}
/>
<Relay(DecisionHistoryItemContainer)
@@ -117,7 +110,6 @@ exports[`renders hasMore 1`] = `
"id": "2",
}
}
key="2"
onClosePopover={[Function]}
/>
<Relay(DecisionHistoryItemContainer)
@@ -126,7 +118,6 @@ exports[`renders hasMore 1`] = `
"id": "3",
}
}
key="3"
onClosePopover={[Function]}
/>
</DecisionList>
@@ -2,7 +2,7 @@
exports[`renders correctly 1`] = `
<div
data-test="decisionHistory-loading-container"
data-testid="decisionHistory-loading-container"
>
<Title />
<Main>
-13
View File
@@ -1,18 +1,5 @@
/* Here we add global stylings for body and document */
:global {
body {
margin: 0;
/* Support for all WebKit browsers. */
-webkit-font-smoothing: antialiased;
/* Support for Firefox. */
-moz-osx-font-smoothing: grayscale;
}
}
.root {
width: 100%;
padding: var(--spacing-unit) var(--spacing-unit) calc(2 * var(--spacing-unit))
var(--spacing-unit);
box-sizing: border-box;
}
+9 -4
View File
@@ -1,14 +1,19 @@
import { shallow } from "enzyme";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { removeFragmentRefs } from "talk-framework/testHelpers";
import { PropTypesOf } from "talk-framework/types";
import App from "./App";
const AppN = removeFragmentRefs(App);
it("renders sign in", () => {
const props: PropTypesOf<typeof App> = {
const props: PropTypesOf<typeof AppN> = {
view: "SIGN_IN",
auth: {},
};
const wrapper = shallow(<App {...props} />);
expect(wrapper).toMatchSnapshot();
const renderer = createRenderer();
renderer.render(<AppN {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
+25 -10
View File
@@ -1,40 +1,55 @@
import React, { StatelessComponent } from "react";
import ForgotPasswordContainer from "../containers/ForgotPasswordContainer";
import ResetPasswordContainer from "../containers/ResetPasswordContainer";
import SignInContainer from "../containers/SignInContainer";
import SignUpContainer from "../containers/SignUpContainer";
import { PropTypesOf } from "talk-framework/types";
import styles from "./App.css";
import AddEmailAddressContainer from "../views/addEmailAddress/containers/AddEmailAddressContainer";
import CreatePasswordContainer from "../views/createPassword/containers/CreatePasswordContainer";
import CreateUsernameContainer from "../views/createUsername/containers/CreateUsernameContainer";
import ForgotPasswordContainer from "../views/forgotPassword/containers/ForgotPasswordContainer";
import ResetPasswordContainer from "../views/resetPassword/containers/ResetPasswordContainer";
import SignInContainer from "../views/signIn/containers/SignInContainer";
import SignUpContainer from "../views/signUp/containers/SignUpContainer";
import "./App.css";
export type View =
| "SIGN_UP"
| "SIGN_IN"
| "FORGOT_PASSWORD"
| "RESET_PASSWORD"
| "CREATE_USERNAME"
| "CREATE_PASSWORD"
| "ADD_EMAIL_ADDRESS"
| "%future added value";
export interface AppProps {
view: View;
auth: PropTypesOf<typeof SignInContainer>["auth"] &
PropTypesOf<typeof SignUpContainer>["auth"];
}
const renderView = (view: View) => {
const renderView = (view: AppProps["view"], auth: AppProps["auth"]) => {
switch (view) {
case "SIGN_UP":
return <SignUpContainer />;
return <SignUpContainer auth={auth} />;
case "SIGN_IN":
return <SignInContainer />;
return <SignInContainer auth={auth} />;
case "FORGOT_PASSWORD":
return <ForgotPasswordContainer />;
case "RESET_PASSWORD":
return <ResetPasswordContainer />;
case "CREATE_USERNAME":
return <CreateUsernameContainer />;
case "CREATE_PASSWORD":
return <CreatePasswordContainer />;
case "ADD_EMAIL_ADDRESS":
return <AddEmailAddressContainer />;
default:
throw new Error(`Unknown view ${view}`);
}
};
const App: StatelessComponent<AppProps> = ({ view }) => (
<div className={styles.root}>{renderView(view)}</div>
const App: StatelessComponent<AppProps> = ({ view, auth }) => (
<div>{renderView(view, auth)}</div>
);
export default App;
@@ -0,0 +1,61 @@
import { Localized } from "fluent-react/compat";
import * as React from "react";
import { StatelessComponent } from "react";
import { Field } from "react-final-form";
import {
composeValidators,
required,
validateEqualEmails,
} from "talk-framework/lib/validation";
import {
FormField,
InputLabel,
TextField,
ValidationMessage,
} from "talk-ui/components";
interface Props {
disabled: boolean;
}
const ConfirmEmailField: StatelessComponent<Props> = props => (
<Field
name="confirmEmail"
validate={composeValidators(required, validateEqualEmails)}
>
{({ input, meta }) => (
<FormField>
<Localized id="general-confirmEmailAddressLabel">
<InputLabel htmlFor={input.name}>Confirm Email Address</InputLabel>
</Localized>
<Localized
id="general-confirmEmailAddressTextField"
attrs={{ placeholder: true }}
>
<TextField
id={input.name}
name={input.name}
onChange={input.onChange}
value={input.value}
placeholder="Confirm Email Address"
color={
meta.touched && (meta.error || meta.submitError)
? "error"
: "regular"
}
disabled={props.disabled}
fullWidth
/>
</Localized>
{meta.touched &&
(meta.error || meta.submitError) && (
<ValidationMessage fullWidth>
{meta.error || meta.submitError}
</ValidationMessage>
)}
</FormField>
)}
</Field>
);
export default ConfirmEmailField;
@@ -0,0 +1,63 @@
import { Localized } from "fluent-react/compat";
import * as React from "react";
import { StatelessComponent } from "react";
import { Field } from "react-final-form";
import {
composeValidators,
required,
validateEqualPasswords,
} from "talk-framework/lib/validation";
import {
FormField,
InputLabel,
TextField,
ValidationMessage,
} from "talk-ui/components";
interface Props {
disabled: boolean;
}
const SetPasswordField: StatelessComponent<Props> = props => (
<Field
name="confirmPassword"
validate={composeValidators(required, validateEqualPasswords)}
>
{({ input, meta }) => (
<FormField>
<Localized id="general-confirmPasswordLabel">
<InputLabel htmlFor={input.name}>Confirm Password</InputLabel>
</Localized>
<Localized
id="general-confirmPasswordTextField"
attrs={{ placeholder: true }}
>
<TextField
id={input.name}
name={input.name}
onChange={input.onChange}
value={input.value}
placeholder="Confirm Password"
type="password"
color={
meta.touched && (meta.error || meta.submitError)
? "error"
: "regular"
}
disabled={props.disabled}
fullWidth
/>
</Localized>
{meta.touched &&
(meta.error || meta.submitError) && (
<ValidationMessage>
{meta.error || meta.submitError}
</ValidationMessage>
)}
</FormField>
)}
</Field>
);
export default SetPasswordField;
@@ -0,0 +1,58 @@
import { Localized } from "fluent-react/compat";
import * as React from "react";
import { StatelessComponent } from "react";
import { Field } from "react-final-form";
import {
composeValidators,
required,
validateEmail,
} from "talk-framework/lib/validation";
import {
FormField,
InputLabel,
TextField,
ValidationMessage,
} from "talk-ui/components";
interface Props {
disabled: boolean;
}
const EmailField: StatelessComponent<Props> = props => (
<Field name="email" validate={composeValidators(required, validateEmail)}>
{({ input, meta }) => (
<FormField>
<Localized id="general-emailAddressLabel">
<InputLabel htmlFor={input.name}>Email Address</InputLabel>
</Localized>
<Localized
id="general-emailAddressTextField"
attrs={{ placeholder: true }}
>
<TextField
id={input.name}
name={input.name}
onChange={input.onChange}
value={input.value}
placeholder="Email Address"
color={
meta.touched && (meta.error || meta.submitError)
? "error"
: "regular"
}
disabled={props.disabled}
fullWidth
/>
</Localized>
{meta.touched &&
(meta.error || meta.submitError) && (
<ValidationMessage fullWidth>
{meta.error || meta.submitError}
</ValidationMessage>
)}
</FormField>
)}
</Field>
);
export default EmailField;
@@ -0,0 +1,16 @@
.variantFilled {
&.colorRegular {
background-color: #3b5998;
}
&:not(.disabled) {
&.colorRegular {
&.mouseHover {
background-color: #4467b0;
}
&:active,
&.active {
background-color: #6583c3;
}
}
}
}
@@ -0,0 +1,17 @@
import { noop } from "lodash";
import React from "react";
import { createRenderer } from "react-test-renderer/shallow";
import { PropTypesOf } from "talk-framework/types";
import FacebookButton from "./FacebookButton";
it("renders correctly", () => {
const props: PropTypesOf<typeof FacebookButton> = {
onClick: noop,
children: "Login with Facebook",
};
const renderer = createRenderer();
renderer.render(<FacebookButton {...props} />);
expect(renderer.getRenderOutput()).toMatchSnapshot();
});
@@ -0,0 +1,42 @@
import React from "react";
import { StatelessComponent } from "react";
import { PropTypesOf } from "talk-framework/types";
import { Button } from "talk-ui/components";
import styles from "./FacebookButton.css";
interface Props {
onClick: PropTypesOf<typeof Button>["onClick"];
children: React.ReactNode;
}
const facebookIcon = (
<svg
width="17"
height="17"
viewBox="0 0 17 17"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M16.0893 1.25391C16.0893 1.00781 15.9838 0.796875 15.808 0.621094C15.6323 0.480469 15.4213 0.375 15.2104 0.375H1.21819C0.936942 0.375 0.726005 0.480469 0.58538 0.621094C0.409598 0.796875 0.339286 1.00781 0.339286 1.25391V15.2461C0.339286 15.4922 0.409598 15.7031 0.58538 15.8789C0.726005 16.0547 0.936942 16.125 1.21819 16.125H8.74163V10.0078H6.70257V7.65234H8.74163V5.89453C8.74163 4.91016 9.02288 4.13672 9.58538 3.57422C10.1479 3.04688 10.8862 2.76562 11.8002 2.76562C12.5033 2.76562 13.1362 2.80078 13.6283 2.83594V4.98047H12.3627C11.9057 4.98047 11.5893 5.08594 11.4135 5.29688C11.2729 5.47266 11.2026 5.75391 11.2026 6.14062V7.65234H13.558L13.2416 10.0078H11.2026V16.125H15.2104C15.4565 16.125 15.6674 16.0547 15.8432 15.8789C15.9838 15.7031 16.0893 15.4922 16.0893 15.2461V1.25391Z"
fill="white"
/>
</svg>
);
const FacebookButton: StatelessComponent<Props> = props => (
<Button
classes={styles}
variant="filled"
size="large"
fullWidth
onClick={props.onClick}
>
{facebookIcon}
<span>{props.children}</span>
</Button>
);
export default FacebookButton;

Some files were not shown because too many files have changed in this diff Show More