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(profile): update profile requx actions, types, and reducers naming and unit tests #4926

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
74 changes: 41 additions & 33 deletions packages/services-store/src/actions/__tests__/profileAPI.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
import configureMockStore from 'redux-mock-store';
import { AnyAction } from 'redux';
import thunk, { ThunkDispatch } from 'redux-thunk';
// import ProfileAPI from '@carbon/ibmdotcom-services/es/services/Profile/Profile.js';
import { PROFILE_API_ACTION, ProfileAPIState } from '../../types/profileAPI';
// import convertValue from '../../../tests/utils/convert-value';
import { setUserStatus } from '../profileAPI';
import ProfileAPI from '@carbon/ibmdotcom-services/es/services/Profile/Profile.js';
import { UNAUTHENTICATED_STATUS, PROFILE_API_ACTION, ProfileAPIState } from '../../types/profileAPI';
import convertValue from '../../../tests/utils/convert-value';
import { loadUserStatus, setUserStatus } from '../profileAPI';

jest.mock('@carbon/ibmdotcom-services/es/services/Profile/Profile');

Expand All @@ -29,38 +29,46 @@ describe('Redux actions for `ProfileAPI`', () => {
expect(store.getActions()).toEqual([
{
type: PROFILE_API_ACTION.SET_USER_STATUS,
status: { user: '[email protected]' },
request: { user: '[email protected]' },
},
]);
});

// it('dispatches the action to get user authentication status', async () => {
// ProfileAPI.getUserStatus.mockResolvedValue({ user: 'Unauthenticated' });
// const store = mockStore();
// await store.dispatch(ProfileAPI.getUserStatus());
// expect(convertValue(store.getActions())).toEqual([
// {
// type: PROFILE_API_ACTION.SET_REQUEST_USER_STATUS_IN_PROGRESS,
// request: 'PROMISE',
// },
// {
// type: PROFILE_API_ACTION.SET_USER_STATUS,
// status: { user: 'Unauthenticated' },
// },
// ]);
// });
it('dispatches the action to get user authentication status', async () => {
ProfileAPI.getUserStatus.mockResolvedValue({ user: UNAUTHENTICATED_STATUS });
const store = mockStore();
await store.dispatch(loadUserStatus());
expect(convertValue(store.getActions())).toEqual([
{
type: PROFILE_API_ACTION.SET_REQUEST_USER_STATUS_IN_PROGRESS,
request: 'PROMISE',
},
{
type: PROFILE_API_ACTION.SET_USER_STATUS,
request: { user: UNAUTHENTICATED_STATUS },
},
]);
});

// it('dispatches the action of error in monitoring user authentication status', () => {
// ProfileAPI.getUserStatus.mockImplementation(callback => {
// callback(new Error('error-getuserstatus'));
// });
// const store = mockStore();
// store.dispatch(getUserStatus());
// expect(convertValue(store.getActions())).toEqual([
// {
// type: PROFILE_API_ACTION.SET_ERROR_REQUEST_USER_STATUS,
// error: 'error-getuserstatus',
// },
// ]);
// });
it('dispatches the action of error in monitoring user authentication status', async () => {
ProfileAPI.getUserStatus.mockRejectedValue(new Error('error-getuserstatus'));
const store = mockStore();
let caught;
try {
await store.dispatch(loadUserStatus());
} catch (error) {
caught = error;
}
expect(caught?.message).toBe('error-getuserstatus');
expect(convertValue(store.getActions())).toEqual([
{
type: PROFILE_API_ACTION.SET_REQUEST_USER_STATUS_IN_PROGRESS,
request: 'PROMISE',
},
{
type: PROFILE_API_ACTION.SET_ERROR_REQUEST_USER_STATUS,
error: 'error-getuserstatus',
},
]);
});
});
16 changes: 8 additions & 8 deletions packages/services-store/src/actions/profileAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,25 @@ export function setErrorRequestUserStatus(error: Error) {
}

