Skip to content

Commit

Permalink
ASUB-8201 Sign In with Apple (#2067)
Browse files Browse the repository at this point in the history
* Sign In with Apple

* fixing linting and tests

* fixing test & linting

* fixing linting errors

* removing update from  package.json

* fixing linting errors

* disable eslint warnings

* fixing warnings

* fixing sintax

* removing keys

* removing only

* fixing linting errors
  • Loading branch information
LauraPinilla authored Apr 15, 2024
1 parent 3eb16fc commit 2c99feb
Show file tree
Hide file tree
Showing 21 changed files with 438 additions and 62 deletions.
20 changes: 20 additions & 0 deletions blocks/identity-block/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@
@include scss.block-components("sign-up-tos-link");
@include scss.block-properties("sign-up-tos-link");
}
@include scss.block-components("sign-up-tos-container-link");
@include scss.block-properties("sign-up-tos-container-link");
}

@include scss.block-components("sign-up");
Expand All @@ -118,6 +120,24 @@
&__button-container {
@include scss.block-components("social-sign-on-button-container");
@include scss.block-properties("social-sign-on-button-container");

&__Apple {
@include scss.block-components("social-sign-on-button-container-apple");
@include scss.block-properties("social-sign-on-button-container-apple");
}
}

&__dividerWithText{
@include scss.block-components("social-sign-on-dividerWithText");
@include scss.block-properties("social-sign-on-dividerWithText");
&::before{
@include scss.block-components("social-sign-on-dividerWithText-before");
@include scss.block-properties("social-sign-on-dividerWithText-before");
}
&::after{
@include scss.block-components("social-sign-on-dividerWithText-after");
@include scss.block-properties("social-sign-on-dividerWithText-after");
}
}

