promotion.e2e-spec.ts 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. import { pick } from '@vendure/common/lib/pick';
  2. import gql from 'graphql-tag';
  3. import path from 'path';
  4. import { LanguageCode } from '../../common/lib/generated-types';
  5. import { PromotionAction, PromotionOrderAction } from '../src/config/promotion/promotion-action';
  6. import { PromotionCondition } from '../src/config/promotion/promotion-condition';
  7. import { TEST_SETUP_TIMEOUT_MS } from './config/test-config';
  8. import { PROMOTION_FRAGMENT } from './graphql/fragments';
  9. import {
  10. CreatePromotion,
  11. DeletePromotion,
  12. DeletionResult,
  13. GetAdjustmentOperations,
  14. GetPromotion,
  15. GetPromotionList,
  16. Promotion,
  17. UpdatePromotion,
  18. } from './graphql/generated-e2e-admin-types';
  19. import { TestAdminClient } from './test-client';
  20. import { TestServer } from './test-server';
  21. import { assertThrowsWithMessage } from './utils/assert-throws-with-message';
  22. // tslint:disable:no-non-null-assertion
  23. describe('Promotion resolver', () => {
  24. const client = new TestAdminClient();
  25. const server = new TestServer();
  26. const promoCondition = generateTestCondition('promo_condition');
  27. const promoCondition2 = generateTestCondition('promo_condition2');
  28. const promoAction = generateTestAction('promo_action');
  29. const snapshotProps = ['name', 'actions', 'conditions', 'enabled'] as Array<
  30. 'name' | 'actions' | 'conditions' | 'enabled'
  31. >;
  32. let promotion: Promotion.Fragment;
  33. beforeAll(async () => {
  34. await server.init(
  35. {
  36. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-minimal.csv'),
  37. customerCount: 1,
  38. },
  39. {
  40. promotionOptions: {
  41. promotionConditions: [promoCondition, promoCondition2],
  42. promotionActions: [promoAction],
  43. },
  44. },
  45. );
  46. await client.init();
  47. }, TEST_SETUP_TIMEOUT_MS);
  48. afterAll(async () => {
  49. await server.destroy();
  50. });
  51. it('createPromotion', async () => {
  52. const result = await client.query<CreatePromotion.Mutation, CreatePromotion.Variables>(
  53. CREATE_PROMOTION,
  54. {
  55. input: {
  56. name: 'test promotion',
  57. enabled: true,
  58. conditions: [
  59. {
  60. code: promoCondition.code,
  61. arguments: [{ name: 'arg', value: '500', type: 'int' }],
  62. },
  63. ],
  64. actions: [
  65. {
  66. code: promoAction.code,
  67. arguments: [
  68. {
  69. name: 'facetValueIds',
  70. value: '["T_1"]',
  71. type: 'facetValueIds',
  72. },
  73. ],
  74. },
  75. ],
  76. },
  77. },
  78. );
  79. promotion = result.createPromotion;
  80. expect(pick(promotion, snapshotProps)).toMatchSnapshot();
  81. });
  82. it('updatePromotion', async () => {
  83. const result = await client.query<UpdatePromotion.Mutation, UpdatePromotion.Variables>(
  84. UPDATE_PROMOTION,
  85. {
  86. input: {
  87. id: promotion.id,
  88. conditions: [
  89. {
  90. code: promoCondition.code,
  91. arguments: [{ name: 'arg', value: '90', type: 'int' }],
  92. },
  93. {
  94. code: promoCondition2.code,
  95. arguments: [{ name: 'arg', value: '10', type: 'int' }],
  96. },
  97. ],
  98. },
  99. },
  100. );
  101. expect(pick(result.updatePromotion, snapshotProps)).toMatchSnapshot();
  102. });
  103. it('promotion', async () => {
  104. const result = await client.query<GetPromotion.Query, GetPromotion.Variables>(GET_PROMOTION, {
  105. id: promotion.id,
  106. });
  107. expect(result.promotion!.name).toBe(promotion.name);
  108. });
  109. it('promotions', async () => {
  110. const result = await client.query<GetPromotionList.Query, GetPromotionList.Variables>(
  111. GET_PROMOTION_LIST,
  112. {},
  113. );
  114. expect(result.promotions.totalItems).toBe(1);
  115. expect(result.promotions.items[0].name).toBe('test promotion');
  116. });
  117. it('adjustmentOperations', async () => {
  118. const result = await client.query<GetAdjustmentOperations.Query, GetAdjustmentOperations.Variables>(
  119. GET_ADJUSTMENT_OPERATIONS,
  120. );
  121. expect(result.promotionActions).toMatchSnapshot();
  122. expect(result.promotionConditions).toMatchSnapshot();
  123. });
  124. describe('deletion', () => {
  125. let allPromotions: GetPromotionList.Items[];
  126. let promotionToDelete: GetPromotionList.Items;
  127. beforeAll(async () => {
  128. const result = await client.query<GetPromotionList.Query>(GET_PROMOTION_LIST);
  129. allPromotions = result.promotions.items;
  130. });
  131. it('deletes a promotion', async () => {
  132. promotionToDelete = allPromotions[0];
  133. const result = await client.query<DeletePromotion.Mutation, DeletePromotion.Variables>(
  134. DELETE_PROMOTION,
  135. { id: promotionToDelete.id },
  136. );
  137. expect(result.deletePromotion).toEqual({ result: DeletionResult.DELETED });
  138. });
  139. it('cannot get a deleted promotion', async () => {
  140. const result = await client.query<GetPromotion.Query, GetPromotion.Variables>(GET_PROMOTION, {
  141. id: promotionToDelete.id,
  142. });
  143. expect(result.promotion).toBe(null);
  144. });
  145. it('deleted promotion omitted from list', async () => {
  146. const result = await client.query<GetPromotionList.Query>(GET_PROMOTION_LIST);
  147. expect(result.promotions.items.length).toBe(allPromotions.length - 1);
  148. expect(result.promotions.items.map(c => c.id).includes(promotionToDelete.id)).toBe(false);
  149. });
  150. it(
  151. 'updatePromotion throws for deleted promotion',
  152. assertThrowsWithMessage(
  153. () =>
  154. client.query<UpdatePromotion.Mutation, UpdatePromotion.Variables>(UPDATE_PROMOTION, {
  155. input: {
  156. id: promotionToDelete.id,
  157. enabled: false,
  158. },
  159. }),
  160. `No Promotion with the id '1' could be found`,
  161. ),
  162. );
  163. });
  164. });
  165. function generateTestCondition(code: string): PromotionCondition<any> {
  166. return new PromotionCondition({
  167. code,
  168. description: [{ languageCode: LanguageCode.en, value: `description for ${code}` }],
  169. args: { arg: { type: 'int' } },
  170. check: (order, args) => true,
  171. });
  172. }
  173. function generateTestAction(code: string): PromotionAction<any> {
  174. return new PromotionOrderAction({
  175. code,
  176. description: [{ languageCode: LanguageCode.en, value: `description for ${code}` }],
  177. args: { facetValueIds: { type: 'facetValueIds' } },
  178. execute: (order, args) => {
  179. return 42;
  180. },
  181. });
  182. }
  183. const DELETE_PROMOTION = gql`
  184. mutation DeletePromotion($id: ID!) {
  185. deletePromotion(id: $id) {
  186. result
  187. }
  188. }
  189. `;
  190. export const GET_PROMOTION_LIST = gql`
  191. query GetPromotionList($options: PromotionListOptions) {
  192. promotions(options: $options) {
  193. items {
  194. ...Promotion
  195. }
  196. totalItems
  197. }
  198. }
  199. ${PROMOTION_FRAGMENT}
  200. `;
  201. export const GET_PROMOTION = gql`
  202. query GetPromotion($id: ID!) {
  203. promotion(id: $id) {
  204. ...Promotion
  205. }
  206. }
  207. ${PROMOTION_FRAGMENT}
  208. `;
  209. export const CREATE_PROMOTION = gql`
  210. mutation CreatePromotion($input: CreatePromotionInput!) {
  211. createPromotion(input: $input) {
  212. ...Promotion
  213. }
  214. }
  215. ${PROMOTION_FRAGMENT}
  216. `;
  217. export const UPDATE_PROMOTION = gql`
  218. mutation UpdatePromotion($input: UpdatePromotionInput!) {
  219. updatePromotion(input: $input) {
  220. ...Promotion
  221. }
  222. }
  223. ${PROMOTION_FRAGMENT}
  224. `;
  225. export const CONFIGURABLE_DEF_FRAGMENT = gql`
  226. fragment ConfigurableOperationDef on ConfigurableOperationDefinition {
  227. args {
  228. name
  229. type
  230. config
  231. }
  232. code
  233. description
  234. }
  235. `;
  236. export const GET_ADJUSTMENT_OPERATIONS = gql`
  237. query GetAdjustmentOperations {
  238. promotionActions {
  239. ...ConfigurableOperationDef
  240. }
  241. promotionConditions {
  242. ...ConfigurableOperationDef
  243. }
  244. }
  245. ${CONFIGURABLE_DEF_FRAGMENT}
  246. `;