Skip to content

Commit

Permalink
fix(profile): update profile requx actions, types, and reducers namin…
Browse files Browse the repository at this point in the history
…g and unit tests (carbon-design-system#4926)

### Related Ticket(s)

Change profile endpoint on Carbon Masthead for signed in state carbon-design-system#4701

### Description

Update naming and unit tests from feedback: carbon-design-system#4909

### Changelog

**Changed**

- update `getUserStatus` action to `loadUserStatus` in accordance to naming strategy
- create `Unauthenticated` const in ProfileAPI type
- use `request` instead of `status` for the `setRequestUserStatusInProgress` and `setUserStatus` actions

<!-- React and Web Component deploy previews are enabled by default. -->
<!-- To enable additional available deploy previews, apply the following -->
<!-- labels for the corresponding package: -->
<!-- *** "package: services": Services -->
<!-- *** "package: utilities": Utilities -->
<!-- *** "package: styles": Carbon Expressive -->
<!-- *** "RTL": React / Web Components (RTL) -->
<!-- *** "feature flag": React / Web Components (experimental) -->
  • Loading branch information
annawen1 authored and IgnacioBecerra committed Feb 22, 2021
1 parent 439df67 commit 2545a46
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 64 deletions.
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

0 comments on commit 2545a46

Please sign in to comment.