@spree/storefront-api-v2-sdk
Version:
Node module to easily integrate your JavaScript or TypeScript application with Spree API V2. You can create an entirely custom Storefront in JS/TS with this package including one page checkout, Single Page Apps, PWAs and so on
306 lines (263 loc) • 9.74 kB
text/typescript
// To import @spree/storefront-api-v2-sdk, run 'npm link' and 'npm link @spree/storefront-api-v2-sdk'
// in the project's root directory.
import { Client, makeClient, result, jsonApi } from '@spree/storefront-api-v2-sdk'
import type { RelationType } from '@spree/storefront-api-v2-sdk/types/interfaces/Relationships'
import createAxiosFetcher from '@spree/storefront-api-v2-sdk/dist/server/createAxiosFetcher'
import createFetchFetcher from '@spree/storefront-api-v2-sdk/dist/server/createFetchFetcher'
const createTests = function () {
it('completes guest order', function () {
const { orderFullAddress } = this
const client: Client = this.clientRef.value
cy.wrap(null)
.then(function () {
return result.extractSuccess(client.cart.create())
})
.then(function (cartCreateResponse) {
const { token: order_token, number: order_number } = cartCreateResponse.data.attributes
return cy
.wrap(null)
.then(function () {
return result.extractSuccess(client.products.list({ include: 'default_variant' }))
})
.then(function (variantsResponse) {
const variantId = jsonApi.findSingleRelationshipDocument(
variantsResponse,
variantsResponse.data[0],
'default_variant'
).id
return client.cart.addItem({ order_token, variant_id: variantId, quantity: 1 })
})
.then(function () {
return client.checkout.orderUpdate({ order_token, order: orderFullAddress })
})
.then(function () {
return result.extractSuccess(client.checkout.shippingRates({ order_token }))
})
.then(function (shippingResponse) {
const firstShipment = shippingResponse.data[0]
const shippingRateId = (firstShipment.relationships.shipping_rates.data as RelationType[])[0].id
return client.checkout.orderUpdate({
order_token,
order: {
shipments_attributes: [
{
id: firstShipment.id,
selected_shipping_rate_id: shippingRateId
}
]
}
})
})
.then(function () {
return result.extractSuccess(client.checkout.paymentMethods({ order_token }))
})
.then(function (paymentsResponse) {
const checkPaymentId = paymentsResponse.data.find(
(paymentMethod) => paymentMethod.attributes.type === 'Spree::PaymentMethod::Check'
)!.id
return client.checkout.orderUpdate({
order_token,
order: {
payments_attributes: [
{
payment_method_id: checkPaymentId
}
]
}
})
})
.then(function () {
return client.checkout.complete({ order_token })
})
.then(function (orderCompleteResponse) {
expect(orderCompleteResponse.isSuccess()).to.be.true
})
.then(function () {
return client.order.status({ order_token, order_number })
})
.then(function (statusResponse) {
expect(statusResponse.isSuccess()).to.be.true
})
})
})
it('shows cart', function () {
const client: Client = this.clientRef.value
cy.wrap(null)
.then(function () {
return result.extractSuccess(client.cart.create())
})
.then(function (cartCreateResponse) {
const orderToken = cartCreateResponse.data.attributes.token
return client.cart.show({ orderToken })
})
.then(function (cartShowResponse) {
expect(cartShowResponse.isSuccess()).to.be.true
})
})
it('removes cart', function () {
const client: Client = this.clientRef.value
cy.wrap(null)
.then(function () {
return result.extractSuccess(client.cart.create())
})
.then(function (cartCreateResponse) {
const orderToken = cartCreateResponse.data.attributes.token
return client.cart.remove({ orderToken })
})
.then(function (cartRemoveResponse) {
expect(cartRemoveResponse.isSuccess()).to.be.true
})
})
it('lists payment methods', function () {
const client: Client = this.clientRef.value
cy.wrap(null)
.then(function () {
return result.extractSuccess(client.cart.create())
})
.then(function (cartCreateResponse) {
const orderToken = cartCreateResponse.data.attributes.token
return client.checkout.paymentMethods({ orderToken })
})
.then(function (paymentMethodsResponse) {
expect(paymentMethodsResponse.isSuccess()).to.be.true
})
})
}
const createServerVersionInTheBrowserTests = ({
host,
fetcherType
}: {
host: string
fetcherType: 'axios' | 'fetch'
}) => {
describe(`server version (i.e. CJS module) in the browser using ${fetcherType}`, function () {
beforeEach(function () {
let createFetcher
switch (fetcherType) {
case 'axios':
createFetcher = createAxiosFetcher
break
case 'fetch':
createFetcher = createFetchFetcher
break
default:
throw new Error(`${fetcherType} not recognized.`)
}
const client = makeClient({ host, createFetcher })
cy.wrap({ value: client }).as('clientRef')
})
createTests()
})
}
const includeFileAsScript = (path: string) => {
return cy.readFile(path).then(function (fileAtPath) {
cy.intercept(path, fileAtPath)
return cy.document().then((document) => {
const scriptElement = document.createElement('script')
scriptElement.src = path
document.head.appendChild(scriptElement)
})
})
}
const createClientVersionInTheBrowserTests = ({
host,
fetcherType
}: {
host: string
fetcherType: 'axios' | 'fetch'
}) => {
describe(`client version (window global) in the browser using ${fetcherType}`, function () {
beforeEach(function () {
cy.wrap(null)
.then(() => {
return includeFileAsScript('/app/node_modules/@spree/storefront-api-v2-sdk/dist/client/index.js')
})
.then(() => {
return includeFileAsScript('/app/node_modules/axios/dist/axios.min.js')
})
.then(() => {
let fetcherPath
switch (fetcherType) {
case 'axios':
fetcherPath = '/app/node_modules/@spree/storefront-api-v2-sdk/dist/client/createAxiosFetcher.js'
break
case 'fetch':
fetcherPath = '/app/node_modules/@spree/storefront-api-v2-sdk/dist/client/createFetchFetcher.js'
break
default:
throw new Error(`${fetcherType} not recognized.`)
}
return includeFileAsScript(fetcherPath)
})
.then(() => {
return cy
.window()
.its('SpreeSDK.makeClient')
.then(function (makeClient) {
let globalKey
switch (fetcherType) {
case 'axios':
globalKey = 'createAxiosFetcher'
break
case 'fetch':
globalKey = 'createFetchFetcher'
break
default:
throw new Error(`${fetcherType} not recognized.`)
}
return cy
.window()
.its(`SpreeSDK.${globalKey}.default`)
.then(function (createFetcher) {
const client = makeClient({ host, createFetcher })
return cy.wrap({ value: client }).as('clientRef')
})
})
})
})
createTests()
})
}
const createServerVersionInTheServerTests = ({
host,
fetcherType
}: {
host: string
fetcherType: 'axios' | 'fetch'
}) => {
describe(`server (i.e. CJS module) in the server using ${fetcherType}`, function () {
beforeEach(function () {
const noop = function () {
// no-op
}
const createSubProxy = function (target: any, clientMethodPath: string[]): any {
return new Proxy(target, {
apply: function (_target, _thisArg, argumentsList) {
const payload = { argumentsList, clientMethodPath, fetcherType }
// Send call to a mini Express server which calls Spree.
return cy.request(host, payload).then(function (response) {
return result.fromJson(response.body)
})
},
get: function (_target: any, property: string | symbol, _receiver: any) {
return createSubProxy(noop, [...clientMethodPath, property.toString()])
}
})
}
const client = createSubProxy(noop, [])
cy.wrap({ value: client }).as('clientRef')
})
createTests()
})
}
describe('using Spree SDK', function () {
before(function () {
cy.fixture('order-full-address').as('orderFullAddress')
})
createServerVersionInTheBrowserTests({ host: 'http://docker-host:3000', fetcherType: 'axios' })
createServerVersionInTheBrowserTests({ host: 'http://docker-host:3000', fetcherType: 'fetch' })
createClientVersionInTheBrowserTests({ host: 'http://docker-host:3000', fetcherType: 'axios' })
createClientVersionInTheBrowserTests({ host: 'http://docker-host:3000', fetcherType: 'fetch' })
createServerVersionInTheServerTests({ host: 'http://express:5000', fetcherType: 'axios' })
createServerVersionInTheServerTests({ host: 'http://express:5000', fetcherType: 'fetch' })
})