facet.e2e-spec.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. import {
  2. CreateFacet,
  3. CreateFacetValues,
  4. DeletionResult,
  5. FacetWithValues,
  6. GetFacetList,
  7. GetFacetWithValues,
  8. GetProductList,
  9. GetProductWithVariants,
  10. LanguageCode,
  11. UpdateFacet,
  12. UpdateFacetValues,
  13. UpdateProduct,
  14. UpdateProductVariants,
  15. } from '@vendure/common/lib/generated-types';
  16. import gql from 'graphql-tag';
  17. import path from 'path';
  18. import {
  19. CREATE_FACET,
  20. CREATE_FACET_VALUES,
  21. GET_FACET_LIST,
  22. GET_FACET_WITH_VALUES,
  23. UPDATE_FACET,
  24. UPDATE_FACET_VALUES,
  25. } from '../../../admin-ui/src/app/data/definitions/facet-definitions';
  26. import {
  27. GET_PRODUCT_LIST,
  28. GET_PRODUCT_WITH_VARIANTS,
  29. UPDATE_PRODUCT,
  30. UPDATE_PRODUCT_VARIANTS,
  31. } from '../../../admin-ui/src/app/data/definitions/product-definitions';
  32. import { TEST_SETUP_TIMEOUT_MS } from './config/test-config';
  33. import { TestAdminClient } from './test-client';
  34. import { TestServer } from './test-server';
  35. // tslint:disable:no-non-null-assertion
  36. describe('Facet resolver', () => {
  37. const client = new TestAdminClient();
  38. const server = new TestServer();
  39. let brandFacet: FacetWithValues.Fragment;
  40. let speakerTypeFacet: FacetWithValues.Fragment;
  41. beforeAll(async () => {
  42. await server.init({
  43. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-full.csv'),
  44. customerCount: 1,
  45. });
  46. await client.init();
  47. }, TEST_SETUP_TIMEOUT_MS);
  48. afterAll(async () => {
  49. await server.destroy();
  50. });
  51. it('createFacet', async () => {
  52. const result = await client.query<CreateFacet.Mutation, CreateFacet.Variables>(CREATE_FACET, {
  53. input: {
  54. isPrivate: false,
  55. code: 'speaker-type',
  56. translations: [{ languageCode: LanguageCode.en, name: 'Speaker Type' }],
  57. values: [
  58. {
  59. code: 'portable',
  60. translations: [{ languageCode: LanguageCode.en, name: 'Portable' }],
  61. },
  62. ],
  63. },
  64. });
  65. speakerTypeFacet = result.createFacet;
  66. expect(speakerTypeFacet).toMatchSnapshot();
  67. });
  68. it('updateFacet', async () => {
  69. const result = await client.query<UpdateFacet.Mutation, UpdateFacet.Variables>(UPDATE_FACET, {
  70. input: {
  71. id: speakerTypeFacet.id,
  72. translations: [{ languageCode: LanguageCode.en, name: 'Speaker Category' }],
  73. },
  74. });
  75. expect(result.updateFacet.name).toBe('Speaker Category');
  76. });
  77. it('createFacetValues', async () => {
  78. const result = await client.query<CreateFacetValues.Mutation, CreateFacetValues.Variables>(
  79. CREATE_FACET_VALUES,
  80. {
  81. input: [
  82. {
  83. facetId: speakerTypeFacet.id,
  84. code: 'pc',
  85. translations: [{ languageCode: LanguageCode.en, name: 'PC Speakers' }],
  86. },
  87. {
  88. facetId: speakerTypeFacet.id,
  89. code: 'hi-fi',
  90. translations: [{ languageCode: LanguageCode.en, name: 'Hi Fi Speakers' }],
  91. },
  92. ],
  93. },
  94. );
  95. expect(result.createFacetValues).toMatchSnapshot();
  96. });
  97. it('updateFacetValues', async () => {
  98. const result = await client.query<UpdateFacetValues.Mutation, UpdateFacetValues.Variables>(
  99. UPDATE_FACET_VALUES,
  100. {
  101. input: [
  102. {
  103. id: speakerTypeFacet.values[0].id,
  104. code: 'compact',
  105. },
  106. ],
  107. },
  108. );
  109. expect(result.updateFacetValues[0].code).toBe('compact');
  110. });
  111. it('facets', async () => {
  112. const result = await client.query<GetFacetList.Query>(GET_FACET_LIST);
  113. const { items } = result.facets;
  114. expect(items.length).toBe(2);
  115. expect(items[0].name).toBe('category');
  116. expect(items[1].name).toBe('Speaker Category');
  117. brandFacet = items[0];
  118. speakerTypeFacet = items[1];
  119. });
  120. it('facet', async () => {
  121. const result = await client.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
  122. GET_FACET_WITH_VALUES,
  123. {
  124. id: speakerTypeFacet.id,
  125. },
  126. );
  127. expect(result.facet!.name).toBe('Speaker Category');
  128. });
  129. describe('deletion', () => {
  130. let products: Array<GetProductList.Items & { variants: Array<{ id: string; name: string }> }>;
  131. beforeAll(async () => {
  132. // add the FacetValues to products and variants
  133. const result1 = await client.query(GET_PRODUCTS_LIST_WITH_VARIANTS);
  134. products = result1.products.items;
  135. await client.query<UpdateProduct.Mutation, UpdateProduct.Variables>(UPDATE_PRODUCT, {
  136. input: {
  137. id: products[0].id,
  138. facetValueIds: [speakerTypeFacet.values[0].id],
  139. },
  140. });
  141. await client.query<UpdateProductVariants.Mutation, UpdateProductVariants.Variables>(
  142. UPDATE_PRODUCT_VARIANTS,
  143. {
  144. input: [
  145. {
  146. id: products[0].variants[0].id,
  147. facetValueIds: [speakerTypeFacet.values[0].id],
  148. },
  149. ],
  150. },
  151. );
  152. await client.query<UpdateProduct.Mutation, UpdateProduct.Variables>(UPDATE_PRODUCT, {
  153. input: {
  154. id: products[1].id,
  155. facetValueIds: [speakerTypeFacet.values[1].id],
  156. },
  157. });
  158. });
  159. it('deleteFacetValues deletes unused facetValue', async () => {
  160. const facetValueToDelete = speakerTypeFacet.values[2];
  161. const result1 = await client.query(DELETE_FACET_VALUES, {
  162. ids: [facetValueToDelete.id],
  163. force: false,
  164. });
  165. const result2 = await client.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
  166. GET_FACET_WITH_VALUES,
  167. {
  168. id: speakerTypeFacet.id,
  169. },
  170. );
  171. expect(result1.deleteFacetValues).toEqual([
  172. {
  173. result: DeletionResult.DELETED,
  174. message: ``,
  175. },
  176. ]);
  177. expect(result2.facet!.values[0]).not.toEqual(facetValueToDelete);
  178. });
  179. it('deleteFacetValues for FacetValue in use returns NOT_DELETED', async () => {
  180. const facetValueToDelete = speakerTypeFacet.values[0];
  181. const result1 = await client.query(DELETE_FACET_VALUES, {
  182. ids: [facetValueToDelete.id],
  183. force: false,
  184. });
  185. const result2 = await client.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
  186. GET_FACET_WITH_VALUES,
  187. {
  188. id: speakerTypeFacet.id,
  189. },
  190. );
  191. expect(result1.deleteFacetValues).toEqual([
  192. {
  193. result: DeletionResult.NOT_DELETED,
  194. message: `The selected FacetValue is assigned to 1 Product, 1 ProductVariant`,
  195. },
  196. ]);
  197. expect(result2.facet!.values[0]).toEqual(facetValueToDelete);
  198. });
  199. it('deleteFacetValues for FacetValue in use can be force deleted', async () => {
  200. const facetValueToDelete = speakerTypeFacet.values[0];
  201. const result1 = await client.query(DELETE_FACET_VALUES, {
  202. ids: [facetValueToDelete.id],
  203. force: true,
  204. });
  205. expect(result1.deleteFacetValues).toEqual([
  206. {
  207. result: DeletionResult.DELETED,
  208. message: `The selected FacetValue was removed from 1 Product, 1 ProductVariant and deleted`,
  209. },
  210. ]);
  211. // FacetValue no longer in the Facet.values array
  212. const result2 = await client.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
  213. GET_FACET_WITH_VALUES,
  214. {
  215. id: speakerTypeFacet.id,
  216. },
  217. );
  218. expect(result2.facet!.values[0]).not.toEqual(facetValueToDelete);
  219. // FacetValue no longer in the Product.facetValues array
  220. const result3 = await client.query<
  221. GetProductWithVariants.Query,
  222. GetProductWithVariants.Variables
  223. >(GET_PRODUCT_WITH_VARIANTS, {
  224. id: products[0].id,
  225. });
  226. expect(result3.product!.facetValues).toEqual([]);
  227. });
  228. it('deleteFacet that is in use returns NOT_DELETED', async () => {
  229. const result1 = await client.query(DELETE_FACET, { id: speakerTypeFacet.id, force: false });
  230. const result2 = await client.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
  231. GET_FACET_WITH_VALUES,
  232. {
  233. id: speakerTypeFacet.id,
  234. },
  235. );
  236. expect(result1.deleteFacet).toEqual({
  237. result: DeletionResult.NOT_DELETED,
  238. message: `The selected Facet includes FacetValues which are assigned to 1 Product`,
  239. });
  240. expect(result2.facet).not.toBe(null);
  241. });
  242. it('deleteFacet that is in use can be force deleted', async () => {
  243. const result1 = await client.query(DELETE_FACET, { id: speakerTypeFacet.id, force: true });
  244. expect(result1.deleteFacet).toEqual({
  245. result: DeletionResult.DELETED,
  246. message: `The Facet was deleted and its FacetValues were removed from 1 Product`,
  247. });
  248. // FacetValue no longer in the Facet.values array
  249. const result2 = await client.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
  250. GET_FACET_WITH_VALUES,
  251. {
  252. id: speakerTypeFacet.id,
  253. },
  254. );
  255. expect(result2.facet).toBe(null);
  256. // FacetValue no longer in the Product.facetValues array
  257. const result3 = await client.query<
  258. GetProductWithVariants.Query,
  259. GetProductWithVariants.Variables
  260. >(GET_PRODUCT_WITH_VARIANTS, {
  261. id: products[1].id,
  262. });
  263. expect(result3.product!.facetValues).toEqual([]);
  264. });
  265. });
  266. });
  267. const DELETE_FACET_VALUES = gql`
  268. mutation DeleteFacetValue($ids: [ID!]!, $force: Boolean) {
  269. deleteFacetValues(ids: $ids, force: $force) {
  270. result
  271. message
  272. }
  273. }
  274. `;
  275. const DELETE_FACET = gql`
  276. mutation DeleteFacet($id: ID!, $force: Boolean) {
  277. deleteFacet(id: $id, force: $force) {
  278. result
  279. message
  280. }
  281. }
  282. `;
  283. const GET_PRODUCTS_LIST_WITH_VARIANTS = gql`
  284. query GetProductListWithVariants {
  285. products {
  286. items {
  287. id
  288. name
  289. variants {
  290. id
  291. name
  292. }
  293. }
  294. totalItems
  295. }
  296. }
  297. `;