populate.e2e-spec.ts 9.4 KB

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