Skip to content

Commit

Permalink
fix(process): Fix process function and missing limit parameter when u…
Browse files Browse the repository at this point in the history
…sing byQueryString method
  • Loading branch information
junajan committed Aug 26, 2017
1 parent 0378f49 commit 907b2c0
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 40 deletions.
36 changes: 21 additions & 15 deletions src/coffee/services/base.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -278,24 +278,31 @@ class BaseService
_.each @_params.plain, (param) =>
if parsed[param]
@_params.query[param] = parsed[param]

# API accepts limit parameter instead of perPage which we use here in SDK so this
# quick hash unifies both worlds
parsed.limit = parsed.perPage if parsed.perPage
delete parsed.perPage
@_params.query.perPage = Number(parsed.limit) if parsed.limit

@_params.queryString = _.stringifyQuery(parsed)
debug 'setting queryString: %s', query
this

# Private: Build a query string from (pre)defined params (can be overriden for custom params)
#
# Returns the built query string
_queryString: ->
qs = if @_params.queryString
@_params.queryString
_queryString: (params = @_params) ->
qs = if params.queryString
params.queryString
else
Utils.buildQueryString
where: @_params.query.where
whereOperator: @_params.query.operator
page: @_params.query.page
perPage: @_params.query.perPage
sort: @_params.query.sort
expand: @_params.query.expand
where: params.query.where
whereOperator: params.query.operator
page: params.query.page
perPage: params.query.perPage
sort: params.query.sort
expand: params.query.expand
debug 'built query string: %s', qs
qs

Expand Down Expand Up @@ -366,19 +373,18 @@ class BaseService

endpoint = @constructor.baseResourceEndpoint
originalQuery = @_params.query
originalPredicate = @_params.query.where

if originalQuery.perPage is 0
debug 'using batch size of 20 since 0 wont return any results'
originalQuery.perPage = 20

_processPage = (lastId, acc = []) =>
_processPage = (params, lastId, acc = []) =>
debug 'processing next page with id: %s', lastId

# set the query to the original query
# this is needed since the query is reset after each request
@_params.query = originalQuery
queryString = @_queryString()
queryString = @_queryString params

if lastId
wherePredicate = encodeURIComponent("id > \"#{lastId}\"")
Expand All @@ -393,7 +399,7 @@ class BaseService
# they had been specified in a single `where` query parameter and
# combined with `and`"
if wherePredicate then "where=#{wherePredicate}" else null,
].filter((el) -> !!el).join('&')
].filter(Boolean).join('&')
debug 'enhanced query: %s', enhancedQueryString

@_get("#{endpoint}?#{enhancedQueryString}")
Expand All @@ -408,11 +414,11 @@ class BaseService

last = _.last(payload.body.results)
newLastId = last && last.id
_processPage newLastId, accumulated
_processPage params, newLastId, accumulated

.catch (error) -> reject error
.done()
_processPage()
_processPage(@_params)

# Public: Save a new resource defined by the `Service` by passing the payload {Object}.
#
Expand Down
10 changes: 7 additions & 3 deletions src/coffee/services/product-projections.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -317,11 +317,15 @@ class ProductProjectionService extends BaseService
# Private: Build a query string from (pre)defined params and custom search params
#
# Returns the built query string
_queryString: ->
_queryString: (params = @_params) ->
# use custom queryString if it is set
if params.queryString
return super(params)

{
staged, fuzzy, text, filter, filterByQuery, filterByFacets, facet, searchKeywords,
priceCurrency, priceCountry, priceCustomerGroup, priceChannel
} = _.defaults @_params.query, @_getProductsProjectionDefault()
} = _.defaults params.query, @_getProductsProjectionDefault()

customQueryString = []
customQueryString.push "staged=#{staged}" if staged
Expand Down Expand Up @@ -354,7 +358,7 @@ class ProductProjectionService extends BaseService
else if priceCountry or priceCustomerGroup or priceChannel
throw new Error "Field priceCurrency is required to enable price selection. Read more here http://dev.commercetools.com/http-api-projects-products.html#price-selection"

_.compact([super()].concat(customQueryString)).join '&'
_.compact([super(params)].concat(customQueryString)).join '&'

# Public: Search `ProductProjections` with all the search parameters
#
Expand Down
83 changes: 61 additions & 22 deletions src/spec/client/services/product-projections.spec.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -220,14 +220,18 @@ describe 'ProductProjectionService', ->
filterByFacets: []
facet: []
searchKeywords: []
perPage: '100'
perPage: 100
staged: 'true'
fuzzy: 'true'
priceCurrency: 'EUR'
priceCountry: 'GB'
priceCustomerGroup: 'UUID1'
priceChannel: 'UUID2'
queryString: 'where=productType(id%3D%22123%22)&perPage=100&staged=true&fuzzy=true&priceCurrency=EUR&priceCountry=GB&priceCustomerGroup=UUID1&priceChannel=UUID2'
queryString: 'where=productType(id%3D%22123%22)&staged=true&fuzzy=true&priceCurrency=EUR&priceCountry=GB&priceCustomerGroup=UUID1&priceChannel=UUID2&limit=100'

