draft-order.e2e-spec.ts 16 KB

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