Skip to content

Commit

Permalink
feat(rna): Add SignIn subcomponent (#2812)
Browse files Browse the repository at this point in the history
* feat(rna): Add SignIn subcomponent
  • Loading branch information
calebpollman authored Oct 25, 2022
1 parent 198eedc commit d6d2e27
Show file tree
Hide file tree
Showing 23 changed files with 1,280 additions and 66 deletions.
53 changes: 46 additions & 7 deletions examples/react-native/storybook/stories/SignIn.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,50 @@
import React from 'react';
import { storiesOf } from '@storybook/react-native';
import { SignIn } from '@aws-amplify/ui-react-native/dist/Authenticator/Defaults';
import { Authenticator } from '@aws-amplify/ui-react-native';
import noop from 'lodash/noop';

const props = {} as any;
const username = {
name: 'username',
label: 'Username',
placeholder: 'Username',
type: 'default' as const,
};

storiesOf('SignIn', module)
.add('default', () => <SignIn {...props} />)
.add('header', () => <SignIn.Header />)
.add('footer', () => <SignIn.Footer />)
.add('formFields', () => <SignIn.FormFields {...props} />);
const password = {
name: 'password',
label: 'Password',
placeholder: 'Password',
type: 'password' as const,
};

const fields = [username, password];

const baseProps = {
fields,
Footer: Authenticator.SignIn.Footer,
FormFields: Authenticator.SignIn.FormFields,
Header: Authenticator.SignIn.Header,
hideSignUp: false,
isPending: false,
handleBlur: noop,
handleSubmit: (values: any) => {
console.log('Values', values);
},
handleChange: noop,
toFederatedSignIn: noop,
toResetPassword: noop,
toSignUp: noop,
error: null as unknown as string,
};

storiesOf('Authenticator.SignIn', module)
.add('Basic', () => <Authenticator.SignIn {...baseProps} />)
.add('With error', () => (
<Authenticator.SignIn {...baseProps} error={'Error!'} />
))
.add('With Social Providers', () => (
<Authenticator.SignIn
{...baseProps}
socialProviders={['amazon', 'facebook']}
/>
));
2 changes: 1 addition & 1 deletion packages/react-native/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"rimraf": "^3.0.2"
},
"dependencies": {
"@aws-amplify/ui": "3.14.0",
"@aws-amplify/ui": "4.0.0",
"@aws-amplify/ui-react-core": "1.0.3"
},
"peerDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Text } from 'react-native';

import { DefaultFooter } from '../../common/DefaultFooter';
import { DefaultHeader } from '../../common/DefaultHeader';
import { DefaultFormFields } from '../FormFields';
import { DefaultFormFields } from '../../common/DefaultFormFields';
import { DefaultConfirmResetPasswordComponent } from '../types';

const ConfirmResetPassword: DefaultConfirmResetPasswordComponent = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Text } from 'react-native';

import { DefaultFooter } from '../../common/DefaultFooter';
import { DefaultHeader } from '../../common/DefaultHeader';
import { DefaultFormFields } from '../FormFields';
import { DefaultFormFields } from '../../common/DefaultFormFields';
import { DefaultConfirmSignInComponent } from '../types';

const ConfirmSignIn: DefaultConfirmSignInComponent = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Text } from 'react-native';

import { DefaultFooter } from '../../common/DefaultFooter';
import { DefaultHeader } from '../../common/DefaultHeader';
import { DefaultFormFields } from '../FormFields';
import { DefaultFormFields } from '../../common/DefaultFormFields';
import { DefaultConfirmSignUpComponent } from '../types';

const ConfirmSignUp: DefaultConfirmSignUpComponent = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import { Text } from 'react-native';

import { DefaultFooter } from '../../common/DefaultFooter';
import { DefaultFormFields } from '../FormFields';
import { DefaultFormFields } from '../../common/DefaultFormFields';
import { DefaultHeader } from '../../common/DefaultHeader';
import { DefaultConfirmVerifyUserComponent } from '../types';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Text } from 'react-native';

import { DefaultFooter } from '../../common/DefaultFooter';
import { DefaultHeader } from '../../common/DefaultHeader';
import { DefaultFormFields } from '../FormFields';
import { DefaultFormFields } from '../../common/DefaultFormFields';
import { DefaultForceNewPasswordComponent } from '../types';

const ForceNewPassword: DefaultForceNewPasswordComponent = () => {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Text } from 'react-native';

import { DefaultFooter } from '../../common/DefaultFooter';
import { DefaultHeader } from '../../common/DefaultHeader';
import { DefaultFormFields } from '../FormFields';
import { DefaultFormFields } from '../../common/DefaultFormFields';
import { DefaultResetPasswordComponent } from '../types';

const ResetPassword: DefaultResetPasswordComponent = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Text } from 'react-native';

import { DefaultFooter } from '../../common/DefaultFooter';
import { DefaultHeader } from '../../common/DefaultHeader';
import { DefaultFormFields } from '../FormFields';
import { DefaultFormFields } from '../../common/DefaultFormFields';
import { DefaultSetupTOTPComponent } from '../types';

