Skip to content
This repository has been archived by the owner on Feb 6, 2024. It is now read-only.

Commit

Permalink
feat: add the rest of the sellers api
Browse files Browse the repository at this point in the history
  • Loading branch information
gigobyte committed May 7, 2020
1 parent eca5c6d commit 8b10bc9
Show file tree
Hide file tree
Showing 7 changed files with 208 additions and 30 deletions.
27 changes: 27 additions & 0 deletions src/parsing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,30 @@ export const mwsBoolean = Codec.custom<boolean>({
encode: (x) => x,
schema: () => ({ type: 'string', enum: ['Yes', 'No'] }),
})

export enum ServiceStatus {
Green = 'GREEN',
Yellow = 'YELLOW',
Red = 'RED',
}

export const serviceStatus = Codec.custom<ServiceStatus>({
decode: (x) => {
switch (x) {
case 'GREEN':
return Right(ServiceStatus.Green)
case 'YELLOW':
return Right(ServiceStatus.Yellow)
case 'RED':
return Right(ServiceStatus.Red)
default:
return Left(
`Expected a string with a value of "GREEN", "YELLOW" or "RED", but received a string with value ${JSON.stringify(
x,
)}`,
)
}
},
encode: (x) => x,
schema: () => ({ type: 'string', enum: ['GREEN', 'YELLOW', 'RED'] }),
})
113 changes: 86 additions & 27 deletions src/sections/sellers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,73 @@ import { Codec, GetInterface, optional, string } from 'purify-ts'

import { ParsingError } from '../error'
import { HttpClient, RequestMeta, Resource } from '../http'
import { ensureArray, mwsBoolean } from '../parsing'
import { ensureArray, mwsBoolean, serviceStatus } from '../parsing'

const SELLERS_API_VERSION = '2011-07-01'

