facet.e2e-spec.ts 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. import gql from 'graphql-tag';
  2. import path from 'path';
  3. import { TEST_SETUP_TIMEOUT_MS } from './config/test-config';
  4. import { FACET_VALUE_FRAGMENT, FACET_WITH_VALUES_FRAGMENT } from './graphql/fragments';
  5. import {
  6. CreateFacet,
  7. CreateFacetValues,
  8. DeleteFacet,
  9. DeleteFacetValues,
  10. DeletionResult,
  11. FacetWithValues,
  12. GetFacetList,
  13. GetFacetWithValues,
  14. GetProductListWithVariants,
  15. GetProductWithVariants,
  16. LanguageCode,
  17. UpdateFacet,
  18. UpdateFacetValues,
  19. UpdateProduct,
  20. UpdateProductVariants,
  21. } from './graphql/generated-e2e-admin-types';
  22. import {
  23. CREATE_FACET,
  24. GET_FACET_LIST,
  25. GET_PRODUCT_WITH_VARIANTS,
  26. UPDATE_FACET,
  27. UPDATE_PRODUCT,
  28. UPDATE_PRODUCT_VARIANTS,
  29. } from './graphql/shared-definitions';
  30. import { TestAdminClient } from './test-client';
  31. import { TestServer } from './test-server';
  32. // tslint:disable:no-non-null-assertion
  33. describe('Facet resolver', () => {
  34. const client = new TestAdminClient();
  35. const server = new TestServer();
  36. let brandFacet: FacetWithValues.Fragment;
  37. let speakerTypeFacet: FacetWithValues.Fragment;
  38. beforeAll(async () => {
  39. await server.init({
  40. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-full.csv'),
  41. customerCount: 1,
  42. });
  43. await client.init();
  44. }, TEST_SETUP_TIMEOUT_MS);
  45. afterAll(async () => {
  46. await server.destroy();
  47. });
  48. it('createFacet', async () => {
  49. const result = await client.query<CreateFacet.Mutation, CreateFacet.Variables>(CREATE_FACET, {
  50. input: {
  51. isPrivate: false,
  52. code: 'speaker-type',
  53. translations: [{ languageCode: LanguageCode.en, name: 'Speaker Type' }],
  54. values: [
  55. {
  56. code: 'portable',
  57. translations: [{ languageCode: LanguageCode.en, name: 'Portable' }],
  58. },
  59. ],
  60. },
  61. });
  62. speakerTypeFacet = result.createFacet;
  63. expect(speakerTypeFacet).toMatchSnapshot();
  64. });
  65. it('updateFacet', async () => {
  66. const result = await client.query<UpdateFacet.Mutation, UpdateFacet.Variables>(UPDATE_FACET, {
  67. input: {
  68. id: speakerTypeFacet.id,
  69. translations: [{ languageCode: LanguageCode.en, name: 'Speaker Category' }],
  70. },
  71. });
  72. expect(result.updateFacet.name).toBe('Speaker Category');
  73. });
  74. it('createFacetValues', async () => {
  75. const result = await client.query<CreateFacetValues.Mutation, CreateFacetValues.Variables>(
  76. CREATE_FACET_VALUES,
  77. {
  78. input: [
  79. {
  80. facetId: speakerTypeFacet.id,
  81. code: 'pc',
  82. translations: [{ languageCode: LanguageCode.en, name: 'PC Speakers' }],
  83. },
  84. {
  85. facetId: speakerTypeFacet.id,
  86. code: 'hi-fi',
  87. translations: [{ languageCode: LanguageCode.en, name: 'Hi Fi Speakers' }],
  88. },
  89. ],
  90. },
  91. );
  92. expect(result.createFacetValues).toMatchSnapshot();
  93. });
  94. it('updateFacetValues', async () => {
  95. const result = await client.query<UpdateFacetValues.Mutation, UpdateFacetValues.Variables>(
  96. UPDATE_FACET_VALUES,
  97. {
  98. input: [
  99. {
  100. id: speakerTypeFacet.values[0].id,
  101. code: 'compact',
  102. },
  103. ],
  104. },
  105. );
  106. expect(result.updateFacetValues[0].code).toBe('compact');
  107. });
  108. it('facets', async () => {
  109. const result = await client.query<GetFacetList.Query>(GET_FACET_LIST);
  110. const { items } = result.facets;
  111. expect(items.length).toBe(2);
  112. expect(items[0].name).toBe('category');
  113. expect(items[1].name).toBe('Speaker Category');
  114. brandFacet = items[0];
  115. speakerTypeFacet = items[1];
  116. });
  117. it('facet', async () => {
  118. const result = await client.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
  119. GET_FACET_WITH_VALUES,
  120. {
  121. id: speakerTypeFacet.id,
  122. },
  123. );
  124. expect(result.facet!.name).toBe('Speaker Category');
  125. });
  126. describe('deletion', () => {
  127. let products: GetProductListWithVariants.Items[];
  128. beforeAll(async () => {
  129. // add the FacetValues to products and variants
  130. const result1 = await client.query<GetProductListWithVariants.Query>(
  131. GET_PRODUCTS_LIST_WITH_VARIANTS,
  132. );
  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<DeleteFacetValues.Mutation, DeleteFacetValues.Variables>(
  161. DELETE_FACET_VALUES,
  162. {
  163. ids: [facetValueToDelete.id],
  164. force: false,
  165. },
  166. );
  167. const result2 = await client.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
  168. GET_FACET_WITH_VALUES,
  169. {
  170. id: speakerTypeFacet.id,
  171. },
  172. );
  173. expect(result1.deleteFacetValues).toEqual([
  174. {
  175. result: DeletionResult.DELETED,
  176. message: ``,
  177. },
  178. ]);
  179. expect(result2.facet!.values[0]).not.toEqual(facetValueToDelete);
  180. });
  181. it('deleteFacetValues for FacetValue in use returns NOT_DELETED', async () => {
  182. const facetValueToDelete = speakerTypeFacet.values[0];
  183. const result1 = await client.query<DeleteFacetValues.Mutation, DeleteFacetValues.Variables>(
  184. DELETE_FACET_VALUES,
  185. {
  186. ids: [facetValueToDelete.id],
  187. force: false,
  188. },
  189. );
  190. const result2 = await client.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
  191. GET_FACET_WITH_VALUES,
  192. {
  193. id: speakerTypeFacet.id,
  194. },
  195. );
  196. expect(result1.deleteFacetValues).toEqual([
  197. {
  198. result: DeletionResult.NOT_DELETED,
  199. message: `The selected FacetValue is assigned to 1 Product, 1 ProductVariant`,
  200. },
  201. ]);
  202. expect(result2.facet!.values[0]).toEqual(facetValueToDelete);
  203. });
  204. it('deleteFacetValues for FacetValue in use can be force deleted', async () => {
  205. const facetValueToDelete = speakerTypeFacet.values[0];
  206. const result1 = await client.query<DeleteFacetValues.Mutation, DeleteFacetValues.Variables>(
  207. DELETE_FACET_VALUES,
  208. {
  209. ids: [facetValueToDelete.id],
  210. force: true,
  211. },
  212. );
  213. expect(result1.deleteFacetValues).toEqual([
  214. {
  215. result: DeletionResult.DELETED,
  216. message: `The selected FacetValue was removed from 1 Product, 1 ProductVariant and deleted`,
  217. },
  218. ]);
  219. // FacetValue no longer in the Facet.values array
  220. const result2 = await client.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
  221. GET_FACET_WITH_VALUES,
  222. {
  223. id: speakerTypeFacet.id,
  224. },
  225. );
  226. expect(result2.facet!.values[0]).not.toEqual(facetValueToDelete);
  227. // FacetValue no longer in the Product.facetValues array
  228. const result3 = await client.query<
  229. GetProductWithVariants.Query,
  230. GetProductWithVariants.Variables
  231. >(GET_PRODUCT_WITH_VARIANTS, {
  232. id: products[0].id,
  233. });
  234. expect(result3.product!.facetValues).toEqual([]);
  235. });
  236. it('deleteFacet that is in use returns NOT_DELETED', async () => {
  237. const result1 = await client.query<DeleteFacet.Mutation, DeleteFacet.Variables>(DELETE_FACET, {
  238. id: speakerTypeFacet.id,
  239. force: false,
  240. });
  241. const result2 = await client.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
  242. GET_FACET_WITH_VALUES,
  243. {
  244. id: speakerTypeFacet.id,
  245. },
  246. );
  247. expect(result1.deleteFacet).toEqual({
  248. result: DeletionResult.NOT_DELETED,
  249. message: `The selected Facet includes FacetValues which are assigned to 1 Product`,
  250. });
  251. expect(result2.facet).not.toBe(null);
  252. });
  253. it('deleteFacet that is in use can be force deleted', async () => {
  254. const result1 = await client.query<DeleteFacet.Mutation, DeleteFacet.Variables>(DELETE_FACET, {
  255. id: speakerTypeFacet.id,
  256. force: true,
  257. });
  258. expect(result1.deleteFacet).toEqual({
  259. result: DeletionResult.DELETED,
  260. message: `The Facet was deleted and its FacetValues were removed from 1 Product`,
  261. });
  262. // FacetValue no longer in the Facet.values array
  263. const result2 = await client.query<GetFacetWithValues.Query, GetFacetWithValues.Variables>(
  264. GET_FACET_WITH_VALUES,
  265. {
  266. id: speakerTypeFacet.id,
  267. },
  268. );
  269. expect(result2.facet).toBe(null);
  270. // FacetValue no longer in the Product.facetValues array
  271. const result3 = await client.query<
  272. GetProductWithVariants.Query,
  273. GetProductWithVariants.Variables
  274. >(GET_PRODUCT_WITH_VARIANTS, {
  275. id: products[1].id,
  276. });
  277. expect(result3.product!.facetValues).toEqual([]);
  278. });
  279. it('deleteFacet with no FacetValues works', async () => {
  280. const { createFacet } = await client.query<CreateFacet.Mutation, CreateFacet.Variables>(
  281. CREATE_FACET,
  282. {
  283. input: {
  284. code: 'test',
  285. isPrivate: false,
  286. translations: [{ languageCode: LanguageCode.en, name: 'Test' }],
  287. },
  288. },
  289. );
  290. const result = await client.query<DeleteFacet.Mutation, DeleteFacet.Variables>(DELETE_FACET, {
  291. id: createFacet.id,
  292. force: false,
  293. });
  294. expect(result.deleteFacet.result).toBe(DeletionResult.DELETED);
  295. });
  296. });
  297. });
  298. export const GET_FACET_WITH_VALUES = gql`
  299. query GetFacetWithValues($id: ID!) {
  300. facet(id: $id) {
  301. ...FacetWithValues
  302. }
  303. }
  304. ${FACET_WITH_VALUES_FRAGMENT}
  305. `;
  306. const DELETE_FACET_VALUES = gql`
  307. mutation DeleteFacetValues($ids: [ID!]!, $force: Boolean) {
  308. deleteFacetValues(ids: $ids, force: $force) {
  309. result
  310. message
  311. }
  312. }
  313. `;
  314. const DELETE_FACET = gql`
  315. mutation DeleteFacet($id: ID!, $force: Boolean) {
  316. deleteFacet(id: $id, force: $force) {
  317. result
  318. message
  319. }
  320. }
  321. `;
  322. const GET_PRODUCTS_LIST_WITH_VARIANTS = gql`
  323. query GetProductListWithVariants {
  324. products {
  325. items {
  326. id
  327. name
  328. variants {
  329. id
  330. name
  331. }
  332. }
  333. totalItems
  334. }
  335. }
  336. `;
  337. export const CREATE_FACET_VALUES = gql`
  338. mutation CreateFacetValues($input: [CreateFacetValueInput!]!) {
  339. createFacetValues(input: $input) {
  340. ...FacetValue
  341. }
  342. }
  343. ${FACET_VALUE_FRAGMENT}
  344. `;
  345. export const UPDATE_FACET_VALUES = gql`
  346. mutation UpdateFacetValues($input: [UpdateFacetValueInput!]!) {
  347. updateFacetValues(input: $input) {
  348. ...FacetValue
  349. }
  350. }
  351. ${FACET_VALUE_FRAGMENT}
  352. `;