draft-order.e2e-spec.ts 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /* tslint:disable:no-non-null-assertion */
  2. import { mergeConfig, orderPercentageDiscount } from '@vendure/core';
  3. import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
  4. import gql from 'graphql-tag';
  5. import path from 'path';
  6. import { initialData } from '../../../e2e-common/e2e-initial-data';
  7. import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
  8. import { singleStageRefundablePaymentMethod } from './fixtures/test-payment-methods';
  9. import { ORDER_WITH_LINES_FRAGMENT } from './graphql/fragments';
  10. import * as Codegen from './graphql/generated-e2e-admin-types';
  11. import { CanceledOrderFragment, OrderWithLinesFragment } from './graphql/generated-e2e-admin-types';
  12. import {
  13. GetActiveCustomerOrdersQuery,
  14. TestOrderFragmentFragment,
  15. UpdatedOrderFragment,
  16. } from './graphql/generated-e2e-shop-types';
  17. import { CREATE_PROMOTION, GET_CUSTOMER_LIST } from './graphql/shared-definitions';
  18. import { GET_ACTIVE_CUSTOMER_ORDERS } from './graphql/shop-definitions';
  19. describe('Draft Orders resolver', () => {
  20. const { server, adminClient, shopClient } = createTestEnvironment(
  21. mergeConfig(testConfig(), {
  22. paymentOptions: {
  23. paymentMethodHandlers: [singleStageRefundablePaymentMethod],
  24. },
  25. }),
  26. );
  27. let customers: Codegen.GetCustomerListQuery['customers']['items'];
  28. let draftOrder: OrderWithLinesFragment;
  29. const freeOrderCouponCode = 'FREE';
  30. const orderGuard: ErrorResultGuard<
  31. TestOrderFragmentFragment | CanceledOrderFragment | UpdatedOrderFragment
  32. > = createErrorResultGuard(input => !!input.lines);
  33. beforeAll(async () => {
  34. await server.init({
  35. initialData: {
  36. ...initialData,
  37. paymentMethods: [
  38. {
  39. name: singleStageRefundablePaymentMethod.code,
  40. handler: { code: singleStageRefundablePaymentMethod.code, arguments: [] },
  41. },
  42. ],
  43. },
  44. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-full.csv'),
  45. customerCount: 3,
  46. });
  47. await adminClient.asSuperAdmin();
  48. // Create a couple of orders to be queried
  49. const result = await adminClient.query<
  50. Codegen.GetCustomerListQuery,
  51. Codegen.GetCustomerListQueryVariables
  52. >(GET_CUSTOMER_LIST, {
  53. options: {
  54. take: 3,
  55. },
  56. });
  57. customers = result.customers.items;
  58. // Create a coupon code promotion
  59. const { createPromotion } = await adminClient.query<
  60. Codegen.CreatePromotionMutation,
  61. Codegen.CreatePromotionMutationVariables
  62. >(CREATE_PROMOTION, {
  63. input: {
  64. name: 'Free Order',
  65. enabled: true,
  66. conditions: [],
  67. couponCode: freeOrderCouponCode,
  68. actions: [
  69. {
  70. code: orderPercentageDiscount.code,
  71. arguments: [{ name: 'discount', value: '100' }],
  72. },
  73. ],
  74. },
  75. });
  76. }, TEST_SETUP_TIMEOUT_MS);
  77. afterAll(async () => {
  78. await server.destroy();
  79. });
  80. it('create draft order', async () => {
  81. const { createDraftOrder } = await adminClient.query<Codegen.CreateDraftOrderMutation>(
  82. CREATE_DRAFT_ORDER,
  83. );
  84. expect(createDraftOrder.state).toBe('Draft');
  85. expect(createDraftOrder.active).toBe(false);
  86. draftOrder = createDraftOrder;
  87. });
  88. it('addItemToDraftOrder', async () => {
  89. const { addItemToDraftOrder } = await adminClient.query<
  90. Codegen.AddItemToDraftOrderMutation,
  91. Codegen.AddItemToDraftOrderMutationVariables
  92. >(ADD_ITEM_TO_DRAFT_ORDER, {
  93. orderId: draftOrder.id,
  94. input: {
  95. productVariantId: 'T_5',
  96. quantity: 2,
  97. },
  98. });
  99. orderGuard.assertSuccess(addItemToDraftOrder);
  100. expect(addItemToDraftOrder.lines.length).toBe(1);
  101. draftOrder = addItemToDraftOrder;
  102. });
  103. it('adjustDraftOrderLine', async () => {
  104. const { adjustDraftOrderLine } = await adminClient.query<
  105. Codegen.AdjustDraftOrderLineMutation,
  106. Codegen.AdjustDraftOrderLineMutationVariables
  107. >(ADJUST_DRAFT_ORDER_LINE, {
  108. orderId: draftOrder.id,
  109. input: {
  110. orderLineId: draftOrder.lines[0]!.id,
  111. quantity: 5,
  112. },
  113. });
  114. orderGuard.assertSuccess(adjustDraftOrderLine);
  115. expect(adjustDraftOrderLine.lines[0].quantity).toBe(5);
  116. });
  117. it('removeDraftOrderLine', async () => {
  118. const { removeDraftOrderLine } = await adminClient.query<
  119. Codegen.RemoveDraftOrderLineMutation,
  120. Codegen.RemoveDraftOrderLineMutationVariables
  121. >(REMOVE_DRAFT_ORDER_LINE, {
  122. orderId: draftOrder.id,
  123. orderLineId: draftOrder.lines[0]!.id,
  124. });
  125. orderGuard.assertSuccess(removeDraftOrderLine);
  126. expect(removeDraftOrderLine.lines.length).toBe(0);
  127. });
  128. it('setCustomerForDraftOrder', async () => {
  129. const { setCustomerForDraftOrder } = await adminClient.query<
  130. Codegen.SetCustomerForDraftOrderMutation,
  131. Codegen.SetCustomerForDraftOrderMutationVariables
  132. >(SET_CUSTOMER_FOR_DRAFT_ORDER, {
  133. orderId: draftOrder.id,
  134. customerId: customers[0].id,
  135. });
  136. orderGuard.assertSuccess(setCustomerForDraftOrder);
  137. expect(setCustomerForDraftOrder.customer?.id).toBe(customers[0].id);
  138. });
  139. it('custom does not see draft orders in history', async () => {
  140. await shopClient.asUserWithCredentials(customers[0].emailAddress, 'test');
  141. const { activeCustomer } = await shopClient.query<GetActiveCustomerOrdersQuery>(
  142. GET_ACTIVE_CUSTOMER_ORDERS,
  143. );
  144. expect(activeCustomer?.orders.totalItems).toBe(0);
  145. expect(activeCustomer?.orders.items.length).toBe(0);
  146. });
  147. it('setDraftOrderShippingAddress', async () => {
  148. const { setDraftOrderShippingAddress } = await adminClient.query<
  149. Codegen.SetDraftOrderShippingAddressMutation,
  150. Codegen.SetDraftOrderShippingAddressMutationVariables
  151. >(SET_SHIPPING_ADDRESS_FOR_DRAFT_ORDER, {
  152. orderId: draftOrder.id,
  153. input: {
  154. streetLine1: 'Shipping Street',
  155. city: 'Wigan',
  156. province: 'Greater Manchester',
  157. postalCode: 'WN1 2DD',
  158. countryCode: 'GB',
  159. },
  160. });
  161. expect(setDraftOrderShippingAddress.shippingAddress).toEqual({
  162. company: null,
  163. fullName: null,
  164. phoneNumber: null,
  165. streetLine2: null,
  166. province: 'Greater Manchester',
  167. city: 'Wigan',
  168. country: 'United Kingdom',
  169. postalCode: 'WN1 2DD',
  170. streetLine1: 'Shipping Street',
  171. });
  172. });
  173. it('setDraftOrderBillingAddress', async () => {
  174. const { setDraftOrderBillingAddress } = await adminClient.query<
  175. Codegen.SetDraftOrderBillingAddressMutation,
  176. Codegen.SetDraftOrderBillingAddressMutationVariables
  177. >(SET_BILLING_ADDRESS_FOR_DRAFT_ORDER, {
  178. orderId: draftOrder.id,
  179. input: {
  180. streetLine1: 'Billing Street',
  181. city: 'Skelmerdale',
  182. province: 'Lancashire',
  183. postalCode: 'WN8 3QW',
  184. countryCode: 'GB',
  185. },
  186. });
  187. expect(setDraftOrderBillingAddress.billingAddress).toEqual({
  188. company: null,
  189. fullName: null,
  190. phoneNumber: null,
  191. streetLine2: null,
  192. province: 'Lancashire',
  193. city: 'Skelmerdale',
  194. country: 'United Kingdom',
  195. postalCode: 'WN8 3QW',
  196. streetLine1: 'Billing Street',
  197. });
  198. });
  199. it('applyCouponCodeToDraftOrder', async () => {
  200. const { addItemToDraftOrder } = await adminClient.query<
  201. Codegen.AddItemToDraftOrderMutation,
  202. Codegen.AddItemToDraftOrderMutationVariables
  203. >(ADD_ITEM_TO_DRAFT_ORDER, {
  204. orderId: draftOrder.id,
  205. input: {
  206. productVariantId: 'T_1',
  207. quantity: 1,
  208. },
  209. });
  210. orderGuard.assertSuccess(addItemToDraftOrder);
  211. expect(addItemToDraftOrder.totalWithTax).toBe(155880);
  212. const { applyCouponCodeToDraftOrder } = await adminClient.query<
  213. Codegen.ApplyCouponCodeToDraftOrderMutation,
  214. Codegen.ApplyCouponCodeToDraftOrderMutationVariables
  215. >(APPLY_COUPON_CODE_TO_DRAFT_ORDER, {
  216. orderId: draftOrder.id,
  217. couponCode: freeOrderCouponCode,
  218. });
  219. orderGuard.assertSuccess(applyCouponCodeToDraftOrder);
  220. expect(applyCouponCodeToDraftOrder.couponCodes).toEqual([freeOrderCouponCode]);
  221. expect(applyCouponCodeToDraftOrder.totalWithTax).toBe(0);
  222. });
  223. it('removeCouponCodeFromDraftOrder', async () => {
  224. const { removeCouponCodeFromDraftOrder } = await adminClient.query<
  225. Codegen.RemoveCouponCodeFromDraftOrderMutation,
  226. Codegen.RemoveCouponCodeFromDraftOrderMutationVariables
  227. >(REMOVE_COUPON_CODE_FROM_DRAFT_ORDER, {
  228. orderId: draftOrder.id,
  229. couponCode: freeOrderCouponCode,
  230. });
  231. expect(removeCouponCodeFromDraftOrder!.couponCodes).toEqual([]);
  232. expect(removeCouponCodeFromDraftOrder!.totalWithTax).toBe(155880);
  233. });
  234. it('eligibleShippingMethodsForDraftOrder', async () => {
  235. const { eligibleShippingMethodsForDraftOrder } = await adminClient.query<
  236. Codegen.DraftOrderEligibleShippingMethodsQuery,
  237. Codegen.DraftOrderEligibleShippingMethodsQueryVariables
  238. >(DRAFT_ORDER_ELIGIBLE_SHIPPING_METHODS, {
  239. orderId: draftOrder.id,
  240. });
  241. expect(eligibleShippingMethodsForDraftOrder).toEqual([
  242. {
  243. code: 'standard-shipping',
  244. description: '',
  245. id: 'T_1',
  246. metadata: null,
  247. name: 'Standard Shipping',
  248. price: 500,
  249. priceWithTax: 500,
  250. },
  251. {
  252. code: 'express-shipping',
  253. description: '',
  254. id: 'T_2',
  255. metadata: null,
  256. name: 'Express Shipping',
  257. price: 1000,
  258. priceWithTax: 1000,
  259. },
  260. ]);
  261. });
  262. it('setDraftOrderShippingMethod', async () => {
  263. const { setDraftOrderShippingMethod } = await adminClient.query<
  264. Codegen.SetDraftOrderShippingMethodMutation,
  265. Codegen.SetDraftOrderShippingMethodMutationVariables
  266. >(SET_DRAFT_ORDER_SHIPPING_METHOD, {
  267. orderId: draftOrder.id,
  268. shippingMethodId: 'T_2',
  269. });
  270. orderGuard.assertSuccess(setDraftOrderShippingMethod);
  271. expect(setDraftOrderShippingMethod.shippingWithTax).toBe(1000);
  272. expect(setDraftOrderShippingMethod.shippingLines.length).toBe(1);
  273. expect(setDraftOrderShippingMethod.shippingLines[0].shippingMethod.id).toBe('T_2');
  274. });
  275. });
  276. export const CREATE_DRAFT_ORDER = gql`
  277. mutation CreateDraftOrder {
  278. createDraftOrder {
  279. ...OrderWithLines
  280. }
  281. }
  282. ${ORDER_WITH_LINES_FRAGMENT}
  283. `;
  284. export const ADD_ITEM_TO_DRAFT_ORDER = gql`
  285. mutation AddItemToDraftOrder($orderId: ID!, $input: AddItemToDraftOrderInput!) {
  286. addItemToDraftOrder(orderId: $orderId, input: $input) {
  287. ...OrderWithLines
  288. ... on ErrorResult {
  289. errorCode
  290. message
  291. }
  292. }
  293. }
  294. ${ORDER_WITH_LINES_FRAGMENT}
  295. `;
  296. export const ADJUST_DRAFT_ORDER_LINE = gql`
  297. mutation AdjustDraftOrderLine($orderId: ID!, $input: AdjustDraftOrderLineInput!) {
  298. adjustDraftOrderLine(orderId: $orderId, input: $input) {
  299. ...OrderWithLines
  300. ... on ErrorResult {
  301. errorCode
  302. message
  303. }
  304. }
  305. }
  306. ${ORDER_WITH_LINES_FRAGMENT}
  307. `;
  308. export const REMOVE_DRAFT_ORDER_LINE = gql`
  309. mutation RemoveDraftOrderLine($orderId: ID!, $orderLineId: ID!) {
  310. removeDraftOrderLine(orderId: $orderId, orderLineId: $orderLineId) {
  311. ...OrderWithLines
  312. ... on ErrorResult {
  313. errorCode
  314. message
  315. }
  316. }
  317. }
  318. ${ORDER_WITH_LINES_FRAGMENT}
  319. `;
  320. export const SET_CUSTOMER_FOR_DRAFT_ORDER = gql`
  321. mutation SetCustomerForDraftOrder($orderId: ID!, $customerId: ID, $input: CreateCustomerInput) {
  322. setCustomerForDraftOrder(orderId: $orderId, customerId: $customerId, input: $input) {
  323. ...OrderWithLines
  324. ... on ErrorResult {
  325. errorCode
  326. message
  327. }
  328. }
  329. }
  330. ${ORDER_WITH_LINES_FRAGMENT}
  331. `;
  332. export const SET_SHIPPING_ADDRESS_FOR_DRAFT_ORDER = gql`
  333. mutation SetDraftOrderShippingAddress($orderId: ID!, $input: CreateAddressInput!) {
  334. setDraftOrderShippingAddress(orderId: $orderId, input: $input) {
  335. ...OrderWithLines
  336. }
  337. }
  338. ${ORDER_WITH_LINES_FRAGMENT}
  339. `;
  340. export const SET_BILLING_ADDRESS_FOR_DRAFT_ORDER = gql`
  341. mutation SetDraftOrderBillingAddress($orderId: ID!, $input: CreateAddressInput!) {
  342. setDraftOrderBillingAddress(orderId: $orderId, input: $input) {
  343. ...OrderWithLines
  344. billingAddress {
  345. ...ShippingAddress
  346. }
  347. }
  348. }
  349. ${ORDER_WITH_LINES_FRAGMENT}
  350. `;
  351. export const APPLY_COUPON_CODE_TO_DRAFT_ORDER = gql`
  352. mutation ApplyCouponCodeToDraftOrder($orderId: ID!, $couponCode: String!) {
  353. applyCouponCodeToDraftOrder(orderId: $orderId, couponCode: $couponCode) {
  354. ...OrderWithLines
  355. ... on Order {
  356. couponCodes
  357. }
  358. ... on ErrorResult {
  359. errorCode
  360. message
  361. }
  362. }
  363. }
  364. ${ORDER_WITH_LINES_FRAGMENT}
  365. `;
  366. export const REMOVE_COUPON_CODE_FROM_DRAFT_ORDER = gql`
  367. mutation RemoveCouponCodeFromDraftOrder($orderId: ID!, $couponCode: String!) {
  368. removeCouponCodeFromDraftOrder(orderId: $orderId, couponCode: $couponCode) {
  369. ...OrderWithLines
  370. ... on Order {
  371. couponCodes
  372. }
  373. }
  374. }
  375. ${ORDER_WITH_LINES_FRAGMENT}
  376. `;
  377. export const DRAFT_ORDER_ELIGIBLE_SHIPPING_METHODS = gql`
  378. query DraftOrderEligibleShippingMethods($orderId: ID!) {
  379. eligibleShippingMethodsForDraftOrder(orderId: $orderId) {
  380. id
  381. name
  382. code
  383. description
  384. price
  385. priceWithTax
  386. metadata
  387. }
  388. }
  389. `;
  390. export const SET_DRAFT_ORDER_SHIPPING_METHOD = gql`
  391. mutation SetDraftOrderShippingMethod($orderId: ID!, $shippingMethodId: ID!) {
  392. setDraftOrderShippingMethod(orderId: $orderId, shippingMethodId: $shippingMethodId) {
  393. ...OrderWithLines
  394. ... on ErrorResult {
  395. errorCode
  396. message
  397. }
  398. }
  399. }
  400. ${ORDER_WITH_LINES_FRAGMENT}
  401. `;