1
0

entity-serialization.e2e-spec.ts 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. import {
  2. Channel,
  3. ChannelService,
  4. discountOnItemWithFacets,
  5. hasFacetValues,
  6. Order,
  7. OrderLine,
  8. OrderService,
  9. ProductVariant,
  10. ProductVariantService,
  11. Promotion,
  12. PromotionService,
  13. RequestContextService,
  14. ShippingLine,
  15. ShippingMethod,
  16. ShippingMethodService,
  17. TransactionalConnection,
  18. } from '@vendure/core';
  19. import { createErrorResultGuard, createTestEnvironment, ErrorResultGuard } from '@vendure/testing';
  20. import { fail } from 'assert';
  21. import path from 'path';
  22. import { afterAll, beforeAll, describe, expect, it } from 'vitest';
  23. import { initialData } from '../../../e2e-common/e2e-initial-data';
  24. import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config';
  25. import { testSuccessfulPaymentMethod } from './fixtures/test-payment-methods';
  26. import * as Codegen from './graphql/generated-e2e-admin-types';
  27. import { LanguageCode } from './graphql/generated-e2e-admin-types';
  28. import * as CodegenShop from './graphql/generated-e2e-shop-types';
  29. import { CREATE_PROMOTION } from './graphql/shared-definitions';
  30. import {
  31. ADD_ITEM_TO_ORDER,
  32. ADD_PAYMENT,
  33. SET_SHIPPING_METHOD,
  34. TRANSITION_TO_STATE,
  35. } from './graphql/shop-definitions';
  36. /**
  37. * This suite tests to make sure entities can be serialized. It focuses on those
  38. * entities that contain methods and/or properties which potentially reference
  39. * non-serializable objects.
  40. *
  41. * See https://github.com/vendurehq/vendure/issues/3277
  42. */
  43. describe('Entity serialization', () => {
  44. type OrderSuccessResult =
  45. | CodegenShop.UpdatedOrderFragment
  46. | CodegenShop.TestOrderFragmentFragment
  47. | CodegenShop.TestOrderWithPaymentsFragment
  48. | CodegenShop.ActiveOrderCustomerFragment
  49. | CodegenShop.OrderWithAddressesFragment;
  50. const orderResultGuard: ErrorResultGuard<OrderSuccessResult> = createErrorResultGuard(
  51. input => !!input.lines,
  52. );
  53. const { server, adminClient, shopClient } = createTestEnvironment({
  54. ...testConfig(),
  55. paymentOptions: {
  56. paymentMethodHandlers: [testSuccessfulPaymentMethod],
  57. },
  58. });
  59. beforeAll(async () => {
  60. await server.init({
  61. initialData: {
  62. ...initialData,
  63. paymentMethods: [
  64. {
  65. name: testSuccessfulPaymentMethod.code,
  66. handler: { code: testSuccessfulPaymentMethod.code, arguments: [] },
  67. },
  68. ],
  69. },
  70. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-full.csv'),
  71. customerCount: 1,
  72. });
  73. await adminClient.asSuperAdmin();
  74. }, TEST_SETUP_TIMEOUT_MS);
  75. afterAll(async () => {
  76. await server.destroy();
  77. });
  78. it('serialize ShippingMethod', async () => {
  79. const ctx = await createCtx();
  80. const result = await server.app.get(ShippingMethodService).findAll(ctx);
  81. expect(result.items.length).toBeGreaterThan(0);
  82. const shippingMethod = result.items[0];
  83. expect(shippingMethod instanceof ShippingMethod).toBe(true);
  84. assertCanBeSerialized(shippingMethod);
  85. const json = JSON.stringify(shippingMethod);
  86. const parsed = JSON.parse(json);
  87. expect(parsed.createdAt).toBe(shippingMethod.createdAt.toISOString());
  88. });
  89. it('serialize Channel', async () => {
  90. const result = await server.app.get(ChannelService).getDefaultChannel();
  91. expect(result instanceof Channel).toBe(true);
  92. assertCanBeSerialized(result);
  93. });
  94. it('serialize Order', async () => {
  95. await shopClient.asUserWithCredentials('hayden.zieme12@hotmail.com', 'test');
  96. await shopClient.query<
  97. CodegenShop.AddItemToOrderMutation,
  98. CodegenShop.AddItemToOrderMutationVariables
  99. >(ADD_ITEM_TO_ORDER, {
  100. productVariantId: 'T_1',
  101. quantity: 1,
  102. });
  103. await shopClient.query<
  104. CodegenShop.SetShippingMethodMutation,
  105. CodegenShop.SetShippingMethodMutationVariables
  106. >(SET_SHIPPING_METHOD, {
  107. id: 'T_1',
  108. });
  109. const result = await shopClient.query<
  110. CodegenShop.TransitionToStateMutation,
  111. CodegenShop.TransitionToStateMutationVariables
  112. >(TRANSITION_TO_STATE, { state: 'ArrangingPayment' });
  113. const { addPaymentToOrder } = await shopClient.query<
  114. CodegenShop.AddPaymentToOrderMutation,
  115. CodegenShop.AddPaymentToOrderMutationVariables
  116. >(ADD_PAYMENT, {
  117. input: {
  118. method: testSuccessfulPaymentMethod.code,
  119. metadata: {
  120. foo: 'bar',
  121. },
  122. },
  123. });
  124. orderResultGuard.assertSuccess(addPaymentToOrder);
  125. const ctx = await createCtx();
  126. const order = await server.app.get(OrderService).findOneByCode(ctx, addPaymentToOrder.code);
  127. expect(order).not.toBeNull();
  128. expect(order instanceof Order).toBe(true);
  129. assertCanBeSerialized(order);
  130. });
  131. it('serialize OrderLine', async () => {
  132. const ctx = await createCtx();
  133. const orderLine = await server.app.get(TransactionalConnection).getEntityOrThrow(ctx, OrderLine, 1);
  134. expect(orderLine instanceof OrderLine).toBe(true);
  135. assertCanBeSerialized(orderLine);
  136. });
  137. it('serialize ProductVariant', async () => {
  138. const ctx = await createCtx();
  139. const productVariant = await server.app.get(ProductVariantService).findOne(ctx, 1);
  140. expect(productVariant instanceof ProductVariant).toBe(true);
  141. assertCanBeSerialized(productVariant);
  142. });
  143. it('serialize Promotion', async () => {
  144. await adminClient.query<Codegen.CreatePromotionMutation, Codegen.CreatePromotionMutationVariables>(
  145. CREATE_PROMOTION,
  146. {
  147. input: {
  148. enabled: true,
  149. startsAt: new Date('2019-10-30T00:00:00.000Z'),
  150. endsAt: new Date('2019-12-01T00:00:00.000Z'),
  151. translations: [
  152. {
  153. languageCode: LanguageCode.en,
  154. name: 'test promotion',
  155. description: 'a test promotion',
  156. },
  157. ],
  158. conditions: [
  159. {
  160. code: hasFacetValues.code,
  161. arguments: [
  162. { name: 'minimum', value: '2' },
  163. { name: 'facets', value: `["T_1"]` },
  164. ],
  165. },
  166. ],
  167. actions: [
  168. {
  169. code: discountOnItemWithFacets.code,
  170. arguments: [
  171. { name: 'discount', value: '50' },
  172. { name: 'facets', value: `["T_1"]` },
  173. ],
  174. },
  175. ],
  176. },
  177. },
  178. );
  179. const ctx = await createCtx();
  180. const promotion = await server.app.get(PromotionService).findOne(ctx, 1);
  181. expect(promotion instanceof Promotion).toBe(true);
  182. assertCanBeSerialized(promotion);
  183. });
  184. it('serialize ShippingLine', async () => {
  185. const ctx = await createCtx();
  186. const shippingLine = await server.app
  187. .get(TransactionalConnection)
  188. .getEntityOrThrow(ctx, ShippingLine, 1);
  189. expect(shippingLine instanceof ShippingLine).toBe(true);
  190. assertCanBeSerialized(shippingLine);
  191. });
  192. it('serialize Order with nested ShippingMethod', async () => {
  193. const ctx = await createCtx();
  194. const order = await server.app
  195. .get(OrderService)
  196. .findOne(ctx, 1, ['lines', 'surcharges', 'shippingLines.shippingMethod']);
  197. expect(order).not.toBeNull();
  198. expect(order instanceof Order).toBe(true);
  199. assertCanBeSerialized(order);
  200. });
  201. function assertCanBeSerialized(entity: any) {
  202. try {
  203. const json = JSON.stringify(entity);
  204. } catch (e: any) {
  205. fail(`Could not serialize entity: ${e.message as string}`);
  206. }
  207. }
  208. async function createCtx() {
  209. return server.app.get(RequestContextService).create({
  210. apiType: 'admin',
  211. });
  212. }
  213. });