const SetupTOTP: DefaultSetupTOTPComponent = () => {
Expand Down
102 changes: 96 additions & 6 deletions packages/react-native/src/Authenticator/Defaults/SignIn/SignIn.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,103 @@
import React from 'react';
import { Text } from 'react-native';
import { StyleSheet, TextStyle, View, ViewStyle } from 'react-native';

import { authenticatorTextUtil } from '@aws-amplify/ui';

import {
DefaultFooter,
DefaultFormFields,
DefaultHeader,
FederatedProviderButtons,
} from '../../common';

import { Button, ErrorMessage, Tab, Tabs } from '../../../primitives';

import { DefaultFooter } from '../../common/DefaultFooter';
import { DefaultHeader } from '../../common/DefaultHeader';
import { DefaultFormFields } from '../FormFields';
import { DefaultSignInComponent } from '../types';

const SignIn: DefaultSignInComponent = () => {
return <Text>SignIn</Text>;
// TODO: clean these up once primitive theming is in place
interface DefaultSignInStyle {
buttonPrimary: ViewStyle;
buttonPrimaryLabel: TextStyle;
buttonSecondary: ViewStyle;
buttonSecondaryLabel: TextStyle;
container: ViewStyle;
tabs: ViewStyle;
}

const styles: DefaultSignInStyle = StyleSheet.create({
container: {
justifyContent: 'center',
flex: 1,
padding: 16,
},
buttonPrimary: {
backgroundColor: 'teal',
marginVertical: 8,
paddingVertical: 12,
},
buttonPrimaryLabel: { color: 'white', fontSize: 16, fontWeight: 'bold' },
buttonSecondary: {
marginVertical: 8,
paddingVertical: 12,
},
buttonSecondaryLabel: { color: 'teal' },
tabs: { marginBottom: 8 },
});

const SignIn: DefaultSignInComponent = ({
error,
fields,
Footer,
FormFields,
Header,
hideSignUp,
isPending,
socialProviders,
toResetPassword,
toFederatedSignIn,
toSignUp,
}) => {
const {
getSignInText,
getSignInTabText,
getCreateAccountText,
getForgotPasswordText,
} = authenticatorTextUtil;

return (
<View style={styles.container}>
{hideSignUp ? null : (
<Tabs style={styles.tabs}>
<Tab>{getSignInTabText()}</Tab>
<Tab onPress={toSignUp}>{getCreateAccountText()}</Tab>
</Tabs>
)}
<Header />
{socialProviders ? (
<FederatedProviderButtons
socialProviders={socialProviders}
toFederatedSignIn={toFederatedSignIn}
/>
) : null}
<FormFields fields={fields} isPending={isPending} />
{error ? <ErrorMessage>{error}</ErrorMessage> : null}
<Button
style={styles.buttonPrimary}
textStyle={styles.buttonPrimaryLabel}
>
{getSignInText()}
</Button>
<Footer>
<Button
onPress={toResetPassword}
style={styles.buttonSecondary}
textStyle={styles.buttonSecondaryLabel}
>
{getForgotPasswordText()}
</Button>
</Footer>
</View>
);
};

SignIn.Footer = DefaultFooter;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,57 @@
import React from 'react';
import { render } from '@testing-library/react-native';

import { SignIn } from '..';
import SignIn from '../SignIn';

const props = {} as any;
const props = {
fields: [],
Footer: SignIn.Footer,
FormFields: SignIn.FormFields,
handleBlur: jest.fn(),
handleChange: jest.fn(),
handleSubmit: jest.fn(),
Header: SignIn.Header,
isPending: false,
socialProviders: undefined,
toResetPassword: jest.fn(),
toFederatedSignIn: jest.fn(),
toSignUp: jest.fn(),
};

describe('SignIn', () => {
it('renders as expected', () => {
const { toJSON, getByRole } = render(
<>
<SignIn {...props} />
<SignIn.Header />
<SignIn.Footer />
<SignIn.FormFields {...props} />
</>
);
const { toJSON, getByRole, getAllByRole } = render(<SignIn {...props} />);
expect(toJSON()).toMatchSnapshot();

expect(getAllByRole('tab')).toHaveLength(2);
expect(getByRole('header')).toBeDefined();
});

it('renders as expected with an error', () => {
const error = 'An error!';
const { getByRole, getByText, toJSON } = render(
<SignIn {...props} error={error} />
);

expect(getByRole('alert')).toBeDefined();
expect(getByText(error)).toBeDefined();

expect(toJSON()).toMatchSnapshot();
});

it('renders as expected when hideSignUp is true', () => {
const { toJSON } = render(<SignIn {...props} hideSignUp />);
expect(toJSON()).toMatchSnapshot();
});

it('renders as expected with socialProviders', () => {
const { toJSON, getByText } = render(
<SignIn {...props} socialProviders={['amazon', 'facebook']} />
);

expect(getByText('Sign In with Amazon')).toBeDefined();
expect(getByText('Sign In with Facebook')).toBeDefined();

expect(toJSON()).toMatchSnapshot();
});
});
Loading

0 comments on commit d6d2e27

Please sign in to comment.