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

fix: add unit tests for different modules to improve coverage #127

Merged
merged 1 commit into from
Aug 28, 2024
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
27 changes: 27 additions & 0 deletions src/common-ui/SocialAuthButtons/index.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { fireEvent, render } from '@testing-library/react';
import configureStore from 'redux-mock-store';

import { COMPLETE_STATE, PENDING_STATE } from '../../data/constants';
import { setCookie } from '../../data/cookies';
import { OnboardingComponentContext } from '../../data/storeHooks';

import SocialAuthProviders, { SocialAuthButton } from './index';
Expand All @@ -18,6 +19,9 @@ jest.mock('@edx/frontend-platform', () => ({
}));

const mockStore = configureStore();
jest.mock('../../data/cookies', () => ({
setCookie: jest.fn(),
}));

describe('SocialAuthButton', () => {
let store = {};
Expand Down Expand Up @@ -84,6 +88,29 @@ describe('SocialAuthButton', () => {

expect(window.location.href).toEqual('http://example.com/login/google');
});

it('sets marketingEmailsOptIn cookie when isLoginForm is false', () => {
store = mockStore({
register: {
registrationFields: {
marketingEmailsOptIn: true,
},
},
});

const { getByText } = render(reduxWrapper(
<IntlSocialAuthButton provider={provider} isLoginForm={false} />,
));

delete window.location;
window.location = { href: 'http://base-url.com' };

const button = getByText('Sign up with Google');
fireEvent.click(button);

expect(setCookie).toHaveBeenCalledWith('marketingEmailsOptIn', true);
expect(window.location.href).toEqual('http://example.com/register/google');
});
});

