facet.e2e-spec.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  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. code: 'speaker-type',
  55. translations: [{ languageCode: LanguageCode.en, name: 'Speaker Type' }],
  56. values: [
  57. {
  58. code: 'portable',
  59. translations: [{ languageCode: LanguageCode.en, name: 'Portable' }],
  60. },
  61. ],
  62. },
  63. });
  64. speakerTypeFacet = result.createFacet;
  65. expect(speakerTypeFacet).toMatchSnapshot();
  66. });
  67. it('updateFacet', async () => {
  68. const result = await client.query<UpdateFacet.Mutation, UpdateFacet.Variables>(UPDATE_FACET, {
  69. input: {
  70. id: speakerTypeFacet.id,
  71. translations: [{ languageCode: LanguageCode.en, name: 'Speaker Category' }],
  72. },
  73. });
  74. expect(result.updateFacet.name).toBe('Speaker Category');
  75. });
  76. it('createFacetValues', async () => {
  77. const result = await client.query<CreateFacetValues.Mutation, CreateFacetValues.Variables>(
  78. CREATE_FACET_VALUES,
  79. {
  80. input: [
  81. {
  82. facetId: speakerTypeFacet.id,
  83. code: 'pc',
  84. translations: [{ languageCode: LanguageCode.en, name: 'PC Speakers' }],
  85. },
  86. {
  87. facetId: speakerTypeFacet.id,
  88. code: 'hi-fi',
  89. translations: [{ languageCode: LanguageCode.en, name: 'Hi Fi Speakers' }],
  90. },
  91. ],
  92. },
  93. );
  94. expect(result.createFacetValues).toMatchSnapshot();
  95. });
  96. it('updateFacetValues', async () => {
  97. const result = await client.query<UpdateFacetValues.Mutation, UpdateFacetValues.Variables>(
  98. UPDATE_FACET_VALUES,
  99. {
  100. input: [
  101. {
  102. id: speakerTypeFacet.values[0].id,
  103. code: 'compact',
  104. },
  105. ],
  106. },
  107. );
  108. expect(result.updateFacetValues[0].code).toBe('compact');
  109. });
  110. it('facets', async () => {
  111. const result = await client.query<GetFacetList.Query>(GET_FACET_LIST);
  112. const { items } = result.facets;
  113. expect(items.length).toBe(2);
  114. expect(items[0].name).toBe('category');
  115. expect(items[1].name).toBe('Speaker Category');
  116. brandFacet = items[0];
  117. speakerTypeFacet = items[1];
  118. });
  119. it('facet', async () => {
  120. const result = await client.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
  121. GET_FACET_WITH_VALUES,
  122. {
  123. id: speakerTypeFacet.id,
  124. },
  125. );
  126. expect(result.facet!.name).toBe('Speaker Category');
  127. });
  128. describe('deletion', () => {
  129. let products: Array<GetProductList.Items & { variants: Array<{ id: string; name: string }> }>;
  130. beforeAll(async () => {
  131. // add the FacetValues to products and variants
  132. const result1 = await client.query(GET_PRODUCTS_LIST_WITH_VARIANTS);
  133. products = result1.products.items;
  134. await client.query<UpdateProduct.Mutation, UpdateProduct.Variables>(UPDATE_PRODUCT, {
  135. input: {
  136. id: products[0].id,
  137. facetValueIds: [speakerTypeFacet.values[0].id],
  138. },
  139. });
  140. await client.query<UpdateProductVariants.Mutation, UpdateProductVariants.Variables>(
  141. UPDATE_PRODUCT_VARIANTS,
  142. {
  143. input: [
  144. {
  145. id: products[0].variants[0].id,
  146. facetValueIds: [speakerTypeFacet.values[0].id],
  147. },
  148. ],
  149. },
  150. );
  151. await client.query<UpdateProduct.Mutation, UpdateProduct.Variables>(UPDATE_PRODUCT, {
  152. input: {
  153. id: products[1].id,
  154. facetValueIds: [speakerTypeFacet.values[1].id],
  155. },
  156. });
  157. });
  158. it('deleteFacetValues deletes unused facetValue', async () => {
  159. const facetValueToDelete = speakerTypeFacet.values[2];
  160. const result1 = await client.query(DELETE_FACET_VALUES, {
  161. ids: [facetValueToDelete.id],
  162. force: false,
  163. });
  164. const result2 = await client.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
  165. GET_FACET_WITH_VALUES,
  166. {
  167. id: speakerTypeFacet.id,
  168. },
  169. );
  170. expect(result1.deleteFacetValues).toEqual([
  171. {
  172. result: DeletionResult.DELETED,
  173. message: ``,
  174. },
  175. ]);
  176. expect(result2.facet!.values[0]).not.toEqual(facetValueToDelete);
  177. });
  178. it('deleteFacetValues for FacetValue in use returns NOT_DELETED', async () => {
  179. const facetValueToDelete = speakerTypeFacet.values[0];
  180. const result1 = await client.query(DELETE_FACET_VALUES, {
  181. ids: [facetValueToDelete.id],
  182. force: false,
  183. });
  184. const result2 = await client.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
  185. GET_FACET_WITH_VALUES,
  186. {
  187. id: speakerTypeFacet.id,
  188. },
  189. );
  190. expect(result1.deleteFacetValues).toEqual([
  191. {
  192. result: DeletionResult.NOT_DELETED,
  193. message: `The selected FacetValue is assigned to 1 Product, 1 ProductVariant`,
  194. },
  195. ]);
  196. expect(result2.facet!.values[0]).toEqual(facetValueToDelete);
  197. });
  198. it('deleteFacetValues for FacetValue in use can be force deleted', async () => {
  199. const facetValueToDelete = speakerTypeFacet.values[0];
  200. const result1 = await client.query(DELETE_FACET_VALUES, {
  201. ids: [facetValueToDelete.id],
  202. force: true,
  203. });
  204. expect(result1.deleteFacetValues).toEqual([
  205. {
  206. result: DeletionResult.DELETED,
  207. message: `The selected FacetValue was removed from 1 Product, 1 ProductVariant and deleted`,
  208. },
  209. ]);
  210. // FacetValue no longer in the Facet.values array
  211. const result2 = await client.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
  212. GET_FACET_WITH_VALUES,
  213. {
  214. id: speakerTypeFacet.id,
  215. },
  216. );
  217. expect(result2.facet!.values[0]).not.toEqual(facetValueToDelete);
  218. // FacetValue no longer in the Product.facetValues array
  219. const result3 = await client.query<
  220. GetProductWithVariants.Query,
  221. GetProductWithVariants.Variables
  222. >(GET_PRODUCT_WITH_VARIANTS, {
  223. id: products[0].id,
  224. });
  225. expect(result3.product!.facetValues).toEqual([]);
  226. });
  227. it('deleteFacet that is in use returns NOT_DELETED', async () => {
  228. const result1 = await client.query(DELETE_FACET, { id: speakerTypeFacet.id, force: false });
  229. const result2 = await client.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
  230. GET_FACET_WITH_VALUES,
  231. {
  232. id: speakerTypeFacet.id,
  233. },
  234. );
  235. expect(result1.deleteFacet).toEqual({
  236. result: DeletionResult.NOT_DELETED,
  237. message: `The selected Facet includes FacetValues which are assigned to 1 Product`,
  238. });
  239. expect(result2.facet).not.toBe(null);
  240. });
  241. it('deleteFacet that is in use can be force deleted', async () => {
  242. const result1 = await client.query(DELETE_FACET, { id: speakerTypeFacet.id, force: true });
  243. expect(result1.deleteFacet).toEqual({
  244. result: DeletionResult.DELETED,
  245. message: `The Facet was deleted and its FacetValues were removed from 1 Product`,
  246. });
  247. // FacetValue no longer in the Facet.values array
  248. const result2 = await client.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
  249. GET_FACET_WITH_VALUES,
  250. {
  251. id: speakerTypeFacet.id,
  252. },
  253. );
  254. expect(result2.facet).toBe(null);
  255. // FacetValue no longer in the Product.facetValues array
  256. const result3 = await client.query<
  257. GetProductWithVariants.Query,
  258. GetProductWithVariants.Variables
  259. >(GET_PRODUCT_WITH_VARIANTS, {
  260. id: products[1].id,
  261. });
  262. expect(result3.product!.facetValues).toEqual([]);
  263. });
  264. });
  265. });
  266. const DELETE_FACET_VALUES = gql`
  267. mutation DeleteFacetValue($ids: [ID!]!, $force: Boolean) {
  268. deleteFacetValues(ids: $ids, force: $force) {
  269. result
  270. message
  271. }
  272. }
  273. `;
  274. const DELETE_FACET = gql`
  275. mutation DeleteFacet($id: ID!, $force: Boolean) {
  276. deleteFacet(id: $id, force: $force) {
  277. result
  278. message
  279. }
  280. }
  281. `;
  282. const GET_PRODUCTS_LIST_WITH_VARIANTS = gql`
  283. query GetProductListWithVariants {
  284. products {
  285. items {
  286. id
  287. name
  288. variants {
  289. id
  290. name
  291. }
  292. }
  293. totalItems
  294. }
  295. }
  296. `;