import.e2e-spec.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. import { omit } from '@vendure/common/lib/omit';
  2. import { User } from '@vendure/core';
  3. import { createTestEnvironment } 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. describe('Import resolver', () => {
  9. const { server, adminClient } = createTestEnvironment({
  10. ...testConfig,
  11. customFields: {
  12. Product: [
  13. { type: 'string', name: 'pageType' },
  14. {
  15. name: 'owner',
  16. public: true,
  17. nullable: true,
  18. type: 'relation',
  19. entity: User,
  20. eager: true,
  21. },
  22. {
  23. name: 'keywords',
  24. public: true,
  25. nullable: true,
  26. type: 'string',
  27. list: true,
  28. },
  29. ],
  30. ProductVariant: [{ type: 'int', name: 'weight' }],
  31. },
  32. });
  33. beforeAll(async () => {
  34. await server.init({
  35. initialData,
  36. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-empty.csv'),
  37. customerCount: 0,
  38. });
  39. await adminClient.asSuperAdmin();
  40. }, TEST_SETUP_TIMEOUT_MS);
  41. afterAll(async () => {
  42. await server.destroy();
  43. });
  44. it('imports products', async () => {
  45. // TODO: waste a few more hours actually fixing this for real
  46. // Forgive me this abomination of a work-around.
  47. // On the inital run (as in CI), when the sqlite db has just been populated,
  48. // this test will fail due to an "out of memory" exception originating from
  49. // SqljsQueryRunner.ts:79:22, which is part of the findOne() operation on the
  50. // Session repository called from the AuthService.validateSession() method.
  51. // After several hours of fruitless hunting, I did what any desperate JavaScript
  52. // developer would do, and threw in a setTimeout. Which of course "works"...
  53. const timeout = process.env.CI ? 2000 : 1000;
  54. await new Promise(resolve => {
  55. setTimeout(resolve, timeout);
  56. });
  57. const csvFile = path.join(__dirname, 'fixtures', 'product-import.csv');
  58. const result = await adminClient.fileUploadMutation({
  59. mutation: gql`
  60. mutation ImportProducts($csvFile: Upload!) {
  61. importProducts(csvFile: $csvFile) {
  62. imported
  63. processed
  64. errors
  65. }
  66. }
  67. `,
  68. filePaths: [csvFile],
  69. mapVariables: () => ({ csvFile: null }),
  70. });
  71. expect(result.importProducts.errors).toEqual([
  72. 'Invalid Record Length: header length is 18, got 1 on line 8',
  73. ]);
  74. expect(result.importProducts.imported).toBe(4);
  75. expect(result.importProducts.processed).toBe(4);
  76. const productResult = await adminClient.query(
  77. gql`
  78. query GetProducts($options: ProductListOptions) {
  79. products(options: $options) {
  80. totalItems
  81. items {
  82. id
  83. name
  84. slug
  85. description
  86. featuredAsset {
  87. id
  88. name
  89. preview
  90. source
  91. }
  92. assets {
  93. id
  94. name
  95. preview
  96. source
  97. }
  98. optionGroups {
  99. id
  100. code
  101. name
  102. }
  103. facetValues {
  104. id
  105. name
  106. facet {
  107. id
  108. name
  109. }
  110. }
  111. customFields {
  112. pageType
  113. owner {
  114. id
  115. }
  116. keywords
  117. }
  118. variants {
  119. id
  120. name
  121. sku
  122. price
  123. taxCategory {
  124. id
  125. name
  126. }
  127. options {
  128. id
  129. code
  130. }
  131. assets {
  132. id
  133. name
  134. preview
  135. source
  136. }
  137. featuredAsset {
  138. id
  139. name
  140. preview
  141. source
  142. }
  143. facetValues {
  144. id
  145. code
  146. name
  147. facet {
  148. id
  149. name
  150. }
  151. }
  152. stockOnHand
  153. trackInventory
  154. stockMovements {
  155. items {
  156. ... on StockMovement {
  157. id
  158. type
  159. quantity
  160. }
  161. }
  162. }
  163. customFields {
  164. weight
  165. }
  166. }
  167. }
  168. }
  169. }
  170. `,
  171. {
  172. options: {},
  173. },
  174. );
  175. expect(productResult.products.totalItems).toBe(4);
  176. const paperStretcher = productResult.products.items.find(
  177. (p: any) => p.name === 'Perfect Paper Stretcher',
  178. );
  179. const easel = productResult.products.items.find((p: any) => p.name === 'Mabef M/02 Studio Easel');
  180. const pencils = productResult.products.items.find((p: any) => p.name === 'Giotto Mega Pencils');
  181. const smock = productResult.products.items.find((p: any) => p.name === 'Artists Smock');
  182. // Omit FacetValues & options due to variations in the ordering between different DB engines
  183. expect(omit(paperStretcher, ['facetValues', 'options'], true)).toMatchSnapshot();
  184. expect(omit(easel, ['facetValues', 'options'], true)).toMatchSnapshot();
  185. expect(omit(pencils, ['facetValues', 'options'], true)).toMatchSnapshot();
  186. expect(omit(smock, ['facetValues', 'options'], true)).toMatchSnapshot();
  187. const byName = (e: { name: string }) => e.name;
  188. const byCode = (e: { code: string }) => e.code;
  189. expect(paperStretcher.facetValues).toEqual([]);
  190. expect(easel.facetValues).toEqual([]);
  191. expect(pencils.facetValues).toEqual([]);
  192. expect(smock.facetValues.map(byName).sort()).toEqual(['Denim', 'clothes']);
  193. expect(paperStretcher.variants[0].facetValues.map(byName).sort()).toEqual(['Accessory', 'KB']);
  194. expect(paperStretcher.variants[1].facetValues.map(byName).sort()).toEqual(['Accessory', 'KB']);
  195. expect(paperStretcher.variants[2].facetValues.map(byName).sort()).toEqual(['Accessory', 'KB']);
  196. expect(paperStretcher.variants[0].options.map(byCode).sort()).toEqual(['half-imperial']);
  197. expect(paperStretcher.variants[1].options.map(byCode).sort()).toEqual(['quarter-imperial']);
  198. expect(paperStretcher.variants[2].options.map(byCode).sort()).toEqual(['full-imperial']);
  199. expect(easel.variants[0].facetValues.map(byName).sort()).toEqual(['Easel', 'Mabef']);
  200. expect(pencils.variants[0].facetValues.map(byName).sort()).toEqual(['Xmas Sale']);
  201. expect(pencils.variants[1].facetValues.map(byName).sort()).toEqual(['Xmas Sale']);
  202. expect(pencils.variants[0].options.map(byCode).sort()).toEqual(['box-of-8']);
  203. expect(pencils.variants[1].options.map(byCode).sort()).toEqual(['box-of-12']);
  204. expect(smock.variants[0].facetValues.map(byName).sort()).toEqual([]);
  205. expect(smock.variants[1].facetValues.map(byName).sort()).toEqual([]);
  206. expect(smock.variants[2].facetValues.map(byName).sort()).toEqual([]);
  207. expect(smock.variants[3].facetValues.map(byName).sort()).toEqual([]);
  208. expect(smock.variants[0].options.map(byCode).sort()).toEqual(['beige', 'small']);
  209. expect(smock.variants[1].options.map(byCode).sort()).toEqual(['beige', 'large']);
  210. expect(smock.variants[2].options.map(byCode).sort()).toEqual(['navy', 'small']);
  211. expect(smock.variants[3].options.map(byCode).sort()).toEqual(['large', 'navy']);
  212. // Import relation custom fields
  213. expect(paperStretcher.customFields.owner.id).toBe('T_1');
  214. expect(easel.customFields.owner.id).toBe('T_1');
  215. expect(pencils.customFields.owner.id).toBe('T_1');
  216. expect(smock.customFields.owner.id).toBe('T_1');
  217. // Import list custom fields
  218. expect(paperStretcher.customFields.keywords).toEqual(['paper', 'stretching', 'watercolor']);
  219. expect(easel.customFields.keywords).toEqual([]);
  220. expect(pencils.customFields.keywords).toEqual([]);
  221. expect(smock.customFields.keywords).toEqual(['apron', 'clothing']);
  222. }, 20000);
  223. });