Skip to content

Commit 4901c15

Browse files
improve coverage reports
1 parent daae12d commit 4901c15

6 files changed

Lines changed: 827 additions & 0 deletions

File tree

test/unit/base-query.spec.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
import { BaseQuery } from '../../src/lib/base-query';
2+
import { httpClient, AxiosInstance } from '@contentstack/core';
3+
import { MOCK_CLIENT_OPTIONS } from '../utils/constant';
4+
import MockAdapter from 'axios-mock-adapter';
5+
import { entryFindMock } from '../utils/mocks';
26

37
describe('BaseQuery class', () => {
48
let baseQuery: BaseQuery;
@@ -69,4 +73,95 @@ describe('BaseQuery class', () => {
6973
baseQuery.removeParam('key2');
7074
expect(baseQuery._queryParams).toEqual({ key1: 'value1' });
7175
});
76+
});
77+
78+
class TestableBaseQuery extends BaseQuery {
79+
constructor(client: AxiosInstance, urlPath: string) {
80+
super();
81+
this._client = client;
82+
this._urlPath = urlPath;
83+
this._variants = '';
84+
}
85+
86+
setVariants(variants: string) {
87+
this._variants = variants;
88+
}
89+
90+
setParameters(params: any) {
91+
this._parameters = params;
92+
}
93+
}
94+
95+
describe('BaseQuery find method', () => {
96+
let client: AxiosInstance;
97+
let mockClient: MockAdapter;
98+
let query: TestableBaseQuery;
99+
100+
beforeAll(() => {
101+
client = httpClient(MOCK_CLIENT_OPTIONS);
102+
mockClient = new MockAdapter(client as any);
103+
});
104+
105+
beforeEach(() => {
106+
query = new TestableBaseQuery(client, '/content_types/test_uid/entries');
107+
mockClient.reset();
108+
});
109+
110+
it('should call find with encode parameter true', async () => {
111+
mockClient.onGet('/content_types/test_uid/entries').reply(200, entryFindMock);
112+
113+
query.setParameters({ title: 'Test' });
114+
const result = await query.find(true);
115+
116+
expect(result).toEqual(entryFindMock);
117+
});
118+
119+
it('should call find without parameters', async () => {
120+
mockClient.onGet('/content_types/test_uid/entries').reply(200, entryFindMock);
121+
122+
const result = await query.find();
123+
124+
expect(result).toEqual(entryFindMock);
125+
});
126+
127+
it('should call find with variants header when variants are set', async () => {
128+
mockClient.onGet('/content_types/test_uid/entries').reply((config) => {
129+
expect(config.headers?.['x-cs-variant-uid']).toBe('variant1,variant2');
130+
return [200, entryFindMock];
131+
});
132+
133+
query.setVariants('variant1,variant2');
134+
await query.find();
135+
});
136+
137+
it('should extract content type UID from URL path', async () => {
138+
mockClient.onGet('/content_types/my_content_type/entries').reply(200, entryFindMock);
139+
140+
const queryWithContentType = new TestableBaseQuery(client, '/content_types/my_content_type/entries');
141+
const result = await queryWithContentType.find();
142+
143+
expect(result).toEqual(entryFindMock);
144+
});
145+
146+
it('should return null for content type UID when URL does not match pattern', async () => {
147+
mockClient.onGet('/assets').reply(200, entryFindMock);
148+
149+
const queryWithoutContentType = new TestableBaseQuery(client, '/assets');
150+
const result = await queryWithoutContentType.find();
151+
152+
expect(result).toEqual(entryFindMock);
153+
});
154+
155+
it('should handle find with both encode and variants', async () => {
156+
mockClient.onGet('/content_types/test_uid/entries').reply((config) => {
157+
expect(config.headers?.['x-cs-variant-uid']).toBe('test-variant');
158+
return [200, entryFindMock];
159+
});
160+
161+
query.setVariants('test-variant');
162+
query.setParameters({ status: 'published' });
163+
const result = await query.find(true);
164+
165+
expect(result).toEqual(entryFindMock);
166+
});
72167
});

