Skip to content

Commit 97cbb6f

Browse files
Merge pull request #156 from contentstack/feat/cs-43915-or-operator-query-implementation
changes in query operators implementation
2 parents 7a0d4cc + 31402d0 commit 97cbb6f

File tree

6 files changed

+121
-82
lines changed

6 files changed

+121
-82
lines changed

src/lib/content-type.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { AxiosInstance, getData } from '@contentstack/core';
22
import { Entry } from './entry';
33
import { Entries } from './entries';
4-
import { Query } from './query';
54

65
interface ContentTypeResponse<T> {
76
content_type: T;
@@ -19,21 +18,6 @@ export class ContentType {
1918
this._urlPath = `/content_types/${this._contentTypeUid}`;
2019
}
2120

22-
/**
23-
* @method Query
24-
* @memberof ContentType
25-
* @description queries get all entries that satisfy the condition of the following function
26-
* @returns {Query}
27-
* @example
28-
* import contentstack from '@contentstack/delivery-sdk'
29-
*
30-
* const stack = contentstack.Stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
31-
* const entries = stack.contentType("contentTypeUid").Query().containedIn('fieldUid', ['value1','value2'])
32-
*/
33-
Query(): Query {
34-
return new Query(this._client, this._contentTypeUid);
35-
};
36-
3721
/**
3822
* @method entry
3923
* @memberof ContentType

src/lib/query.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ export class Query extends BaseQuery {
173173
* import contentstack from '@contentstack/delivery-sdk'
174174
*
175175
* const stack = contentstack.Stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
176-
* const query = stack.contentType("contentTypeUid").Query();
176+
* const query = stack.contentType("contentTypeUid").entry().query();
177177
* const result = containedIn('fieldUid', ['value1', 'value2']).find()
178178
*
179179
* @returns {Query}
@@ -191,7 +191,7 @@ export class Query extends BaseQuery {
191191
* import contentstack from '@contentstack/delivery-sdk'
192192
*
193193
* const stack = contentstack.Stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
194-
* const query = stack.contentType("contentTypeUid").Query();
194+
* const query = stack.contentType("contentTypeUid").entry().query();
195195
* const result = notContainedIn('fieldUid', ['value1', 'value2']).find()
196196
*
197197
* @returns {Query}
@@ -202,20 +202,32 @@ export class Query extends BaseQuery {
202202
}
203203

204204
/**
205-
* @method notExists
205+
* @method or
206206
* @memberof Query
207207
* @description Returns the raw (JSON) query based on the filters applied on Query object.
208208
* @example
209209
* import contentstack from '@contentstack/delivery-sdk'
210210
*
211211
* const stack = contentstack.Stack({ apiKey: "apiKey", deliveryToken: "deliveryToken", environment: "environment" });
212-
* const query = stack.contentType("contentTypeUid").Query();
213-
* const result = notExists('fieldUid').find()
214-
*
212+
* const query1 = await contentType.Entry().query().containedIn('fieldUID', ['value']);
213+
* const query2 = await contentType.Entry().query().where('fieldUID', QueryOperation.EQUALS, 'value2');
214+
* const query = await contentType.Entry().query().or(query1, query2).find();
215+
*
215216
* @returns {Query}
216217
*/
217218
notExists(key: string): Query {
218219
this._parameters[key] = { '$exists': false };
219220
return this;
220221
}
222+
223+
or(...queries: Query[]): Query {
224+
const combinedQuery: any = { $or: [] };
225+
for (const query of queries) {
226+
combinedQuery.$or.push(query._parameters);
227+
}
228+
const newQuery: Query = Object.create(this);
229+
newQuery._parameters = combinedQuery;
230+
231+
return newQuery;
232+
}
221233
}

test/api/contenttype.spec.ts

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
/* eslint-disable no-console */
22
/* eslint-disable promise/always-return */
3-
import { BaseContentType, BaseEntry, FindResponse } from 'src';
43
import { ContentType } from '../../src/lib/content-type';
54
import { stackInstance } from '../utils/stack-instance';
6-
import { TContentType, TEntries, TEntry } from './types';
5+
import { TContentType, TEntry } from './types';
76
import dotenv from 'dotenv';
87