it 'should support also API limit parameter', ->
@service.byQueryString('where=productType(id="123")&limit=100&staged=true&fuzzy=true&priceCurrency=EUR&priceCountry=GB&priceCustomerGroup=UUID1&priceChannel=UUID2')
expect(@service._params.queryString).toEqual 'where=productType(id%3D%22123%22)&limit=100&staged=true&fuzzy=true&priceCurrency=EUR&priceCountry=GB&priceCustomerGroup=UUID1&priceChannel=UUID2'

describe ':: priceSelection required params', ->
_.each [
Expand Down Expand Up @@ -313,28 +317,63 @@ describe 'ProductProjectionService', ->
.catch (err) -> done(_.prettify err)

it 'should call each page with the same query (given sorting)', (done) ->
offset = -20
count = 20
# create a list of 80 products
products = [1..80].map (i) -> {id: "id_#{i}"}
perPage = 30
offset = -perPage

spyOn(@restMock, 'GET').andCallFake (endpoint, callback) ->
offset += 20
offset += perPage
# get subset of 30 products starting with a given offset
results = products.slice(offset, offset + perPage)
callback(null, {statusCode: 200}, {
# total: 50
count: if offset is 40 then 10 else count
total: products.length
count: results.length
offset: offset
results: _.map (if offset is 40 then [1..10] else [1..20]), (i) -> {id: "id_#{i}", endpoint}
results: results
})

@service
.staged(true)
.perPage(perPage)
.sort('name', false)
.where('foo=bar')
.where('hello=world')
.whereOperator('or')
.process -> Promise.resolve()
.then =>
expect(@restMock.GET.calls.length).toEqual 3
expect(@restMock.GET.calls[0].args[0]).toMatch /\?sort=id%20asc&where=foo%3Dbar%20or%20hello%3Dworld&limit=30&sort=name%20desc&staged=true&withTotal=false$/
expect(@restMock.GET.calls[1].args[0]).toMatch /\?sort=id%20asc&where=foo%3Dbar%20or%20hello%3Dworld&limit=30&sort=name%20desc&staged=true&withTotal=false&where=id%20%3E%20%22id_30%22$/
expect(@restMock.GET.calls[2].args[0]).toMatch /\?sort=id%20asc&where=foo%3Dbar%20or%20hello%3Dworld&limit=30&sort=name%20desc&staged=true&withTotal=false&where=id%20%3E%20%22id_60%22$/
done()
.catch (err) -> done(_.prettify err)

it 'should call each page with the same query when using byQueryString', (done) ->
# create a list of 80 products
products = [1..80].map (i) -> {id: "id_#{i}"}
perPage = 30
offset = -perPage

spyOn(@restMock, 'GET').andCallFake (endpoint, callback) ->
offset += perPage
# get subset of 30 products starting with a given offset
results = products.slice(offset, offset + perPage)
callback(null, {statusCode: 200}, {
total: products.length
count: results.length
offset: offset
results: results
})
fn = (payload) ->
Promise.resolve payload.body.results[0]
@service.staged(true).sort('name', false)
.where('foo=bar')
.where('hello=world')
.whereOperator('or')
.process(fn)
.then (result) ->
expect(_.size result).toBe 3
expect(result[0].endpoint).toMatch /\?sort=id%20asc&where=foo%3Dbar%20or%20hello%3Dworld&sort=name%20desc&staged=true&withTotal=false$/
expect(result[1].endpoint).toMatch /\?sort=id%20asc&where=foo%3Dbar%20or%20hello%3Dworld&sort=name%20desc&staged=true&withTotal=false&where=id%20%3E%20%22id_20%22$/
expect(result[2].endpoint).toMatch /\?sort=id%20asc&where=foo%3Dbar%20or%20hello%3Dworld&sort=name%20desc&staged=true&withTotal=false&where=id%20%3E%20%22id_20%22$/
done()
.catch (err) -> done(_.prettify err)

@service
.byQueryString('where=foo=bar&staged=true&limit=30')
.process -> Promise.resolve()
.then =>
# sdk should use custom queryString
expect(@restMock.GET.calls.length).toEqual 3
expect(@restMock.GET.calls[0].args[0]).toMatch /\?sort=id%20asc&where=foo%3Dbar&staged=true&limit=30&withTotal=false$/
expect(@restMock.GET.calls[1].args[0]).toMatch /\?sort=id%20asc&where=foo%3Dbar&staged=true&limit=30&withTotal=false&where=id%20%3E%20%22id_30%22$/
expect(@restMock.GET.calls[2].args[0]).toMatch /\?sort=id%20asc&where=foo%3Dbar&staged=true&limit=30&withTotal=false&where=id%20%3E%20%22id_60%22$/
done()
.catch (err) -> done(_.prettify err)

0 comments on commit 907b2c0

Please sign in to comment.