channel.e2e-spec.ts 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /* tslint:disable:no-non-null-assertion */
  2. import { DEFAULT_CHANNEL_CODE } from '@vendure/common/lib/shared-constants';
  3. import {
  4. createErrorResultGuard,
  5. createTestEnvironment,
  6. E2E_DEFAULT_CHANNEL_TOKEN,
  7. ErrorResultGuard,
  8. } from '@vendure/testing';
  9. import gql from 'graphql-tag';
  10. import path from 'path';
  11. import { initialData } from '../../../e2e-common/e2e-initial-data';
  12. import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
  13. import {
  14. AssignProductsToChannel,
  15. ChannelFragment,
  16. CreateAdministrator,
  17. CreateChannel,
  18. CreateRole,
  19. CurrencyCode,
  20. DeleteChannel,
  21. DeletionResult,
  22. ErrorCode,
  23. GetChannels,
  24. GetCustomerList,
  25. GetProductWithVariants,
  26. LanguageCode,
  27. Me,
  28. Permission,
  29. UpdateChannel,
  30. UpdateGlobalLanguages,
  31. } from './graphql/generated-e2e-admin-types';
  32. import {
  33. ASSIGN_PRODUCT_TO_CHANNEL,
  34. CREATE_ADMINISTRATOR,
  35. CREATE_CHANNEL,
  36. CREATE_ROLE,
  37. GET_CUSTOMER_LIST,
  38. GET_PRODUCT_WITH_VARIANTS,
  39. ME,
  40. UPDATE_CHANNEL,
  41. } from './graphql/shared-definitions';
  42. import { assertThrowsWithMessage } from './utils/assert-throws-with-message';
  43. describe('Channels', () => {
  44. const { server, adminClient, shopClient } = createTestEnvironment(testConfig);
  45. const SECOND_CHANNEL_TOKEN = 'second_channel_token';
  46. let secondChannelAdminRole: CreateRole.CreateRole;
  47. let customerUser: GetCustomerList.Items;
  48. const channelGuard: ErrorResultGuard<ChannelFragment> = createErrorResultGuard<ChannelFragment>(
  49. input => !!input.defaultLanguageCode,
  50. );
  51. beforeAll(async () => {
  52. await server.init({
  53. initialData,
  54. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-full.csv'),
  55. customerCount: 1,
  56. });
  57. await adminClient.asSuperAdmin();
  58. const { customers } = await adminClient.query<GetCustomerList.Query, GetCustomerList.Variables>(
  59. GET_CUSTOMER_LIST,
  60. {
  61. options: { take: 1 },
  62. },
  63. );
  64. customerUser = customers.items[0];
  65. }, TEST_SETUP_TIMEOUT_MS);
  66. afterAll(async () => {
  67. await server.destroy();
  68. });
  69. it('createChannel returns error result defaultLanguageCode not available', async () => {
  70. const { createChannel } = await adminClient.query<CreateChannel.Mutation, CreateChannel.Variables>(
  71. CREATE_CHANNEL,
  72. {
  73. input: {
  74. code: 'second-channel',
  75. token: SECOND_CHANNEL_TOKEN,
  76. defaultLanguageCode: LanguageCode.zh,
  77. currencyCode: CurrencyCode.GBP,
  78. pricesIncludeTax: true,
  79. defaultShippingZoneId: 'T_1',
  80. defaultTaxZoneId: 'T_1',
  81. },
  82. },
  83. );
  84. channelGuard.assertErrorResult(createChannel);
  85. expect(createChannel.message).toBe(
  86. 'Language "zh" is not available. First enable it via GlobalSettings and try again',
  87. );
  88. expect(createChannel.errorCode).toBe(ErrorCode.LANGUAGE_NOT_AVAILABLE_ERROR);
  89. expect(createChannel.languageCode).toBe('zh');
  90. });
  91. it('create a new Channel', async () => {
  92. const { createChannel } = await adminClient.query<CreateChannel.Mutation, CreateChannel.Variables>(
  93. CREATE_CHANNEL,
  94. {
  95. input: {
  96. code: 'second-channel',
  97. token: SECOND_CHANNEL_TOKEN,
  98. defaultLanguageCode: LanguageCode.en,
  99. currencyCode: CurrencyCode.GBP,
  100. pricesIncludeTax: true,
  101. defaultShippingZoneId: 'T_1',
  102. defaultTaxZoneId: 'T_1',
  103. },
  104. },
  105. );
  106. channelGuard.assertSuccess(createChannel);
  107. expect(createChannel).toEqual({
  108. id: 'T_2',
  109. code: 'second-channel',
  110. token: SECOND_CHANNEL_TOKEN,
  111. currencyCode: 'GBP',
  112. defaultLanguageCode: 'en',
  113. defaultShippingZone: {
  114. id: 'T_1',
  115. },
  116. defaultTaxZone: {
  117. id: 'T_1',
  118. },
  119. pricesIncludeTax: true,
  120. });
  121. });
  122. it('superadmin has all permissions on new channel', async () => {
  123. const { me } = await adminClient.query<Me.Query>(ME);
  124. expect(me!.channels.length).toBe(2);
  125. const secondChannelData = me!.channels.find(c => c.token === SECOND_CHANNEL_TOKEN);
  126. const nonOwnerPermissions = Object.values(Permission).filter(
  127. p => p !== Permission.Owner && p !== Permission.Public,
  128. );
  129. expect(secondChannelData!.permissions).toEqual(nonOwnerPermissions);
  130. });
  131. it('customer has Authenticated permission on new channel', async () => {
  132. await shopClient.asUserWithCredentials(customerUser.emailAddress, 'test');
  133. const { me } = await shopClient.query<Me.Query>(ME);
  134. expect(me!.channels.length).toBe(2);
  135. const secondChannelData = me!.channels.find(c => c.token === SECOND_CHANNEL_TOKEN);
  136. expect(me!.channels).toEqual([
  137. {
  138. code: DEFAULT_CHANNEL_CODE,
  139. permissions: ['Authenticated'],
  140. token: E2E_DEFAULT_CHANNEL_TOKEN,
  141. },
  142. {
  143. code: 'second-channel',
  144. permissions: ['Authenticated'],
  145. token: SECOND_CHANNEL_TOKEN,
  146. },
  147. ]);
  148. });
  149. it('createRole on second Channel', async () => {
  150. const { createRole } = await adminClient.query<CreateRole.Mutation, CreateRole.Variables>(
  151. CREATE_ROLE,
  152. {
  153. input: {
  154. description: 'second channel admin',
  155. code: 'second-channel-admin',
  156. channelIds: ['T_2'],
  157. permissions: [
  158. Permission.ReadCatalog,
  159. Permission.ReadSettings,
  160. Permission.ReadAdministrator,
  161. Permission.CreateAdministrator,
  162. Permission.UpdateAdministrator,
  163. ],
  164. },
  165. },
  166. );
  167. expect(createRole.channels).toEqual([
  168. {
  169. id: 'T_2',
  170. code: 'second-channel',
  171. token: SECOND_CHANNEL_TOKEN,
  172. },
  173. ]);
  174. secondChannelAdminRole = createRole;
  175. });
  176. it('createAdministrator with second-channel-admin role', async () => {
  177. const { createAdministrator } = await adminClient.query<
  178. CreateAdministrator.Mutation,
  179. CreateAdministrator.Variables
  180. >(CREATE_ADMINISTRATOR, {
  181. input: {
  182. firstName: 'Admin',
  183. lastName: 'Two',
  184. emailAddress: 'admin2@test.com',
  185. password: 'test',
  186. roleIds: [secondChannelAdminRole.id],
  187. },
  188. });
  189. expect(createAdministrator.user.roles.map(r => r.description)).toEqual(['second channel admin']);
  190. });
  191. it(
  192. 'cannot create role on channel for which admin does not have CreateAdministrator permission',
  193. assertThrowsWithMessage(async () => {
  194. await adminClient.asUserWithCredentials('admin2@test.com', 'test');
  195. await adminClient.query<CreateRole.Mutation, CreateRole.Variables>(CREATE_ROLE, {
  196. input: {
  197. description: 'read default channel catalog',
  198. code: 'read default channel catalog',
  199. channelIds: ['T_1'],
  200. permissions: [Permission.ReadCatalog],
  201. },
  202. });
  203. }, 'You are not currently authorized to perform this action'),
  204. );
  205. it('can create role on channel for which admin has CreateAdministrator permission', async () => {
  206. const { createRole } = await adminClient.query<CreateRole.Mutation, CreateRole.Variables>(
  207. CREATE_ROLE,
  208. {
  209. input: {
  210. description: 'read second channel catalog',
  211. code: 'read-second-channel-catalog',
  212. channelIds: ['T_2'],
  213. permissions: [Permission.ReadCatalog],
  214. },
  215. },
  216. );
  217. expect(createRole.channels).toEqual([
  218. {
  219. id: 'T_2',
  220. code: 'second-channel',
  221. token: SECOND_CHANNEL_TOKEN,
  222. },
  223. ]);
  224. });
  225. it('createRole with no channelId implicitly uses active channel', async () => {
  226. const { createRole } = await adminClient.query<CreateRole.Mutation, CreateRole.Variables>(
  227. CREATE_ROLE,
  228. {
  229. input: {
  230. description: 'update second channel catalog',
  231. code: 'update-second-channel-catalog',
  232. permissions: [Permission.UpdateCatalog],
  233. },
  234. },
  235. );
  236. expect(createRole.channels).toEqual([
  237. {
  238. id: 'T_2',
  239. code: 'second-channel',
  240. token: SECOND_CHANNEL_TOKEN,
  241. },
  242. ]);
  243. });
  244. describe('setting defaultLanguage', () => {
  245. it('returns error result if languageCode not in availableLanguages', async () => {
  246. await adminClient.asSuperAdmin();
  247. await adminClient.setChannelToken(E2E_DEFAULT_CHANNEL_TOKEN);
  248. const { updateChannel } = await adminClient.query<
  249. UpdateChannel.Mutation,
  250. UpdateChannel.Variables
  251. >(UPDATE_CHANNEL, {
  252. input: {
  253. id: 'T_1',
  254. defaultLanguageCode: LanguageCode.zh,
  255. },
  256. });
  257. channelGuard.assertErrorResult(updateChannel);
  258. expect(updateChannel.message).toBe(
  259. 'Language "zh" is not available. First enable it via GlobalSettings and try again',
  260. );
  261. expect(updateChannel.errorCode).toBe(ErrorCode.LANGUAGE_NOT_AVAILABLE_ERROR);
  262. expect(updateChannel.languageCode).toBe('zh');
  263. });
  264. it('allows setting to an available language', async () => {
  265. await adminClient.asSuperAdmin();
  266. await adminClient.setChannelToken(E2E_DEFAULT_CHANNEL_TOKEN);
  267. await adminClient.query<UpdateGlobalLanguages.Mutation, UpdateGlobalLanguages.Variables>(
  268. UPDATE_GLOBAL_LANGUAGES,
  269. {
  270. input: {
  271. availableLanguages: [LanguageCode.en, LanguageCode.zh],
  272. },
  273. },
  274. );
  275. const { updateChannel } = await adminClient.query<
  276. UpdateChannel.Mutation,
  277. UpdateChannel.Variables
  278. >(UPDATE_CHANNEL, {
  279. input: {
  280. id: 'T_1',
  281. defaultLanguageCode: LanguageCode.zh,
  282. },
  283. });
  284. expect(updateChannel.defaultLanguageCode).toBe(LanguageCode.zh);
  285. });
  286. });
  287. it('deleteChannel', async () => {
  288. const PROD_ID = 'T_1';
  289. await adminClient.asSuperAdmin();
  290. await adminClient.setChannelToken(E2E_DEFAULT_CHANNEL_TOKEN);
  291. const { assignProductsToChannel } = await adminClient.query<
  292. AssignProductsToChannel.Mutation,
  293. AssignProductsToChannel.Variables
  294. >(ASSIGN_PRODUCT_TO_CHANNEL, {
  295. input: {
  296. channelId: 'T_2',
  297. productIds: [PROD_ID],
  298. },
  299. });
  300. expect(assignProductsToChannel[0].channels.map(c => c.id).sort()).toEqual(['T_1', 'T_2']);
  301. const { deleteChannel } = await adminClient.query<DeleteChannel.Mutation, DeleteChannel.Variables>(
  302. DELETE_CHANNEL,
  303. {
  304. id: 'T_2',
  305. },
  306. );
  307. expect(deleteChannel.result).toBe(DeletionResult.DELETED);
  308. const { channels } = await adminClient.query<GetChannels.Query>(GET_CHANNELS);
  309. expect(channels.map(c => c.id).sort()).toEqual(['T_1']);
  310. const { product } = await adminClient.query<
  311. GetProductWithVariants.Query,
  312. GetProductWithVariants.Variables
  313. >(GET_PRODUCT_WITH_VARIANTS, {
  314. id: PROD_ID,
  315. });
  316. expect(product!.channels.map(c => c.id)).toEqual(['T_1']);
  317. });
  318. });
  319. const GET_CHANNELS = gql`
  320. query GetChannels {
  321. channels {
  322. id
  323. code
  324. token
  325. }
  326. }
  327. `;
  328. const DELETE_CHANNEL = gql`
  329. mutation DeleteChannel($id: ID!) {
  330. deleteChannel(id: $id) {
  331. message
  332. result
  333. }
  334. }
  335. `;
  336. const UPDATE_GLOBAL_LANGUAGES = gql`
  337. mutation UpdateGlobalLanguages($input: UpdateGlobalSettingsInput!) {
  338. updateGlobalSettings(input: $input) {
  339. ... on GlobalSettings {
  340. id
  341. availableLanguages
  342. }
  343. }
  344. }
  345. `;