Skip to content

Commit

Permalink
[C-3139] Add create password page (#6186)
Browse files Browse the repository at this point in the history
  • Loading branch information
dylanjeffers authored Oct 2, 2023
1 parent 50f9e28 commit e254d74
Show file tree
Hide file tree
Showing 17 changed files with 308 additions and 61 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 16 additions & 2 deletions packages/mobile/e2e/signUp.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,28 @@ describe('Sign up', () => {
await assertOnSignUp()
})

it.only('should create an account', async () => {
it('should create an account', async () => {
const testUser = generateTestUser()
const { email } = testUser
const { email, password } = testUser
await byRole('textbox', { name: /email/i }).typeText(email)
await byRole('button', { name: /sign up free/i }).tap()

await expect(
byRole('heading', { name: /create your password/i })
).toBeVisible()

await expect(
byText(/create a password that's secure and easy to remember! .*/i)
).toBeVisible()

await expect(byText(/your email/i)).toBeVisible()

await expect(byText(email)).toBeVisible()

await byRole('textbox', { name: /^password/i }).typeText(password)
await byRole('textbox', { name: /confirm password/i }).typeText(password)
await byRole('button', { name: /continue/i }).tap()

await expect(byRole('heading', { name: /pick your handle/i })).toBeVisible()
})
})
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { createNativeStackNavigator } from '@react-navigation/native-stack'

import { CreatePasswordScreen } from './screens/CreatePasswordScreen'
import { PickHandleScreen } from './screens/PickHandleScreen'
import { SignUpScreen } from './screens/SignUpScreen'

const Stack = createNativeStackNavigator()
Expand All @@ -11,6 +12,7 @@ export const SignUpRootScreen = () => {
<Stack.Navigator initialRouteName='SignUp' screenOptions={screenOptions}>
<Stack.Screen name='SignUp' component={SignUpScreen} />
<Stack.Screen name='CreatePassword' component={CreatePasswordScreen} />
<Stack.Screen name='PickHandle' component={PickHandleScreen} />
</Stack.Navigator>
)
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,83 @@
import { useCallback } from 'react'

import { setValueField } from 'audius-client/src/common/store/pages/signon/actions'
import { Formik } from 'formik'
import { View } from 'react-native'
import { useDispatch } from 'react-redux'

import { Button, Text } from 'app/components/core'
import { TextField } from 'app/components/fields'
import { useNavigation } from 'app/hooks/useNavigation'

import { Text } from 'app/components/core'
import type { SignUpScreenParamList } from '../types'
import { useRoute } from '../useRoute'

const messages = {
header: 'Create Your Password'
header: 'Create Your Password',
description:
"Create a password that's secure and easy to remember! We can't reset your password, so write it down or use a password manager.",
yourEmail: 'Your Email',
passwordLabel: 'Password',
confirmPasswordLabel: 'Confirm Password',
continue: 'Continue'
}

export type CreatePasswordParams = {
email: string
}

const initialValues = {
password: '',
confirmPassword: ''
}

type CreatePasswordValues = {
password: string
confirmPassword: string
}

export const CreatePasswordScreen = () => {
const { params } = useRoute<'CreatePassword'>()
const { email } = params
const dispatch = useDispatch()
const navigation = useNavigation<SignUpScreenParamList>()

const handleSubmit = useCallback(
(values: CreatePasswordValues) => {
const { password } = values
dispatch(setValueField('password', password))
navigation.navigate('PickHandle')
},
[dispatch, navigation]
)

return (
<View>
<Text>{messages.header}</Text>
<Text>{messages.description}</Text>

<Text>{messages.yourEmail}</Text>
<Text>{email}</Text>

<Formik initialValues={initialValues} onSubmit={handleSubmit}>
{({ handleSubmit }) => (
<View>
<TextField
name='password'
label={messages.passwordLabel}
textContentType='password'
secureTextEntry
/>
<TextField
name='confirmPassword'
label={messages.confirmPasswordLabel}
textContentType='password'
secureTextEntry
/>
<Button title={messages.continue} onPress={() => handleSubmit()} />
</View>
)}
</Formik>
</View>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { View } from 'react-native'

import { Text } from 'app/components/core'

const messages = {
header: 'Pick Your Handle'
}
export const PickHandleScreen = () => {
return (
<View>
<Text>{messages.header}</Text>
</View>
)
}
5 changes: 4 additions & 1 deletion packages/mobile/src/screens/sign-up-screen/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import type { CreatePasswordParams } from './screens/CreatePasswordScreen'

export type SignUpScreenParamList = {
SignUp: undefined
CreatePassword: { email: string }
CreatePassword: CreatePasswordParams
PickHandle: undefined
}
8 changes: 8 additions & 0 deletions packages/mobile/src/screens/sign-up-screen/useRoute.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { RouteProp } from '@react-navigation/core'
import { useRoute as useRouteRN } from '@react-navigation/core'

import type { SignUpScreenParamList } from './types'

export const useRoute = <RouteName extends keyof SignUpScreenParamList>() => {
return useRouteRN<RouteProp<SignUpScreenParamList, RouteName>>()
}
51 changes: 37 additions & 14 deletions packages/probers/cypress/e2e/signUp.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,27 @@ function generateTestUser() {
}
}

type User = {
email: string
}

function assertOnSignUpPage() {
cy.findByRole('heading', { name: /sign up for audius/i, level: 1 }).should(
'exist'
)
}

function assertOnCreatePasswordPage(user: User) {
cy.findByRole('heading', { name: /create your password/i }).should('exist')

cy.findByText(
/create a password that's secure and easy to remember!/i
).should('exist')

cy.findByText(/your email/i).should('exist')
cy.findByText(user.email).should('exist')
}

describe('Sign Up', () => {
beforeEach(() => {
localStorage.setItem('FeatureFlagOverride:sign_up_redesign', 'enabled')
Expand Down Expand Up @@ -55,57 +70,65 @@ describe('Sign Up', () => {

it('should create an account', () => {
const testUser = generateTestUser()
const { email } = testUser
const { email, password } = testUser
cy.visit('signup')
cy.findByRole('textbox', { name: /email/i }).type(email)
cy.findByRole('button', { name: /sign up free/i }).click()

cy.findByRole('heading', { name: /create your password/i }).should(
'exist'
)
assertOnCreatePasswordPage(testUser)

cy.findByRole('textbox', { name: /^password/i }).type(password)
cy.findByRole('textbox', { name: /confirm password/i }).type(password)
cy.findByRole('button', { name: /continue/i }).click()

cy.findByRole('heading', { name: /pick your handle/i }).should('exist')
})
})

context.only('mobile', () => {
context('mobile', () => {
beforeEach(() => {
cy.viewport('iphone-x')
})

it('can navigate to signup from trending', () => {
cy.visitMobile('trending')
cy.visit('trending')
cy.findByRole('link', { name: /sign up/i }).click()
assertOnSignUpPage()
})

it('/signup goes to sign-up', () => {
cy.visitMobile('signup')
cy.visit('signup')
assertOnSignUpPage()
})

it('can navigate to sign-up from sign-in', () => {
cy.visitMobile('signin')
cy.visit('signin')
cy.findByRole('link', { name: /create an account/i }).click()

assertOnSignUpPage()
})

it('can navigate to sign-up from the public site', () => {
cy.visitMobile('')
cy.visit('')
cy.findByRole('button', { name: /sign up free/i }).click()

assertOnSignUpPage()
})

it('should create an account', () => {
const testUser = generateTestUser()
const { email } = testUser
cy.visitMobile('signup')
const { email, password } = testUser
cy.visit('signup')
cy.findByRole('textbox', { name: /email/i }).type(email)
cy.findByRole('button', { name: /sign up free/i }).click()

cy.findByRole('heading', { name: /create your password/i }).should(
'exist'
)
assertOnCreatePasswordPage(testUser)

cy.findByRole('textbox', { name: /^password/i }).type(password)
cy.findByRole('textbox', { name: /confirm password/i }).type(password)
cy.findByRole('button', { name: /continue/i }).click()

cy.findByRole('heading', { name: /pick your handle/i }).should('exist')
})
})
})
14 changes: 0 additions & 14 deletions packages/probers/cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,6 @@ declare global {
* @example cy.login()
*/
login(): Chainable<JQuery<HTMLElement>>
/**
* Custom command to visit url from mobile device.
* @example cy.visitMobile('trending')
*/
visitMobile(url: string): Chainable<JQuery<HTMLElement>>
}
}
}
Expand All @@ -28,12 +23,3 @@ Cypress.Commands.add('login', () => {
cy.visit(`trending?login=${base64Entropy}`)
cy.findByRole('link', { name: user.name }).should('exist')
})

Cypress.Commands.add('visitMobile', (url) => {
cy.visit(url, {
headers: {
'user-agent':
'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1'
}
})
})
2 changes: 1 addition & 1 deletion packages/web/src/common/utils/isMobileWeb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const isMobileWeb = () => {
if (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)
check = true

if (navigator.userAgent === 'probers' && window.innerWidth < 300) {
if (navigator.userAgent === 'probers' && window.innerWidth < 500) {
check = true
}
return check
Expand Down
4 changes: 2 additions & 2 deletions packages/web/src/pages/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ import { WithdrawalsPage } from './purchases-and-sales/WithdrawalsPage'
import SettingsPage from './settings-page/SettingsPage'
import { SubPage } from './settings-page/components/mobile/SettingsPage'
import { SignInPage } from './sign-in-page'
import { SignUpPage } from './sign-up-page'
import { SignUpRootPage } from './sign-up-page'
import SmartCollectionPage from './smart-collection/SmartCollectionPage'
import SupportingPage from './supporting-page/SupportingPage'
import TopSupportersPage from './top-supporters-page/TopSupportersPage'
Expand Down Expand Up @@ -514,7 +514,7 @@ class App extends Component {
<Route exact path={SIGN_UP_PAGE} isMobile={isMobileClient}>
(
{isSignInRedesignEnabled ? (
<SignUpPage />
<SignUpRootPage />
) : (
<SignOn signIn={false} initialPage={initialPage} />
)}
Expand Down
32 changes: 32 additions & 0 deletions packages/web/src/pages/sign-up-page/SignUpRootPage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { useState } from 'react'

import {
CreatePasswordPage,
CreatePasswordState
} from './pages/CreatePasswordPage'
import { PickHandlePage, PickHandleState } from './pages/PickHandlePage'
import { SignUpPage, SignUpState } from './pages/SignUpPage'

type SignUpRootState = SignUpState | CreatePasswordState | PickHandleState

export const SignUpRootPage = () => {
const [signUpState, setSignUpState] = useState<SignUpRootState>({
stage: 'sign-up'
})

return (
<div>
{signUpState.stage === 'sign-up' ? (
<SignUpPage onNext={setSignUpState} />
) : null}
{signUpState.stage === 'create-password' ? (
<CreatePasswordPage
params={signUpState.params}
onPrevious={setSignUpState}
onNext={setSignUpState}
/>
) : null}
{signUpState.stage === 'create-password' ? <PickHandlePage /> : null}
</div>
)
}
2 changes: 1 addition & 1 deletion packages/web/src/pages/sign-up-page/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from './SignUpPage'
export * from './SignUpRootPage'
Loading

0 comments on commit e254d74

Please sign in to comment.