Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Search and count by post #226

Merged
merged 1 commit into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
10 changes: 5 additions & 5 deletions javascript/lib/api/src/client/handles/messages-http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export class DefaultHttpMessagesHandle implements HttpMessagesHandle {
claim(thingId: string, claimMessage: any, options?: MessagesOptions): Promise<GenericResponse> {
const messageOptions = options === undefined ? DefaultMessagesOptions.getInstance() : options;
messageOptions.addHeader(Header.CONTENT_TYPE, ContentType.JSON);
return this.requestFactory.fetchRequest({
return this.requestFactory.fetchGenericJsonRequest({
verb: HttpVerb.POST,
id: thingId,
path: 'inbox/claim',
Expand All @@ -135,7 +135,7 @@ export class DefaultHttpMessagesHandle implements HttpMessagesHandle {
contentType: string = ContentType.JSON, options?: MessagesOptions): Promise<GenericResponse> {
const messageOptions = options === undefined ? DefaultMessagesOptions.getInstance() : options;
messageOptions.addHeader(Header.CONTENT_TYPE, contentType);
return this.requestFactory.fetchRequest({
return this.requestFactory.fetchGenericJsonRequest({
verb: HttpVerb.POST,
id: thingId,
path: `inbox/messages/${messageSubject}`,
Expand All @@ -158,7 +158,7 @@ export class DefaultHttpMessagesHandle implements HttpMessagesHandle {
contentType: string = ContentType.JSON, options?: MessagesOptions): Promise<GenericResponse> {
const messageOptions = options === undefined ? DefaultMessagesOptions.getInstance() : options;
messageOptions.addHeader(Header.CONTENT_TYPE, contentType);
return this.requestFactory.fetchRequest({
return this.requestFactory.fetchGenericJsonRequest({
verb: HttpVerb.POST,
id: thingId,
path: `outbox/messages/${messageSubject}`,
Expand All @@ -183,7 +183,7 @@ export class DefaultHttpMessagesHandle implements HttpMessagesHandle {
Promise<GenericResponse> {
const messageOptions = options === undefined ? DefaultMessagesOptions.getInstance() : options;
messageOptions.addHeader(Header.CONTENT_TYPE, contentType);
return this.requestFactory.fetchRequest({
return this.requestFactory.fetchGenericJsonRequest({
verb: HttpVerb.POST,
id: thingId,
path: `features/${featureId}/inbox/messages/${messageSubject}`,
Expand All @@ -208,7 +208,7 @@ export class DefaultHttpMessagesHandle implements HttpMessagesHandle {
Promise<GenericResponse> {
const messageOptions = options === undefined ? DefaultMessagesOptions.getInstance() : options;
messageOptions.addHeader(Header.CONTENT_TYPE, contentType);
return this.requestFactory.fetchRequest({
return this.requestFactory.fetchGenericJsonRequest({
verb: HttpVerb.POST,
id: thingId,
path: `features/${featureId}/outbox/messages/${messageSubject}`,
Expand Down
44 changes: 44 additions & 0 deletions javascript/lib/api/src/client/handles/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,29 @@ export interface SearchHandle {
*/
search(options?: SearchOptions): Promise<SearchThingsResponse>;

/**
* Searches for Things that match the restrictions set in options using a http post request.
*
* @param options - Options to use for the search.
* @returns The search result
*/
postSearch(options?: SearchOptions): Promise<SearchThingsResponse>;

/**
* Counts the Things that match the restrictions set in options.
*
* @param options - Options to use for the search.
* @returns The count
*/
count(options?: CountOptions): Promise<number>;

/**
* Counts the Things that match the restrictions set in options using a http post request.
*
* @param options - Options to use for the search.
* @returns The count
*/
postCount(options?: CountOptions): Promise<number>;
}

/**
Expand Down Expand Up @@ -66,6 +82,20 @@ export class DefaultSearchHandle implements SearchHandle {
});
}

/**
* Searches for Things that match the restrictions set in options using a http post request.
*
* @param options - Options to use for the search.
* @returns The search result
*/
postSearch(options?: SearchOptions): Promise<SearchThingsResponse> {
return this.requestFactory.fetchFormRequest({
verb: HttpVerb.POST,
parser: SearchThingsResponse.fromObject,
payload: options?.getOptions()
});
}

/**
* Counts the Things that match the restrictions set in options.
*
Expand All @@ -81,4 +111,18 @@ export class DefaultSearchHandle implements SearchHandle {
});
}

/**
* Counts the Things that match the restrictions set in options using a http post request.
*
* @param options - Options to use for the search.
* @returns The count
*/
postCount(options?: CountOptions): Promise<number> {
return this.requestFactory.fetchFormRequest({
verb: HttpVerb.POST,
parser: Number,
path: 'count',
payload: options?.getOptions()
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class HttpRequestSender extends RequestSender {

public fetchRequest(options: FetchRequest): Promise<GenericResponse> {
return this.requester.doRequest(options.verb, this.buildUrl(options.id, options.path, options.requestOptions),
this.buildHeader(options.requestOptions), JSON.stringify(options.payload))
this.buildHeader(options.requestOptions), options.payload)
.then(response => {
if (response.status >= 200 && response.status < 300) {
return response;
Expand All @@ -52,12 +52,7 @@ export class HttpRequestSender extends RequestSender {
let urlSuffix = id === undefined ? '' : `/${id}`;
urlSuffix = path === undefined ? urlSuffix : `${urlSuffix}/${path}`;
if (options !== undefined && options.getOptions().size > 0) {
const values = options.getOptions();
let result = '';
values.forEach((v, k) => {
result += `&${k}=${v}`;
});
urlSuffix = `${urlSuffix}?${result.substr(1)}`;
urlSuffix = `${urlSuffix}?${this.mapToQueryParams(options.getOptions())}`;
}
const baseUrlWithSuffix = this.baseUrl.withPath(`${this.baseUrl.path}${urlSuffix}`);
const authenticatedBaseUrl = authenticateWithUrl(baseUrlWithSuffix, this.authenticationProviders);
Expand Down
72 changes: 59 additions & 13 deletions javascript/lib/api/src/client/request-factory/request-sender.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import { RequestOptions } from '../../options/request.options';
* Handle to send requests.
*/
export abstract class RequestSender {

/**
* Fetches the specified request and returns an object of type T.
*
Expand All @@ -27,8 +26,31 @@ export abstract class RequestSender {
* @returns A Promise for the specified object
*/
public fetchJsonRequest<T>(options: ParseRequest<T>): Promise<T> {
return this.fetchRequest(options)
.then(response => options.parser(response.body));
return this.fetchGenericJsonRequest(options).then(response => options.parser(response.body));
}

/**
* Fetches the specified request and returns an object of type T.
*
* @typeParam T - The type of object to return
* @param options - The options to use for the request.
* @returns A Promise for the specified object
*/
public fetchFormRequest<T>(options: FetchFormRequest<T>): Promise<T> {
return this.fetchRequest({
...options,
payload: options.payload
? this.mapToQueryParams(options.payload)
: undefined
}).then(response => options.parser(response.body));
}

protected mapToQueryParams(map: Map<string, string>): string {
let result = '';
map.forEach((value, key) => {
result += `&${key}=${value}`;
});
return result.substring(1);
}

/**
Expand All @@ -39,16 +61,32 @@ export abstract class RequestSender {
* @returns A Promise for the specified object
*/
public fetchPutRequest<T>(options: ParseRequest<T>): Promise<PutResponse<T>> {
return this.fetchRequest(options)
.then(response => {
if (response.status === 201) {
return new PutResponse(options.parser(response.body), response.status, response.headers);
}
if (response.status === 204) {
return new PutResponse<T>(null, response.status, response.headers);
}
return Promise.reject(`Received unknown status code: ${response.status}`);
});
return this.fetchGenericJsonRequest(options).then(response => {
if (response.status === 201) {
return new PutResponse(
options.parser(response.body),
response.status,
response.headers
);
}
if (response.status === 204) {
return new PutResponse<T>(null, response.status, response.headers);
}
return Promise.reject(`Received unknown status code: ${response.status}`);
});
}

/**
* Fetches the specified request and checks if the request was successful.
*
* @param options - The options to use for the request.
* @returns A Promise for the response
*/
public fetchGenericJsonRequest(options: FetchRequest): Promise<GenericResponse> {
return this.fetchRequest({
...options,
payload: JSON.stringify(options.payload)
});
}

/**
Expand Down Expand Up @@ -90,6 +128,14 @@ export interface FetchRequest {
payload?: any;
}

/**
* The options needed for a Request.
*/
export interface FetchFormRequest<T> extends ParseRequest<T> {
/** The payload to send with he request. */
payload?: Map<string, string>;
}

/**
* The options needed for a Request that parses the server response.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,16 @@ export class WebSocketRequestSender extends RequestSender {
});
}

/**
* Fetches the specified request and checks if the request was successful.
*
* @param options - The options to use for the request.
* @returns A Promise for the response
*/
public fetchGenericJsonRequest(options: FetchRequest): Promise<GenericResponse> {
return this.fetchRequest(options);
}

/**
* Sends a Message and returns the response.
*
Expand Down
62 changes: 61 additions & 1 deletion javascript/lib/api/tests/client/http/search.http.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,51 @@
import { HttpVerb } from '../../../src/client/constants/http-verb';
import { SearchHandle } from '../../../src/client/handles/search';
import { SearchThingsResponse } from '../../../src/model/response';
import { DefaultSearchOptions } from '../../../src/options/request.options';
import { HttpHelper as H } from './http.helper';

describe('Http Search Handle', () => {
const baseRequest = 'search/things';
const handle: SearchHandle = H.thingsClient.getSearchHandle();
const errorHandle: SearchHandle = H.errorThingsClient.getSearchHandle();

it('gets the Thing', () => {
const searchOptions = DefaultSearchOptions.getInstance()
.withLimit(0, 25)
.withFilter(
'and(like(definition,"*test*"),and(or(ilike(/attributes/test,"*test*"),eq(/definition,"test"))))'
)
.withFields("thingId", "definition", "attributes", "features");

const expectedPayload =
"option=limit(0%2C25)&filter=and(like(definition%2C%22*test*%22)%2Cand(or(ilike(%2Fattributes%2Ftest%2C%22*test*%22)%2Ceq(%2Fdefinition%2C%22test%22))))&fields=thingId%2Cdefinition%2Cattributes%2Cfeatures";


it('gets the Thing by post with search options', () => {
const response = new SearchThingsResponse([H.thing], -1);
return H.test({
toTest: () => handle.postSearch(searchOptions),
testBody: response.toObject(),
expected: response,
payload:expectedPayload,
request: baseRequest,
method: HttpVerb.POST,
status: 200,
});
});

it("gets the Thing by post", () => {
const response = new SearchThingsResponse([H.thing], -1);
return H.test({
toTest: () => handle.postSearch(),
testBody: response.toObject(),
expected: response,
request: baseRequest,
method: HttpVerb.POST,
status: 200,
});
});

it("gets the Thing", () => {
const response = new SearchThingsResponse([H.thing], -1);
return H.test({
toTest: () => handle.search(),
Expand All @@ -44,6 +81,29 @@ describe('Http Search Handle', () => {
});
});

it("counts Things by post with search options", () => {
return H.test({
toTest: () => handle.postCount(searchOptions),
testBody: 4,
expected: 4,
request: `${baseRequest}/count`,
method: HttpVerb.POST,
payload: expectedPayload,
status: 200,
});
});

it("counts Things by post", () => {
return H.test({
toTest: () => handle.postCount(),
testBody: 4,
expected: 4,
request: `${baseRequest}/count`,
method: HttpVerb.POST,
status: 200,
});
});

it('returns a search error message', () => {
return H.testError(() => errorHandle.search());
});
Expand Down
Loading