default-search-plugin.e2e-spec.ts 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. import { pick } from '@vendure/common/lib/pick';
  2. import { DefaultSearchPlugin, mergeConfig } from '@vendure/core';
  3. import { facetValueCollectionFilter } from '@vendure/core/dist/config/collection/default-collection-filters';
  4. import { createTestEnvironment, E2E_DEFAULT_CHANNEL_TOKEN, SimpleGraphQLClient } from '@vendure/testing';
  5. import gql from 'graphql-tag';
  6. import path from 'path';
  7. import { initialData } from '../../../e2e-common/e2e-initial-data';
  8. import { TEST_SETUP_TIMEOUT_MS, testConfig } from '../../../e2e-common/test-config';
  9. import {
  10. AssignProductsToChannel,
  11. CreateChannel,
  12. CreateCollection,
  13. CreateFacet,
  14. CurrencyCode,
  15. DeleteProduct,
  16. DeleteProductVariant,
  17. LanguageCode,
  18. RemoveProductsFromChannel,
  19. SearchFacetValues,
  20. SearchGetPrices,
  21. SearchInput,
  22. UpdateCollection,
  23. UpdateProduct,
  24. UpdateProductVariants,
  25. UpdateTaxRate,
  26. } from './graphql/generated-e2e-admin-types';
  27. import { SearchProductsShop } from './graphql/generated-e2e-shop-types';
  28. import {
  29. ASSIGN_PRODUCT_TO_CHANNEL,
  30. CREATE_CHANNEL,
  31. CREATE_COLLECTION,
  32. CREATE_FACET,
  33. DELETE_PRODUCT,
  34. DELETE_PRODUCT_VARIANT,
  35. REMOVE_PRODUCT_FROM_CHANNEL,
  36. UPDATE_COLLECTION,
  37. UPDATE_PRODUCT,
  38. UPDATE_PRODUCT_VARIANTS,
  39. UPDATE_TAX_RATE,
  40. } from './graphql/shared-definitions';
  41. import { SEARCH_PRODUCTS_SHOP } from './graphql/shop-definitions';
  42. import { awaitRunningJobs } from './utils/await-running-jobs';
  43. describe('Default search plugin', () => {
  44. const { server, adminClient, shopClient } = createTestEnvironment(
  45. mergeConfig(testConfig, { plugins: [DefaultSearchPlugin] }),
  46. );
  47. beforeAll(async () => {
  48. await server.init({
  49. dataDir: path.join(__dirname, '__data__'),
  50. initialData,
  51. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-full.csv'),
  52. customerCount: 1,
  53. });
  54. await adminClient.asSuperAdmin();
  55. }, TEST_SETUP_TIMEOUT_MS);
  56. afterAll(async () => {
  57. await server.destroy();
  58. });
  59. function doAdminSearchQuery(input: SearchInput) {
  60. return adminClient.query<SearchProductsShop.Query, SearchProductsShop.Variables>(SEARCH_PRODUCTS, {
  61. input,
  62. });
  63. }
  64. async function testGroupByProduct(client: SimpleGraphQLClient) {
  65. const result = await client.query<SearchProductsShop.Query, SearchProductsShop.Variables>(
  66. SEARCH_PRODUCTS_SHOP,
  67. {
  68. input: {
  69. groupByProduct: true,
  70. },
  71. },
  72. );
  73. expect(result.search.totalItems).toBe(20);
  74. }
  75. async function testNoGrouping(client: SimpleGraphQLClient) {
  76. const result = await client.query<SearchProductsShop.Query, SearchProductsShop.Variables>(
  77. SEARCH_PRODUCTS_SHOP,
  78. {
  79. input: {
  80. groupByProduct: false,
  81. },
  82. },
  83. );
  84. expect(result.search.totalItems).toBe(34);
  85. }
  86. async function testMatchSearchTerm(client: SimpleGraphQLClient) {
  87. const result = await client.query<SearchProductsShop.Query, SearchProductsShop.Variables>(
  88. SEARCH_PRODUCTS_SHOP,
  89. {
  90. input: {
  91. term: 'camera',
  92. groupByProduct: true,
  93. },
  94. },
  95. );
  96. expect(result.search.items.map(i => i.productName)).toEqual([
  97. 'Instant Camera',
  98. 'Camera Lens',
  99. 'SLR Camera',
  100. ]);
  101. }
  102. async function testMatchFacetIds(client: SimpleGraphQLClient) {
  103. const result = await client.query<SearchProductsShop.Query, SearchProductsShop.Variables>(
  104. SEARCH_PRODUCTS_SHOP,
  105. {
  106. input: {
  107. facetValueIds: ['T_1', 'T_2'],
  108. groupByProduct: true,
  109. },
  110. },
  111. );
  112. expect(result.search.items.map(i => i.productName)).toEqual([
  113. 'Laptop',
  114. 'Curvy Monitor',
  115. 'Gaming PC',
  116. 'Hard Drive',
  117. 'Clacky Keyboard',
  118. 'USB Cable',
  119. ]);
  120. }
  121. async function testMatchCollectionId(client: SimpleGraphQLClient) {
  122. const result = await client.query<SearchProductsShop.Query, SearchProductsShop.Variables>(
  123. SEARCH_PRODUCTS_SHOP,
  124. {
  125. input: {
  126. collectionId: 'T_2',
  127. groupByProduct: true,
  128. },
  129. },
  130. );
  131. expect(result.search.items.map(i => i.productName)).toEqual([
  132. 'Spiky Cactus',
  133. 'Orchid',
  134. 'Bonsai Tree',
  135. ]);
  136. }
  137. async function testSinglePrices(client: SimpleGraphQLClient) {
  138. const result = await client.query<SearchGetPrices.Query, SearchGetPrices.Variables>(
  139. SEARCH_GET_PRICES,
  140. {
  141. input: {
  142. groupByProduct: false,
  143. take: 3,
  144. } as SearchInput,
  145. },
  146. );
  147. expect(result.search.items).toEqual([
  148. {
  149. price: { value: 129900 },
  150. priceWithTax: { value: 155880 },
  151. },
  152. {
  153. price: { value: 139900 },
  154. priceWithTax: { value: 167880 },
  155. },
  156. {
  157. price: { value: 219900 },
  158. priceWithTax: { value: 263880 },
  159. },
  160. ]);
  161. }
  162. async function testPriceRanges(client: SimpleGraphQLClient) {
  163. const result = await client.query<SearchGetPrices.Query, SearchGetPrices.Variables>(
  164. SEARCH_GET_PRICES,
  165. {
  166. input: {
  167. groupByProduct: true,
  168. take: 3,
  169. } as SearchInput,
  170. },
  171. );
  172. expect(result.search.items).toEqual([
  173. {
  174. price: { min: 129900, max: 229900 },
  175. priceWithTax: { min: 155880, max: 275880 },
  176. },
  177. {
  178. price: { min: 14374, max: 16994 },
  179. priceWithTax: { min: 17249, max: 20393 },
  180. },
  181. {
  182. price: { min: 93120, max: 109995 },
  183. priceWithTax: { min: 111744, max: 131994 },
  184. },
  185. ]);
  186. }
  187. describe('shop api', () => {
  188. it('group by product', () => testGroupByProduct(shopClient));
  189. it('no grouping', () => testNoGrouping(shopClient));
  190. it('matches search term', () => testMatchSearchTerm(shopClient));
  191. it('matches by facetId', () => testMatchFacetIds(shopClient));
  192. it('matches by collectionId', () => testMatchCollectionId(shopClient));
  193. it('single prices', () => testSinglePrices(shopClient));
  194. it('price ranges', () => testPriceRanges(shopClient));
  195. it('returns correct facetValues when not grouped by product', async () => {
  196. const result = await shopClient.query<SearchFacetValues.Query, SearchFacetValues.Variables>(
  197. SEARCH_GET_FACET_VALUES,
  198. {
  199. input: {
  200. groupByProduct: false,
  201. },
  202. },
  203. );
  204. expect(result.search.facetValues).toEqual([
  205. { count: 21, facetValue: { id: 'T_1', name: 'electronics' } },
  206. { count: 17, facetValue: { id: 'T_2', name: 'computers' } },
  207. { count: 4, facetValue: { id: 'T_3', name: 'photo' } },
  208. { count: 10, facetValue: { id: 'T_4', name: 'sports equipment' } },
  209. { count: 3, facetValue: { id: 'T_5', name: 'home & garden' } },
  210. { count: 3, facetValue: { id: 'T_6', name: 'plants' } },
  211. ]);
  212. });
  213. it('returns correct facetValues when grouped by product', async () => {
  214. const result = await shopClient.query<SearchFacetValues.Query, SearchFacetValues.Variables>(
  215. SEARCH_GET_FACET_VALUES,
  216. {
  217. input: {
  218. groupByProduct: true,
  219. },
  220. },
  221. );
  222. expect(result.search.facetValues).toEqual([
  223. { count: 10, facetValue: { id: 'T_1', name: 'electronics' } },
  224. { count: 6, facetValue: { id: 'T_2', name: 'computers' } },
  225. { count: 4, facetValue: { id: 'T_3', name: 'photo' } },
  226. { count: 7, facetValue: { id: 'T_4', name: 'sports equipment' } },
  227. { count: 3, facetValue: { id: 'T_5', name: 'home & garden' } },
  228. { count: 3, facetValue: { id: 'T_6', name: 'plants' } },
  229. ]);
  230. });
  231. it('omits facetValues of private facets', async () => {
  232. const { createFacet } = await adminClient.query<CreateFacet.Mutation, CreateFacet.Variables>(
  233. CREATE_FACET,
  234. {
  235. input: {
  236. code: 'profit-margin',
  237. isPrivate: true,
  238. translations: [{ languageCode: LanguageCode.en, name: 'Profit Margin' }],
  239. values: [
  240. {
  241. code: 'massive',
  242. translations: [{ languageCode: LanguageCode.en, name: 'massive' }],
  243. },
  244. ],
  245. },
  246. },
  247. );
  248. await adminClient.query<UpdateProduct.Mutation, UpdateProduct.Variables>(UPDATE_PRODUCT, {
  249. input: {
  250. id: 'T_2',
  251. // T_1 & T_2 are the existing facetValues (electronics & photo)
  252. facetValueIds: ['T_1', 'T_2', createFacet.values[0].id],
  253. },
  254. });
  255. const result = await shopClient.query<SearchFacetValues.Query, SearchFacetValues.Variables>(
  256. SEARCH_GET_FACET_VALUES,
  257. {
  258. input: {
  259. groupByProduct: true,
  260. },
  261. },
  262. );
  263. expect(result.search.facetValues).toEqual([
  264. { count: 10, facetValue: { id: 'T_1', name: 'electronics' } },
  265. { count: 6, facetValue: { id: 'T_2', name: 'computers' } },
  266. { count: 4, facetValue: { id: 'T_3', name: 'photo' } },
  267. { count: 7, facetValue: { id: 'T_4', name: 'sports equipment' } },
  268. { count: 3, facetValue: { id: 'T_5', name: 'home & garden' } },
  269. { count: 3, facetValue: { id: 'T_6', name: 'plants' } },
  270. ]);
  271. });
  272. it('encodes the productId and productVariantId', async () => {
  273. const result = await shopClient.query<SearchProductsShop.Query, SearchProductsShop.Variables>(
  274. SEARCH_PRODUCTS_SHOP,
  275. {
  276. input: {
  277. groupByProduct: false,
  278. take: 1,
  279. },
  280. },
  281. );
  282. expect(pick(result.search.items[0], ['productId', 'productVariantId'])).toEqual({
  283. productId: 'T_1',
  284. productVariantId: 'T_1',
  285. });
  286. });
  287. it('omits results for disabled ProductVariants', async () => {
  288. await adminClient.query<UpdateProductVariants.Mutation, UpdateProductVariants.Variables>(
  289. UPDATE_PRODUCT_VARIANTS,
  290. {
  291. input: [{ id: 'T_3', enabled: false }],
  292. },
  293. );
  294. await awaitRunningJobs(adminClient);
  295. const result = await shopClient.query<SearchProductsShop.Query, SearchProductsShop.Variables>(
  296. SEARCH_PRODUCTS_SHOP,
  297. {
  298. input: {
  299. groupByProduct: false,
  300. take: 3,
  301. },
  302. },
  303. );
  304. expect(result.search.items.map(i => i.productVariantId)).toEqual(['T_1', 'T_2', 'T_4']);
  305. });
  306. it('encodes collectionIds', async () => {
  307. const result = await shopClient.query<SearchProductsShop.Query, SearchProductsShop.Variables>(
  308. SEARCH_PRODUCTS_SHOP,
  309. {
  310. input: {
  311. groupByProduct: false,
  312. term: 'cactus',
  313. take: 1,
  314. },
  315. },
  316. );
  317. expect(result.search.items[0].collectionIds).toEqual(['T_2']);
  318. });
  319. });
  320. describe('admin api', () => {
  321. it('group by product', () => testGroupByProduct(adminClient));
  322. it('no grouping', () => testNoGrouping(adminClient));
  323. it('matches search term', () => testMatchSearchTerm(adminClient));
  324. it('matches by facetId', () => testMatchFacetIds(adminClient));
  325. it('matches by collectionId', () => testMatchCollectionId(adminClient));
  326. it('single prices', () => testSinglePrices(adminClient));
  327. it('price ranges', () => testPriceRanges(adminClient));
  328. describe('updating the index', () => {
  329. it('updates index when ProductVariants are changed', async () => {
  330. await awaitRunningJobs(adminClient);
  331. const { search } = await doAdminSearchQuery({ term: 'drive', groupByProduct: false });
  332. expect(search.items.map(i => i.sku)).toEqual([
  333. 'IHD455T1',
  334. 'IHD455T2',
  335. 'IHD455T3',
  336. 'IHD455T4',
  337. 'IHD455T6',
  338. ]);
  339. await adminClient.query<UpdateProductVariants.Mutation, UpdateProductVariants.Variables>(
  340. UPDATE_PRODUCT_VARIANTS,
  341. {
  342. input: search.items.map(i => ({
  343. id: i.productVariantId,
  344. sku: i.sku + '_updated',
  345. })),
  346. },
  347. );
  348. await awaitRunningJobs(adminClient);
  349. const { search: search2 } = await doAdminSearchQuery({
  350. term: 'drive',
  351. groupByProduct: false,
  352. });
  353. expect(search2.items.map(i => i.sku)).toEqual([
  354. 'IHD455T1_updated',
  355. 'IHD455T2_updated',
  356. 'IHD455T3_updated',
  357. 'IHD455T4_updated',
  358. 'IHD455T6_updated',
  359. ]);
  360. });
  361. it('updates index when ProductVariants are deleted', async () => {
  362. await awaitRunningJobs(adminClient);
  363. const { search } = await doAdminSearchQuery({ term: 'drive', groupByProduct: false });
  364. await adminClient.query<DeleteProductVariant.Mutation, DeleteProductVariant.Variables>(
  365. DELETE_PRODUCT_VARIANT,
  366. {
  367. id: search.items[0].productVariantId,
  368. },
  369. );
  370. await awaitRunningJobs(adminClient);
  371. const { search: search2 } = await doAdminSearchQuery({
  372. term: 'drive',
  373. groupByProduct: false,
  374. });
  375. expect(search2.items.map(i => i.sku)).toEqual([
  376. 'IHD455T2_updated',
  377. 'IHD455T3_updated',
  378. 'IHD455T4_updated',
  379. 'IHD455T6_updated',
  380. ]);
  381. });
  382. it('updates index when a Product is changed', async () => {
  383. await adminClient.query<UpdateProduct.Mutation, UpdateProduct.Variables>(UPDATE_PRODUCT, {
  384. input: {
  385. id: 'T_1',
  386. facetValueIds: [],
  387. },
  388. });
  389. await awaitRunningJobs(adminClient);
  390. const result = await doAdminSearchQuery({ facetValueIds: ['T_2'], groupByProduct: true });
  391. expect(result.search.items.map(i => i.productName)).toEqual([
  392. 'Curvy Monitor',
  393. 'Gaming PC',
  394. 'Hard Drive',
  395. 'Clacky Keyboard',
  396. 'USB Cable',
  397. ]);
  398. });
  399. it('updates index when a Product is deleted', async () => {
  400. const { search } = await doAdminSearchQuery({ facetValueIds: ['T_2'], groupByProduct: true });
  401. expect(search.items.map(i => i.productId)).toEqual(['T_2', 'T_3', 'T_4', 'T_5', 'T_6']);
  402. await adminClient.query<DeleteProduct.Mutation, DeleteProduct.Variables>(DELETE_PRODUCT, {
  403. id: 'T_5',
  404. });
  405. await awaitRunningJobs(adminClient);
  406. const { search: search2 } = await doAdminSearchQuery({
  407. facetValueIds: ['T_2'],
  408. groupByProduct: true,
  409. });
  410. expect(search2.items.map(i => i.productId)).toEqual(['T_2', 'T_3', 'T_4', 'T_6']);
  411. });
  412. it('updates index when a Collection is changed', async () => {
  413. await adminClient.query<UpdateCollection.Mutation, UpdateCollection.Variables>(
  414. UPDATE_COLLECTION,
  415. {
  416. input: {
  417. id: 'T_2',
  418. filters: [
  419. {
  420. code: facetValueCollectionFilter.code,
  421. arguments: [
  422. {
  423. name: 'facetValueIds',
  424. value: `["T_4"]`,
  425. type: 'facetValueIds',
  426. },
  427. {
  428. name: 'containsAny',
  429. value: `false`,
  430. type: 'boolean',
  431. },
  432. ],
  433. },
  434. ],
  435. },
  436. },
  437. );
  438. await awaitRunningJobs(adminClient);
  439. const result = await doAdminSearchQuery({ collectionId: 'T_2', groupByProduct: true });
  440. expect(result.search.items.map(i => i.productName)).toEqual([
  441. 'Road Bike',
  442. 'Skipping Rope',
  443. 'Boxing Gloves',
  444. 'Tent',
  445. 'Cruiser Skateboard',
  446. 'Football',
  447. 'Running Shoe',
  448. ]);
  449. });
  450. it('updates index when a Collection created', async () => {
  451. const { createCollection } = await adminClient.query<
  452. CreateCollection.Mutation,
  453. CreateCollection.Variables
  454. >(CREATE_COLLECTION, {
  455. input: {
  456. translations: [
  457. {
  458. languageCode: LanguageCode.en,
  459. name: 'Photo',
  460. description: '',
  461. },
  462. ],
  463. filters: [
  464. {
  465. code: facetValueCollectionFilter.code,
  466. arguments: [
  467. {
  468. name: 'facetValueIds',
  469. value: `["T_3"]`,
  470. type: 'facetValueIds',
  471. },
  472. {
  473. name: 'containsAny',
  474. value: `false`,
  475. type: 'boolean',
  476. },
  477. ],
  478. },
  479. ],
  480. },
  481. });
  482. await awaitRunningJobs(adminClient);
  483. const result = await doAdminSearchQuery({
  484. collectionId: createCollection.id,
  485. groupByProduct: true,
  486. });
  487. expect(result.search.items.map(i => i.productName)).toEqual([
  488. 'Instant Camera',
  489. 'Camera Lens',
  490. 'Tripod',
  491. 'SLR Camera',
  492. ]);
  493. });
  494. it('updates index when a taxRate is changed', async () => {
  495. await adminClient.query<UpdateTaxRate.Mutation, UpdateTaxRate.Variables>(UPDATE_TAX_RATE, {
  496. input: {
  497. // Default Channel's defaultTaxZone is Europe (id 2) and the id of the standard TaxRate
  498. // to Europe is 2.
  499. id: 'T_2',
  500. value: 50,
  501. },
  502. });
  503. await awaitRunningJobs(adminClient);
  504. const result = await adminClient.query<SearchGetPrices.Query, SearchGetPrices.Variables>(
  505. SEARCH_GET_PRICES,
  506. {
  507. input: {
  508. groupByProduct: true,
  509. term: 'laptop',
  510. } as SearchInput,
  511. },
  512. );
  513. expect(result.search.items).toEqual([
  514. {
  515. price: { min: 129900, max: 229900 },
  516. priceWithTax: { min: 194850, max: 344850 },
  517. },
  518. ]);
  519. });
  520. it('returns disabled field when not grouped', async () => {
  521. const result = await doAdminSearchQuery({ groupByProduct: false, take: 3 });
  522. expect(result.search.items.map(pick(['productVariantId', 'enabled']))).toEqual([
  523. { productVariantId: 'T_1', enabled: true },
  524. { productVariantId: 'T_2', enabled: true },
  525. { productVariantId: 'T_3', enabled: false },
  526. ]);
  527. });
  528. it('when grouped, disabled is false if at least one variant is enabled', async () => {
  529. await adminClient.query<UpdateProductVariants.Mutation, UpdateProductVariants.Variables>(
  530. UPDATE_PRODUCT_VARIANTS,
  531. {
  532. input: [{ id: 'T_1', enabled: false }, { id: 'T_2', enabled: false }],
  533. },
  534. );
  535. await awaitRunningJobs(adminClient);
  536. const result = await doAdminSearchQuery({ groupByProduct: true, take: 3 });
  537. expect(result.search.items.map(pick(['productId', 'enabled']))).toEqual([
  538. { productId: 'T_1', enabled: true },
  539. { productId: 'T_2', enabled: true },
  540. { productId: 'T_3', enabled: true },
  541. ]);
  542. });
  543. it('when grouped, disabled is true if all variants are disabled', async () => {
  544. await adminClient.query<UpdateProductVariants.Mutation, UpdateProductVariants.Variables>(
  545. UPDATE_PRODUCT_VARIANTS,
  546. {
  547. input: [{ id: 'T_4', enabled: false }],
  548. },
  549. );
  550. await awaitRunningJobs(adminClient);
  551. const result = await doAdminSearchQuery({ groupByProduct: true, take: 3 });
  552. expect(result.search.items.map(pick(['productId', 'enabled']))).toEqual([
  553. { productId: 'T_1', enabled: false },
  554. { productId: 'T_2', enabled: true },
  555. { productId: 'T_3', enabled: true },
  556. ]);
  557. });
  558. it('when grouped, disabled is true product is disabled', async () => {
  559. await adminClient.query<UpdateProduct.Mutation, UpdateProduct.Variables>(UPDATE_PRODUCT, {
  560. input: {
  561. id: 'T_3',
  562. enabled: false,
  563. },
  564. });
  565. await awaitRunningJobs(adminClient);
  566. const result = await doAdminSearchQuery({ groupByProduct: true, take: 3 });
  567. expect(result.search.items.map(pick(['productId', 'enabled']))).toEqual([
  568. { productId: 'T_1', enabled: false },
  569. { productId: 'T_2', enabled: true },
  570. { productId: 'T_3', enabled: false },
  571. ]);
  572. });
  573. });
  574. describe('channel handling', () => {
  575. const SECOND_CHANNEL_TOKEN = 'second-channel-token';
  576. let secondChannel: CreateChannel.CreateChannel;
  577. beforeAll(async () => {
  578. const { createChannel } = await adminClient.query<
  579. CreateChannel.Mutation,
  580. CreateChannel.Variables
  581. >(CREATE_CHANNEL, {
  582. input: {
  583. code: 'second-channel',
  584. token: SECOND_CHANNEL_TOKEN,
  585. defaultLanguageCode: LanguageCode.en,
  586. currencyCode: CurrencyCode.GBP,
  587. pricesIncludeTax: true,
  588. defaultTaxZoneId: 'T_1',
  589. defaultShippingZoneId: 'T_1',
  590. },
  591. });
  592. secondChannel = createChannel;
  593. });
  594. it('adding product to channel', async () => {
  595. adminClient.setChannelToken(E2E_DEFAULT_CHANNEL_TOKEN);
  596. await adminClient.query<AssignProductsToChannel.Mutation, AssignProductsToChannel.Variables>(
  597. ASSIGN_PRODUCT_TO_CHANNEL,
  598. {
  599. input: { channelId: secondChannel.id, productIds: ['T_1', 'T_2'] },
  600. },
  601. );
  602. await awaitRunningJobs(adminClient);
  603. adminClient.setChannelToken(SECOND_CHANNEL_TOKEN);
  604. const { search } = await doAdminSearchQuery({ groupByProduct: true });
  605. expect(search.items.map(i => i.productId)).toEqual(['T_1', 'T_2']);
  606. }, 10000);
  607. it('removing product from channel', async () => {
  608. adminClient.setChannelToken(E2E_DEFAULT_CHANNEL_TOKEN);
  609. const { removeProductsFromChannel } = await adminClient.query<
  610. RemoveProductsFromChannel.Mutation,
  611. RemoveProductsFromChannel.Variables
  612. >(REMOVE_PRODUCT_FROM_CHANNEL, {
  613. input: {
  614. productIds: ['T_2'],
  615. channelId: secondChannel.id,
  616. },
  617. });
  618. await awaitRunningJobs(adminClient);
  619. adminClient.setChannelToken(SECOND_CHANNEL_TOKEN);
  620. const { search } = await doAdminSearchQuery({ groupByProduct: true });
  621. expect(search.items.map(i => i.productId)).toEqual(['T_1']);
  622. }, 10000);
  623. });
  624. });
  625. });
  626. export const SEARCH_PRODUCTS = gql`
  627. query SearchProductsAdmin($input: SearchInput!) {
  628. search(input: $input) {
  629. totalItems
  630. items {
  631. enabled
  632. productId
  633. productName
  634. productPreview
  635. productVariantId
  636. productVariantName
  637. productVariantPreview
  638. sku
  639. }
  640. }
  641. }
  642. `;
  643. export const SEARCH_GET_FACET_VALUES = gql`
  644. query SearchFacetValues($input: SearchInput!) {
  645. search(input: $input) {
  646. totalItems
  647. facetValues {
  648. count
  649. facetValue {
  650. id
  651. name
  652. }
  653. }
  654. }
  655. }
  656. `;
  657. export const SEARCH_GET_PRICES = gql`
  658. query SearchGetPrices($input: SearchInput!) {
  659. search(input: $input) {
  660. items {
  661. price {
  662. ... on PriceRange {
  663. min
  664. max
  665. }
  666. ... on SinglePrice {
  667. value
  668. }
  669. }
  670. priceWithTax {
  671. ... on PriceRange {
  672. min
  673. max
  674. }
  675. ... on SinglePrice {
  676. value
  677. }
  678. }
  679. }
  680. }
  681. }
  682. `;