@include scss.block-components("social-sign-on");
Expand Down
19 changes: 18 additions & 1 deletion blocks/identity-block/components/login/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,31 @@ const useLogin = ({
redirectToPreviousPage,
loggedInPageLocation,
isOIDC,
appleCode,
}) => {

const { Identity } = useIdentity();
const validatedRedirectURL = validateURL(redirectURL);
const [redirectToURL, setRedirectToURL] = useState(validatedRedirectURL);
const [redirectQueryParam, setRedirectQueryParam] = useState(null);
const [isAppleAuthSuccess, setIsAppleAuthSuccess] = useState(false);
const { loginByOIDC } = useOIDCLogin();

useEffect(()=>{
const askForloginWithApple = async (code) => {
await Identity.appleSignOn(code);
const isLoggedIn = await Identity.isLoggedIn();

if(isLoggedIn){
setIsAppleAuthSuccess(true);
}
};

if(Identity && appleCode){
askForloginWithApple(appleCode);
}
},[appleCode, Identity]);

useEffect(() => {
if (window?.location?.search) {
const searchParams = new URLSearchParams(window.location.search.substring(1));
Expand Down Expand Up @@ -69,7 +86,7 @@ const useLogin = ({
if (Identity && !isAdmin) {
checkLoggedInStatus();
}
}, [Identity, redirectQueryParam, loggedInPageLocation, isAdmin, loginByOIDC, isOIDC]);
}, [Identity, redirectQueryParam, loggedInPageLocation, isAdmin, loginByOIDC, isOIDC, isAppleAuthSuccess]);

return {
loginRedirect: redirectQueryParam || redirectToURL,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from "react";
import { Button, Icon, useIdentity } from "@wpmedia/arc-themes-components";
import { useFusionContext } from "fusion:context";
import getTranslatedPhrases from "fusion:intl";

import { SIGN_UP } from "../constants";

const AppleIcon = <Icon name="Apple" width={21} height={24} viewBox="0 0 24 24" />;

function AppleSignIn({ socialSignOnIn, className }) {
const { siteProperties } = useFusionContext();
const { locale } = siteProperties;
const phrases = getTranslatedPhrases(locale);
const { Identity } = useIdentity();

return (
<Button
id="apple-btn"
variant="secondary-reverse"
onClick={() => Identity.initAppleSignOn()}
iconLeft={AppleIcon}
className={`${className}__Apple`}
>
{socialSignOnIn !== SIGN_UP ? (
<span>{phrases.t("identity-block.social-signOn-apple-login")}</span>
) : (
<span>{phrases.t("identity-block.social-signOn-apple-signUp")}</span>
)}
</Button>
);
}

export default AppleSignIn;
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from "react";
import { render, screen } from "@testing-library/react";
import { useFusionContext } from "fusion:context";

import AppleSignIn from "./AppleSignIn";

const SITE_PROPS_MOCK = {
breakpoints: {
small: 0,
medium: 768,
large: 992,
},
websiteAdPath: "news",
dfpId: 701,
};

jest.mock("@wpmedia/arc-themes-components", () => ({
...jest.requireActual("@wpmedia/arc-themes-components"),
Icon: () => <div data-testid="Apple-icon" />,
}));

describe("Identity Social Login Component", () => {
beforeEach(() => {
jest.clearAllMocks();
useFusionContext.mockReturnValue({
isAdmin: true,
siteProperties: SITE_PROPS_MOCK,
});
});

it("renders Apple button for signIn", () => {
render(<AppleSignIn socialSignOnIn="Login" />);
expect(screen.getByText("identity-block.social-signOn-apple-login")).not.toBeNull();
});

it("renders Apple button for signUp", () => {
render(<AppleSignIn socialSignOnIn="SignUp" />);
expect(screen.getByText("identity-block.social-signOn-apple-signUp")).not.toBeNull();
});
});
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import React from "react";

function FacebookSignIn() {
import { SIGN_UP } from "../constants";

function FacebookSignIn({socialSignOnIn}) {
const facebookTextType = socialSignOnIn === SIGN_UP ? 'continue_with' : 'login_with';
return (
<div
className="fb-login-button"
data-width="300"
data-width="400"
data-size="large"
data-button-type="continue_with"
data-button-type={facebookTextType}
data-scope="public_profile,email"
data-auto-logout-link="false"
data-use-continue-as="true"
Expand Down
3 changes: 3 additions & 0 deletions blocks/identity-block/components/social-sign-on/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/* eslint-disable */
export const LOGIN = "Login";
export const SIGN_UP = "SignUp"
12 changes: 6 additions & 6 deletions blocks/identity-block/components/social-sign-on/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import React from "react";
import PropTypes from "@arc-fusion/prop-types";
import FacebookSignIn from "./_children/FacebookSignIn";
import GoogleSignIn from "./_children/GoogleSignIn";

import AppleSignIn from "./_children/AppleSignIn";
import useSocialSignIn from "./utils/useSocialSignIn";

const SocialSignOn = ({ className, onError, redirectURL, isOIDC }) => {
const { facebookAppId, googleClientId } = useSocialSignIn(redirectURL, onError, isOIDC);

const SocialSignOn = ({ className, onError, redirectURL, isOIDC, socialSignOnIn }) => {
const { facebookAppId, googleClientId, appleTeamId, appleKeyId, appleUrlToReceiveAuthToken} = useSocialSignIn(redirectURL, isOIDC, socialSignOnIn, onError);
return (
<section className={className}>
{googleClientId ? <GoogleSignIn onError={onError} redirectURL={redirectURL} /> : null}
{facebookAppId ? <FacebookSignIn /> : null}
{googleClientId ? <GoogleSignIn onError={onError} redirectURL={redirectURL} socialSignOnIn={socialSignOnIn} className={className} /> : null}
{facebookAppId ? <FacebookSignIn socialSignOnIn={socialSignOnIn}/> : null}
{appleTeamId && appleKeyId && appleUrlToReceiveAuthToken ? <AppleSignIn socialSignOnIn={socialSignOnIn} className={className} /> : null}
</section>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { GoogleSignInContext } from "./googleContext";
import useOIDCLogin from "../../../utils/useOIDCLogin";
import validateURL from "../../../utils/validate-redirect-url";

function useSocialSignIn(redirectURL, onError = () => {}, isOIDC) {
import {SIGN_UP} from "../constants";

function useSocialSignIn(redirectURL, isOIDC, socialSignOnIn, onError = () => {}) {
const { Identity } = useIdentity();
const { isGoogleLoaded } = useContext(GoogleSignInContext);
const [config, setConfig] = useState(() => Identity?.configOptions ?? {});
Expand All @@ -25,7 +27,7 @@ function useSocialSignIn(redirectURL, onError = () => {}, isOIDC) {
onError();
}
};
}, [Identity, onError, redirectURL]);
}, [Identity, onError, redirectURL, isOIDC, loginByOIDC]);

useEffect(() => {
const fetchConfig = async () => {
Expand Down Expand Up @@ -56,15 +58,15 @@ function useSocialSignIn(redirectURL, onError = () => {}, isOIDC) {
};

window.google.accounts.id.initialize(googleIdConfig);

const googleTextType = socialSignOnIn === SIGN_UP ? 'signup_with' : 'signin_with';
window.google.accounts.id.renderButton(document.getElementById("google-sign-in-button"), {
type: "standard",
theme: "outline",
size: "large",
text: "continue_with",
text: googleTextType,
shape: "rectangular",
logo_alignment: "left",
width: "300",
width: "400",
});

Identity.isLoggedIn().then((isLoggedIn) => {
Expand All @@ -75,7 +77,7 @@ function useSocialSignIn(redirectURL, onError = () => {}, isOIDC) {
}
});
}
}, [config.googleClientId, Identity, isGoogleLoaded]);
}, [config.googleClientId, Identity, isGoogleLoaded, isOIDC, loginByOIDC, redirectURL, socialSignOnIn ]);

useEffect(() => {
const initializeFacebook = async () => {
Expand All @@ -91,6 +93,9 @@ function useSocialSignIn(redirectURL, onError = () => {}, isOIDC) {
// then they will have a truthy value here
facebookAppId: config.facebookAppId,
googleClientId: config.googleClientId,
appleTeamId: config.teamId,
appleKeyId: config.keyId,
appleUrlToReceiveAuthToken: config.urlToReceiveAuthToken
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';
import { render, fireEvent, screen} from '@testing-library/react';
import EmailEditableFieldContainer from './EmailEditableFieldContainer';

const mockUpdateProfile = jest.fn(() => Promise.resolve())
const mockIdentity = {
apiOrigin: "http://origin/",
isLoggedIn: jest.fn(() => false),
getConfig: jest.fn(() => ({})),
updateUserProfile: mockUpdateProfile
};

jest.mock("@wpmedia/arc-themes-components", () => ({
...jest.requireActual("@wpmedia/arc-themes-components"),
useIdentity: jest.fn(() => ({
isInitialized: true,
Identity: {
...mockIdentity,
},
}))
}));

describe('EmailEditableFieldContainer', () => {
it('updates email and clears error on successful submission', async () => {
const setEmail = jest.fn();
render(
<EmailEditableFieldContainer
blockClassName="test-class"
email="[email protected]"
setEmail={setEmail}
/>
);

fireEvent.click(screen.getByText('identity-block.edit'));
const inputElement = screen.getByLabelText('identity-block.email')
fireEvent.input(inputElement, { target: { value: '[email protected]' } });

expect(inputElement.value).toBe('[email protected]');
});
});
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import React from "react";
import { fireEvent, render, screen } from "@testing-library/react";
import { act } from "react-dom/test-utils";

import PasswordEditableFieldContainer from "./PasswordEditableFieldContainer";
import FormPasswordConfirm from "../../../components/form-password-confirm";

jest.mock("../../../components/form-password-confirm", () => () => <div>Password Confirm</div>);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ function AccountManagement({ customFields }) {
const header = phrases.t("identity-block.account-information");
const socialProfileHeader = phrases.t("identity-block.connected-accounts");

console.log(header, socialProfileHeader);

// if logged in, return account info
return (
Expand Down
Loading

0 comments on commit 2c99feb

Please sign in to comment.