draft-order.e2e-spec.ts 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  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 up', 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('adjustDraftOrderLine down', async () => {
  118. const { adjustDraftOrderLine } = await adminClient.query<
  119. Codegen.AdjustDraftOrderLineMutation,
  120. Codegen.AdjustDraftOrderLineMutationVariables
  121. >(ADJUST_DRAFT_ORDER_LINE, {
  122. orderId: draftOrder.id,
  123. input: {
  124. orderLineId: draftOrder.lines[0]!.id,
  125. quantity: 2,
  126. },
  127. });
  128. orderGuard.assertSuccess(adjustDraftOrderLine);
  129. expect(adjustDraftOrderLine.lines[0].quantity).toBe(2);
  130. });
  131. it('removeDraftOrderLine', async () => {
  132. const { removeDraftOrderLine } = await adminClient.query<
  133. Codegen.RemoveDraftOrderLineMutation,
  134. Codegen.RemoveDraftOrderLineMutationVariables
  135. >(REMOVE_DRAFT_ORDER_LINE, {
  136. orderId: draftOrder.id,
  137. orderLineId: draftOrder.lines[0]!.id,
  138. });
  139. orderGuard.assertSuccess(removeDraftOrderLine);
  140. expect(removeDraftOrderLine.lines.length).toBe(0);
  141. });
  142. it('setCustomerForDraftOrder', async () => {
  143. const { setCustomerForDraftOrder } = await adminClient.query<
  144. Codegen.SetCustomerForDraftOrderMutation,
  145. Codegen.SetCustomerForDraftOrderMutationVariables
  146. >(SET_CUSTOMER_FOR_DRAFT_ORDER, {
  147. orderId: draftOrder.id,
  148. customerId: customers[0].id,
  149. });
  150. orderGuard.assertSuccess(setCustomerForDraftOrder);
  151. expect(setCustomerForDraftOrder.customer?.id).toBe(customers[0].id);
  152. });
  153. it('custom does not see draft orders in history', async () => {
  154. await shopClient.asUserWithCredentials(customers[0].emailAddress, 'test');
  155. const { activeCustomer } = await shopClient.query<GetActiveCustomerOrdersQuery>(
  156. GET_ACTIVE_CUSTOMER_ORDERS,
  157. );
  158. expect(activeCustomer?.orders.totalItems).toBe(0);
  159. expect(activeCustomer?.orders.items.length).toBe(0);
  160. });
  161. it('setDraftOrderShippingAddress', async () => {
  162. const { setDraftOrderShippingAddress } = await adminClient.query<
  163. Codegen.SetDraftOrderShippingAddressMutation,
  164. Codegen.SetDraftOrderShippingAddressMutationVariables
  165. >(SET_SHIPPING_ADDRESS_FOR_DRAFT_ORDER, {
  166. orderId: draftOrder.id,
  167. input: {
  168. streetLine1: 'Shipping Street',
  169. city: 'Wigan',
  170. province: 'Greater Manchester',
  171. postalCode: 'WN1 2DD',
  172. countryCode: 'GB',
  173. },
  174. });
  175. expect(setDraftOrderShippingAddress.shippingAddress).toEqual({
  176. company: null,
  177. fullName: null,
  178. phoneNumber: null,
  179. streetLine2: null,
  180. province: 'Greater Manchester',
  181. city: 'Wigan',
  182. country: 'United Kingdom',
  183. postalCode: 'WN1 2DD',
  184. streetLine1: 'Shipping Street',
  185. });
  186. });
  187. it('setDraftOrderBillingAddress', async () => {
  188. const { setDraftOrderBillingAddress } = await adminClient.query<
  189. Codegen.SetDraftOrderBillingAddressMutation,
  190. Codegen.SetDraftOrderBillingAddressMutationVariables
  191. >(SET_BILLING_ADDRESS_FOR_DRAFT_ORDER, {
  192. orderId: draftOrder.id,
  193. input: {
  194. streetLine1: 'Billing Street',
  195. city: 'Skelmerdale',
  196. province: 'Lancashire',
  197. postalCode: 'WN8 3QW',
  198. countryCode: 'GB',
  199. },
  200. });
  201. expect(setDraftOrderBillingAddress.billingAddress).toEqual({
  202. company: null,
  203. fullName: null,
  204. phoneNumber: null,
  205. streetLine2: null,
  206. province: 'Lancashire',
  207. city: 'Skelmerdale',
  208. country: 'United Kingdom',
  209. postalCode: 'WN8 3QW',
  210. streetLine1: 'Billing Street',
  211. });
  212. });
  213. it('applyCouponCodeToDraftOrder', async () => {
  214. const { addItemToDraftOrder } = await adminClient.query<
  215. Codegen.AddItemToDraftOrderMutation,
  216. Codegen.AddItemToDraftOrderMutationVariables
  217. >(ADD_ITEM_TO_DRAFT_ORDER, {
  218. orderId: draftOrder.id,
  219. input: {
  220. productVariantId: 'T_1',
  221. quantity: 1,
  222. },
  223. });
  224. orderGuard.assertSuccess(addItemToDraftOrder);
  225. expect(addItemToDraftOrder.totalWithTax).toBe(155880);
  226. const { applyCouponCodeToDraftOrder } = await adminClient.query<
  227. Codegen.ApplyCouponCodeToDraftOrderMutation,
  228. Codegen.ApplyCouponCodeToDraftOrderMutationVariables
  229. >(APPLY_COUPON_CODE_TO_DRAFT_ORDER, {
  230. orderId: draftOrder.id,
  231. couponCode: freeOrderCouponCode,
  232. });
  233. orderGuard.assertSuccess(applyCouponCodeToDraftOrder);
  234. expect(applyCouponCodeToDraftOrder.couponCodes).toEqual([freeOrderCouponCode]);
  235. expect(applyCouponCodeToDraftOrder.totalWithTax).toBe(0);
  236. });
  237. it('removeCouponCodeFromDraftOrder', async () => {
  238. const { removeCouponCodeFromDraftOrder } = await adminClient.query<
  239. Codegen.RemoveCouponCodeFromDraftOrderMutation,
  240. Codegen.RemoveCouponCodeFromDraftOrderMutationVariables
  241. >(REMOVE_COUPON_CODE_FROM_DRAFT_ORDER, {
  242. orderId: draftOrder.id,
  243. couponCode: freeOrderCouponCode,
  244. });
  245. expect(removeCouponCodeFromDraftOrder!.couponCodes).toEqual([]);
  246. expect(removeCouponCodeFromDraftOrder!.totalWithTax).toBe(155880);
  247. });
  248. it('eligibleShippingMethodsForDraftOrder', async () => {
  249. const { eligibleShippingMethodsForDraftOrder } = await adminClient.query<
  250. Codegen.DraftOrderEligibleShippingMethodsQuery,
  251. Codegen.DraftOrderEligibleShippingMethodsQueryVariables
  252. >(DRAFT_ORDER_ELIGIBLE_SHIPPING_METHODS, {
  253. orderId: draftOrder.id,
  254. });
  255. expect(eligibleShippingMethodsForDraftOrder).toEqual([
  256. {
  257. code: 'standard-shipping',
  258. description: '',
  259. id: 'T_1',
  260. metadata: null,
  261. name: 'Standard Shipping',
  262. price: 500,
  263. priceWithTax: 500,
  264. },
  265. {
  266. code: 'express-shipping',
  267. description: '',
  268. id: 'T_2',
  269. metadata: null,
  270. name: 'Express Shipping',
  271. price: 1000,
  272. priceWithTax: 1000,
  273. },
  274. ]);
  275. });
  276. it('setDraftOrderShippingMethod', async () => {
  277. const { setDraftOrderShippingMethod } = await adminClient.query<
  278. Codegen.SetDraftOrderShippingMethodMutation,
  279. Codegen.SetDraftOrderShippingMethodMutationVariables
  280. >(SET_DRAFT_ORDER_SHIPPING_METHOD, {
  281. orderId: draftOrder.id,
  282. shippingMethodId: 'T_2',
  283. });
  284. orderGuard.assertSuccess(setDraftOrderShippingMethod);
  285. expect(setDraftOrderShippingMethod.shippingWithTax).toBe(1000);
  286. expect(setDraftOrderShippingMethod.shippingLines.length).toBe(1);
  287. expect(setDraftOrderShippingMethod.shippingLines[0].shippingMethod.id).toBe('T_2');
  288. });
  289. });
  290. export const CREATE_DRAFT_ORDER = gql`
  291. mutation CreateDraftOrder {
  292. createDraftOrder {
  293. ...OrderWithLines
  294. }
  295. }
  296. ${ORDER_WITH_LINES_FRAGMENT}
  297. `;
  298. export const ADD_ITEM_TO_DRAFT_ORDER = gql`
  299. mutation AddItemToDraftOrder($orderId: ID!, $input: AddItemToDraftOrderInput!) {
  300. addItemToDraftOrder(orderId: $orderId, input: $input) {
  301. ...OrderWithLines
  302. ... on ErrorResult {
  303. errorCode
  304. message
  305. }
  306. }
  307. }
  308. ${ORDER_WITH_LINES_FRAGMENT}
  309. `;
  310. export const ADJUST_DRAFT_ORDER_LINE = gql`
  311. mutation AdjustDraftOrderLine($orderId: ID!, $input: AdjustDraftOrderLineInput!) {
  312. adjustDraftOrderLine(orderId: $orderId, input: $input) {
  313. ...OrderWithLines
  314. ... on ErrorResult {
  315. errorCode
  316. message
  317. }
  318. }
  319. }
  320. ${ORDER_WITH_LINES_FRAGMENT}
  321. `;
  322. export const REMOVE_DRAFT_ORDER_LINE = gql`
  323. mutation RemoveDraftOrderLine($orderId: ID!, $orderLineId: ID!) {
  324. removeDraftOrderLine(orderId: $orderId, orderLineId: $orderLineId) {
  325. ...OrderWithLines
  326. ... on ErrorResult {
  327. errorCode
  328. message
  329. }
  330. }
  331. }
  332. ${ORDER_WITH_LINES_FRAGMENT}
  333. `;
  334. export const SET_CUSTOMER_FOR_DRAFT_ORDER = gql`
  335. mutation SetCustomerForDraftOrder($orderId: ID!, $customerId: ID, $input: CreateCustomerInput) {
  336. setCustomerForDraftOrder(orderId: $orderId, customerId: $customerId, input: $input) {
  337. ...OrderWithLines
  338. ... on ErrorResult {
  339. errorCode
  340. message
  341. }
  342. }
  343. }
  344. ${ORDER_WITH_LINES_FRAGMENT}
  345. `;
  346. export const SET_SHIPPING_ADDRESS_FOR_DRAFT_ORDER = gql`
  347. mutation SetDraftOrderShippingAddress($orderId: ID!, $input: CreateAddressInput!) {
  348. setDraftOrderShippingAddress(orderId: $orderId, input: $input) {
  349. ...OrderWithLines
  350. }
  351. }
  352. ${ORDER_WITH_LINES_FRAGMENT}
  353. `;
  354. export const SET_BILLING_ADDRESS_FOR_DRAFT_ORDER = gql`
  355. mutation SetDraftOrderBillingAddress($orderId: ID!, $input: CreateAddressInput!) {
  356. setDraftOrderBillingAddress(orderId: $orderId, input: $input) {
  357. ...OrderWithLines
  358. billingAddress {
  359. ...ShippingAddress
  360. }
  361. }
  362. }
  363. ${ORDER_WITH_LINES_FRAGMENT}
  364. `;
  365. export const APPLY_COUPON_CODE_TO_DRAFT_ORDER = gql`
  366. mutation ApplyCouponCodeToDraftOrder($orderId: ID!, $couponCode: String!) {
  367. applyCouponCodeToDraftOrder(orderId: $orderId, couponCode: $couponCode) {
  368. ...OrderWithLines
  369. ... on Order {
  370. couponCodes
  371. }
  372. ... on ErrorResult {
  373. errorCode
  374. message
  375. }
  376. }
  377. }
  378. ${ORDER_WITH_LINES_FRAGMENT}
  379. `;
  380. export const REMOVE_COUPON_CODE_FROM_DRAFT_ORDER = gql`
  381. mutation RemoveCouponCodeFromDraftOrder($orderId: ID!, $couponCode: String!) {
  382. removeCouponCodeFromDraftOrder(orderId: $orderId, couponCode: $couponCode) {
  383. ...OrderWithLines
  384. ... on Order {
  385. couponCodes
  386. }
  387. }
  388. }
  389. ${ORDER_WITH_LINES_FRAGMENT}
  390. `;
  391. export const DRAFT_ORDER_ELIGIBLE_SHIPPING_METHODS = gql`
  392. query DraftOrderEligibleShippingMethods($orderId: ID!) {
  393. eligibleShippingMethodsForDraftOrder(orderId: $orderId) {
  394. id
  395. name
  396. code
  397. description
  398. price
  399. priceWithTax
  400. metadata
  401. }
  402. }
  403. `;
  404. export const SET_DRAFT_ORDER_SHIPPING_METHOD = gql`
  405. mutation SetDraftOrderShippingMethod($orderId: ID!, $shippingMethodId: ID!) {
  406. setDraftOrderShippingMethod(orderId: $orderId, shippingMethodId: $shippingMethodId) {
  407. ...OrderWithLines
  408. ... on ErrorResult {
  409. errorCode
  410. message
  411. }
  412. }
  413. }
  414. ${ORDER_WITH_LINES_FRAGMENT}
  415. `;