const MarketplaceParticipations = Codec.interface({
ListMarketplaceParticipationsResponse: Codec.interface({
ListMarketplaceParticipationsResult: Codec.interface({
NextToken: optional(string),
ListParticipations: Codec.interface({
Participation: ensureArray(
Codec.interface({
MarketplaceId: string,
SellerId: string,
HasSellerSuspendedListings: mwsBoolean,
}),
),
NextToken: optional(string),
ListParticipations: Codec.interface({
Participation: ensureArray(
Codec.interface({
MarketplaceId: string,
SellerId: string,
HasSellerSuspendedListings: mwsBoolean,
}),
ListMarketplaces: Codec.interface({
Marketplace: ensureArray(
Codec.interface({
MarketplaceId: string,
Name: string,
DefaultCountryCode: string,
DefaultCurrencyCode: string,
DefaultLanguageCode: string,
DomainName: string,
}),
),
),
}),
ListMarketplaces: Codec.interface({
Marketplace: ensureArray(
Codec.interface({
MarketplaceId: string,
Name: string,
DefaultCountryCode: string,
DefaultCurrencyCode: string,
DefaultLanguageCode: string,
DomainName: string,
}),
),
}),
})

const MarketplaceParticipationsResponse = Codec.interface({
ListMarketplaceParticipationsResponse: Codec.interface({
ListMarketplaceParticipationsResult: MarketplaceParticipations,
}),
})

const MarketplaceParticipationsByNextTokenResponse = Codec.interface({
ListMarketplaceParticipationsByNextTokenResponse: Codec.interface({
ListMarketplaceParticipationsByNextTokenResult: MarketplaceParticipations,
}),
})

const ServiceStatusResponse = Codec.interface({
GetServiceStatusResponse: Codec.interface({
GetServiceStatusResult: Codec.interface({
Status: serviceStatus,
Timestamp: string,
}),
}),
})

type MarketplaceParticipationsResponse = GetInterface<typeof MarketplaceParticipations>
type MarketplaceParticipations = MarketplaceParticipationsResponse['ListMarketplaceParticipationsResponse']['ListMarketplaceParticipationsResult']
type MarketplaceParticipations = GetInterface<typeof MarketplaceParticipations>
type ServiceStatusResponse = GetInterface<
typeof ServiceStatusResponse
>['GetServiceStatusResponse']['GetServiceStatusResult']

export class Sellers {
constructor(private httpClient: HttpClient) {}

async listMarketplaceParticipations(): Promise<[MarketplaceParticipations, RequestMeta]> {
const [response, meta] = await this.httpClient.request('POST', {
resource: Resource.Sellers,
version: '2011-07-01',
version: SELLERS_API_VERSION,
action: 'ListMarketplaceParticipations',
parameters: {},
})

return MarketplaceParticipations.decode(response).caseOf({
return MarketplaceParticipationsResponse.decode(response).caseOf({
Right: (x) => [
x.ListMarketplaceParticipationsResponse.ListMarketplaceParticipationsResult,
meta,
Expand All @@ -57,4 +78,42 @@ export class Sellers {
},
})
}

async listMarketplaceParticipationsByNextToken(
nextToken: string,
): Promise<[MarketplaceParticipations, RequestMeta]> {
const [response, meta] = await this.httpClient.request('POST', {
resource: Resource.Sellers,
version: SELLERS_API_VERSION,
action: 'ListMarketplaceParticipationsByNextToken',
parameters: { NextToken: nextToken },
})

return MarketplaceParticipationsByNextTokenResponse.decode(response).caseOf({
Right: (x) => [
x.ListMarketplaceParticipationsByNextTokenResponse
.ListMarketplaceParticipationsByNextTokenResult,
meta,
],
Left: (error) => {
throw new ParsingError(error)
},
})
}

async getServiceStatus(): Promise<[ServiceStatusResponse, RequestMeta]> {
const [response, meta] = await this.httpClient.request('POST', {
resource: Resource.Sellers,
version: SELLERS_API_VERSION,
action: 'GetServiceStatus',
parameters: {},
})

return ServiceStatusResponse.decode(response).caseOf({
Right: (x) => [x.GetServiceStatusResponse.GetServiceStatusResult, meta],
Left: (error) => {
throw new ParsingError(error)
},
})
}
}
10 changes: 10 additions & 0 deletions test/integration/sellers-list-market-participation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,15 @@ describe(`${Sellers.name}`, () => {
expect.objectContaining({ MarketplaceId: amazonMarketplaces.CA.id }),
)
})

itci('should be able to query service status', async () => {
expect.assertions(1)

const sellers = new Sellers(httpClient)

const [marketplaceParticipations] = await sellers.getServiceStatus()

expect(marketplaceParticipations.Status).toMatch(/GREEN|YELLOW|RED/)
})
})
/* eslint-enable jest/no-standalone-expect */
2 changes: 2 additions & 0 deletions test/unit/__snapshots__/parsing.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`mwsBoolean decodes any other string as a failure 1`] = `"Expected a string with a value of either \\"Yes\\" or \\"No\\", but received a string with value \\"YES\\""`;

exports[`serviceStatus decodes any other string as a failure 1`] = `"Expected a string with a value of \\"GREEN\\", \\"YELLOW\\" or \\"RED\\", but received a string with value \\"Green\\""`;
16 changes: 16 additions & 0 deletions test/unit/__snapshots__/sellers.test.ts.snap
Original file line number Diff line number Diff line change
@@ -1,5 +1,21 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`sellers getServiceStatus returns a parsed model when the response is valid 1`] = `
Array [
Object {
"Status": "GREEN",
"Timestamp": "2020-05-06T08:22:23.582Z",
},
Object {
"quotaMax": 1000,
"quotaRemaining": 999,
"quotaResetOn": "2020-05-06T10:22:23.582Z",
"requestId": "0",
"timestamp": "2020-05-06T08:22:23.582Z",
},
]
`;

exports[`sellers listMarketplaceParticipations returns a parsed model when the response is valid 1`] = `
Array [
Object {
Expand Down
28 changes: 27 additions & 1 deletion test/unit/parsing.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { number, Right } from 'purify-ts'

import { ensureArray, mwsBoolean } from '../../src/parsing'
import { ensureArray, mwsBoolean, ServiceStatus, serviceStatus } from '../../src/parsing'

describe('ensureArray', () => {
it('acts like an idenity if the value to be decoded is already an array', () => {
Expand Down Expand Up @@ -35,3 +35,29 @@ describe('mwsBoolean', () => {
expect(mwsBoolean.decode('YES')).toMatchSnapshot()
})
})

describe('serviceStatus', () => {
it('decodes the string "GREEN"', () => {
expect.assertions(1)

expect(serviceStatus.decode('GREEN')).toStrictEqual(Right(ServiceStatus.Green))
})

it('decodes the string "YELLOW"', () => {
expect.assertions(1)

expect(serviceStatus.decode('YELLOW')).toStrictEqual(Right(ServiceStatus.Yellow))
})

it('decodes the string "RED"', () => {
expect.assertions(1)

expect(serviceStatus.decode('RED')).toStrictEqual(Right(ServiceStatus.Red))
})

it('decodes any other string as a failure', () => {
expect.assertions(1)

expect(serviceStatus.decode('Green')).toMatchSnapshot()
})
})
42 changes: 40 additions & 2 deletions test/unit/sellers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ const httpConfig = {
sellerId: '',
}

const mockMws = new MWS(
const mockMwsMarketplaceParticipations = new MWS(
new HttpClient(httpConfig, () =>
Promise.resolve({
data: `<ListMarketplaceParticipationsResponse xmlns="https://mws.amazonservices.com/Sellers/2011-07-01">
Expand Down Expand Up @@ -60,6 +60,26 @@ const mockMws = new MWS(
),
)

const mockMwsServiceStatus = new MWS(
new HttpClient(httpConfig, () =>
Promise.resolve({
data: `<GetServiceStatusResponse xmlns="https://mws.amazonservices.com/Sellers/2011-07-01">
<GetServiceStatusResult>
<Status>GREEN</Status>
<Timestamp>2020-05-06T08:22:23.582Z</Timestamp>
</GetServiceStatusResult>
</GetServiceStatusResponse>`,
headers: {
'x-mws-request-id': '0',
'x-mws-timestamp': '2020-05-06T08:22:23.582Z',
'x-mws-quota-max': '1000',
'x-mws-quota-remaining': '999',
'x-mws-quota-resetson': '2020-05-06T10:22:23.582Z',
},
}),
),
)

const mockMwsFail = new MWS(
new HttpClient(httpConfig, () => Promise.resolve({ data: '', headers: {} })),
)
Expand All @@ -69,7 +89,9 @@ describe('sellers', () => {
it('returns a parsed model when the response is valid', async () => {
expect.assertions(1)

expect(await mockMws.sellers.listMarketplaceParticipations()).toMatchSnapshot()
expect(
await mockMwsMarketplaceParticipations.sellers.listMarketplaceParticipations(),
).toMatchSnapshot()
})

it('throws a parsing error when the response is not valid', async () => {
Expand All @@ -80,4 +102,20 @@ describe('sellers', () => {
)
})
})

describe('getServiceStatus', () => {
it('returns a parsed model when the response is valid', async () => {
expect.assertions(1)

expect(await mockMwsServiceStatus.sellers.getServiceStatus()).toMatchSnapshot()
})

it('throws a parsing error when the response is not valid', async () => {
expect.assertions(1)

await expect(() => mockMwsFail.sellers.getServiceStatus()).rejects.toStrictEqual(
new ParsingError(''),
)
})
})
})

0 comments on commit 8b10bc9

Please sign in to comment.