98
dotenv.config()
@@ -26,38 +25,7 @@ describe('ContentType API test cases', () => {
2625
expect(result.schema).toBeDefined();
2726
});
2827
});
29-
describe('ContentType Query API test cases', () => {
30-
it('should get entries which matches the fieldUid and values', async () => {
31-
const query = await makeContentType('contenttype_uid').Query().containedIn('title', ['value']).find<TEntry>()
32-
if (query.entries) {
33-
expect(query.entries[0]._version).toBeDefined();
34-
expect(query.entries[0].title).toBeDefined();
35-
expect(query.entries[0].uid).toBeDefined();
36-
expect(query.entries[0].created_at).toBeDefined();
37-
}
38-
});
39-
40-
it('should get entries which does not match the fieldUid and values', async () => {
41-
const query = await makeContentType('contenttype_uid').Query().notContainedIn('title', ['test', 'test2']).find<TEntry>()
42-
if (query.entries) {
43-
expect(query.entries[0]._version).toBeDefined();
44-
expect(query.entries[0].title).toBeDefined();
45-
expect(query.entries[0].uid).toBeDefined();
46-
expect(query.entries[0].created_at).toBeDefined();
47-
}
48-
});
4928

50-
it('should get entries which does not match the fieldUid - notExists', async () => {
51-
const query = await makeContentType('contenttype_uid').Query().notExists('multi_line').find<TEntry>()
52-
if (query.entries) {
53-
expect(query.entries[0]._version).toBeDefined();
54-
expect(query.entries[0].title).toBeDefined();
55-
expect(query.entries[0].uid).toBeDefined();
56-
expect(query.entries[0].created_at).toBeDefined();
57-
expect((query.entries[0] as any).multi_line).not.toBeDefined()
58-
}
59-
});
60-
});
6129
function makeContentType(uid = ''): ContentType {
6230
const contentType = stack.ContentType(uid);
6331

test/api/entry-queryables.spec.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { stackInstance } from '../utils/stack-instance';
2+
import { Entries } from '../../src/lib/entries';
3+
import { TEntry } from './types';
4+
import { QueryOperation } from 'src/lib/types';
5+
import { Query } from 'src/lib/query';
6+
7+
const stack = stackInstance();
8+
9+
describe('Query Operators API test cases', () => {
10+
it('should get entries which matches the fieldUid and values', async () => {
11+
const query = await makeEntries('contenttype_uid').query().containedIn('title', ['value']).find<TEntry>()
12+
if (query.entries) {
13+
expect(query.entries[0]._version).toBeDefined();
14+
expect(query.entries[0].title).toBeDefined();
15+
expect(query.entries[0].uid).toBeDefined();
16+
expect(query.entries[0].created_at).toBeDefined();
17+
}
18+
});
19+
20+
it('should get entries which does not match the fieldUid and values', async () => {
21+
const query = await makeEntries('contenttype_uid').query().notContainedIn('title', ['test', 'test2']).find<TEntry>()
22+
if (query.entries) {
23+
expect(query.entries[0]._version).toBeDefined();
24+
expect(query.entries[0].title).toBeDefined();
25+
expect(query.entries[0].uid).toBeDefined();
26+
expect(query.entries[0].created_at).toBeDefined();
27+
}
28+
});
29+
30+
it('should get entries which does not match the fieldUid - notExists', async () => {
31+
const query = await makeEntries('contenttype_uid').query().notExists('multi_line').find<TEntry>()
32+
if (query.entries) {
33+
expect(query.entries[0]._version).toBeDefined();
34+
expect(query.entries[0].title).toBeDefined();
35+
expect(query.entries[0].uid).toBeDefined();
36+
expect(query.entries[0].created_at).toBeDefined();
37+
expect((query.entries[0] as any).multi_line).not.toBeDefined()
38+
}
39+
});
40+
it('should return entries matching any of the conditions - or', async () => {
41+
const query1: Query = await makeEntries('contenttype_uid').query().containedIn('title', ['value']);
42+
const query2: Query = await makeEntries('contenttype_uid').query().where('title', QueryOperation.EQUALS, 'value2');
43+
const query = await makeEntries('contenttype_uid').query().or(query1, query2).find<TEntry>();
44+
45+
if (query.entries) {
46+
expect(query.entries).toHaveLength(2);
47+
expect(query.entries[0]._version).toBeDefined();
48+
expect(query.entries[0].locale).toBeDefined();
49+
expect(query.entries[0].uid).toBeDefined();
50+
expect(query.entries[0].title).toBe('value2');
51+
expect(query.entries[1]._version).toBeDefined();
52+
expect(query.entries[1].locale).toBeDefined();
53+
expect(query.entries[1].uid).toBeDefined();
54+
expect(query.entries[1].title).toBe('value');
55+
}
56+
});
57+
});
58+
59+
function makeEntries(contentTypeUid = ''): Entries {
60+
const entries = stack.ContentType(contentTypeUid).Entry();
61+
return entries;
62+
}

test/unit/contenttype.spec.ts

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -42,30 +42,3 @@ describe('ContentType class', () => {
4242
expect(response).toEqual(contentTypeResponseMock.content_type);
4343
});
4444
});
45-
46-
describe('ContentType Query class', () => {
47-
let contentType: ContentType;
48-
let client: AxiosInstance;
49-
let mockClient: MockAdapter;
50-
51-
beforeAll(() => {
52-
client = httpClient(MOCK_CLIENT_OPTIONS);
53-
mockClient = new MockAdapter(client as any);
54-
});
55-
56-
beforeEach(() => {
57-
contentType = new ContentType(client, 'contentTypeUid');
58-
});
59-
it('should get entries which matches the fieldUid and values', () => {
60-
const query = contentType.Query().containedIn('fieldUID', ['value']);
61-
expect(query._parameters).toStrictEqual({'fieldUID': {'$in': ['value']}});
62-
});
63-
it('should get entries which does not match the fieldUid and values', () => {
64-
const query = contentType.Query().notContainedIn('fieldUID', ['value', 'value2']);
65-
expect(query._parameters).toStrictEqual({'fieldUID': {'$nin': ['value', 'value2']}});
66-
});
67-
it('should get entries which does not match the fieldUid - notExists', () => {
68-
const query = contentType.Query().notExists('fieldUID');
69-
expect(query._parameters).toStrictEqual({'fieldUID': {'$exists': false}});
70-
});
71-
});

