Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
7 changes: 7 additions & 0 deletions spec/CioPlp/CioPlp.server.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ describe('CioPlp React Server-Side Rendering', () => {
expect(html).toContain('');
});

it('renders CioPlp provider without children on the server without error, if client is provided', () => {
// Render the component to a string
const html = ReactDOMServer.renderToString(<CioPlp cioClient={{}} />);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we're not passing the mocked JS client here?

Copy link
Contributor Author

@Mudaafi Mudaafi Feb 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going for an arbitrary client, but we can do that too. Scratch that, did you mean the mock client in test-utils? Wouldn't that resolve to null in this server context?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're correct it's not necessary


expect(html).toContain('');
});

it('renders CioPlp provider with children correctly on the server', () => {
// Render the component to a string
const html = ReactDOMServer.renderToString(
Expand Down
4 changes: 4 additions & 0 deletions spec/CioPlp/CioPlp.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ describe('CioPlp React Client-Side Rendering', () => {
expect(() => render(<CioPlp apiKey={DEMO_API_KEY} />)).not.toThrow();
});

it('renders CioPlp provider without children on the client without error, if client is provided', () => {
expect(() => render(<CioPlp cioClient={{}} />)).not.toThrow();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we're not passing the mocked JS client here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, I didn't see the need to specifically pass the mocked client here since an empty object is more generic but I can change that.

});

it('renders CioPlp provider with children correctly on the client', () => {
// Render the component to a string
const { getByText } = render(
Expand Down
13 changes: 7 additions & 6 deletions spec/useCioClient.server.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@ describe('Testing Hook on the server: useCioClient', () => {
renderHookServerSide(() => useCioClient(), {
initialProps: {},
}),
).toThrow('Api Key required');
).toThrow('Api Key or Constructor Client required');
});

it('Should return null when apiKey is provided', () => {
const { result } = renderHookServerSide(({ apiKey }) => useCioClient(apiKey), {
initialProps: { apiKey: 'xx' },
it('Should return client when custom client is provided', () => {
const mockClient = { tracker: () => {} };
const { result } = renderHookServerSide(({ cioClient }) => useCioClient({ cioClient }), {
initialProps: { cioClient: mockClient },
});

expect(result).toBe(null);
expect(result).toBe(mockClient);
});

it('Should return when clientOptions are provided', () => {
Expand All @@ -47,7 +48,7 @@ describe('Testing Hook on the server: useCioClient', () => {
};

const { result } = renderHookServerSide(
({ apiKey, options }) => useCioClient(apiKey, options),
({ apiKey, options }) => useCioClient({ apiKey, options }),
{
initialProps: { apiKey: key, options: clientOptions },
},
Expand Down
13 changes: 11 additions & 2 deletions spec/useCioClient.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,17 @@ describe('Testing Hook: useCioClient', () => {
spy.mockRestore();
});

test('Should return client when custom client is provided', () => {
const mockClient = { tracker: () => {} };
const { result } = renderHook(({ cioClient }) => useCioClient({ cioClient }), {
initialProps: { cioClient: mockClient },
});

expect(result.current).toBe(mockClient);
});

test('Should return a ConstructorIO Client Object', () => {
const { result } = renderHook(({ apiKey }) => useCioClient(apiKey), {
const { result } = renderHook(({ apiKey }) => useCioClient({ apiKey }), {
initialProps: { apiKey: 'xx' },
});
const client = result.current;
Expand Down Expand Up @@ -42,7 +51,7 @@ describe('Testing Hook: useCioClient', () => {
networkParameters: { timeout: 1000 },
};

const { result } = renderHook(({ apiKey, options }) => useCioClient(apiKey, options), {
const { result } = renderHook(({ apiKey, options }) => useCioClient({ apiKey, options }), {
initialProps: { apiKey: key, options: clientOptions },
});

Expand Down
5 changes: 2 additions & 3 deletions src/components/CioPlp/CioPlpProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ export default function CioPlpProvider(
} = props;
const [cioClientOptions, setCioClientOptions] = useState({});

const cioClient = useCioClient(apiKey);
const cioClient = useCioClient({ apiKey, cioClient: customCioClient, options: cioClientOptions });

const contextValue = useMemo(
(): PlpContextValue => ({
cioClient: customCioClient || cioClient,
cioClient,
cioClientOptions,
setCioClientOptions,
staticRequestConfigs,
Expand All @@ -36,7 +36,6 @@ export default function CioPlpProvider(
}),
[
cioClient,
customCioClient,
cioClientOptions,
itemFieldGetters,
formatters,
Expand Down
36 changes: 21 additions & 15 deletions src/hooks/useCioClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,35 @@ import {
import { useMemo } from 'react';
import version from '../version';

export type CioClientConfig = { apiKey?: string };
type UseCioClient = (
apiKey: string,
options?: Omit<ConstructorClientOptions, 'apiKey' | 'sendTrackingEvents' | 'version'>,
) => Nullable<ConstructorIOClient> | never;
type UseCioClientProps = {
apiKey?: string;
cioClient?: any;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any since we might want to pass in a node client instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's very unlikely that we will pass a node client to it. Can we make it ConstructorIO from client javascript for now and change it later if we decided that we can pass a node client

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

idm going down that path, but TypeScript server-side consumers might feel undervalued

options?: Omit<ConstructorClientOptions, 'apiKey' | 'sendTrackingEvents' | 'version'>;
};

type UseCioClient = (props: UseCioClientProps) => Nullable<ConstructorIOClient> | never;

const useCioClient: UseCioClient = (apiKey, options?) => {
if (!apiKey) {
throw new Error('Api Key required');
const useCioClient: UseCioClient = ({ apiKey, cioClient, options } = {}) => {
if (!apiKey && !cioClient) {
throw new Error('Api Key or Constructor Client required');
}

const memoizedCioClient = useMemo(() => {
if (cioClient) return cioClient;
if (apiKey && typeof window !== 'undefined') {
return new ConstructorIOClient({
apiKey,
sendTrackingEvents: true,
version: `cio-ui-plp-${version}`,
...options,
});
return (
cioClient ||
Copy link
Contributor

@mocca102 mocca102 Feb 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can remove this line 26 ☝️

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch!

new ConstructorIOClient({
apiKey,
sendTrackingEvents: true,
version: `cio-ui-plp-${version}`,
...options,
})
);
}

return null;
}, [apiKey, options]);
}, [apiKey, cioClient, options]);
return memoizedCioClient!;
};

Expand Down
13 changes: 9 additions & 4 deletions src/hooks/useCioPlp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,28 @@ import {
IBrowseParameters,
SearchParameters,
Nullable,
ConstructorClientOptions,
} from '@constructor-io/constructorio-client-javascript/lib/types';
import useCioClient from './useCioClient';
import useSearchResults from './useSearchResults';
import useBrowseResults from './useBrowseResults';

export type CioPlpConfigs = { apiKey?: string };
export type CioPlpConfigs = {
apiKey?: string;
cioClient: any;
options: Omit<ConstructorClientOptions, 'apiKey' | 'sendTrackingEvents' | 'version'>;
};
export type UseCioPlpHook = { cioClient: Nullable<ConstructorIOClient> };

type UseCioPlp = (configs: CioPlpConfigs) => UseCioPlpHook;

const useCioPlp: UseCioPlp = (configs) => {
const { apiKey } = configs;
const { apiKey, cioClient: customClient, options } = configs;
if (!apiKey) {
throw new Error('Api Key required');
throw new Error('Api Key or Constructor Client required');
}

const cioClient = useCioClient(apiKey);
const cioClient = useCioClient({ apiKey, cioClient: customClient, options });
const useCustomSearchResults = (query: string, searchParams: SearchParameters) =>
useSearchResults({ query, searchParams });
const useCustomBrowseResults = (
Expand Down
22 changes: 0 additions & 22 deletions src/hooks/useProductCardProps.ts

This file was deleted.