Skip to content
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
46 changes: 42 additions & 4 deletions src/main/java/lol/pbu/z4j/client/SearchClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import io.micronaut.http.client.annotation.Client;
import io.micronaut.retry.annotation.Retryable;
import jakarta.validation.Valid;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.NotNull;
import lol.pbu.z4j.model.SearchExportType;
import lol.pbu.z4j.model.SearchResponse;
Expand Down Expand Up @@ -56,7 +57,34 @@ public interface SearchClient {

/**
* <h1>{@summary Export Search Results}</h1>
* <p>Exports a set of results. See <a href='https://developer.zendesk.com/api-reference/ticketing/ticket-management/search/#query-syntax'>Query syntax</a> for the syntax of the {@code query} parameter.</p> <p>Use this endpoint for search queries that will return more than 1000 results. The result set is ordered only by the {@code created_at} attribute.</p> <p>The search only returns results of a single object type. The following object types are supported: ticket, organization, user, or group.</p> <p>You must specify the type in the {@code filter[type]} parameter. Searches with type in the query string will result in an error.</p> Allowed for Agents <h4>Pagination</h4> <ul> <li>Cursor pagination</li> </ul> <p>See <a href='https://developer.zendesk.com/api-reference/introduction/pagination/'>Pagination</a>.</p> <p>Returns a maximum of 1000 records per page. The number of results shown in a page is determined by the {@code page[size]} parameter.</p> <p><strong>Note</strong>: You may experience a speed reduction or a timeout if you request 1000 results per page and you have many archived tickets in the results. Try reducing the number of results per page. We recommend 100 results per page.</p> <p>The cursor specified by the {@code after_cursor} property in a response expires after one hour.</p> <p>For more information on cursor-based pagination, see the following articles:</p> <ul> <li><a href='https://developer.zendesk.com/documentation/developer-tools/pagination/comparing-cursor-pagination-and-offset-pagination'>Comparing cursor pagination and offset pagination</a></li> <li><a href='https://developer.zendesk.com/documentation/developer-tools/pagination/paginating-through-lists-using-cursor-pagination'>Paginating through lists using cursor pagination</a></li> </ul> <h4>Export Search Results Limits</h4> <p>This API endpoint is rate-limited to 100 requests per minute per account. The limit also counts towards the global API rate limit.</p>
* <p>Exports a set of results. See <a
* href='https://developer.zendesk.com/api-reference/ticketing/ticket-management/search/#query-syntax'>Query
* syntax</a> for the syntax of the {@code query} parameter.</p> <p>Use this endpoint for search queries that will
* return more than 1000 results. The result set is ordered only by the {@code created_at} attribute.</p> <p>The search
* only returns results of a single object type. The following object types are supported: ticket, organization, user,
* or group.</p> <p>You must specify the type in the {@code filter[type]} parameter. Searches with type in the query
* string will result in an error.</p> Allowed for Agents <h4>Pagination</h4>
* <ul>
* <li>Cursor
* pagination
* </li>
* </ul> <p>See <a href='https://developer.zendesk.com/api-reference/introduction/pagination/'>Pagination</a>.</p> <p>
* Returns a maximum of 1000 records per page. The number of results shown in a page is determined by the {@code
* page[size]} parameter.</p> <p><strong>Note</strong>: You may experience a speed reduction or a timeout if you
* request 1000 results per page and you have many archived tickets in the results. Try reducing the number of results
* per page. We recommend 100 results per page.</p> <p>The cursor specified by the {@code after_cursor} property in a
* response expires after one hour.</p> <p>For more information on cursor-based pagination, see the following
* articles:</p>
* <ul>
* <li>
* <a href='https://developer.zendesk.com/documentation/developer-tools/pagination/comparing-cursor-pagination-and-offset-pagination'>Comparing
* cursor pagination and offset pagination</a></li>
* <li>
* <a href='https://developer.zendesk.com/documentation/developer-tools/pagination/paginating-through-lists-using-cursor-pagination'>Paginating
* through lists using cursor pagination</a></li>
* </ul> <h4>Export Search Results Limits</h4> <p>This API endpoint is rate-limited to 100 requests per minute per account.
* The limit also counts towards the global API rate
* limit.</p>
*
* @param query Returns the search results. See <a href='https://developer.zendesk.com/api-reference/ticketing/ticket-management/search/#query-syntax'>Query syntax</a> for details on the {@code query} parameter. For details on the query syntax, see the <a href='https://support.zendesk.com/hc/en-us/articles/203663226'>Zendesk Support search reference</a>. (required)
* @param pageSize The number of results shown in a page. (required)
Expand All @@ -69,20 +97,28 @@ public interface SearchClient {
@Get("/api/v2/search/export")
Mono<@Valid SearchResponse> export(
@QueryValue("query") @NotNull String query,
@QueryValue("page[size]") @NotNull Integer pageSize,
@QueryValue("page[size]") @NotNull @Max(1000) Integer pageSize,
@QueryValue("page[after]") @NotNull String pageAfter,
@QueryValue("filter[type]") @NotNull SearchExportType filterType,
@QueryValue("include") @Nullable String include
);

/**
* <h1>{@summary List Search Results}</h1>
* <p>Returns the search results. See <a href='https://developer.zendesk.com/api-reference/ticketing/ticket-management/search/#query-syntax'>Query syntax</a> for details on the {@code query} parameter.</p> <p>Use the ampersand character (&amp;) to append the {@code sort_by} or {@code sort_order} parameters to the URL.</p> <p>For examples, see <a href='https://developer.zendesk.com/documentation/ticketing/using-the-zendesk-api/searching-with-the-zendesk-api'>Searching with Zendesk API</a>.</p> <p>This endpoint has its own rate limit. The rate limit counts towards the global API rate limit. See <a href='https://developer.zendesk.com/api-reference/ticketing/introduction/#limits'>Limits</a>.</p><h4>Allowed For Agents</h4> <h4>Pagination</h4> <ul> <li>Offset pagination only</li> </ul> <p>Offset pagination may result in duplicate results when paging. You can also use the <a href='https://developer.zendesk.com/api-reference/ticketing/ticket-management/search/#export-search-results'>Export Search Results</a> endpoint, which uses cursor-based pagination and doesn't return duplicate results. See <a href='https://developer.zendesk.com/api-reference/introduction/pagination/#using-cursor-pagination'>Using cursor pagination</a> for more information.</p>
* <p>Returns the search results. See <a
* href='https://developer.zendesk.com/api-reference/ticketing/ticket-management/search/#query-syntax'>Query
* syntax</a> for details on the {@code query} parameter.</p>
*
* <p>This endpoint has its own rate limit. The rate limit counts towards the global API rate
* limit. See <a href='https://developer.zendesk.com/api-reference/ticketing/introduction/#limits'>Limits</a>.</p><h4>
* Allowed For Agents</h4>
*
* @param query Returns the search results. See <a href='https://developer.zendesk.com/api-reference/ticketing/ticket-management/search/#query-syntax'>Query syntax</a> for details on the {@code query} parameter. For details on the query syntax, see the <a href='https://support.zendesk.com/hc/en-us/articles/203663226'>Zendesk Support search reference</a>. (required)
* @param sortBy One of {@code updated_at}, {@code created_at}, {@code priority}, {@code status}, or {@code ticket_type}. Defaults to sorting by relevance (optional)
* @param sortOrder Defaults to descending (optional)
* @param include Sideloads to include in the response. Accepts a comma-separated list of values. The available sideloads depend on the search result types. (optional)
* @param page The page number to retrieve. (optional)
* @param perPage The count of results to include in each page. (optional)
* @return Success response (status code 200)
* or Error response (status code 400)
*/
Expand All @@ -91,6 +127,8 @@ public interface SearchClient {
@QueryValue("query") @NotNull String query,
@QueryValue("sort_by") @Nullable SortBy sortBy,
@QueryValue("sort_order") @Nullable SortOrder sortOrder,
@QueryValue("include") @Nullable String include
@QueryValue("include") @Nullable String include,
@QueryValue("page") @Nullable Integer page,
@QueryValue("per_page") @Nullable @Max(100) Integer perPage
);
}
2 changes: 1 addition & 1 deletion src/main/java/lol/pbu/z4j/client/TicketClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public interface TicketClient {
* <h1>{@summary List Ticket Fields}</h1>
* <p>Returns a list of all system and custom ticket fields in your account.</p> <p>For end users, only the ticket fields with visible_in_portal set to true are returned.</p> <p>Consider caching this resource to use with the{@link TicketClient}.</p> <h4 id=\"allowed-for'>Allowed For</h4> <ul> <li>Anyone</li> </ul>
*
* @param locale Forces the {@code titleInPortal} property to return a dynamic content variant for the specified locale. Only accepts {@link LocaleClient#listLocales() active locale ids}. (optional)
* @param localeAbbreviation Forces the {@code titleInPortal} property to return a dynamic content variant for the specified locale. Only accepts {@link LocaleClient#listLocales() active locale ids}. (optional)
* @param creator Includes the {@code creatorUserId} and {@code creatorAppName} properties in the response. If the ticket field is created by an app, {@code creatorAppName} is the name of the app and {@code creatorUserId} is {@code -1}. If the ticket field is not created by an app, {@code creatorAppName} is null. (optional)
* @return Success response (status code 200)
*/
Expand Down
53 changes: 47 additions & 6 deletions src/test/groovy/lol/pbu/z4j/client/SearchClientSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,28 @@ package lol.pbu.z4j.client

import io.micronaut.http.client.exceptions.HttpClientResponseException
import lol.pbu.z4j.Z4jSpec
import lol.pbu.z4j.model.SearchExportType
import lol.pbu.z4j.model.SortBy
import lol.pbu.z4j.model.SortOrder
import lol.pbu.z4j.model.*
import spock.lang.Shared
import spock.lang.Unroll

class SearchClientSpec extends Z4jSpec {
@Shared
SearchClient adminSearchClient, agentSearchClient, userSearchClient

@Shared
TicketClient ticketClient

def setupSpec() {
adminSearchClient = adminCtx.getBean(SearchClient.class)
agentSearchClient = agentCtx.getBean(SearchClient.class)
userSearchClient = userCtx.getBean(SearchClient.class)
}

@SuppressWarnings("GroovyAssignabilityCheck")
@Unroll("an #clientName user can run the list method with sortby: #sortBy, sortOrder: #sortOrder and include: #include")
void "can run the list method"(String clientName, SearchClient client, SortBy sortBy, SortOrder sortOrder, String include) {
when:
client.list(faker.bluey().quote(), sortBy, sortOrder, include).block()
client.list(faker.bluey().quote(), sortBy, sortOrder, include, null, null).block()

then:
noExceptionThrown()
Expand All @@ -59,10 +61,50 @@ class SearchClientSpec extends Z4jSpec {
[client, clientName] << [[adminSearchClient, "admin"], [agentSearchClient, "agent"]]
}


@SuppressWarnings("GroovyAssignabilityCheck")
@Unroll("an #clientName user can paginate the list method with sortby: #sortBy, sortOrder: #sortOrder and include: #include")
void "can query the list method when results include more than the page size"(
String clientName, SearchClient client, SortBy sortBy, SortOrder sortOrder, String include) {
given:
if (null == ticketClient) {
ticketClient = adminCtx.getBean(TicketClient.class)
}
if (client.count("frank").block().getCount() < 5) {
(1..5).each {
TicketComment ticketComment = new TicketComment().setBody("frank " + faker.chuckNorris().fact())
TicketCreateRequest createTicketRequest = new TicketCreateRequest(new TicketCreateInput(ticketComment))
createTicketRequest.ticket.setSubject(faker.chuckNorris().fact())
ticketClient.createTicket(createTicketRequest).block()
}
}

when:
def page = 1
List<SearchResponse> responses = []
SearchResponse response = client.list("frank", sortBy, sortOrder, include, page, 2).block()
responses << response
while (response.nextPage != null) {
page++
response = client.list("frank", sortBy, sortOrder, include, page, 2).block()
responses << response
}

then:

noExceptionThrown()

where:
[[client, clientName], sortBy, sortOrder, include] << [[[adminSearchClient, "admin"], [agentSearchClient, "agent"]],
[SortBy.values(), null].flatten(),
[SortOrder.values(), null].flatten(),
[null, faker.cat().name()]].combinations()
}

@Unroll("a simple user querying the list method fails with #sortBy, #sortOrder and #include")
void "cannot run searchClient.list()"(SearchClient client, SortBy sortBy, SortOrder sortOrder, String include) {
when:
client.list(faker.bluey().quote(), sortBy, sortOrder, include).block()
client.list(faker.bluey().quote(), sortBy, sortOrder, include, null, null).block()

then:
thrown(HttpClientResponseException)
Expand Down Expand Up @@ -103,4 +145,3 @@ class SearchClientSpec extends Z4jSpec {
["organizations"]].combinations()
}
}

Loading