test/unit/entry-queryable.spec.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { AxiosInstance, httpClient } from '@contentstack/core';
2+
import { ContentType } from '../../src/lib/content-type';
3+
import MockAdapter from 'axios-mock-adapter';
4+
import { MOCK_CLIENT_OPTIONS } from '../utils/constant';
5+
import { Query } from 'src/lib/query';
6+
import { QueryOperation } from 'src/lib/types';
7+
8+
9+
describe('Query Operators API test cases', () => {
10+
let contentType: ContentType;
11+
let client: AxiosInstance;
12+
let mockClient: MockAdapter;
13+
14+
beforeAll(() => {
15+
client = httpClient(MOCK_CLIENT_OPTIONS);
16+
mockClient = new MockAdapter(client as any);
17+
});
18+
19+
beforeEach(() => {
20+
contentType = new ContentType(client, 'contentTypeUid');
21+
});
22+
it('should get entries which matches the fieldUid and values', () => {
23+
const query = contentType.Entry().query().containedIn('fieldUID', ['value']);
24+
expect(query._parameters).toStrictEqual({'fieldUID': {'$in': ['value']}});
25+
});
26+
it('should get entries which does not match the fieldUid and values', () => {
27+
const query = contentType.Entry().query().notContainedIn('fieldUID', ['value', 'value2']);
28+
expect(query._parameters).toStrictEqual({'fieldUID': {'$nin': ['value', 'value2']}});
29+
});
30+
it('should get entries which does not match the fieldUid - notExists', () => {
31+
const query = contentType.Entry().query().notExists('fieldUID');
32+
expect(query._parameters).toStrictEqual({'fieldUID': {'$exists': false}});
33+
});
34+
it('should return entries matching any of the conditions - or', async () => {
35+
const query1: Query = await contentType.Entry().query().containedIn('fieldUID', ['value']);
36+
const query2: Query = await contentType.Entry().query().where('fieldUID', QueryOperation.EQUALS, 'value2');
37+
const query = await contentType.Entry().query().or(query1, query2);
38+
expect(query._parameters).toStrictEqual({ '$or': [ {'fieldUID': {'$in': ['value']}}, { 'fieldUID': 'value2' } ] });
39+
});
40+
});

0 commit comments

Comments
 (0)