1
0

populate.e2e-spec.ts 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. import { INestApplication } from '@nestjs/common';
  2. import { User } from '@vendure/core';
  3. import { populate } from '@vendure/core/cli';
  4. import { createTestEnvironment, E2E_DEFAULT_CHANNEL_TOKEN } from '@vendure/testing';
  5. import path from 'path';
  6. import { afterAll, beforeAll, describe, expect, it } from 'vitest';
  7. import { initialData } from '../../../e2e-common/e2e-initial-data';
  8. import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config';
  9. import { InitialData } from '../src/index';
  10. import {
  11. ChannelFragment,
  12. CreateChannelMutation,
  13. CreateChannelMutationVariables,
  14. CurrencyCode,
  15. GetAssetListQuery,
  16. GetCollectionsQuery,
  17. GetProductListQuery,
  18. GetProductListQueryVariables,
  19. GetProductWithVariantsQuery,
  20. GetProductWithVariantsQueryVariables,
  21. LanguageCode,
  22. } from './graphql/generated-e2e-admin-types';
  23. import {
  24. CREATE_CHANNEL,
  25. GET_ASSET_LIST,
  26. GET_COLLECTIONS,
  27. GET_PRODUCT_LIST,
  28. GET_PRODUCT_WITH_VARIANTS,
  29. } from './graphql/shared-definitions';
  30. describe('populate() function', () => {
  31. let channel2: ChannelFragment;
  32. const { server, adminClient } = createTestEnvironment({
  33. ...testConfig(),
  34. // logger: new DefaultLogger(),
  35. customFields: {
  36. Product: [
  37. { type: 'string', name: 'pageType' },
  38. {
  39. name: 'owner',
  40. public: true,
  41. nullable: true,
  42. type: 'relation',
  43. entity: User,
  44. eager: true,
  45. },
  46. {
  47. name: 'keywords',
  48. public: true,
  49. nullable: true,
  50. type: 'string',
  51. list: true,
  52. },
  53. {
  54. name: 'localName',
  55. type: 'localeString',
  56. },
  57. ],
  58. ProductVariant: [
  59. { type: 'boolean', name: 'valid' },
  60. { type: 'int', name: 'weight' },
  61. ],
  62. },
  63. });
  64. beforeAll(async () => {
  65. await server.init({
  66. initialData: { ...initialData, collections: [] },
  67. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-empty.csv'),
  68. customerCount: 1,
  69. });
  70. await adminClient.asSuperAdmin();
  71. const { createChannel } = await adminClient.query<
  72. CreateChannelMutation,
  73. CreateChannelMutationVariables
  74. >(CREATE_CHANNEL, {
  75. input: {
  76. code: 'Channel 2',
  77. token: 'channel-2',
  78. currencyCode: CurrencyCode.EUR,
  79. defaultLanguageCode: LanguageCode.en,
  80. defaultShippingZoneId: 'T_1',
  81. defaultTaxZoneId: 'T_2',
  82. pricesIncludeTax: true,
  83. },
  84. });
  85. channel2 = createChannel as ChannelFragment;
  86. await server.destroy();
  87. }, TEST_SETUP_TIMEOUT_MS);
  88. describe('populating default channel', () => {
  89. let app: INestApplication;
  90. beforeAll(async () => {
  91. const initialDataForPopulate: InitialData = {
  92. defaultLanguage: initialData.defaultLanguage,
  93. defaultZone: initialData.defaultZone,
  94. taxRates: [],
  95. shippingMethods: [],
  96. paymentMethods: [],
  97. countries: [],
  98. collections: [{ name: 'Collection 1', filters: [] }],
  99. };
  100. const csvFile = path.join(__dirname, 'fixtures', 'product-import.csv');
  101. app = await populate(
  102. async () => {
  103. await server.bootstrap();
  104. return server.app;
  105. },
  106. initialDataForPopulate,
  107. csvFile,
  108. );
  109. }, TEST_SETUP_TIMEOUT_MS);
  110. afterAll(async () => {
  111. await app.close();
  112. });
  113. it('populates products', async () => {
  114. await adminClient.asSuperAdmin();
  115. const { products } = await adminClient.query<GetProductListQuery>(GET_PRODUCT_LIST);
  116. expect(products.totalItems).toBe(4);
  117. expect(products.items.map(i => i.name).sort()).toEqual([
  118. 'Artists Smock',
  119. 'Giotto Mega Pencils',
  120. 'Mabef M/02 Studio Easel',
  121. 'Perfect Paper Stretcher',
  122. ]);
  123. });
  124. it('populates assets', async () => {
  125. const { assets } = await adminClient.query<GetAssetListQuery>(GET_ASSET_LIST);
  126. expect(assets.items.map(i => i.name).sort()).toEqual([
  127. 'box-of-12.jpg',
  128. 'box-of-8.jpg',
  129. 'pps1.jpg',
  130. 'pps2.jpg',
  131. ]);
  132. });
  133. it('populates collections', async () => {
  134. const { collections } = await adminClient.query<GetCollectionsQuery>(GET_COLLECTIONS);
  135. expect(collections.items.map(i => i.name).sort()).toEqual(['Collection 1']);
  136. });
  137. });
  138. describe('populating a non-default channel', () => {
  139. let app: INestApplication;
  140. beforeAll(async () => {
  141. const initialDataForPopulate: InitialData = {
  142. defaultLanguage: initialData.defaultLanguage,
  143. defaultZone: initialData.defaultZone,
  144. taxRates: [],
  145. shippingMethods: [],
  146. paymentMethods: [],
  147. countries: [],
  148. collections: [{ name: 'Collection 2', filters: [] }],
  149. };
  150. const csvFile = path.join(__dirname, 'fixtures', 'product-import-channel.csv');
  151. app = await populate(
  152. async () => {
  153. await server.bootstrap();
  154. return server.app;
  155. },
  156. initialDataForPopulate,
  157. csvFile,
  158. channel2.token,
  159. );
  160. });
  161. afterAll(async () => {
  162. await app.close();
  163. });
  164. it('populates products', async () => {
  165. await adminClient.asSuperAdmin();
  166. adminClient.setChannelToken(channel2.token);
  167. const { products } = await adminClient.query<GetProductListQuery>(GET_PRODUCT_LIST);
  168. expect(products.totalItems).toBe(1);
  169. expect(products.items.map(i => i.name).sort()).toEqual(['Model Hand']);
  170. });
  171. it('populates assets', async () => {
  172. const { assets } = await adminClient.query<GetAssetListQuery>(GET_ASSET_LIST);
  173. expect(assets.items.map(i => i.name).sort()).toEqual(['vincent-botta-736919-unsplash.jpg']);
  174. });
  175. it('populates collections', async () => {
  176. const { collections } = await adminClient.query<GetCollectionsQuery>(GET_COLLECTIONS);
  177. expect(collections.items.map(i => i.name).sort()).toEqual(['Collection 2']);
  178. });
  179. it('product also assigned to default channel', async () => {
  180. adminClient.setChannelToken(E2E_DEFAULT_CHANNEL_TOKEN);
  181. const { products } = await adminClient.query<GetProductListQuery>(GET_PRODUCT_LIST);
  182. expect(products.items.map(i => i.name).includes('Model Hand')).toBe(true);
  183. });
  184. });
  185. // https://github.com/vendurehq/vendure/issues/1445
  186. describe('clashing option names', () => {
  187. let app: INestApplication;
  188. beforeAll(async () => {
  189. const initialDataForPopulate: InitialData = {
  190. defaultLanguage: initialData.defaultLanguage,
  191. defaultZone: initialData.defaultZone,
  192. taxRates: [],
  193. shippingMethods: [],
  194. paymentMethods: [],
  195. countries: [],
  196. collections: [{ name: 'Collection 1', filters: [] }],
  197. };
  198. const csvFile = path.join(__dirname, 'fixtures', 'product-import-option-values.csv');
  199. app = await populate(
  200. async () => {
  201. await server.bootstrap();
  202. return server.app;
  203. },
  204. initialDataForPopulate,
  205. csvFile,
  206. );
  207. }, TEST_SETUP_TIMEOUT_MS);
  208. afterAll(async () => {
  209. await app.close();
  210. });
  211. it('populates variants & options', async () => {
  212. await adminClient.asSuperAdmin();
  213. adminClient.setChannelToken(E2E_DEFAULT_CHANNEL_TOKEN);
  214. const { products } = await adminClient.query<GetProductListQuery, GetProductListQueryVariables>(
  215. GET_PRODUCT_LIST,
  216. {
  217. options: {
  218. filter: {
  219. slug: { eq: 'foo' },
  220. },
  221. },
  222. },
  223. );
  224. expect(products.totalItems).toBe(1);
  225. const fooProduct = products.items[0];
  226. expect(fooProduct.name).toBe('Foo');
  227. const { product } = await adminClient.query<
  228. GetProductWithVariantsQuery,
  229. GetProductWithVariantsQueryVariables
  230. >(GET_PRODUCT_WITH_VARIANTS, {
  231. id: fooProduct.id,
  232. });
  233. expect(product?.variants.length).toBe(4);
  234. expect(product?.optionGroups.map(og => og.name).sort()).toEqual(['Bar', 'Foo']);
  235. expect(
  236. product?.variants
  237. .find(v => v.sku === 'foo-fiz-buz')
  238. ?.options.map(o => o.name)
  239. .sort(),
  240. ).toEqual(['buz', 'fiz']);
  241. });
  242. });
  243. });