import.e2e-spec.ts 9.0 KB

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