describe('SocialAuthProviders', () => {
Expand Down
14 changes: 13 additions & 1 deletion src/data/tests/cookies.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getConfig } from '@edx/frontend-platform';
import Cookies from 'universal-cookie';

import { setCookie } from '../cookies';
import { getCookie, setCookie } from '../cookies';

// Mock getConfig function
jest.mock('@edx/frontend-platform', () => ({
Expand Down Expand Up @@ -50,3 +50,15 @@ describe('setCookie function', () => {
expect(Cookies).not.toHaveBeenCalled();
});
});

describe('getCookie function', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('should return null if cookieName is undefined', () => {
const result = getCookie(undefined);
expect(result).toBeNull();
expect(Cookies).not.toHaveBeenCalled();
});
});
24 changes: 23 additions & 1 deletion src/data/tests/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { getConfig, mergeConfig } from '@edx/frontend-platform';
import Cookies from 'universal-cookie';

import { getCountryCookieValue } from '../cookies';
import getAllPossibleQueryParams from '../utils';
import getAllPossibleQueryParams, { moveScrollToTop } from '../utils';

describe('getAllPossibleQueryParams', () => {
beforeEach(() => {
Expand Down Expand Up @@ -50,3 +50,25 @@ describe('getCountryCookieValue', () => {
expect(countryCode).toEqual(undefined);
});
});
describe('moveScrollToTop', () => {
it('should call scrollIntoView on the provided ref', () => {
const scrollIntoViewMock = jest.fn();
const ref = {
current: {
scrollIntoView: scrollIntoViewMock,
},
};

moveScrollToTop(ref, 'end');

expect(scrollIntoViewMock).toHaveBeenCalledWith({ behavior: 'smooth', block: 'end' });
});

it('should not throw an error if ref.current is undefined', () => {
const ref = {
current: null,
};

expect(() => moveScrollToTop(ref, 'end')).not.toThrow();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { MemoryRouter } from 'react-router-dom';
import configureStore from 'redux-mock-store';

import { PROGRESSIVE_PROFILING_FORM } from '../../../data/constants';
import { LINK_TIMEOUT } from '../../../data/segment/utils';
import { OnboardingComponentContext } from '../../../data/storeHooks';
import { setCurrentOpenedForm } from '../../../onboarding-component/data/reducers';
import AuthenticatedRedirection from '../AuthenticatedRedirection';
Expand Down Expand Up @@ -48,10 +49,12 @@ describe('AuthenticatedRedirection', () => {
store = mockStore(initialState);
delete window.location;
window.location = { href: '' };
jest.useFakeTimers();
});

afterEach(() => {
jest.clearAllMocks();
jest.useRealTimers();
});

it('should not redirect if success is false', () => {
Expand Down Expand Up @@ -103,4 +106,21 @@ describe('AuthenticatedRedirection', () => {

expect(store.dispatch).toHaveBeenCalledWith(setCurrentOpenedForm(PROGRESSIVE_PROFILING_FORM));
});

it('should redirect after a delay if isLinkTracked is true', () => {
render(reduxWrapper(
<IntlAuthenticatedRedirection
finishAuthUrl={null}
redirectUrl={mockRedirectUrl}
success={mockSuccess}
isLinkTracked
/>,
));

expect(window.location.href).toBe(''); // Shouldn't redirect immediately

jest.advanceTimersByTime(LINK_TIMEOUT); // Fast-forward time by LINK_TIMEOUT

expect(window.location.href).toBe(mockRedirectUrl); // Should have redirected after timeout
});
});
69 changes: 69 additions & 0 deletions src/forms/enterprise-sso-popup/data/utils.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import QueryString from 'query-string';

import { getTpaHint, getTpaProvider } from './utils';

// Mocking the query-string library
jest.mock('query-string');

describe('Utility Functions', () => {
describe('getTpaProvider', () => {
it('should return the provider from primaryProviders', () => {
const tpaHintProvider = 'google-oauth2';
const primaryProviders = [{ id: 'google-oauth2' }, { id: 'facebook' }];
const secondaryProviders = [{ id: 'twitter' }];

const result = getTpaProvider(tpaHintProvider, primaryProviders, secondaryProviders);
expect(result.provider).toEqual({ id: 'google-oauth2' });
});

it('should return the provider from secondaryProviders', () => {
const tpaHintProvider = 'twitter';
const primaryProviders = [{ id: 'google-oauth2' }, { id: 'facebook' }];
const secondaryProviders = [{ id: 'twitter' }];

const result = getTpaProvider(tpaHintProvider, primaryProviders, secondaryProviders);
expect(result.provider).toEqual({ id: 'twitter' });
});

it('should return null if provider is not found', () => {
const tpaHintProvider = 'linkedin';
const primaryProviders = [{ id: 'google-oauth2' }, { id: 'facebook' }];
const secondaryProviders = [{ id: 'twitter' }];

const result = getTpaProvider(tpaHintProvider, primaryProviders, secondaryProviders);
expect(result.provider).toBeNull();
});

it('should return null if tpaHintProvider is not provided', () => {
const tpaHintProvider = null;
const primaryProviders = [{ id: 'google-oauth2' }, { id: 'facebook' }];
const secondaryProviders = [{ id: 'twitter' }];

const result = getTpaProvider(tpaHintProvider, primaryProviders, secondaryProviders);
expect(result.provider).toBeNull();
});
});

describe('getTpaHint', () => {
it('should return tpa_hint from the query string', () => {
QueryString.parse.mockReturnValue({ tpa_hint: 'google-oauth2' });

const result = getTpaHint();
expect(result).toBe('google-oauth2');
});

it('should return tpa_hint from the "next" parameter in the query string', () => {
QueryString.parse.mockReturnValue({ next: 'some-path?tpa_hint=facebook' });

const result = getTpaHint();
expect(result).toBe('facebook');
});

it('should return undefined if tpa_hint is not found', () => {
QueryString.parse.mockReturnValue({ next: 'some-path' });

const result = getTpaHint();
expect(result).toBeUndefined();
});
});
});
11 changes: 11 additions & 0 deletions src/forms/enterprise-sso-popup/index.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,15 @@ describe('EnterpriseSSO', () => {

expect(store.dispatch).toHaveBeenCalledWith(setCurrentOpenedForm(LOGIN_FORM));
});

it('should prevent default behavior on mouse down for "Show me other ways to sign in or register" button', () => {
const { container } = render(reduxWrapper(<IntlEnterpriseSSO provider={provider} isLoginForm />));

const button = container.querySelector('#other-ways-to-sign-in');

const preventDefaultMock = jest.fn();
button.onmousedown = preventDefaultMock;
fireEvent.mouseDown(button);
expect(preventDefaultMock).toHaveBeenCalledTimes(1);
});
});
16 changes: 12 additions & 4 deletions src/forms/login-popup/components/AccountActivationMessage.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@ import React from 'react';

import { mergeConfig } from '@edx/frontend-platform';
import { injectIntl, IntlProvider } from '@edx/frontend-platform/i18n';
import {
render, screen,
} from '@testing-library/react';
import { render, screen } from '@testing-library/react';

import AccountActivationMessage from './AccountActivationMessage';
import { ACCOUNT_ACTIVATION_MESSAGE } from '../data/constants';

const IntlAccountActivationMessage = injectIntl(AccountActivationMessage);

describe('EmailConfirmationMessage', () => {
describe('AccountActivationMessage', () => {
beforeEach(() => {
mergeConfig({
MARKETING_EMAILS_OPT_IN: 'true',
Expand Down Expand Up @@ -64,4 +62,14 @@ describe('EmailConfirmationMessage', () => {
{ selector: '#account-activation-message' },
).textContent).toBe(expectedMessage);
});

it('should render nothing for unknown messageType', () => {
render(
<IntlProvider locale="en">
<IntlAccountActivationMessage messageType="UNKNOWN_TYPE" />
</IntlProvider>,
);
// Expect nothing to be rendered
expect(screen.queryByText('', { selector: '#account-activation-message' })).toBeNull();
});
});
56 changes: 54 additions & 2 deletions src/forms/login-popup/data/tests/reducer.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import {
COMPLETE_STATE, FAILURE_STATE, PENDING_STATE,
COMPLETE_STATE,
DEFAULT_STATE,
FAILURE_STATE,
PENDING_STATE,
} from '../../../../data/constants';
import loginReducer, {
loginInitialState, loginUser, loginUserFailed, loginUserSuccess,
backupLoginForm,
loginErrorClear,
loginInitialState,
loginUser,
loginUserFailed,
loginUserSuccess,
setLoginSSOIntent,
setShowPasswordResetBanner,
} from '../reducers';

describe('loginSlice reducer', () => {
Expand Down Expand Up @@ -47,4 +57,46 @@ describe('loginSlice reducer', () => {
});
expect(nextState.loginResult).toEqual({});
});

it('should handle setShowPasswordResetBanner action', () => {
const nextState = loginReducer(loginInitialState, setShowPasswordResetBanner());

expect(nextState.showResetPasswordSuccessBanner).toEqual(true);
});

it('should handle loginErrorClear action', () => {
const stateWithErrors = {
...loginInitialState,
loginError: { errorCode: 'SOME_ERROR_CODE', errorContext: {} },
submitState: FAILURE_STATE,
};

const nextState = loginReducer(stateWithErrors, loginErrorClear());

expect(nextState.loginError).toEqual({});
expect(nextState.submitState).toEqual(DEFAULT_STATE);
});

it('should handle setLoginSSOIntent action', () => {
const nextState = loginReducer(loginInitialState, setLoginSSOIntent());

expect(nextState.isLoginSSOIntent).toEqual(true);
});

it('should handle backupLoginForm action', () => {
const mockPayload = {
formFields: {
emailOrUsername: '[email protected]',
password: 'password123',
},
errors: {
emailOrUsername: '',
password: '',
},
};

const nextState = loginReducer(loginInitialState, backupLoginForm(mockPayload));

expect(nextState.loginFormData).toEqual(mockPayload);
});
});
Loading
Loading