Skip to content

Commit

Permalink
feat: create and associate inquiry x offer-order using exchange x imp…
Browse files Browse the repository at this point in the history
…ulse

Co-authored-by: sepans <sepans@sepans.com>
  • Loading branch information
erikdstock and sepans committed Feb 4, 2021
1 parent 897f4b5 commit fccb599
Show file tree
Hide file tree
Showing 3 changed files with 203 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/lib/loaders/loaders_with_authentication/impulse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,10 @@ export default (accessToken, userID, opts) => {
},
{ method: "POST" }
),
conversationCreateConversationOrderLoader: impulseLoader(
`conversation_orders`,
{},
{ method: "POST" }
),
}
}
112 changes: 112 additions & 0 deletions src/lib/stitching/exchange/__tests__/stitching.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,115 @@ it("doesn't delegate to the local schema for an Order's creditCard if creditCard
...restOfResolveArgs,
})
})

describe("commerceCreateInquiryOfferOrderWithArtwork", () => {
const context = {
conversationLoader: jest.fn(),
conversationCreateConversationOrderLoader: jest.fn(),
}
const mergeInfo = { delegateToSchema: jest.fn() }

beforeEach(() => {
jest.resetAllMocks()
})

it("calls impulse after creating the order", async () => {
const { resolvers } = await getExchangeStitchedSchema()
const resolver =
resolvers.Mutation.commerceCreateInquiryOfferOrderWithArtwork.resolve

const args = {
input: {
artworkId: "artwork-id",
impulseConversationId: "conversation-id",
},
}
const orderResult = { orderOrError: { order: { internalID: "order-id" } } }
context.conversationLoader.mockResolvedValue({})
mergeInfo.delegateToSchema.mockResolvedValue(orderResult)
context.conversationCreateConversationOrderLoader.mockResolvedValue({
conversation_id: "it worked",
})

const result = await resolver({}, args, context, { mergeInfo })

expect(mergeInfo.delegateToSchema).toHaveBeenCalledWith({
args,
fieldName: "commerceCreateInquiryOfferOrderWithArtwork",
operation: "mutation",
schema: expect.anything(),
context: expect.anything(),
info: expect.anything(),
})
expect(result).toEqual(orderResult)
expect(context.conversationLoader).toHaveBeenCalledWith("conversation-id")
expect(
context.conversationCreateConversationOrderLoader
).toHaveBeenCalledWith({
conversation_id: "conversation-id",
exchange_order_id: "order-id",
})
})

it("returns an error from exchange", async () => {
const { resolvers } = await getExchangeStitchedSchema()
const resolver =
resolvers.Mutation.commerceCreateInquiryOfferOrderWithArtwork.resolve
const args = {
input: {
artworkId: "artwork-id",
impulseConversationId: "conversation-id",
},
}
const orderResult = { orderOrError: { error: { message: "who cares" } } }

context.conversationLoader.mockResolvedValue({})
mergeInfo.delegateToSchema.mockResolvedValue(orderResult)
const result = await resolver({}, args, context, { mergeInfo })

expect(result).toEqual(orderResult)
expect(
context.conversationCreateConversationOrderLoader
).not.toHaveBeenCalled()
})

it("returns an error if the conversationLoader does not return a conversation", async () => {
const { resolvers } = await getExchangeStitchedSchema()
const resolver =
resolvers.Mutation.commerceCreateInquiryOfferOrderWithArtwork.resolve
const args = {
input: {
artworkId: "artwork-id",
impulseConversationId: "conversation-id",
},
}

context.conversationLoader.mockRejectedValue({})

await expect(resolver({}, args, context, { mergeInfo })).rejects.toThrow(
"Bad Request"
)
})
it("returns an error if the conversationCreateConversationOrderLoader fails", async () => {
const { resolvers } = await getExchangeStitchedSchema()
const resolver =
resolvers.Mutation.commerceCreateInquiryOfferOrderWithArtwork.resolve
const args = {
input: {
artworkId: "artwork-id",
impulseConversationId: "conversation-id",
},
}
const orderResult = { orderOrError: { order: { internalID: "order-id" } } }

context.conversationLoader.mockResolvedValue({})
mergeInfo.delegateToSchema.mockResolvedValue(orderResult)
context.conversationCreateConversationOrderLoader.mockRejectedValue({
message: "bad stuff",
})

await expect(resolver({}, args, context, { mergeInfo })).rejects.toThrow(
"Impulse: request to associate offer with conversation failed"
)
})
})
87 changes: 86 additions & 1 deletion src/lib/stitching/exchange/v2/stitching.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { GraphQLSchema, Kind, SelectionSetNode } from "graphql"
import { GraphQLError, GraphQLSchema, Kind, SelectionSetNode } from "graphql"
import { amountSDL, amount } from "schema/v1/fields/money"
import gql from "lib/gql"
import { toGlobalId } from "graphql-relay"
Expand Down Expand Up @@ -154,6 +154,7 @@ export const exchangeStitchingEnvironment = ({
return {
// The SDL used to declare how to stitch an object
extensionSchema: gql`
extend type CommerceLineItem {
artwork: Artwork
artworkVersion: ArtworkVersion
Expand Down Expand Up @@ -349,6 +350,90 @@ export const exchangeStitchingEnvironment = ({
},
},
},
Mutation: {
// monkey-patch the existing exchange mutation
// to add operations dependent on impulse
commerceCreateInquiryOfferOrderWithArtwork: {
resolve: async (_source, args, context, info) => {
const {
conversationLoader,
conversationCreateConversationOrderLoader,
} = context
const {
input: { impulseConversationId },
} = args

try {
await conversationLoader(impulseConversationId)
} catch (e) {
// be more elegant?
throw new GraphQLError(`Bad Request`)
}

const offerResult = await info.mergeInfo.delegateToSchema({
schema: exchangeSchema,
operation: "mutation",
fieldName: "commerceCreateInquiryOfferOrderWithArtwork",
args,
context,
info,
// transforms: [
// new WrapQuery(
// [
// "createInquiryOfferOrderWithArtwork",
// "orderOrError",
// "order",
// ],
// (selectionSet: SelectionSetNode) => {
// // const newSelections = [
// // ...selectionSet.selections,
// return {
// kind: Kind.FIELD,
// name: {
// kind: Kind.NAME,
// value: "internalID",
// },
// selectionSet,
// }
// // ]
// // return { ...selectionSet, selections: newSelections }
// },
// (result) => result
// // result.createInquiryOfferOrderWithArtwork.orderOrError.order
// ),
// ],
})
const { orderOrError } = offerResult

if (orderOrError.error) {
// if we got an error from exchange, return it immediately
return offerResult
} else if (orderOrError.order) {
// attempt to associate the order with the conversation
const {
order: { internalID: orderId },
} = orderOrError

if (!orderId) {
throw new GraphQLError("Bad request (no order id)")
}

try {
await conversationCreateConversationOrderLoader({
conversation_id: impulseConversationId,
exchange_order_id: orderId,
})
} catch (e) {
throw new GraphQLError(
"Impulse: request to associate offer with conversation failed"
)
}
}

return offerResult
},
},
},
},
}
}

0 comments on commit fccb599

Please sign in to comment.