test/unit/contentstack.spec.ts

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as core from "@contentstack/core";
33
import * as Contentstack from "../../src/lib/contentstack";
44
import { Stack } from "../../src/lib/stack";
55
import { Policy, Region, StackConfig } from "../../src/lib/types";
6+
import { StorageType } from "../../src/persistance/types/storage-type";
67
import {
78
CUSTOM_HOST,
89
DUMMY_URL,
@@ -401,4 +402,261 @@ describe("Contentstack", () => {
401402
getHostforRegionSpy.mockRestore();
402403
});
403404
});
405+
406+
describe('locale configuration', () => {
407+
it('should set locale in params when locale is provided in config', () => {
408+
const config = {
409+
apiKey: "apiKey",
410+
deliveryToken: "delivery",
411+
environment: "env",
412+
locale: "fr-fr",
413+
};
414+
415+
const stackInstance = createStackInstance(config);
416+
417+
expect(stackInstance).toBeInstanceOf(Stack);
418+
expect(stackInstance.config.locale).toEqual("fr-fr");
419+
});
420+
});
421+
422+
describe('live preview configuration in browser environment', () => {
423+
const originalDocument = global.document;
424+
const originalWindow = global.window;
425+
426+
beforeEach(() => {
427+
// Mock browser environment
428+
(utils.isBrowser as jest.Mock) = jest.fn();
429+
delete (global as any).document;
430+
delete (global as any).window;
431+
});
432+
433+
afterEach(() => {
434+
global.document = originalDocument;
435+
global.window = originalWindow;
436+
jest.restoreAllMocks();
437+
});
438+
439+
it('should extract live_preview params from URL in browser environment', () => {
440+
const isBrowserSpy = jest.spyOn(utils, 'isBrowser').mockReturnValue(true);
441+
442+
// Mock document.location
443+
const mockSearchParams = new Map([
444+
['live_preview', 'test_hash'],
445+
['release_id', 'release123'],
446+
['preview_timestamp', '123456789']
447+
]);
448+
449+
(global as any).document = {
450+
location: {
451+
toString: () => 'http://localhost?live_preview=test_hash&release_id=release123&preview_timestamp=123456789'
452+
}
453+
};
454+
455+
const config = {
456+
apiKey: "apiKey",
457+
deliveryToken: "delivery",
458+
environment: "env",
459+
live_preview: {
460+
enable: true,
461+
live_preview: 'default_hash'
462+
},
463+
};
464+
465+
const stackInstance = createStackInstance(config);
466+
467+
expect(isBrowserSpy).toHaveBeenCalled();
468+
expect(stackInstance).toBeInstanceOf(Stack);
469+
470+
isBrowserSpy.mockRestore();
471+
});
472+
473+
it('should not extract params when not in browser environment', () => {
474+
const isBrowserSpy = jest.spyOn(utils, 'isBrowser').mockReturnValue(false);
475+
476+
const config = {
477+
apiKey: "apiKey",
478+
deliveryToken: "delivery",
479+
environment: "env",
480+
live_preview: {
481+
enable: true,
482+
},
483+
};
484+
485+
const stackInstance = createStackInstance(config);
486+
487+
expect(isBrowserSpy).toHaveBeenCalled();
488+
expect(stackInstance).toBeInstanceOf(Stack);
489+
490+
isBrowserSpy.mockRestore();
491+
});
492+
});
493+
494+
describe('cache adapter configuration', () => {
495+
it('should set cache adapter when cacheOptions with policy is provided', () => {
496+
const mockAdapter = jest.fn();
497+
const mockClient = {
498+
defaults: {
499+
host: HOST_URL,
500+
adapter: mockAdapter,
501+
},
502+
interceptors: {
503+
request: {
504+
use: reqInterceptor,
505+
},
506+
response: {
507+
use: resInterceptor,
508+
},
509+
},
510+
};
511+
512+
createHttpClientMock.mockReturnValue(mockClient as any);
513+
514+
const config = {
515+
apiKey: "apiKey",
516+
deliveryToken: "delivery",
517+
environment: "env",
518+
cacheOptions: {
519+
policy: Policy.CACHE_THEN_NETWORK,
520+
storeType: 'localStorage' as StorageType
521+
},
522+
};
523+
524+
const stackInstance = createStackInstance(config);
525+
526+
expect(stackInstance).toBeInstanceOf(Stack);
527+
expect(mockClient.defaults.adapter).toBeDefined();
528+
});
529+
});
530+
531+
describe('debug mode with logging interceptors', () => {
532+
it('should add request and response logging interceptors when debug is enabled', () => {
533+
const mockLogHandler = jest.fn();
534+
const config = {
535+
apiKey: "apiKey",
536+
deliveryToken: "delivery",
537+
environment: "env",
538+
debug: true,
539+
logHandler: mockLogHandler,
540+
};
541+
542+
const stackInstance = createStackInstance(config);
543+
544+
expect(stackInstance).toBeInstanceOf(Stack);
545+
expect(reqInterceptor).toHaveBeenCalled();
546+
expect(resInterceptor).toHaveBeenCalled();
547+
});
548+
});
549+
550+
describe('plugin interceptors execution', () => {
551+
it('should execute plugin onRequest and onResponse methods', () => {
552+
const mockOnRequest = jest.fn((req) => req);
553+
const mockOnResponse = jest.fn((req, res, data) => res);
554+
let requestInterceptor: any;
555+
let responseInterceptor: any;
556+
557+
const mockClient = {
558+
defaults: {
559+
host: HOST_URL,
560+
},
561+
interceptors: {
562+
request: {
563+
use: jest.fn((interceptor) => {
564+
requestInterceptor = interceptor;
565+
}),
566+
},
567+
response: {
568+
use: jest.fn((successInterceptor) => {
569+
responseInterceptor = successInterceptor;
570+
}),
571+
},
572+
},
573+
};
574+
575+
createHttpClientMock.mockReturnValue(mockClient as any);
576+
577+
const mockPlugin = {
578+
onRequest: mockOnRequest,
579+
onResponse: mockOnResponse,
580+
};
581+
582+
const config = {
583+
apiKey: "apiKey",
584+
deliveryToken: "delivery",
585+
environment: "env",
586+
plugins: [mockPlugin],
587+
};
588+
589+
createStackInstance(config);
590+
591+
// Test that interceptors were registered
592+
expect(mockClient.interceptors.request.use).toHaveBeenCalled();
593+
expect(mockClient.interceptors.response.use).toHaveBeenCalled();
594+
595+
// Test request interceptor execution
596+
const mockRequest = { url: '/test' };
597+
requestInterceptor(mockRequest);
598+
expect(mockOnRequest).toHaveBeenCalledWith(mockRequest);
599+
600+
// Test response interceptor execution
601+
const mockResponse = {
602+
request: {},
603+
data: {},
604+
};
605+
responseInterceptor(mockResponse);
606+
expect(mockOnResponse).toHaveBeenCalledWith(mockResponse.request, mockResponse, mockResponse.data);
607+
});
608+
609+
it('should handle multiple plugins in order', () => {
610+
const executionOrder: string[] = [];
611+
let requestInterceptor: any;
612+
613+
const mockClient = {
614+
defaults: {
615+
host: HOST_URL,
616+
},
617+
interceptors: {
618+
request: {
619+
use: jest.fn((interceptor) => {
620+
requestInterceptor = interceptor;
621+
}),
622+
},
623+
response: {
624+
use: jest.fn(),
625+
},
626+
},
627+
};
628+
629+
createHttpClientMock.mockReturnValue(mockClient as any);
630+
631+
const mockPlugin1 = {
632+
onRequest: jest.fn((req) => {
633+
executionOrder.push('plugin1');
634+
return req;
635+
}),
636+
onResponse: jest.fn((req, res, data) => res),
637+
};
638+
639+
const mockPlugin2 = {
640+
onRequest: jest.fn((req) => {
641+
executionOrder.push('plugin2');
642+
return req;
643+
}),
644+
onResponse: jest.fn((req, res, data) => res),
645+
};
646+
647+
const config = {
648+
apiKey: "apiKey",
649+
deliveryToken: "delivery",
650+
environment: "env",
651+
plugins: [mockPlugin1, mockPlugin2],
652+
};
653+
654+
createStackInstance(config);
655+
656+
const mockRequest = { url: '/test' };
657+
requestInterceptor(mockRequest);
658+
659+
expect(executionOrder).toEqual(['plugin1', 'plugin2']);
660+
});
661+
});
404662
});

0 commit comments

Comments
 (0)