Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[C-3139] Add create password page #6186

Merged
merged 3 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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