draft-order.e2e-spec.ts 16 KB

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