/**
* @param status The promise of the REST call for user status that is in progress.
* @param request The promise of the REST call for user status that is in progress.
* @returns A Redux action to set the state that the REST call for user status is in progress.
* @private
*/
export function setRequestUserStatusInProgress(status: Promise<UserStatus>) {
export function setRequestUserStatusInProgress(request: Promise<UserStatus>) {
return {
type: PROFILE_API_ACTION.SET_REQUEST_USER_STATUS_IN_PROGRESS,
status,
request,
};
}

/**
* @param status The user authentication status from the JSONP call.
* @param request The user authentication status from the JSONP call.
* @returns A Redux action to set the given user authentication status.
*/
export function setUserStatus(status: UserStatus) {
export function setUserStatus(request: UserStatus) {
return {
type: PROFILE_API_ACTION.SET_USER_STATUS,
status,
request,
};
}

Expand All @@ -52,9 +52,9 @@ export type ProfileAPIActions =
| ReturnType<typeof setUserStatus>;

/**
* @returns A Redux action that gets user authentication status.
* @returns A Redux action that sends a REST call for user authentication status.
*/
export function getUserStatus(): ThunkAction<Promise<UserStatus>, { profileAPI: ProfileAPIState }, void, ProfileAPIActions> {
export function loadUserStatus(): ThunkAction<Promise<UserStatus>, { profileAPI: ProfileAPIState }, void, ProfileAPIActions> {
return async dispatch => {
const promiseStatus: Promise<UserStatus> = ProfileAPI.getUserStatus();
dispatch(setRequestUserStatusInProgress(promiseStatus));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import reducer from '../profileAPI';

describe('Redux reducers for `ProfileAPI`', () => {
it('should return the state unmodified for unknown action', () => {
const state = { status: { user: '[email protected]' } };
const state = { request: { user: '[email protected]' } };
expect(reducer(state, {} as ProfileAPIActions)).toEqual(state);
});

Expand All @@ -36,11 +36,11 @@ describe('Redux reducers for `ProfileAPI`', () => {
convertValue(
reducer({} as ProfileAPIState, {
type: PROFILE_API_ACTION.SET_USER_STATUS,
status: { user: '[email protected]' },
request: { user: '[email protected]' },
})
)
).toEqual({
status: { user: '[email protected]' },
request: { user: '[email protected]' },
});
});
});
4 changes: 2 additions & 2 deletions packages/services-store/src/reducers/profileAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ export default function reducer(state: ProfileAPIState = {}, action: ProfileAPIA
};
}
case PROFILE_API_ACTION.SET_USER_STATUS: {
const { status } = action as ReturnType<typeof setUserStatus>;
const { request } = action as ReturnType<typeof setUserStatus>;
return {
...state,
status,
request,
};
}
default:
Expand Down
7 changes: 6 additions & 1 deletion packages/services-store/src/types/profileAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ export interface UserStatus {
user: string;
}

/**
* Unauthenticated user status
*/
export const UNAUTHENTICATED_STATUS = 'Unauthenticated';

/**
* The Redux action ID for `ProfileAPI`.
*/
Expand Down Expand Up @@ -48,5 +53,5 @@ export interface ProfileAPIState {
/**
* The user authentication status.
*/
status?: UserStatus;
request?: UserStatus;
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
MastheadProfileItem,
Translation,
} from '../../internal/vendor/@carbon/ibmdotcom-services-store/types/translateAPI.d';
import { UNAUTHENTICATED_STATUS } from '../../internal/vendor/@carbon/ibmdotcom-services-store/types/profileAPI';
import { FOOTER_SIZE } from '../footer/footer';
import '../footer/footer-composite';
import './dotcom-shell';
Expand Down Expand Up @@ -89,11 +90,11 @@ class DDSDotcomShellComposite extends LitElement {
_loadTranslation?: (language?: string) => Promise<Translation>;

/**
* The placeholder for `getUserStatus()` Redux action that will be mixed in. This goes to masthead.
* The placeholder for `loadUserStatus()` Redux action that will be mixed in. This goes to masthead.
*
* @internal
*/
_getUserStatus?: () => void;
_loadUserStatus?: () => void;

/**
* The placeholder for `setLanguage()` Redux action that will be mixed in. This goes to masthead.
Expand Down Expand Up @@ -260,7 +261,7 @@ class DDSDotcomShellComposite extends LitElement {
* but if you need an alternate way of integration (e.g. rendering Web Components tags in server-side) this property helps.
*/
@property({ attribute: 'user-status' })
userStatus = 'Unauthenticated';
userStatus = UNAUTHENTICATED_STATUS;

update(changedProperties) {
super.update(changedProperties);
Expand Down Expand Up @@ -295,7 +296,7 @@ class DDSDotcomShellComposite extends LitElement {
_setLanguage,
_loadLocaleList,
_loadTranslation,
_getUserStatus,
_loadUserStatus,
_loadSearchResults,
} = this;
Object.assign(
Expand All @@ -319,7 +320,7 @@ class DDSDotcomShellComposite extends LitElement {
userStatus,
_loadSearchResults,
_loadTranslation,
_getUserStatus,
_loadUserStatus,
_setLanguage,
},
value => value !== undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ import DDSLeftNav from '../left-nav';
import '../masthead-container';
import styles from './masthead.stories.scss';
import { mastheadLinks as links, l1Data, logoData } from './links';
import { UNAUTHENTICATED_STATUS } from '../../../internal/vendor/@carbon/ibmdotcom-services-store/types/profileAPI';
import { authenticatedProfileItems, unauthenticatedProfileItems } from './profile-items';
import readme from './README.stories.mdx';

const userStatuses = {
[`Authenticated`]: '[email protected]',
[`Unauthenticated`]: 'Unauthenticated',
[`Unauthenticated`]: UNAUTHENTICATED_STATUS,
};

const StoryContent = () => html`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
MastheadProfileItem,
Translation,
} from '../../internal/vendor/@carbon/ibmdotcom-services-store/types/translateAPI.d';
import { UNAUTHENTICATED_STATUS } from '../../internal/vendor/@carbon/ibmdotcom-services-store/types/profileAPI';
import { MEGAMENU_RIGHT_NAVIGATION_STYLE_SCHEME } from './megamenu-right-navigation';
import './masthead';
import './masthead-logo';
Expand Down Expand Up @@ -409,11 +410,11 @@ class DDSMastheadComposite extends LitElement {
_loadTranslation?: (language?: string) => Promise<Translation>;

/**
* The placeholder for `getUserStatus()` Redux action that will be mixed in.
* The placeholder for `loadUserStatus()` Redux action that will be mixed in.
*
* @internal
*/
_getUserStatus?: () => void;
_loadUserStatus?: () => void;

/**
* The placeholder for `setLanguage()` Redux action that will be mixed in.
Expand Down Expand Up @@ -528,7 +529,7 @@ class DDSMastheadComposite extends LitElement {
* The user authentication status.
*/
@property({ attribute: 'user-status' })
userStatus = 'Unauthenticated';
userStatus = UNAUTHENTICATED_STATUS;

createRenderRoot() {
// We render child elements of `<dds-masthead-container>` by ourselves
Expand All @@ -541,7 +542,7 @@ class DDSMastheadComposite extends LitElement {
this._setLanguage?.(language);
}
this._loadTranslation?.(language).catch(() => {}); // The error is logged in the Redux store
this._getUserStatus?.();
this._loadUserStatus?.();
}

updated(changedProperties) {
Expand Down Expand Up @@ -574,8 +575,7 @@ class DDSMastheadComposite extends LitElement {
l1Data,
_loadSearchResults: loadSearchResults,
} = this;
console.log('userStatus', userStatus);
const authenticated = userStatus !== 'Unauthenticated';
const authenticated = userStatus !== UNAUTHENTICATED_STATUS;
const profileItems = authenticated ? authenticatedProfileItems : unauthenticatedProfileItems;
return html`
<dds-left-nav-overlay></dds-left-nav-overlay>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { loadLanguage, setLanguage } from '../../internal/vendor/@carbon/ibmdotc
import { LocaleAPIActions } from '../../internal/vendor/@carbon/ibmdotcom-services-store/actions/localeAPI.d';
import { loadTranslation } from '../../internal/vendor/@carbon/ibmdotcom-services-store/actions/translateAPI';
import { TranslateAPIActions } from '../../internal/vendor/@carbon/ibmdotcom-services-store/actions/translateAPI.d';
import { getUserStatus } from '../../internal/vendor/@carbon/ibmdotcom-services-store/actions/profileAPI';
import { loadUserStatus } from '../../internal/vendor/@carbon/ibmdotcom-services-store/actions/profileAPI';
import { ProfileAPIActions } from '../../internal/vendor/@carbon/ibmdotcom-services-store/actions/profileAPI.d';
import { loadSearchResults } from '../../internal/vendor/@carbon/ibmdotcom-services-store/actions/searchAPI';
import { SearchAPIActions } from '../../internal/vendor/@carbon/ibmdotcom-services-store/actions/searchAPI.d';
Expand Down Expand Up @@ -76,7 +76,7 @@ export type MastheadContainerActions =
| ReturnType<typeof loadLanguage>
| ReturnType<typeof setLanguage>
| ReturnType<typeof loadTranslation>
| ReturnType<typeof getUserStatus>;
| ReturnType<typeof loadUserStatus>;

/**
* @param state The Redux state for masthead.
Expand All @@ -86,7 +86,7 @@ export function mapStateToProps(state: MastheadContainerState): MastheadContaine
const { localeAPI, translateAPI, profileAPI, searchAPI } = state;
const { language } = localeAPI ?? {};
const { translations } = translateAPI ?? {};
const { status } = profileAPI ?? {};
const { request } = profileAPI ?? {};
const { currentSearchQueryString, searchResults } = searchAPI ?? {};
let currentSearchResults;
for (let { length = 0 } = currentSearchQueryString ?? {}; !currentSearchResults && length > 0; --length) {
Expand All @@ -97,7 +97,7 @@ export function mapStateToProps(state: MastheadContainerState): MastheadContaine
authenticatedProfileItems: !language ? undefined : translations?.[language]?.profileMenu.signedin,
navLinks: !language ? undefined : translations?.[language]?.mastheadNav?.links,
unauthenticatedProfileItems: !language ? undefined : translations?.[language]?.profileMenu.signedout,
userStatus: status?.user,
userStatus: request?.user,
currentSearchResults: currentSearchResults ?? [],
},
value => value !== undefined
Expand All @@ -114,7 +114,7 @@ export function mapDispatchToProps(dispatch: Dispatch<LocaleAPIActions | Transla
_loadLanguage: loadLanguage,
_setLanguage: setLanguage,
_loadTranslation: loadTranslation,
_getUserStatus: getUserStatus,
_loadUserStatus: loadUserStatus,
_loadSearchResults: loadSearchResults,
},
dispatch as Dispatch // TS definition of `bindActionCreators()` seems to have no templated `Dispatch`
Expand Down