Skip to content

Commit

Permalink
fix(react|redux): commerce pages in ssr not working
Browse files Browse the repository at this point in the history
  • Loading branch information
richard190m committed Jan 10, 2024
1 parent 44bcf36 commit 2429d79
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
mockCommercePagesInitialState,
mockCommercePagesLoadingState,
mockCommercePagesState,
slug,
} from 'tests/__fixtures__/contents/index.mjs';
import { fetchCommercePages } from '@farfetch/blackout-redux';
import { withStore } from '../../../../tests/helpers/index.js';
Expand Down Expand Up @@ -84,6 +85,7 @@ describe('useCommercePages', () => {

expect(fetchCommercePages).toHaveBeenCalledWith(
{
slug,
brand: commercePageQuery.brand,
category: commercePageQuery.category,
contentTypeCode: commercePageQuery.contentTypeCode,
Expand Down Expand Up @@ -124,6 +126,7 @@ describe('useCommercePages', () => {

expect(fetchCommercePages).toHaveBeenCalledWith(
{
slug,
brand: commercePageQuery.brand,
category: commercePageQuery.category,
contentTypeCode: commercePageQuery.contentTypeCode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { cleanup, renderHook } from '@testing-library/react';
import { ContentPageType } from '@farfetch/blackout-client';
import { fetchContentPage } from '@farfetch/blackout-redux';
import {
mockCommercePageWithDataState,
mockContentPageEntry,
mockContentPageErrorState,
mockContentPageInitialState,
Expand Down Expand Up @@ -102,6 +103,34 @@ describe('useContentPage', () => {

expect(fetchContentPage).not.toHaveBeenCalled();
});

it('should return values correctly with commercePagesHash option', () => {
const { result } = renderHook(
() =>
useContentPage(
ContentPageType.Listing,
{ slug },
{ isCommercePage: true },
),
{
wrapper: withStore(mockCommercePageWithDataState),
},
);

expect(result.current).toStrictEqual({
data: [
mockCommercePageWithDataState.entities.contents[
mockContentPageEntry.publicationId
],
],
isLoading: false,
error: null,
isFetched: true,
actions: {
fetch: expect.any(Function),
},
});
});
});

describe('actions', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { CommercePagesRankingStrategy } from '@farfetch/blackout-redux';
import type { Config, QueryCommercePages } from '@farfetch/blackout-client';

export interface UseCommercePagesOptions extends QueryCommercePages {
slug: string;
enableAutoFetch?: boolean;
strategy?: CommercePagesRankingStrategy;
fetchConfig?: Config;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ import type { Config } from '@farfetch/blackout-client';
export interface UseContentPageOptions {
enableAutoFetch?: boolean;
fetchConfig?: Config;
isCommercePage?: boolean;
}
2 changes: 1 addition & 1 deletion packages/react/src/contents/hooks/useCommercePages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const useCommercePages = <T = ComponentType[]>(
const query = useMemo(
() => ({
contentTypeCode: ContentTypeCode.CommercePages,
...fetchQuery,
codes: fetchQuery.slug,
}),
[fetchQuery],
);
Expand Down
14 changes: 10 additions & 4 deletions packages/react/src/contents/hooks/useContentPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,20 @@ const useContentPage = <T = [ComponentType]>(
) => {
const store = useStore();

const { enableAutoFetch = true, fetchConfig } = options;
const {
enableAutoFetch = true,
fetchConfig,
isCommercePage = false,
} = options;

const query = useMemo(
() => ({
contentTypeCode: ContentTypeCode.ContentPage,
codes: fetchQuery.slug.split('?')[0] as string,
contentTypeCode: isCommercePage
? ContentTypeCode.CommercePages
: ContentTypeCode.ContentPage,
codes: fetchQuery.slug,
}),
[fetchQuery.slug],
[fetchQuery.slug, isCommercePage],
);

const fetchQueryWithoutSlug = useMemo(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import {
type CommercePages,
type Config,
type GetCommercePages,
type QueryCommercePages,
toBlackoutError,
} from '@farfetch/blackout-client';
import {
type CommercePagesRankingStrategy,
ContentTypeCode,
type FetchCommercePagesAction,
type QueryCommercePagesWithSlug,
} from '../../types/index.js';
import { contentEntries } from '../../../entities/schemas/content.js';
import { normalize } from 'normalizr';
Expand All @@ -29,7 +29,7 @@ import type { Dispatch } from 'redux';
const fetchCommercePagesFactory =
(getCommercePages: GetCommercePages) =>
(
query: QueryCommercePages,
query: QueryCommercePagesWithSlug,
strategy?: CommercePagesRankingStrategy,
config?: Config,
) =>
Expand All @@ -39,17 +39,19 @@ const fetchCommercePagesFactory =
let hash: string | undefined;

try {
const { slug, ...queryWithoutSlug } = query;

hash = generateContentHash({
contentTypeCode: ContentTypeCode.CommercePages,
...query,
codes: slug,
});

dispatch({
payload: { hash },
type: actionTypes.FETCH_COMMERCE_PAGES_REQUEST,
});

const result = await getCommercePages(query, config);
const result = await getCommercePages(queryWithoutSlug, config);
const rankedResult = applyCommercePagesRankingStrategy(result, strategy);

dispatch({
Expand Down
36 changes: 22 additions & 14 deletions packages/redux/src/contents/serverInitialState.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import {
applyCommercePagesRankingStrategy,
generateContentHash,
} from './utils.js';
import { buildQueryStringFromObject } from '../helpers/index.js';
import { contentEntries } from '../entities/schemas/content.js';
import { generateContentHash } from './utils.js';
import { type ContentsState } from './types/index.js';
import { get, merge } from 'lodash-es';
import { INITIAL_STATE_CONTENT } from './reducer.js';
import { normalize } from 'normalizr';
import parse from 'url-parse';
import type { ContentsState } from './types/index.js';
import type { ServerInitialState } from '../types/serverInitialState.types.js';

/**
Expand All @@ -15,28 +18,34 @@ import type { ServerInitialState } from '../types/serverInitialState.types.js';
*
* @returns Initial state for the contents reducer.
*/
const serverInitialState: ServerInitialState = ({ model }) => {
const serverInitialState: ServerInitialState = ({ model, strategy }) => {
if (!get(model, 'searchContentRequests')) {
return { contents: INITIAL_STATE_CONTENT };
}

const { searchContentRequests, slug, seoMetadata, subfolder } = model;
const url = subfolder !== '/' ? slug?.replace(subfolder, '') : slug;
const normalizedUrl = url.replace('?json=true', '').replace('&json=true', '');

const contents = searchContentRequests.reduce((acc, item) => {
const { searchResponse } = item;
const firstSearchResponseItem = searchResponse.entries[0];

if (!firstSearchResponseItem) {
return acc;
}

const {
searchResponse,
filters: { codes, contentTypeCode },
} = item;
let response = searchResponse;
const isCommercePage = contentTypeCode === 'commerce_pages';
const code = isCommercePage ? normalizedUrl : codes?.[0];
const hash = generateContentHash({
codes: firstSearchResponseItem.code,
contentTypeCode: firstSearchResponseItem.contentTypeCode,
codes: code,
contentTypeCode: contentTypeCode,
});

if (isCommercePage) {
response = applyCommercePagesRankingStrategy(searchResponse, strategy);
}

const { entities, result } = {
...normalize({ hash, ...searchResponse }, contentEntries),
...normalize({ hash, ...response }, contentEntries),
};

return merge(acc, {
Expand All @@ -53,7 +62,6 @@ const serverInitialState: ServerInitialState = ({ model }) => {
});
}, {});

const url = subfolder !== '/' ? slug?.replace(subfolder, '') : slug;
const { pathname, query } = parse(url, true);

delete query.json;
Expand Down
5 changes: 5 additions & 0 deletions packages/redux/src/contents/types/actions.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
BlackoutError,
Contents,
ContentType,
QueryCommercePages,
SEOMetadata,
} from '@farfetch/blackout-client';
import type { ContentEntity } from '../../entities/index.js';
Expand All @@ -22,6 +23,10 @@ export type ContentsPayload = NormalizedSchema<
ContentsNormalized
> & { hash: Hash };

export interface QueryCommercePagesWithSlug extends QueryCommercePages {
slug: string;
}

/**
* Fetch Content Page Action
*/
Expand Down
2 changes: 2 additions & 0 deletions packages/redux/src/types/serverInitialState.types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { CommercePagesRankingStrategy } from '../contents/types/commercePagesRankingStrategy.types.js';
import type { LocaleState } from '../locale/index.js';
import type { Model } from './model.types.js';
import type { ProductsState } from '../products/index.js';
import type { StoreState } from './storeState.types.js';

export type ServerInitialState = (data: {
model: Model;
strategy?: CommercePagesRankingStrategy;
options?: { productImgQueryParam?: string };
}) => Omit<StoreState, 'products' | 'locale'> & {
products?: Partial<ProductsState>;
Expand Down
6 changes: 5 additions & 1 deletion tests/__fixtures__/contents/commercePages.fixtures.mts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const commercePagesQuery = {

export const slug = 'woman/gucci';
export const commercePageQuery = {
slug,
brand: 5030844,
category: '136643',
type: CommercePagesType.Listing,
Expand All @@ -28,7 +29,10 @@ export const commercePageQuery = {
export const commercePageContentPublicationId =
'dc9c0c95-9485-45c2-a76c-6923bb39b544';

export const commercePagesHash = generateContentHash(commercePageQuery);
export const commercePagesHash = generateContentHash({
contentTypeCode: commercePageQuery.contentTypeCode,
codes: commercePageQuery.slug,
});

export const mockCommercePages = {
number: 1,
Expand Down
43 changes: 43 additions & 0 deletions tests/__fixtures__/contents/contentPage.fixtures.mts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ const contentQuery = {

export const contentPagesHash = generateContentHash(contentQuery);

const commerceQuery = {
codes: slugContentWithoutQuery,
contentTypeCode: 'commerce_pages',
};
const commercePagesHash = generateContentHash(commerceQuery);

export const mockContentPageEntry = {
publicationId: 'dc9c0c95-9485-45c2-a76c-6923bb39b544',
versionId: '78f1922d-0ef1-46ed-b02c-ca541d0a0d80',
Expand Down Expand Up @@ -65,6 +71,11 @@ export const mockContentPageEntry = {
],
};

const mockCommercePageEntry = {
...mockContentPageEntry,
contentTypeCode: 'commerce_pages',
};

export const mockContentPage = {
number: 1,
totalItems: 1,
Expand Down Expand Up @@ -153,3 +164,35 @@ export const mockContentPageWithDataState = {
},
},
};

export const mockCommercePageWithDataState = {
entities: {
contents: {
[mockCommercePageEntry.publicationId]: {
...mockCommercePageEntry,
publicationDate: 0,
metadata: {
...mockCommercePageEntry.metadata,
custom: {
...mockCommercePageEntry.metadata.custom,
eventDate: 0,
},
},
},
},
},
contents: {
...mockContentPageInitialState.contents,
searchResults: {
[commercePagesHash]: {
isLoading: false,
error: null,
result: {
hash: commercePagesHash,
...mockContentPage,
entries: [mockCommercePageEntry.publicationId],
},
},
},
},
};

0 comments on commit 2429d79

Please sign in to comment.