order-taxes.e2e-spec.ts 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /* tslint:disable:no-non-null-assertion */
  2. import { summate } from '@vendure/common/lib/shared-utils';
  3. import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
  4. import path from 'path';
  5. import { initialData } from '../../../e2e-common/e2e-initial-data';
  6. import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
  7. import { testSuccessfulPaymentMethod } from './fixtures/test-payment-methods';
  8. import { GetProductsWithVariantPrices, UpdateChannel } from './graphql/generated-e2e-admin-types';
  9. import {
  10. AddItemToOrder,
  11. GetActiveOrderWithPriceData,
  12. TestOrderFragmentFragment,
  13. UpdatedOrderFragment,
  14. } from './graphql/generated-e2e-shop-types';
  15. import { GET_PRODUCTS_WITH_VARIANT_PRICES, UPDATE_CHANNEL } from './graphql/shared-definitions';
  16. import { ADD_ITEM_TO_ORDER, GET_ACTIVE_ORDER_WITH_PRICE_DATA } from './graphql/shop-definitions';
  17. import { sortById } from './utils/test-order-utils';
  18. describe('Order taxes', () => {
  19. const { server, adminClient, shopClient } = createTestEnvironment({
  20. ...testConfig(),
  21. paymentOptions: {
  22. paymentMethodHandlers: [testSuccessfulPaymentMethod],
  23. },
  24. });
  25. type OrderSuccessResult = UpdatedOrderFragment | TestOrderFragmentFragment;
  26. const orderResultGuard: ErrorResultGuard<OrderSuccessResult> = createErrorResultGuard(
  27. input => !!input.lines,
  28. );
  29. let products: GetProductsWithVariantPrices.Items[];
  30. beforeAll(async () => {
  31. await server.init({
  32. initialData: {
  33. ...initialData,
  34. paymentMethods: [
  35. {
  36. name: testSuccessfulPaymentMethod.code,
  37. handler: { code: testSuccessfulPaymentMethod.code, arguments: [] },
  38. },
  39. ],
  40. },
  41. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-order-taxes.csv'),
  42. customerCount: 2,
  43. });
  44. await adminClient.asSuperAdmin();
  45. const result = await adminClient.query<GetProductsWithVariantPrices.Query>(
  46. GET_PRODUCTS_WITH_VARIANT_PRICES,
  47. );
  48. products = result.products.items;
  49. }, TEST_SETUP_TIMEOUT_MS);
  50. afterAll(async () => {
  51. await server.destroy();
  52. });
  53. describe('Channel.pricesIncludeTax = false', () => {
  54. beforeAll(async () => {
  55. await adminClient.query<UpdateChannel.Mutation, UpdateChannel.Variables>(UPDATE_CHANNEL, {
  56. input: {
  57. id: 'T_1',
  58. pricesIncludeTax: false,
  59. },
  60. });
  61. await shopClient.asAnonymousUser();
  62. });
  63. it('prices are correct', async () => {
  64. const variant = products.sort(sortById)[0].variants.sort(sortById)[0];
  65. await shopClient.query<AddItemToOrder.Mutation, AddItemToOrder.Variables>(ADD_ITEM_TO_ORDER, {
  66. productVariantId: variant.id,
  67. quantity: 2,
  68. });
  69. const { activeOrder } = await shopClient.query<GetActiveOrderWithPriceData.Query>(
  70. GET_ACTIVE_ORDER_WITH_PRICE_DATA,
  71. );
  72. expect(activeOrder?.totalWithTax).toBe(240);
  73. expect(activeOrder?.total).toBe(200);
  74. expect(activeOrder?.lines[0].taxRate).toBe(20);
  75. expect(activeOrder?.lines[0].linePrice).toBe(200);
  76. expect(activeOrder?.lines[0].lineTax).toBe(40);
  77. expect(activeOrder?.lines[0].linePriceWithTax).toBe(240);
  78. expect(activeOrder?.lines[0].unitPrice).toBe(100);
  79. expect(activeOrder?.lines[0].unitPriceWithTax).toBe(120);
  80. expect(activeOrder?.lines[0].items[0].unitPrice).toBe(100);
  81. expect(activeOrder?.lines[0].items[0].unitPriceWithTax).toBe(120);
  82. expect(activeOrder?.lines[0].items[0].taxRate).toBe(20);
  83. expect(activeOrder?.lines[0].taxLines).toEqual([
  84. {
  85. description: 'Standard Tax Europe',
  86. taxRate: 20,
  87. },
  88. ]);
  89. });
  90. });
  91. describe('Channel.pricesIncludeTax = true', () => {
  92. beforeAll(async () => {
  93. await adminClient.query<UpdateChannel.Mutation, UpdateChannel.Variables>(UPDATE_CHANNEL, {
  94. input: {
  95. id: 'T_1',
  96. pricesIncludeTax: true,
  97. },
  98. });
  99. await shopClient.asAnonymousUser();
  100. });
  101. it('prices are correct', async () => {
  102. const variant = products[0].variants[0];
  103. await shopClient.query<AddItemToOrder.Mutation, AddItemToOrder.Variables>(ADD_ITEM_TO_ORDER, {
  104. productVariantId: variant.id,
  105. quantity: 2,
  106. });
  107. const { activeOrder } = await shopClient.query<GetActiveOrderWithPriceData.Query>(
  108. GET_ACTIVE_ORDER_WITH_PRICE_DATA,
  109. );
  110. expect(activeOrder?.totalWithTax).toBe(200);
  111. expect(activeOrder?.total).toBe(166);
  112. expect(activeOrder?.lines[0].taxRate).toBe(20);
  113. expect(activeOrder?.lines[0].linePrice).toBe(166);
  114. expect(activeOrder?.lines[0].lineTax).toBe(34);
  115. expect(activeOrder?.lines[0].linePriceWithTax).toBe(200);
  116. expect(activeOrder?.lines[0].unitPrice).toBe(83);
  117. expect(activeOrder?.lines[0].unitPriceWithTax).toBe(100);
  118. expect(activeOrder?.lines[0].items[0].unitPrice).toBe(83);
  119. expect(activeOrder?.lines[0].items[0].unitPriceWithTax).toBe(100);
  120. expect(activeOrder?.lines[0].items[0].taxRate).toBe(20);
  121. expect(activeOrder?.lines[0].taxLines).toEqual([
  122. {
  123. description: 'Standard Tax Europe',
  124. taxRate: 20,
  125. },
  126. ]);
  127. });
  128. });
  129. it('taxSummary works', async () => {
  130. await adminClient.query<UpdateChannel.Mutation, UpdateChannel.Variables>(UPDATE_CHANNEL, {
  131. input: {
  132. id: 'T_1',
  133. pricesIncludeTax: false,
  134. },
  135. });
  136. await shopClient.asAnonymousUser();
  137. await shopClient.query<AddItemToOrder.Mutation, AddItemToOrder.Variables>(ADD_ITEM_TO_ORDER, {
  138. productVariantId: products[0].variants[0].id,
  139. quantity: 2,
  140. });
  141. await shopClient.query<AddItemToOrder.Mutation, AddItemToOrder.Variables>(ADD_ITEM_TO_ORDER, {
  142. productVariantId: products[1].variants[0].id,
  143. quantity: 2,
  144. });
  145. await shopClient.query<AddItemToOrder.Mutation, AddItemToOrder.Variables>(ADD_ITEM_TO_ORDER, {
  146. productVariantId: products[2].variants[0].id,
  147. quantity: 2,
  148. });
  149. const { activeOrder } = await shopClient.query<GetActiveOrderWithPriceData.Query>(
  150. GET_ACTIVE_ORDER_WITH_PRICE_DATA,
  151. );
  152. expect(activeOrder?.taxSummary).toEqual([
  153. {
  154. description: 'Standard Tax Europe',
  155. taxRate: 20,
  156. taxBase: 200,
  157. taxTotal: 40,
  158. },
  159. {
  160. description: 'Reduced Tax Europe',
  161. taxRate: 10,
  162. taxBase: 200,
  163. taxTotal: 20,
  164. },
  165. {
  166. description: 'Zero Tax Europe',
  167. taxRate: 0,
  168. taxBase: 200,
  169. taxTotal: 0,
  170. },
  171. ]);
  172. // ensure that the summary total add up to the overall totals
  173. const taxSummaryBaseTotal = summate(activeOrder!.taxSummary, 'taxBase');
  174. const taxSummaryTaxTotal = summate(activeOrder!.taxSummary, 'taxTotal');
  175. expect(taxSummaryBaseTotal).toBe(activeOrder?.total);
  176. expect(taxSummaryBaseTotal + taxSummaryTaxTotal).toBe(activeOrder?.totalWithTax);
  177. });
  178. });