draft-order.e2e-spec.ts 16 KB

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