mirror of
https://github.com/wassname/talk.git
synced 2026-07-23 13:10:20 +08:00
[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:
@@ -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";
|
||||
|
||||
@@ -12,6 +12,7 @@ it("renders correctly", () => {
|
||||
gutterEnd: true,
|
||||
className: "custom",
|
||||
};
|
||||
const wrapper = shallow(<AppBar {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const renderer = createRenderer();
|
||||
renderer.render(<AppBar {...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";
|
||||
|
||||
@@ -11,6 +11,7 @@ it("renders correctly", () => {
|
||||
className: "custom",
|
||||
itemGutter: true,
|
||||
};
|
||||
const wrapper = shallow(<End {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const renderer = createRenderer();
|
||||
renderer.render(<End {...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 Divider from "./Divider";
|
||||
|
||||
it("renders correctly", () => {
|
||||
const wrapper = shallow(<Divider />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const renderer = createRenderer();
|
||||
renderer.render(<Divider />);
|
||||
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", () => {
|
||||
className: "custom",
|
||||
itemGutter: true,
|
||||
};
|
||||
const wrapper = shallow(<End {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const renderer = createRenderer();
|
||||
renderer.render(<End {...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: "children",
|
||||
};
|
||||
const wrapper = shallow(<Navigation {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const renderer = createRenderer();
|
||||
renderer.render(<Navigation {...props} />);
|
||||
expect(renderer.getRenderOutput()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
.active {
|
||||
composes: navItemActive from "talk-ui/shared/typography.css";
|
||||
background-color: var(--palette-brand);
|
||||
background-color: var(--palette-brand-main);
|
||||
text-decoration: none;
|
||||
color: var(--palette-text-light);
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -14,6 +14,7 @@ it("renders correctly", () => {
|
||||
active: true,
|
||||
className: "custom",
|
||||
};
|
||||
const wrapper = shallow(<NavigationItem {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const renderer = createRenderer();
|
||||
renderer.render(<NavigationItem {...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";
|
||||
|
||||
@@ -10,6 +10,7 @@ it("renders correctly", () => {
|
||||
className: "custom",
|
||||
size: "lg",
|
||||
};
|
||||
const wrapper = shallow(<BrandIcon {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const renderer = createRenderer();
|
||||
renderer.render(<BrandIcon {...props} />);
|
||||
expect(renderer.getRenderOutput()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.root {
|
||||
font-weight: var(--font-weight-bold);
|
||||
font-family: var(--font-family-sans-serif);
|
||||
color: var(--palette-brand);
|
||||
color: var(--palette-brand-main);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -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", () => {
|
||||
className: "custom",
|
||||
size: "lg",
|
||||
};
|
||||
const wrapper = shallow(<BrandName {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const renderer = createRenderer();
|
||||
renderer.render(<BrandName {...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 Logo> = {
|
||||
className: "custom",
|
||||
};
|
||||
const wrapper = shallow(<Logo {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const renderer = createRenderer();
|
||||
renderer.render(<Logo {...props} />);
|
||||
expect(renderer.getRenderOutput()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
}
|
||||
|
||||
.fullWidth {
|
||||
display: block;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
@@ -57,6 +57,9 @@
|
||||
&.colorSuccess {
|
||||
color: var(--palette-success-main);
|
||||
}
|
||||
&.colorBrand {
|
||||
color: var(--palette-brand-main);
|
||||
}
|
||||
|
||||
&:not(.disabled) {
|
||||
&.colorRegular {
|
||||
@@ -95,6 +98,15 @@
|
||||
color: var(--palette-success-lighter);
|
||||
}
|
||||
}
|
||||
&.colorBrand {
|
||||
&.mouseHover {
|
||||
color: var(--palette-brand-light);
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
color: var(--palette-brand-lighter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +124,9 @@
|
||||
&.colorSuccess {
|
||||
background-color: var(--palette-success-main);
|
||||
}
|
||||
&.colorBrand {
|
||||
background-color: var(--palette-brand-main);
|
||||
}
|
||||
|
||||
&:not(.disabled) {
|
||||
&.colorRegular {
|
||||
@@ -150,6 +165,15 @@
|
||||
background-color: var(--palette-success-lighter);
|
||||
}
|
||||
}
|
||||
&.colorBrand {
|
||||
&.mouseHover {
|
||||
background-color: var(--palette-brand-light);
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
background-color: var(--palette-brand-lighter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,6 +195,10 @@
|
||||
color: var(--palette-success-main);
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
&.colorBrand {
|
||||
color: var(--palette-brand-main);
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
|
||||
&:not(.disabled) {
|
||||
&.colorRegular {
|
||||
@@ -217,6 +245,17 @@
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
}
|
||||
&.colorBrand {
|
||||
&.mouseHover {
|
||||
color: var(--palette-brand-light);
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
color: var(--palette-brand-lighter);
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,6 +273,9 @@
|
||||
&.colorSuccess {
|
||||
color: var(--palette-success-main);
|
||||
}
|
||||
&.colorBrand {
|
||||
color: var(--palette-brand-main);
|
||||
}
|
||||
|
||||
&:not(.disabled) {
|
||||
&.colorRegular {
|
||||
@@ -280,6 +322,17 @@
|
||||
background-color: var(--palette-success-main);
|
||||
}
|
||||
}
|
||||
&.colorBrand {
|
||||
&.mouseHover {
|
||||
border: 1px solid currentColor;
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
border: 1px solid currentColor;
|
||||
color: var(--palette-text-light);
|
||||
background-color: var(--palette-brand-main);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,6 +355,9 @@
|
||||
&.colorSuccess {
|
||||
color: var(--palette-success-main);
|
||||
}
|
||||
&.colorBrand {
|
||||
color: var(--palette-brand-main);
|
||||
}
|
||||
|
||||
&:not(.disabled) {
|
||||
&.colorRegular {
|
||||
@@ -340,5 +396,14 @@
|
||||
color: var(--palette-success-lighter);
|
||||
}
|
||||
}
|
||||
&.colorBrand {
|
||||
&.mouseHover {
|
||||
color: var(--palette-brand-light);
|
||||
}
|
||||
&:active,
|
||||
&.active {
|
||||
color: var(--palette-brand-lighter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ interface InnerProps extends BaseButtonProps {
|
||||
size?: "small" | "regular" | "large";
|
||||
|
||||
/** Color of the button */
|
||||
color?: "regular" | "primary" | "error" | "success";
|
||||
color?: "regular" | "primary" | "error" | "success" | "brand";
|
||||
|
||||
/** Variant of the button */
|
||||
variant?: "regular" | "filled" | "outlined" | "ghost" | "underlined";
|
||||
@@ -72,6 +72,7 @@ export class Button extends React.Component<InnerProps> {
|
||||
[classes.colorPrimary]: color === "primary",
|
||||
[classes.colorError]: color === "error",
|
||||
[classes.colorSuccess]: color === "success",
|
||||
[classes.colorBrand]: color === "brand",
|
||||
[classes.variantRegular]: variant === "regular",
|
||||
[classes.variantFilled]: variant === "filled",
|
||||
[classes.variantOutlined]: variant === "outlined",
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { shallow } from "enzyme";
|
||||
import React from "react";
|
||||
import { createRenderer } from "react-test-renderer/shallow";
|
||||
|
||||
import Counter from "./Counter";
|
||||
|
||||
it("renders correctly", () => {
|
||||
const wrapper = shallow(<Counter>20</Counter>);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const renderer = createRenderer();
|
||||
renderer.render(<Counter>20</Counter>);
|
||||
expect(renderer.getRenderOutput()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -7,6 +7,8 @@ import Typography from "../Typography";
|
||||
import styles from "./InputLabel.css";
|
||||
|
||||
export interface InputLabelProps {
|
||||
id?: string;
|
||||
htmlFor?: string;
|
||||
/**
|
||||
* The content of the component.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { mount, shallow } from "enzyme";
|
||||
import { mount } from "enzyme";
|
||||
import React from "react";
|
||||
import { MediaQueryMatchers } from "react-responsive";
|
||||
import { createRenderer } from "react-test-renderer/shallow";
|
||||
|
||||
import { PropTypesOf } from "talk-ui/types";
|
||||
|
||||
@@ -15,8 +16,9 @@ it("renders correctly", () => {
|
||||
screen: true,
|
||||
children: <div>Hello World</div>,
|
||||
};
|
||||
const wrapper = shallow(<MatchMedia {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const renderer = createRenderer();
|
||||
renderer.render(<MatchMedia {...props} />);
|
||||
expect(renderer.getRenderOutput()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("renders less than and great than correctly", () => {
|
||||
@@ -25,8 +27,9 @@ it("renders less than and great than correctly", () => {
|
||||
gtWidth: "sm",
|
||||
children: <div>Hello World</div>,
|
||||
};
|
||||
const wrapper = shallow(<MatchMedia {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const renderer = createRenderer();
|
||||
renderer.render(<MatchMedia {...props} />);
|
||||
expect(renderer.getRenderOutput()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("map new speech prop to older aural prop", () => {
|
||||
@@ -34,8 +37,9 @@ it("map new speech prop to older aural prop", () => {
|
||||
speech: true,
|
||||
children: <div>Hello World</div>,
|
||||
};
|
||||
const wrapper = shallow(<MatchMedia {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const renderer = createRenderer();
|
||||
renderer.render(<MatchMedia {...props} />);
|
||||
expect(renderer.getRenderOutput()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it("should get mediaQueryValues from context", () => {
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
.root {
|
||||
width: calc(29 * var(--spacing-unit));
|
||||
height: 36px;
|
||||
width: 100%;
|
||||
line-height: 36px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.colorRegular {
|
||||
background-color: var(--palette-common-white);
|
||||
color: var(--palette-common-black);
|
||||
border: 1px solid var(--palette-grey-light);
|
||||
}
|
||||
|
||||
.colorError {
|
||||
background-color: var(--palette-common-white);
|
||||
border-color: var(--palette-error-main);
|
||||
border: 2px solid var(--palette-error-darkest);
|
||||
}
|
||||
|
||||
.fullWidth {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.icon {
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
right: 0px;
|
||||
padding: 4px calc(1 * var(--spacing-unit));
|
||||
cursor: pointer;
|
||||
line-height: 0;
|
||||
}
|
||||
|
||||
.input {
|
||||
composes: inputText placeholderPseudo from "talk-ui/shared/typography.css";
|
||||
display: block;
|
||||
padding: calc(0.5 * var(--spacing-unit)) calc(3 * var(--spacing-unit))
|
||||
calc(0.5 * var(--spacing-unit)) calc(0.5 * var(--spacing-unit));
|
||||
border-radius: var(--round-corners);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:read-only {
|
||||
background-color: var(--palette-grey-lightest);
|
||||
}
|
||||
&:disabled {
|
||||
color: var(--palette-text-secondary);
|
||||
background-color: var(--palette-grey-lightest);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
---
|
||||
name: PasswordField
|
||||
menu: UI Kit
|
||||
---
|
||||
|
||||
import { Playground, PropsTable } from "docz";
|
||||
import PasswordField from "./PasswordField.tsx";
|
||||
import HorizontalGutter from "../HorizontalGutter";
|
||||
|
||||
# PasswordField
|
||||
|
||||
## Basic Use
|
||||
|
||||
<Playground>
|
||||
<HorizontalGutter>
|
||||
<PasswordField placeholder="This is a placeholder" />
|
||||
<PasswordField defaultValue="This is an input field" />
|
||||
<PasswordField color="error" defaultValue="A PasswordField with an error" />
|
||||
<PasswordField
|
||||
color="error"
|
||||
defaultValue="A PasswordField with an error"
|
||||
fullWidth
|
||||
/>
|
||||
</HorizontalGutter>
|
||||
</Playground>
|
||||
@@ -0,0 +1,18 @@
|
||||
import React from "react";
|
||||
import TestRenderer from "react-test-renderer";
|
||||
|
||||
import { PropTypesOf } from "talk-ui/types";
|
||||
|
||||
import PasswordField from "./PasswordField";
|
||||
|
||||
it("renders correctly", () => {
|
||||
const props: PropTypesOf<typeof PasswordField> = {
|
||||
className: "custom",
|
||||
defaultValue: "Hello World",
|
||||
};
|
||||
const renderer = TestRenderer.create(<PasswordField {...props} />);
|
||||
expect(renderer.toJSON()).toMatchSnapshot();
|
||||
|
||||
renderer.root.findByProps({ role: "button" }).props.onClick();
|
||||
expect(renderer.toJSON()).toMatchSnapshot();
|
||||
});
|
||||
@@ -0,0 +1,148 @@
|
||||
import cn from "classnames";
|
||||
import React, {
|
||||
AllHTMLAttributes,
|
||||
ChangeEvent,
|
||||
Component,
|
||||
EventHandler,
|
||||
MouseEvent,
|
||||
} from "react";
|
||||
import { withStyles } from "talk-ui/hocs";
|
||||
|
||||
import Icon from "../Icon";
|
||||
import styles from "./PasswordField.css";
|
||||
|
||||
export interface PasswordFieldProps {
|
||||
id?: string;
|
||||
/**
|
||||
* The content value of the component.
|
||||
*/
|
||||
defaultValue?: string;
|
||||
/**
|
||||
* The content value of the component.
|
||||
*/
|
||||
value?: string;
|
||||
/**
|
||||
* Convenient prop to override the root styling.
|
||||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Override or extend the styles applied to the component.
|
||||
*/
|
||||
classes: typeof styles;
|
||||
/**
|
||||
* Color of the PasswordField
|
||||
*/
|
||||
color?: "regular" | "error";
|
||||
/*
|
||||
* If set renders a full width button
|
||||
*/
|
||||
fullWidth?: boolean;
|
||||
/**
|
||||
* Placeholder
|
||||
*/
|
||||
placeholder?: string;
|
||||
/**
|
||||
* Mark as readonly
|
||||
*/
|
||||
readOnly?: boolean;
|
||||
/**
|
||||
* Name
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* onChange
|
||||
*/
|
||||
onChange?: EventHandler<ChangeEvent<HTMLInputElement>>;
|
||||
|
||||
disabled?: boolean;
|
||||
|
||||
autoComplete?: AllHTMLAttributes<HTMLInputElement>["autoComplete"];
|
||||
autoCorrect?: AllHTMLAttributes<HTMLInputElement>["autoCorrect"];
|
||||
autoCapitalize?: AllHTMLAttributes<HTMLInputElement>["autoCapitalize"];
|
||||
spellCheck?: AllHTMLAttributes<HTMLInputElement>["spellCheck"];
|
||||
|
||||
showPasswordTitle?: string;
|
||||
hidePasswordTitle?: string;
|
||||
}
|
||||
|
||||
interface State {
|
||||
reveal: boolean;
|
||||
}
|
||||
|
||||
class PasswordField extends Component<PasswordFieldProps, State> {
|
||||
public static defaultProps: Partial<PasswordFieldProps> = {
|
||||
color: "regular",
|
||||
placeholder: "",
|
||||
showPasswordTitle: "Hide password",
|
||||
hidePasswordTitle: "Show password",
|
||||
};
|
||||
|
||||
public state = {
|
||||
reveal: false,
|
||||
};
|
||||
|
||||
private handleToggleVisibility = (e: MouseEvent) => {
|
||||
this.setState(state => ({
|
||||
reveal: !state.reveal,
|
||||
}));
|
||||
};
|
||||
|
||||
public render() {
|
||||
const {
|
||||
className,
|
||||
classes,
|
||||
color,
|
||||
fullWidth,
|
||||
value,
|
||||
placeholder,
|
||||
hidePasswordTitle,
|
||||
showPasswordTitle,
|
||||
...rest
|
||||
} = this.props;
|
||||
|
||||
const rootClassName = cn(
|
||||
{
|
||||
[classes.fullWidth]: fullWidth,
|
||||
},
|
||||
classes.root,
|
||||
className
|
||||
);
|
||||
|
||||
const inputClassName = cn(
|
||||
{
|
||||
[classes.colorRegular]: color === "regular",
|
||||
[classes.colorError]: color === "error",
|
||||
[classes.fullWidth]: fullWidth,
|
||||
},
|
||||
classes.input
|
||||
);
|
||||
|
||||
const reveal = this.state.reveal;
|
||||
|
||||
return (
|
||||
<div className={rootClassName}>
|
||||
<div className={classes.wrapper}>
|
||||
<input
|
||||
className={inputClassName}
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
type={reveal ? "text" : "password"}
|
||||
{...rest}
|
||||
/>
|
||||
<div
|
||||
role="button"
|
||||
className={styles.icon}
|
||||
title={reveal ? hidePasswordTitle : showPasswordTitle}
|
||||
onClick={this.handleToggleVisibility}
|
||||
tabIndex={0}
|
||||
>
|
||||
<Icon>{reveal ? "visibility_off" : "visibility"}</Icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const enhanced = withStyles(styles)(PasswordField);
|
||||
export default enhanced;
|
||||
@@ -0,0 +1,63 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`renders correctly 1`] = `
|
||||
<div
|
||||
className="PasswordField-root custom"
|
||||
>
|
||||
<div
|
||||
className="PasswordField-wrapper"
|
||||
>
|
||||
<input
|
||||
className="PasswordField-colorRegular PasswordField-input"
|
||||
defaultValue="Hello World"
|
||||
placeholder=""
|
||||
type="password"
|
||||
/>
|
||||
<div
|
||||
className="PasswordField-icon"
|
||||
onClick={[Function]}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
title="Hide password"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="Icon-root Icon-sm"
|
||||
>
|
||||
visibility
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders correctly 2`] = `
|
||||
<div
|
||||
className="PasswordField-root custom"
|
||||
>
|
||||
<div
|
||||
className="PasswordField-wrapper"
|
||||
>
|
||||
<input
|
||||
className="PasswordField-colorRegular PasswordField-input"
|
||||
defaultValue="Hello World"
|
||||
placeholder=""
|
||||
type="text"
|
||||
/>
|
||||
<div
|
||||
className="PasswordField-icon"
|
||||
onClick={[Function]}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
title="Show password"
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className="Icon-root Icon-sm"
|
||||
>
|
||||
visibility_off
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@@ -0,0 +1,2 @@
|
||||
export * from "./PasswordField";
|
||||
export { default } from "./PasswordField";
|
||||
@@ -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: "children",
|
||||
};
|
||||
const wrapper = shallow(<Navigation {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const renderer = createRenderer();
|
||||
renderer.render(<Navigation {...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";
|
||||
|
||||
@@ -14,6 +14,7 @@ it("renders correctly", () => {
|
||||
active: true,
|
||||
className: "custom",
|
||||
};
|
||||
const wrapper = shallow(<NavigationItem {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const renderer = createRenderer();
|
||||
renderer.render(<NavigationItem {...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";
|
||||
|
||||
@@ -12,6 +12,7 @@ it("renders correctly", () => {
|
||||
gutterEnd: true,
|
||||
className: "custom",
|
||||
};
|
||||
const wrapper = shallow(<SubBar {...props} />);
|
||||
expect(wrapper).toMatchSnapshot();
|
||||
const renderer = createRenderer();
|
||||
renderer.render(<SubBar {...props} />);
|
||||
expect(renderer.getRenderOutput()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@@ -45,3 +45,4 @@ export { BrandIcon, BrandName, Logo } from "./Brand";
|
||||
export { default as Counter } from "./Counter";
|
||||
export { Marker, Count as MarkerCount } from "./Marker";
|
||||
export { default as Card } from "./Card";
|
||||
export { default as PasswordField } from "./PasswordField";
|
||||
|
||||
@@ -61,8 +61,12 @@ const variables = {
|
||||
},
|
||||
/* Divider */
|
||||
divider: "rgba(0, 0, 0, 0.12)",
|
||||
brand: "#F77160",
|
||||
highlight: "#FFD863",
|
||||
brand: {
|
||||
main: "#f77160",
|
||||
light: "#f97f70",
|
||||
lighter: "#fc9e92",
|
||||
},
|
||||
},
|
||||
/* gitter and spacing */
|
||||
spacingUnitSmall: 5,
|
||||
|
||||
Reference in New Issue
Block a user