diff --git a/cypress/e2e/alerts.cy.ts b/cypress/e2e/alerts.cy.ts
index b4e666af14f..b9881ded5c4 100644
--- a/cypress/e2e/alerts.cy.ts
+++ b/cypress/e2e/alerts.cy.ts
@@ -2,7 +2,7 @@ describe("user/alerts", () => {
describe("unauthenticated", () => {
it("redirects to the login page", () => {
cy.visit("user/alerts")
- cy.contains("Log in")
+ cy.contains("Sign up or log in")
})
})
})
diff --git a/cypress/e2e/notifications.cy.ts b/cypress/e2e/notifications.cy.ts
index 66d4117d929..e10b11e966d 100644
--- a/cypress/e2e/notifications.cy.ts
+++ b/cypress/e2e/notifications.cy.ts
@@ -4,7 +4,7 @@ describe("/notifications", () => {
describe("unauthenticated", () => {
it("redirects to the login page", () => {
cy.visit("/notifications")
- cy.contains("Log in")
+ cy.contains("Sign up or log in")
})
})
})
diff --git a/cypress/e2e/userPayments.cy.js b/cypress/e2e/userPayments.cy.js
index eb70bd91025..73f853e665a 100644
--- a/cypress/e2e/userPayments.cy.js
+++ b/cypress/e2e/userPayments.cy.js
@@ -2,7 +2,7 @@ describe("user/payments", () => {
describe("unauthenticated", () => {
it("redirects to the login page", () => {
cy.visit("user/payments")
- cy.contains("Log in")
+ cy.contains("Sign up or log in")
})
})
})
diff --git a/cypress/e2e/userShipping.cy.js b/cypress/e2e/userShipping.cy.js
index 5448657bbe9..4a1d893a42a 100644
--- a/cypress/e2e/userShipping.cy.js
+++ b/cypress/e2e/userShipping.cy.js
@@ -2,7 +2,7 @@ describe("user/shipping", () => {
describe("unauthenticated", () => {
it("redirects to the login page", () => {
cy.visit("user/shipping")
- cy.contains("Log in")
+ cy.contains("Sign up or log in")
})
})
})
diff --git a/docs/authentication.md b/docs/authentication.md
index f5d9894b85a..b1cb00c0ff0 100644
--- a/docs/authentication.md
+++ b/docs/authentication.md
@@ -41,7 +41,6 @@ const YourComponent = () => {
+
+ {isFallback && (
+
+ Already have an account?{" "}
+ {
+ dispatch({ type: "MODE", payload: { mode: "Login" } })
+ }}
+ >
+ Log in.
+
+
)}
- .
-
+
-
- This site is protected by reCAPTCHA and the{" "}
-
- Google Privacy Policy
- {" "}
- and{" "}
-
- Terms of Service
- {" "}
- apply.
-
-
+
+
)
}}
@@ -264,34 +208,3 @@ const VALIDATION_SCHEMA = Yup.object().shape({
.required("Please enter a valid email."),
password: passwordValidator,
})
-
-const GDPR_COUNTRY_CODES = [
- "AT",
- "BE",
- "BG",
- "CY",
- "CZ",
- "DE",
- "DK",
- "EE",
- "ES",
- "FI",
- "FR",
- "GB",
- "GR",
- "HR",
- "HU",
- "IE",
- "IT",
- "LT",
- "LU",
- "LV",
- "MT",
- "NL",
- "PL",
- "PT",
- "RO",
- "SE",
- "SI",
- "SK",
-]
diff --git a/src/Components/AuthDialog/Views/AuthDialogWelcome.tsx b/src/Components/AuthDialog/Views/AuthDialogWelcome.tsx
new file mode 100644
index 00000000000..575a101ca4a
--- /dev/null
+++ b/src/Components/AuthDialog/Views/AuthDialogWelcome.tsx
@@ -0,0 +1,139 @@
+import * as Yup from "yup"
+import { Button, Input, Stack, Text } from "@artsy/palette"
+import { FC } from "react"
+import { Form, Formik } from "formik"
+import { AuthDialogSocial } from "Components/AuthDialog/Components/AuthDialogSocial"
+import { AuthDialogDisclaimer } from "Components/AuthDialog/Views/AuthDialogDisclaimer"
+import { fetchQuery, graphql } from "react-relay"
+import { AuthDialogWelcomeQuery } from "__generated__/AuthDialogWelcomeQuery.graphql"
+import { useSystemContext } from "System/Hooks/useSystemContext"
+import {
+ DEFAULT_AUTH_MODAL_INTENTS,
+ useAuthDialogContext,
+} from "Components/AuthDialog/AuthDialogContext"
+import { recaptcha } from "Utils/recaptcha"
+
+interface AuthDialogWelcomeProps {}
+
+export const AuthDialogWelcome: FC = () => {
+ const { relayEnvironment } = useSystemContext()
+
+ const { dispatch, state } = useAuthDialogContext()
+
+ return (
+ {
+ try {
+ const recaptchaToken = await recaptcha("verify_user")
+
+ const res = await fetchQuery(
+ relayEnvironment,
+ QUERY,
+ { email, recaptchaToken: recaptchaToken ?? "" }
+ ).toPromise()
+
+ const exists = !!res?.verifyUser?.exists
+ const mode = exists ? "Login" : "SignUp"
+
+ dispatch({
+ type: "SET",
+ payload: {
+ values: { email },
+ analytics: {
+ ...state.analytics,
+ intent: DEFAULT_AUTH_MODAL_INTENTS[mode],
+ },
+ },
+ })
+
+ dispatch({
+ type: "MODE",
+ payload: { mode },
+ })
+ } catch (error) {
+ console.error(error)
+
+ dispatch({
+ type: "SET",
+ payload: {
+ values: { email },
+ analytics: {
+ ...state.analytics,
+ intent: DEFAULT_AUTH_MODAL_INTENTS.SignUp,
+ },
+ },
+ })
+
+ dispatch({ type: "FALLBACK" })
+ }
+ }}
+ >
+ {({
+ dirty,
+ errors,
+ handleBlur,
+ handleChange,
+ isSubmitting,
+ isValid,
+ touched,
+ values,
+ }) => {
+ return (
+
+ )
+ }}
+
+ )
+}
+
+const VALIDATION_SCHEMA = Yup.object().shape({
+ email: Yup.string()
+ .email("Please enter a valid email.")
+ .required("Email required."),
+})
+
+const QUERY = graphql`
+ query AuthDialogWelcomeQuery($email: String!, $recaptchaToken: String!) {
+ verifyUser(email: $email, recaptchaToken: $recaptchaToken) {
+ exists
+ }
+ }
+`
diff --git a/src/Components/AuthDialog/Views/__tests__/AuthDialogForgotPassword.jest.tsx b/src/Components/AuthDialog/Views/__tests__/AuthDialogForgotPassword.jest.tsx
index e091f3971a4..d130a55d5d0 100644
--- a/src/Components/AuthDialog/Views/__tests__/AuthDialogForgotPassword.jest.tsx
+++ b/src/Components/AuthDialog/Views/__tests__/AuthDialogForgotPassword.jest.tsx
@@ -36,8 +36,6 @@ describe("AuthDialogForgotPassword", () => {
// eslint-disable-next-line testing-library/no-node-access
const button = submit.parentElement!
- expect(button).toBeDisabled()
-
fireEvent.change(input, { target: { value: "example@example.com" } })
expect(button).toBeEnabled()
diff --git a/src/Components/AuthDialog/Views/__tests__/AuthDialogLogin.jest.tsx b/src/Components/AuthDialog/Views/__tests__/AuthDialogLogin.jest.tsx
index 1285e2d5d34..119d3e55575 100644
--- a/src/Components/AuthDialog/Views/__tests__/AuthDialogLogin.jest.tsx
+++ b/src/Components/AuthDialog/Views/__tests__/AuthDialogLogin.jest.tsx
@@ -19,6 +19,18 @@ jest.mock("Utils/auth", () => ({
login: jest.fn(),
}))
+jest.mock("Components/AuthDialog/AuthDialogContext", () => ({
+ useAuthDialogContext: jest.fn().mockReturnValue({
+ state: {
+ analytics: {},
+ options: {},
+ values: {
+ email: "example@example.com",
+ },
+ },
+ }),
+}))
+
describe("AuthDialogLogin", () => {
it("renders correctly", () => {
render()
@@ -26,21 +38,12 @@ describe("AuthDialogLogin", () => {
expect(screen.getByText("Log in")).toBeInTheDocument()
})
- it("renders the social auth buttons", () => {
- render()
-
- expect(screen.getByText("Continue with Facebook")).toBeInTheDocument()
- expect(screen.getByText("Continue with Google")).toBeInTheDocument()
- expect(screen.getByText("Continue with Apple")).toBeInTheDocument()
- })
-
- it("submits the email and password", async () => {
+ it("submits the password", async () => {
render()
const loginMock = jest.fn().mockReturnValue(Promise.resolve())
;(login as jest.Mock).mockImplementationOnce(loginMock)
- const email = screen.getByPlaceholderText("Enter your email address")
const password = screen.getByPlaceholderText("Enter your password")
const submit = screen.getByText("Log in")
@@ -49,7 +52,6 @@ describe("AuthDialogLogin", () => {
expect(button).toBeDisabled()
- fireEvent.change(email, { target: { value: "example@example.com" } })
fireEvent.change(password, { target: { value: "secret" } })
expect(button).toBeEnabled()
@@ -75,7 +77,6 @@ describe("AuthDialogLogin", () => {
)
;(login as jest.Mock).mockImplementationOnce(loginMock)
- const email = screen.getByPlaceholderText("Enter your email address")
const password = screen.getByPlaceholderText("Enter your password")
const submit = screen.getByText("Log in")
@@ -84,7 +85,6 @@ describe("AuthDialogLogin", () => {
expect(button).toBeDisabled()
- fireEvent.change(email, { target: { value: "example@example.com" } })
fireEvent.change(password, { target: { value: "secret" } })
fireEvent.click(button)
@@ -125,7 +125,6 @@ describe("AuthDialogLogin", () => {
)
;(login as jest.Mock).mockImplementationOnce(loginMock)
- const email = screen.getByPlaceholderText("Enter your email address")
const password = screen.getByPlaceholderText("Enter your password")
const submit = screen.getByText("Log in")
@@ -134,7 +133,6 @@ describe("AuthDialogLogin", () => {
expect(button).toBeDisabled()
- fireEvent.change(email, { target: { value: "example@example.com" } })
fireEvent.change(password, { target: { value: "secret" } })
fireEvent.click(button)
diff --git a/src/Components/AuthDialog/Views/__tests__/AuthDialogSignUp.jest.tsx b/src/Components/AuthDialog/Views/__tests__/AuthDialogSignUp.jest.tsx
index c6a18256b30..a6d036d27f0 100644
--- a/src/Components/AuthDialog/Views/__tests__/AuthDialogSignUp.jest.tsx
+++ b/src/Components/AuthDialog/Views/__tests__/AuthDialogSignUp.jest.tsx
@@ -1,7 +1,6 @@
import { fireEvent, render, screen, waitFor } from "@testing-library/react"
import { useCountryCode } from "Components/AuthDialog/Hooks/useCountryCode"
import { AuthDialogSignUp } from "Components/AuthDialog/Views/AuthDialogSignUp"
-import { useFeatureFlag } from "System/Hooks/useFeatureFlag"
import { signUp } from "Utils/auth"
jest.mock("Utils/getENV", () => ({
@@ -21,6 +20,18 @@ jest.mock("Utils/auth", () => ({
signUp: jest.fn(),
}))
+jest.mock("Components/AuthDialog/AuthDialogContext", () => ({
+ useAuthDialogContext: jest.fn().mockReturnValue({
+ state: {
+ analytics: {},
+ options: {},
+ values: {
+ email: "example@example.com",
+ },
+ },
+ }),
+}))
+
// mocks the module that tells us if the user is on a touch device
let mockIsTouch = false
jest.mock("Utils/device", () => ({
@@ -30,13 +41,14 @@ jest.mock("Utils/device", () => ({
}))
jest.mock("Components/AuthDialog/Hooks/useCountryCode")
+
jest.mock("System/Hooks/useFeatureFlag")
describe("AuthDialogSignUp", () => {
beforeAll(() => {
;(useCountryCode as jest.Mock).mockImplementation(() => ({
loading: false,
- countryCode: "US",
+ isAutomaticallySubscribed: true,
}))
})
@@ -46,24 +58,15 @@ describe("AuthDialogSignUp", () => {
expect(screen.getByText("Sign up")).toBeInTheDocument()
})
- it("renders the social auth buttons", () => {
- render()
-
- expect(screen.getByText("Continue with Facebook")).toBeInTheDocument()
- expect(screen.getByText("Continue with Google")).toBeInTheDocument()
- expect(screen.getByText("Continue with Apple")).toBeInTheDocument()
- })
-
it("renders a disclaimer", () => {
render()
expect(screen.getByTestId("disclaimer")).toHaveTextContent(
- "By clicking Sign Up or Continue with Apple, Google, or Facebook, you agree to Artsy’s Terms of Use and Privacy Policy and to receiving emails from Artsy."
- )
- expect(screen.getByRole("link", { name: "Terms of Use" })).toHaveAttribute(
- "href",
- "/terms"
+ "By clicking Sign Up or Continue with Email, Apple, Google, or Facebook, you agree to Artsy’s Terms and Conditions and Privacy Policy and to receiving emails from Artsy."
)
+ expect(
+ screen.getByRole("link", { name: "Terms and Conditions" })
+ ).toHaveAttribute("href", "/terms")
expect(
screen.getByRole("link", { name: "Privacy Policy" })
).toHaveAttribute("href", "/privacy")
@@ -82,7 +85,7 @@ describe("AuthDialogSignUp", () => {
render()
expect(screen.getByTestId("disclaimer")).toHaveTextContent(
- "By tapping Sign Up or Continue with Apple, Google, or Facebook, you agree to Artsy’s Terms of Use and Privacy Policy and to receiving emails from Artsy."
+ "By tapping Sign Up or Continue with Email, Apple, Google, or Facebook, you agree to Artsy’s Terms and Conditions and Privacy Policy and to receiving emails from Artsy."
)
})
})
@@ -91,14 +94,14 @@ describe("AuthDialogSignUp", () => {
beforeAll(() => {
;(useCountryCode as jest.Mock).mockImplementation(() => ({
loading: false,
- countryCode: "DE",
+ isAutomaticallySubscribed: false,
}))
})
afterAll(() => {
;(useCountryCode as jest.Mock).mockImplementation(() => ({
loading: false,
- countryCode: "US",
+ isAutomaticallySubscribed: true,
}))
})
@@ -106,7 +109,7 @@ describe("AuthDialogSignUp", () => {
render()
expect(screen.getByTestId("disclaimer")).toHaveTextContent(
- "By clicking Sign Up or Continue with Apple, Google, or Facebook, you agree to Artsy’s Terms of Use and Privacy Policy."
+ "By clicking Sign Up or Continue with Email, Apple, Google, or Facebook, you agree to Artsy’s Terms and Conditions and Privacy Policy."
)
})
})
@@ -115,14 +118,14 @@ describe("AuthDialogSignUp", () => {
beforeAll(() => {
;(useCountryCode as jest.Mock).mockImplementation(() => ({
loading: true,
- countryCode: "US",
+ isAutomaticallySubscribed: true,
}))
})
afterAll(() => {
;(useCountryCode as jest.Mock).mockImplementation(() => ({
loading: false,
- countryCode: "US",
+ isAutomaticallySubscribed: true,
}))
})
@@ -130,54 +133,8 @@ describe("AuthDialogSignUp", () => {
render()
expect(screen.getByTestId("skeleton-disclaimer")).toHaveTextContent(
- "By clicking Sign Up or Continue with Apple, Google, or Facebook, you agree to Artsy’s Terms of Use and Privacy Policy and to receiving emails from Artsy."
- )
- })
-
- describe("when the new disclaimer is enabled", () => {
- beforeAll(() => {
- ;(useFeatureFlag as jest.Mock).mockImplementation(
- (f: string) => f === "diamond_new-terms-and-conditions"
- )
- })
-
- afterAll(() => {
- ;(useFeatureFlag as jest.Mock).mockReset()
- })
-
- it("renders a disclaimer with the new text", () => {
- render()
-
- expect(screen.getByTestId("skeleton-disclaimer")).toHaveTextContent(
- "By clicking Sign Up or Continue with Email, Apple, Google, or Facebook, you agree to Artsy’s Terms and Conditions and Privacy Policy and to receiving emails from Artsy."
- )
- })
- })
- })
-
- describe("when the new disclaimer is enabled", () => {
- beforeAll(() => {
- ;(useFeatureFlag as jest.Mock).mockImplementation(
- (f: string) => f === "diamond_new-terms-and-conditions"
- )
- })
-
- afterAll(() => {
- ;(useFeatureFlag as jest.Mock).mockReset()
- })
-
- it("renders a disclaimer with the new text", () => {
- render()
-
- expect(screen.getByTestId("disclaimer")).toHaveTextContent(
"By clicking Sign Up or Continue with Email, Apple, Google, or Facebook, you agree to Artsy’s Terms and Conditions and Privacy Policy and to receiving emails from Artsy."
)
- expect(
- screen.getByRole("link", { name: "Terms and Conditions" })
- ).toHaveAttribute("href", "/terms")
- expect(
- screen.getByRole("link", { name: "Privacy Policy" })
- ).toHaveAttribute("href", "/privacy")
})
})
@@ -188,7 +145,6 @@ describe("AuthDialogSignUp", () => {
;(signUp as jest.Mock).mockImplementationOnce(signUpMock)
const name = screen.getByPlaceholderText("Enter your full name")
- const email = screen.getByPlaceholderText("Enter your email address")
const password = screen.getByPlaceholderText("Enter your password")
const submit = screen.getByText("Sign up")
@@ -199,7 +155,6 @@ describe("AuthDialogSignUp", () => {
expect(button).toBeDisabled()
fireEvent.change(name, { target: { value: "Test User" } })
- fireEvent.change(email, { target: { value: "example@example.com" } })
fireEvent.change(password, { target: { value: "Secret000" } }) // pragma: allowlist secret
expect(button).toBeEnabled()
diff --git a/src/Components/FollowButton/FollowArtistButton.tsx b/src/Components/FollowButton/FollowArtistButton.tsx
index 2a281090d70..cca17feb0e1 100644
--- a/src/Components/FollowButton/FollowArtistButton.tsx
+++ b/src/Components/FollowButton/FollowArtistButton.tsx
@@ -126,12 +126,8 @@ const FollowArtistButton: React.FC = ({
if (!isLoggedIn) {
showAuthDialog({
- mode: "SignUp",
options: {
- title: mode => {
- const action = mode === "SignUp" ? "Sign up" : "Log in"
- return `${action} to follow ${artist.name}`
- },
+ title: `Sign up or log in to follow ${artist.name}`,
afterAuthAction: {
action: "follow",
kind: "artist",
diff --git a/src/Components/FollowButton/FollowGeneButton.tsx b/src/Components/FollowButton/FollowGeneButton.tsx
index f22c90750d7..f00fe8cfdd4 100644
--- a/src/Components/FollowButton/FollowGeneButton.tsx
+++ b/src/Components/FollowButton/FollowGeneButton.tsx
@@ -68,12 +68,8 @@ const FollowGeneButton: React.FC = ({
if (!isLoggedIn) {
showAuthDialog({
- mode: "SignUp",
options: {
- title: mode => {
- const action = mode === "SignUp" ? "Sign up" : "Log in"
- return `${action} to follow ${gene.name}`
- },
+ title: `Sign up or log in to follow ${gene.name}`,
afterAuthAction: {
action: "follow",
kind: "gene",
diff --git a/src/Components/FollowButton/FollowProfileButton.tsx b/src/Components/FollowButton/FollowProfileButton.tsx
index c563a0a6f8a..fda8f59b522 100644
--- a/src/Components/FollowButton/FollowProfileButton.tsx
+++ b/src/Components/FollowButton/FollowProfileButton.tsx
@@ -92,12 +92,8 @@ const FollowProfileButton: React.FC = ({
if (!isLoggedIn) {
showAuthDialog({
- mode: "SignUp",
options: {
- title: mode => {
- const action = mode === "SignUp" ? "Sign up" : "Log in"
- return `${action} to follow ${profile.name}`
- },
+ title: `Sign up or log in to follow ${profile.name}`,
afterAuthAction: {
action: "follow",
kind: "profile",
diff --git a/src/Components/FollowButton/__tests__/FollowArtistButton.jest.tsx b/src/Components/FollowButton/__tests__/FollowArtistButton.jest.tsx
index 60f87855fc2..c5f5b4c6c6b 100644
--- a/src/Components/FollowButton/__tests__/FollowArtistButton.jest.tsx
+++ b/src/Components/FollowButton/__tests__/FollowArtistButton.jest.tsx
@@ -88,14 +88,13 @@ describe("FollowArtistButton", () => {
expect(showAuthDialog).toBeCalledWith({
analytics: { contextModule: "artistHeader", intent: "followArtist" },
- mode: "SignUp",
options: {
afterAuthAction: {
action: "follow",
kind: "artist",
objectId: "example",
},
- title: expect.any(Function),
+ title: expect.any(String),
},
})
})
diff --git a/src/Components/FollowButton/__tests__/FollowGeneButton.jest.tsx b/src/Components/FollowButton/__tests__/FollowGeneButton.jest.tsx
index 272cd84a654..d4626dabd69 100644
--- a/src/Components/FollowButton/__tests__/FollowGeneButton.jest.tsx
+++ b/src/Components/FollowButton/__tests__/FollowGeneButton.jest.tsx
@@ -84,14 +84,13 @@ describe("FollowGeneButton", () => {
expect(showAuthDialog).toBeCalledWith({
analytics: { contextModule: "geneHeader", intent: "followGene" },
- mode: "SignUp",
options: {
afterAuthAction: {
action: "follow",
kind: "gene",
objectId: "example",
},
- title: expect.any(Function),
+ title: expect.any(String),
},
})
})
diff --git a/src/Components/FollowButton/__tests__/FollowProfileButton.jest.tsx b/src/Components/FollowButton/__tests__/FollowProfileButton.jest.tsx
index 59f03f54578..a9d76498d5a 100644
--- a/src/Components/FollowButton/__tests__/FollowProfileButton.jest.tsx
+++ b/src/Components/FollowButton/__tests__/FollowProfileButton.jest.tsx
@@ -93,14 +93,13 @@ describe("FollowProfileButton", () => {
contextModule: "partnerHeader",
intent: "followPartner",
},
- mode: "SignUp",
options: {
afterAuthAction: {
action: "follow",
kind: "profile",
objectId: "example",
},
- title: expect.any(Function),
+ title: expect.any(String),
},
})
})
diff --git a/src/Components/NavBar/NavBarLoggedOutActions.tsx b/src/Components/NavBar/NavBarLoggedOutActions.tsx
index a9c064801dc..2eec1814e90 100644
--- a/src/Components/NavBar/NavBarLoggedOutActions.tsx
+++ b/src/Components/NavBar/NavBarLoggedOutActions.tsx
@@ -15,7 +15,6 @@ export const NavBarLoggedOutActions = () => {
size="small"
onClick={() => {
showAuthDialog({
- mode: "Login",
analytics: {
contextModule: ContextModule.header,
intent: Intent.login,
@@ -32,7 +31,6 @@ export const NavBarLoggedOutActions = () => {
size="small"
onClick={() => {
showAuthDialog({
- mode: "SignUp",
analytics: {
contextModule: ContextModule.header,
intent: Intent.signup,
diff --git a/src/Components/NavBar/__tests__/NavBar.jest.tsx b/src/Components/NavBar/__tests__/NavBar.jest.tsx
index cfc72c56b76..df4bf59b09b 100644
--- a/src/Components/NavBar/__tests__/NavBar.jest.tsx
+++ b/src/Components/NavBar/__tests__/NavBar.jest.tsx
@@ -119,7 +119,6 @@ describe("NavBar", () => {
wrapper.find("button").at(0).simulate("click")
expect(showAuthDialog).toBeCalledWith({
- mode: "Login",
analytics: {
contextModule: "header",
intent: "login",
@@ -136,7 +135,6 @@ describe("NavBar", () => {
wrapper.find("button").at(1).simulate("click")
expect(showAuthDialog).toBeCalledWith({
- mode: "SignUp",
analytics: {
contextModule: "header",
intent: "signup",
diff --git a/src/Utils/Hooks/useScrollToOpenArtistAuthModal.ts b/src/Utils/Hooks/useScrollToOpenArtistAuthModal.ts
index cdec91f197c..b009ebcff6b 100644
--- a/src/Utils/Hooks/useScrollToOpenArtistAuthModal.ts
+++ b/src/Utils/Hooks/useScrollToOpenArtistAuthModal.ts
@@ -31,17 +31,13 @@ export const useScrollToOpenArtistAuthModal = ({
const handleScroll = () => {
timeout = setTimeout(() => {
showAuthDialog({
- mode: "SignUp",
options: {
image: true,
onClose: dismiss,
onSuccess: dismiss,
- title: mode => {
- const action = mode === "SignUp" ? "Sign up" : "Log in"
- return `${action} to discover new works by ${
- name || "this artist"
- } and more artists you love`
- },
+ title: `Sign up or log in to discover new works by ${
+ name || "this artist"
+ } and more artists you love`,
},
analytics: {
contextModule: ContextModule.popUpModal,
diff --git a/src/Utils/Hooks/useScrollToOpenEditorialAuthModal.ts b/src/Utils/Hooks/useScrollToOpenEditorialAuthModal.ts
index 6fd2c4b27f2..2e8a1fbf22d 100644
--- a/src/Utils/Hooks/useScrollToOpenEditorialAuthModal.ts
+++ b/src/Utils/Hooks/useScrollToOpenEditorialAuthModal.ts
@@ -5,12 +5,8 @@ export const useScrollToOpenEditorialAuthModal = () => {
useScrollToOpenAuthModal({
key: "editorial-signup-dismissed",
options: {
- mode: "SignUp",
options: {
- title: mode => {
- const action = mode === "SignUp" ? "Sign up" : "Log in"
- return `${action} for the latest in art market news`
- },
+ title: `Sign up or log in for the latest in art market news`,
},
analytics: {
contextModule: ContextModule.popUpModal,
diff --git a/src/Utils/__tests__/auth.jest.ts b/src/Utils/__tests__/auth.jest.ts
index 938c56cf381..bdfb374d9ce 100644
--- a/src/Utils/__tests__/auth.jest.ts
+++ b/src/Utils/__tests__/auth.jest.ts
@@ -20,6 +20,12 @@ jest.mock("sharify", () => ({
},
}))
+jest.mock("Utils/recaptcha", () => ({
+ recaptcha: jest
+ .fn()
+ .mockReturnValue(Promise.resolve("EXAMPLE_RECAPTCHA_KEY")),
+}))
+
describe("login", () => {
it("makes the correct request", async () => {
const mockFetch = jest.fn(() =>
@@ -162,7 +168,7 @@ describe("signUp", () => {
expect(mockFetch).toBeCalledWith("https://www.artsy.net/signup", {
body:
- '{"agreed_to_receive_emails":true,"accepted_terms_of_service":true,"email":"example@example.com","name":"Example Example","password":"secret","session_id":"session_id"}',
+ '{"agreed_to_receive_emails":true,"accepted_terms_of_service":true,"email":"example@example.com","name":"Example Example","password":"secret","recaptcha_token":"EXAMPLE_RECAPTCHA_KEY","session_id":"session_id"}',
credentials: "same-origin",
headers: {
Accept: "application/json",
diff --git a/src/Utils/__tests__/recaptcha.jest.ts b/src/Utils/__tests__/recaptcha.jest.ts
index a3e0824d269..96f01bd0da7 100644
--- a/src/Utils/__tests__/recaptcha.jest.ts
+++ b/src/Utils/__tests__/recaptcha.jest.ts
@@ -1,12 +1,14 @@
-import { recaptcha } from "../recaptcha"
-jest.mock("sharify", () => ({ data: jest.fn() }))
-const sd = require("sharify").data
+import { getENV } from "Utils/getENV"
+import { recaptcha } from "Utils/recaptcha"
+
+jest.mock("Utils/getENV", () => ({
+ getENV: jest.fn(() => "recaptcha-api-key"),
+}))
describe("repcaptcha", () => {
beforeEach(() => {
window.grecaptcha.execute.mockClear()
window.grecaptcha.ready.mockClear()
- sd.RECAPTCHA_KEY = "recaptcha-api-key"
})
it("fires an action", () => {
@@ -16,45 +18,30 @@ describe("repcaptcha", () => {
})
})
- it("fires an action with callback", done => {
+ it("fires an action with callback", async () => {
const action = jest.fn()
- const callback = jest.fn(token => {
- action(token)
- expect(action).toBeCalledWith("recaptcha-token")
- done()
- })
- recaptcha("signup_submit", callback)
- expect(window.grecaptcha.execute).toBeCalledWith("recaptcha-api-key", {
- action: "signup_submit",
- })
- })
+ const token = await recaptcha("signup_submit")
- it("Still calls the callback if firing action fails", done => {
- window.grecaptcha.execute.mockRejectedValueOnce(new Error("google failed"))
- const action = jest.fn()
- const callback = jest.fn(() => {
- action()
- expect(action).toBeCalled()
- done()
- })
-
- recaptcha("signup_submit", callback)
+ action(token)
+ expect(action).toBeCalledWith("recaptcha-token")
expect(window.grecaptcha.execute).toBeCalledWith("recaptcha-api-key", {
action: "signup_submit",
})
})
- it("Fires the callback but no action if sd.RECAPTCHA_KEY is missing", done => {
- sd.RECAPTCHA_KEY = ""
+ it("rejects if sd.RECAPTCHA_KEY is missing", async () => {
+ ;(getENV as jest.Mock).mockImplementation(() => undefined)
+
const action = jest.fn()
- const callback = jest.fn(() => {
+
+ try {
+ await recaptcha("signup_submit")
+ } catch (err) {
action()
- expect(action).toBeCalled()
- done()
- })
+ }
- recaptcha("signup_submit", callback)
+ expect(action).toBeCalled()
expect(window.grecaptcha.ready).not.toBeCalled()
expect(window.grecaptcha.execute).not.toBeCalled()
})
diff --git a/src/Utils/auth.ts b/src/Utils/auth.ts
index ee200b365e4..83bcbdc9d0d 100644
--- a/src/Utils/auth.ts
+++ b/src/Utils/auth.ts
@@ -4,7 +4,7 @@
import Cookies from "cookies-js"
import { getENV } from "Utils/getENV"
-import { recaptcha as _recaptcha, RecaptchaAction } from "Utils/recaptcha"
+import { recaptcha } from "Utils/recaptcha"
const headers = {
Accept: "application/json",
@@ -120,10 +120,6 @@ export const resetPassword = async (args: {
return await Promise.reject(new Error(JSON.stringify(err)))
}
-const recaptcha = (action: RecaptchaAction) => {
- return new Promise(resolve => _recaptcha(action, resolve))
-}
-
/**
* To use ensure that `EnableRecaptcha` is included somewhere on your page
*/
diff --git a/src/Utils/recaptcha.ts b/src/Utils/recaptcha.ts
index 8698fa89074..81afa1253a9 100644
--- a/src/Utils/recaptcha.ts
+++ b/src/Utils/recaptcha.ts
@@ -3,38 +3,31 @@ import createLogger from "Utils/logger"
const logger = createLogger("recaptcha.ts")
-// TODO: Should return a Promise instead of accepting a callback
-export const recaptcha = (
- action: RecaptchaAction,
- callback?: RecaptchaCallback
-) => {
- if (getENV("RECAPTCHA_KEY")) {
- window.grecaptcha?.ready(async () => {
- try {
- const token = await window.grecaptcha.execute(getENV("RECAPTCHA_KEY"), {
- action,
- })
-
- callback?.(token)
- } catch (err) {
- logger.error(err)
-
- if (action === "signup_submit") {
- logger.warn("Signup submitted without Recaptcha Token")
+export const recaptcha = async (action: RecaptchaAction): Promise => {
+ return new Promise((resolve, reject) => {
+ if (getENV("RECAPTCHA_KEY")) {
+ window.grecaptcha?.ready(async () => {
+ try {
+ const token = await window.grecaptcha.execute(
+ getENV("RECAPTCHA_KEY"),
+ { action }
+ )
+
+ return resolve(token)
+ } catch (err) {
+ logger.error(err)
+
+ if (action === "signup_submit") {
+ logger.warn("Signup submitted without Recaptcha Token")
+ }
+
+ return reject(err)
}
-
- callback?.()
- }
- })
-
- return
- }
-
- if (action === "signup_submit") {
- logger.warn("Signup submitted without Recaptcha Key")
- }
-
- callback?.()
+ })
+ } else {
+ reject("`RECAPTCHA_KEY` not found")
+ }
+ })
}
export type RecaptchaAction =
@@ -48,5 +41,4 @@ export type RecaptchaAction =
| "login_submit"
| "signup_submit"
| "submission_submit"
-
-type RecaptchaCallback = (token?: string) => void
+ | "verify_user"
diff --git a/src/__generated__/AuthDialogWelcomeQuery.graphql.ts b/src/__generated__/AuthDialogWelcomeQuery.graphql.ts
new file mode 100644
index 00000000000..f88f496b22e
--- /dev/null
+++ b/src/__generated__/AuthDialogWelcomeQuery.graphql.ts
@@ -0,0 +1,100 @@
+/**
+ * @generated SignedSource<>
+ * @lightSyntaxTransform
+ * @nogrep
+ */
+
+/* tslint:disable */
+/* eslint-disable */
+// @ts-nocheck
+
+import { ConcreteRequest, Query } from 'relay-runtime';
+export type AuthDialogWelcomeQuery$variables = {
+ email: string;
+ recaptchaToken: string;
+};
+export type AuthDialogWelcomeQuery$data = {
+ readonly verifyUser: {
+ readonly exists: boolean;
+ } | null | undefined;
+};
+export type AuthDialogWelcomeQuery = {
+ response: AuthDialogWelcomeQuery$data;
+ variables: AuthDialogWelcomeQuery$variables;
+};
+
+const node: ConcreteRequest = (function(){
+var v0 = [
+ {
+ "defaultValue": null,
+ "kind": "LocalArgument",
+ "name": "email"
+ },
+ {
+ "defaultValue": null,
+ "kind": "LocalArgument",
+ "name": "recaptchaToken"
+ }
+],
+v1 = [
+ {
+ "alias": null,
+ "args": [
+ {
+ "kind": "Variable",
+ "name": "email",
+ "variableName": "email"
+ },
+ {
+ "kind": "Variable",
+ "name": "recaptchaToken",
+ "variableName": "recaptchaToken"
+ }
+ ],
+ "concreteType": "VerifyUser",
+ "kind": "LinkedField",
+ "name": "verifyUser",
+ "plural": false,
+ "selections": [
+ {
+ "alias": null,
+ "args": null,
+ "kind": "ScalarField",
+ "name": "exists",
+ "storageKey": null
+ }
+ ],
+ "storageKey": null
+ }
+];
+return {
+ "fragment": {
+ "argumentDefinitions": (v0/*: any*/),
+ "kind": "Fragment",
+ "metadata": null,
+ "name": "AuthDialogWelcomeQuery",
+ "selections": (v1/*: any*/),
+ "type": "Query",
+ "abstractKey": null
+ },
+ "kind": "Request",
+ "operation": {
+ "argumentDefinitions": (v0/*: any*/),
+ "kind": "Operation",
+ "name": "AuthDialogWelcomeQuery",
+ "selections": (v1/*: any*/)
+ },
+ "params": {
+ "cacheID": "1a726d22d475625907540026eb1a39ff",
+ "id": null,
+ "metadata": {},
+ "name": "AuthDialogWelcomeQuery",
+ "operationKind": "query",
+ "text": "query AuthDialogWelcomeQuery(\n $email: String!\n $recaptchaToken: String!\n) {\n verifyUser(email: $email, recaptchaToken: $recaptchaToken) {\n exists\n }\n}\n"
+ }
+};
+})();
+
+(node as any).hash = "187a4934af565bf023955eca066dce73";
+
+export default node;