custom-field-relations.e2e-spec.ts 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867
  1. import {
  2. Asset,
  3. Collection,
  4. Country,
  5. CustomFields,
  6. defaultShippingCalculator,
  7. defaultShippingEligibilityChecker,
  8. Facet,
  9. FacetValue,
  10. manualFulfillmentHandler,
  11. mergeConfig,
  12. Product,
  13. ProductOption,
  14. ProductOptionGroup,
  15. ProductVariant,
  16. ShippingMethod,
  17. } from '@vendure/core';
  18. import { createTestEnvironment } from '@vendure/testing';
  19. import gql from 'graphql-tag';
  20. import path from 'path';
  21. import { initialData } from '../../../e2e-common/e2e-initial-data';
  22. import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
  23. import { AddItemToOrder } from './graphql/generated-e2e-shop-types';
  24. import { ADD_ITEM_TO_ORDER } from './graphql/shop-definitions';
  25. import { sortById } from './utils/test-order-utils';
  26. // From https://github.com/microsoft/TypeScript/issues/13298#issuecomment-654906323
  27. // to ensure that we _always_ test all entities which support custom fields
  28. type ValueOf<T> = T[keyof T];
  29. type NonEmptyArray<T> = [T, ...T[]];
  30. type MustInclude<T, U extends T[]> = [T] extends [ValueOf<U>] ? U : never;
  31. const enumerate =
  32. <T>() =>
  33. <U extends NonEmptyArray<T>>(...elements: MustInclude<T, U>) =>
  34. elements;
  35. const entitiesWithCustomFields = enumerate<keyof CustomFields>()(
  36. 'Address',
  37. 'Administrator',
  38. 'Asset',
  39. 'Channel',
  40. 'Collection',
  41. 'Customer',
  42. 'Facet',
  43. 'FacetValue',
  44. 'Fulfillment',
  45. 'GlobalSettings',
  46. 'Order',
  47. 'OrderLine',
  48. 'Product',
  49. 'ProductOption',
  50. 'ProductOptionGroup',
  51. 'ProductVariant',
  52. 'User',
  53. 'ShippingMethod',
  54. );
  55. const customFieldConfig: CustomFields = {};
  56. for (const entity of entitiesWithCustomFields) {
  57. customFieldConfig[entity] = [
  58. { name: 'single', type: 'relation', entity: Asset, graphQLType: 'Asset', list: false },
  59. { name: 'multi', type: 'relation', entity: Asset, graphQLType: 'Asset', list: true },
  60. ];
  61. }
  62. customFieldConfig.Product?.push(
  63. { name: 'cfCollection', type: 'relation', entity: Collection, list: false },
  64. { name: 'cfCountry', type: 'relation', entity: Country, list: false },
  65. { name: 'cfFacetValue', type: 'relation', entity: FacetValue, list: false },
  66. { name: 'cfFacet', type: 'relation', entity: Facet, list: false },
  67. { name: 'cfProductOptionGroup', type: 'relation', entity: ProductOptionGroup, list: false },
  68. { name: 'cfProductOption', type: 'relation', entity: ProductOption, list: false },
  69. { name: 'cfProductVariant', type: 'relation', entity: ProductVariant, list: false },
  70. { name: 'cfProduct', type: 'relation', entity: Product, list: false },
  71. { name: 'cfShippingMethod', type: 'relation', entity: ShippingMethod, list: false },
  72. { name: 'cfInternalAsset', type: 'relation', entity: Asset, list: false, internal: true },
  73. );
  74. const customConfig = mergeConfig(testConfig(), {
  75. dbConnectionOptions: {
  76. timezone: 'Z',
  77. },
  78. customFields: customFieldConfig,
  79. });
  80. describe('Custom field relations', () => {
  81. const { server, adminClient, shopClient } = createTestEnvironment(customConfig);
  82. beforeAll(async () => {
  83. await server.init({
  84. initialData,
  85. productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-full.csv'),
  86. customerCount: 3,
  87. });
  88. await adminClient.asSuperAdmin();
  89. }, TEST_SETUP_TIMEOUT_MS);
  90. afterAll(async () => {
  91. await server.destroy();
  92. });
  93. it('customFieldConfig query returns entity and scalar fields', async () => {
  94. const { globalSettings } = await adminClient.query(gql`
  95. query {
  96. globalSettings {
  97. serverConfig {
  98. customFieldConfig {
  99. Customer {
  100. ... on RelationCustomFieldConfig {
  101. name
  102. entity
  103. scalarFields
  104. }
  105. }
  106. }
  107. }
  108. }
  109. }
  110. `);
  111. const single = globalSettings.serverConfig.customFieldConfig.Customer[0];
  112. expect(single.entity).toBe('Asset');
  113. expect(single.scalarFields).toEqual([
  114. 'id',
  115. 'createdAt',
  116. 'updatedAt',
  117. 'name',
  118. 'type',
  119. 'fileSize',
  120. 'mimeType',
  121. 'width',
  122. 'height',
  123. 'source',
  124. 'preview',
  125. ]);
  126. });
  127. describe('special data resolution', () => {
  128. let productId: string;
  129. it('translatable entities get translated', async () => {
  130. const { createProduct } = await adminClient.query(gql`
  131. mutation {
  132. createProduct(
  133. input: {
  134. translations: [
  135. {
  136. languageCode: en
  137. name: "Test product"
  138. description: ""
  139. slug: "test-product"
  140. }
  141. ]
  142. customFields: {
  143. cfCollectionId: "T_1"
  144. cfCountryId: "T_1"
  145. cfFacetValueId: "T_1"
  146. cfFacetId: "T_1"
  147. cfProductOptionGroupId: "T_1"
  148. cfProductOptionId: "T_1"
  149. cfProductVariantId: "T_1"
  150. cfProductId: "T_1"
  151. cfShippingMethodId: "T_1"
  152. }
  153. }
  154. ) {
  155. id
  156. customFields {
  157. cfCollection {
  158. languageCode
  159. name
  160. }
  161. cfCountry {
  162. languageCode
  163. name
  164. }
  165. cfFacetValue {
  166. languageCode
  167. name
  168. }
  169. cfFacet {
  170. languageCode
  171. name
  172. }
  173. cfProductOptionGroup {
  174. languageCode
  175. name
  176. }
  177. cfProductOption {
  178. languageCode
  179. name
  180. }
  181. cfProductVariant {
  182. languageCode
  183. name
  184. }
  185. cfProduct {
  186. languageCode
  187. name
  188. }
  189. cfShippingMethod {
  190. name
  191. }
  192. }
  193. }
  194. }
  195. `);
  196. productId = createProduct.id;
  197. expect(createProduct.customFields.cfCollection).toEqual({
  198. languageCode: 'en',
  199. name: '__root_collection__',
  200. });
  201. expect(createProduct.customFields.cfCountry).toEqual({ languageCode: 'en', name: 'Australia' });
  202. expect(createProduct.customFields.cfFacetValue).toEqual({
  203. languageCode: 'en',
  204. name: 'electronics',
  205. });
  206. expect(createProduct.customFields.cfFacet).toEqual({ languageCode: 'en', name: 'category' });
  207. expect(createProduct.customFields.cfProductOptionGroup).toEqual({
  208. languageCode: 'en',
  209. name: 'screen size',
  210. });
  211. expect(createProduct.customFields.cfProductOption).toEqual({
  212. languageCode: 'en',
  213. name: '13 inch',
  214. });
  215. expect(createProduct.customFields.cfProductVariant).toEqual({
  216. languageCode: 'en',
  217. name: 'Laptop 13 inch 8GB',
  218. });
  219. expect(createProduct.customFields.cfProduct).toEqual({ languageCode: 'en', name: 'Laptop' });
  220. expect(createProduct.customFields.cfShippingMethod).toEqual({ name: 'Standard Shipping' });
  221. });
  222. it('ProductVariant prices get resolved', async () => {
  223. debugger;
  224. const { product } = await adminClient.query(gql`
  225. query {
  226. product(id: "${productId}") {
  227. id
  228. customFields {
  229. cfProductVariant {
  230. price
  231. currencyCode
  232. priceWithTax
  233. }
  234. }
  235. }
  236. }`);
  237. expect(product.customFields.cfProductVariant).toEqual({
  238. price: 129900,
  239. currencyCode: 'USD',
  240. priceWithTax: 155880,
  241. });
  242. });
  243. });
  244. describe('entity-specific implementation', () => {
  245. function assertCustomFieldIds(customFields: any, single: string, multi: string[]) {
  246. expect(customFields.single).toEqual({ id: single });
  247. expect(customFields.multi.sort(sortById)).toEqual(multi.map(id => ({ id })));
  248. }
  249. const customFieldsSelection = `
  250. customFields {
  251. single {
  252. id
  253. }
  254. multi {
  255. id
  256. }
  257. }`;
  258. describe('Address entity', () => {
  259. it('admin createCustomerAddress', async () => {
  260. const { createCustomerAddress } = await adminClient.query(gql`
  261. mutation {
  262. createCustomerAddress(
  263. customerId: "T_1"
  264. input: {
  265. countryCode: "GB"
  266. streetLine1: "Test Street"
  267. customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
  268. }
  269. ) {
  270. id
  271. ${customFieldsSelection}
  272. }
  273. }
  274. `);
  275. assertCustomFieldIds(createCustomerAddress.customFields, 'T_1', ['T_1', 'T_2']);
  276. });
  277. it('shop createCustomerAddress', async () => {
  278. await shopClient.asUserWithCredentials('hayden.zieme12@hotmail.com', 'test');
  279. const { createCustomerAddress } = await shopClient.query(gql`
  280. mutation {
  281. createCustomerAddress(
  282. input: {
  283. countryCode: "GB"
  284. streetLine1: "Test Street"
  285. customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
  286. }
  287. ) {
  288. id
  289. ${customFieldsSelection}
  290. }
  291. }
  292. `);
  293. assertCustomFieldIds(createCustomerAddress.customFields, 'T_1', ['T_1', 'T_2']);
  294. });
  295. it('admin updateCustomerAddress', async () => {
  296. const { updateCustomerAddress } = await adminClient.query(gql`
  297. mutation {
  298. updateCustomerAddress(
  299. input: { id: "T_1", customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] } }
  300. ) {
  301. id
  302. ${customFieldsSelection}
  303. }
  304. }
  305. `);
  306. assertCustomFieldIds(updateCustomerAddress.customFields, 'T_2', ['T_3', 'T_4']);
  307. });
  308. it('shop updateCustomerAddress', async () => {
  309. const { updateCustomerAddress } = await shopClient.query(gql`
  310. mutation {
  311. updateCustomerAddress(
  312. input: { id: "T_1", customFields: { singleId: "T_3", multiIds: ["T_4", "T_2"] } }
  313. ) {
  314. id
  315. ${customFieldsSelection}
  316. }
  317. }
  318. `);
  319. assertCustomFieldIds(updateCustomerAddress.customFields, 'T_3', ['T_2', 'T_4']);
  320. });
  321. });
  322. describe('Collection entity', () => {
  323. let collectionId: string;
  324. it('admin createCollection', async () => {
  325. const { createCollection } = await adminClient.query(gql`
  326. mutation {
  327. createCollection(
  328. input: {
  329. translations: [
  330. { languageCode: en, name: "Test", description: "test", slug: "test" }
  331. ]
  332. filters: []
  333. customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
  334. }
  335. ) {
  336. id
  337. ${customFieldsSelection}
  338. }
  339. }
  340. `);
  341. assertCustomFieldIds(createCollection.customFields, 'T_1', ['T_1', 'T_2']);
  342. collectionId = createCollection.id;
  343. });
  344. it('admin updateCollection', async () => {
  345. const { updateCollection } = await adminClient.query(gql`
  346. mutation {
  347. updateCollection(
  348. input: {
  349. id: "${collectionId}"
  350. customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
  351. }
  352. ) {
  353. id
  354. ${customFieldsSelection}
  355. }
  356. }
  357. `);
  358. assertCustomFieldIds(updateCollection.customFields, 'T_2', ['T_3', 'T_4']);
  359. });
  360. });
  361. describe('Customer entity', () => {
  362. let customerId: string;
  363. it('admin createCustomer', async () => {
  364. const { createCustomer } = await adminClient.query(gql`
  365. mutation {
  366. createCustomer(
  367. input: {
  368. emailAddress: "test@test.com"
  369. firstName: "Test"
  370. lastName: "Person"
  371. customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
  372. }
  373. ) {
  374. ... on Customer {
  375. id
  376. ${customFieldsSelection}
  377. }
  378. }
  379. }
  380. `);
  381. assertCustomFieldIds(createCustomer.customFields, 'T_1', ['T_1', 'T_2']);
  382. customerId = createCustomer.id;
  383. });
  384. it('admin updateCustomer', async () => {
  385. const { updateCustomer } = await adminClient.query(gql`
  386. mutation {
  387. updateCustomer(
  388. input: {
  389. id: "${customerId}"
  390. customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
  391. }
  392. ) {
  393. ...on Customer {
  394. id
  395. ${customFieldsSelection}
  396. }
  397. }
  398. }
  399. `);
  400. assertCustomFieldIds(updateCustomer.customFields, 'T_2', ['T_3', 'T_4']);
  401. });
  402. it('shop updateCustomer', async () => {
  403. const { updateCustomer } = await shopClient.query(gql`
  404. mutation {
  405. updateCustomer(input: { customFields: { singleId: "T_4", multiIds: ["T_2", "T_4"] } }) {
  406. id
  407. ${customFieldsSelection}
  408. }
  409. }
  410. `);
  411. assertCustomFieldIds(updateCustomer.customFields, 'T_4', ['T_2', 'T_4']);
  412. });
  413. });
  414. describe('Facet entity', () => {
  415. let facetId: string;
  416. it('admin createFacet', async () => {
  417. const { createFacet } = await adminClient.query(gql`
  418. mutation {
  419. createFacet(
  420. input: {
  421. code: "test"
  422. isPrivate: false
  423. translations: [{ languageCode: en, name: "test" }]
  424. customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
  425. }
  426. ) {
  427. id
  428. ${customFieldsSelection}
  429. }
  430. }
  431. `);
  432. assertCustomFieldIds(createFacet.customFields, 'T_1', ['T_1', 'T_2']);
  433. facetId = createFacet.id;
  434. });
  435. it('admin updateFacet', async () => {
  436. const { updateFacet } = await adminClient.query(gql`
  437. mutation {
  438. updateFacet(
  439. input: {
  440. id: "${facetId}"
  441. customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
  442. }
  443. ) {
  444. id
  445. ${customFieldsSelection}
  446. }
  447. }
  448. `);
  449. assertCustomFieldIds(updateFacet.customFields, 'T_2', ['T_3', 'T_4']);
  450. });
  451. });
  452. describe('FacetValue entity', () => {
  453. let facetValueId: string;
  454. it('admin createFacetValues', async () => {
  455. const { createFacetValues } = await adminClient.query(gql`
  456. mutation {
  457. createFacetValues(
  458. input: {
  459. code: "test"
  460. facetId: "T_1"
  461. translations: [{ languageCode: en, name: "test" }]
  462. customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
  463. }
  464. ) {
  465. id
  466. ${customFieldsSelection}
  467. }
  468. }
  469. `);
  470. assertCustomFieldIds(createFacetValues[0].customFields, 'T_1', ['T_1', 'T_2']);
  471. facetValueId = createFacetValues[0].id;
  472. });
  473. it('admin updateFacetValues', async () => {
  474. const { updateFacetValues } = await adminClient.query(gql`
  475. mutation {
  476. updateFacetValues(
  477. input: {
  478. id: "${facetValueId}"
  479. customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
  480. }
  481. ) {
  482. id
  483. ${customFieldsSelection}
  484. }
  485. }
  486. `);
  487. assertCustomFieldIds(updateFacetValues[0].customFields, 'T_2', ['T_3', 'T_4']);
  488. });
  489. });
  490. describe('Fulfillment entity', () => {
  491. // Currently no GraphQL API to set customFields on fulfillments
  492. });
  493. describe('GlobalSettings entity', () => {
  494. it('admin updateGlobalSettings', async () => {
  495. const { updateGlobalSettings } = await adminClient.query(gql`
  496. mutation {
  497. updateGlobalSettings(
  498. input: {
  499. customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
  500. }
  501. ) {
  502. ... on GlobalSettings {
  503. id
  504. ${customFieldsSelection}
  505. }
  506. }
  507. }
  508. `);
  509. assertCustomFieldIds(updateGlobalSettings.customFields, 'T_2', ['T_3', 'T_4']);
  510. });
  511. });
  512. describe('Order entity', () => {
  513. let orderId: string;
  514. beforeAll(async () => {
  515. const { addItemToOrder } = await shopClient.query<any, AddItemToOrder.Variables>(
  516. ADD_ITEM_TO_ORDER,
  517. {
  518. productVariantId: 'T_1',
  519. quantity: 1,
  520. },
  521. );
  522. orderId = addItemToOrder.id;
  523. });
  524. it('shop setOrderCustomFields', async () => {
  525. const { setOrderCustomFields } = await shopClient.query(gql`
  526. mutation {
  527. setOrderCustomFields(
  528. input: {
  529. customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
  530. }
  531. ) {
  532. ... on Order {
  533. id
  534. ${customFieldsSelection}
  535. }
  536. }
  537. }
  538. `);
  539. assertCustomFieldIds(setOrderCustomFields.customFields, 'T_2', ['T_3', 'T_4']);
  540. });
  541. it('admin setOrderCustomFields', async () => {
  542. const { setOrderCustomFields } = await adminClient.query(gql`
  543. mutation {
  544. setOrderCustomFields(
  545. input: {
  546. id: "${orderId}"
  547. customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
  548. }
  549. ) {
  550. ... on Order {
  551. id
  552. ${customFieldsSelection}
  553. }
  554. }
  555. }
  556. `);
  557. assertCustomFieldIds(setOrderCustomFields.customFields, 'T_1', ['T_1', 'T_2']);
  558. });
  559. });
  560. describe('OrderLine entity', () => {
  561. it('shop addItemToOrder', async () => {
  562. const { addItemToOrder } = await shopClient.query(
  563. gql`mutation {
  564. addItemToOrder(productVariantId: "T_1", quantity: 1, customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }) {
  565. ... on Order {
  566. id
  567. ${customFieldsSelection}
  568. }
  569. }
  570. }`,
  571. );
  572. assertCustomFieldIds(addItemToOrder.customFields, 'T_1', ['T_1', 'T_2']);
  573. });
  574. });
  575. describe('Product, ProductVariant entity', () => {
  576. let productId: string;
  577. it('admin createProduct', async () => {
  578. const { createProduct } = await adminClient.query(gql`
  579. mutation {
  580. createProduct(
  581. input: {
  582. translations: [{ languageCode: en, name: "test" slug: "test" description: "test" }]
  583. customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
  584. }
  585. ) {
  586. id
  587. ${customFieldsSelection}
  588. }
  589. }
  590. `);
  591. assertCustomFieldIds(createProduct.customFields, 'T_1', ['T_1', 'T_2']);
  592. productId = createProduct.id;
  593. });
  594. it('admin updateProduct', async () => {
  595. const { updateProduct } = await adminClient.query(gql`
  596. mutation {
  597. updateProduct(
  598. input: {
  599. id: "${productId}"
  600. customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
  601. }
  602. ) {
  603. id
  604. ${customFieldsSelection}
  605. }
  606. }
  607. `);
  608. assertCustomFieldIds(updateProduct.customFields, 'T_2', ['T_3', 'T_4']);
  609. });
  610. let productVariantId: string;
  611. it('admin createProductVariant', async () => {
  612. const { createProductVariants } = await adminClient.query(gql`
  613. mutation {
  614. createProductVariants(
  615. input: [{
  616. sku: "TEST01"
  617. productId: "${productId}"
  618. translations: [{ languageCode: en, name: "test" }]
  619. customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
  620. }]
  621. ) {
  622. id
  623. ${customFieldsSelection}
  624. }
  625. }
  626. `);
  627. assertCustomFieldIds(createProductVariants[0].customFields, 'T_1', ['T_1', 'T_2']);
  628. productVariantId = createProductVariants[0].id;
  629. });
  630. it('admin updateProductVariant', async () => {
  631. const { updateProductVariants } = await adminClient.query(gql`
  632. mutation {
  633. updateProductVariants(
  634. input: [{
  635. id: "${productVariantId}"
  636. customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
  637. }]
  638. ) {
  639. id
  640. ${customFieldsSelection}
  641. }
  642. }
  643. `);
  644. assertCustomFieldIds(updateProductVariants[0].customFields, 'T_2', ['T_3', 'T_4']);
  645. });
  646. });
  647. describe('ProductOptionGroup, ProductOption entity', () => {
  648. let productOptionGroupId: string;
  649. it('admin createProductOptionGroup', async () => {
  650. const { createProductOptionGroup } = await adminClient.query(gql`
  651. mutation {
  652. createProductOptionGroup(
  653. input: {
  654. code: "test"
  655. options: []
  656. translations: [{ languageCode: en, name: "test" }]
  657. customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
  658. }
  659. ) {
  660. id
  661. ${customFieldsSelection}
  662. }
  663. }
  664. `);
  665. assertCustomFieldIds(createProductOptionGroup.customFields, 'T_1', ['T_1', 'T_2']);
  666. productOptionGroupId = createProductOptionGroup.id;
  667. });
  668. it('admin updateProductOptionGroup', async () => {
  669. const { updateProductOptionGroup } = await adminClient.query(gql`
  670. mutation {
  671. updateProductOptionGroup(
  672. input: {
  673. id: "${productOptionGroupId}"
  674. customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
  675. }
  676. ) {
  677. id
  678. ${customFieldsSelection}
  679. }
  680. }
  681. `);
  682. assertCustomFieldIds(updateProductOptionGroup.customFields, 'T_2', ['T_3', 'T_4']);
  683. });
  684. let productOptionId: string;
  685. it('admin createProductOption', async () => {
  686. const { createProductOption } = await adminClient.query(gql`
  687. mutation {
  688. createProductOption(
  689. input: {
  690. productOptionGroupId: "${productOptionGroupId}"
  691. code: "test-option"
  692. translations: [{ languageCode: en, name: "test-option" }]
  693. customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
  694. }
  695. ) {
  696. id
  697. ${customFieldsSelection}
  698. }
  699. }
  700. `);
  701. assertCustomFieldIds(createProductOption.customFields, 'T_1', ['T_1', 'T_2']);
  702. productOptionId = createProductOption.id;
  703. });
  704. it('admin updateProductOption', async () => {
  705. const { updateProductOption } = await adminClient.query(gql`
  706. mutation {
  707. updateProductOption(
  708. input: {
  709. id: "${productOptionId}"
  710. customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
  711. }
  712. ) {
  713. id
  714. ${customFieldsSelection}
  715. }
  716. }
  717. `);
  718. assertCustomFieldIds(updateProductOption.customFields, 'T_2', ['T_3', 'T_4']);
  719. });
  720. });
  721. describe('User entity', () => {
  722. // Currently no GraphQL API to set User custom fields
  723. });
  724. describe('ShippingMethod entity', () => {
  725. let shippingMethodId: string;
  726. it('admin createShippingMethod', async () => {
  727. const { createShippingMethod } = await adminClient.query(gql`
  728. mutation {
  729. createShippingMethod(
  730. input: {
  731. code: "test"
  732. calculator: {
  733. code: "${defaultShippingCalculator.code}"
  734. arguments: [
  735. { name: "rate" value: "10"},
  736. { name: "includesTax" value: "true"},
  737. { name: "taxRate" value: "10"},
  738. ]
  739. }
  740. checker: {
  741. code: "${defaultShippingEligibilityChecker.code}"
  742. arguments: [
  743. { name: "orderMinimum" value: "0"},
  744. ]
  745. }
  746. fulfillmentHandler: "${manualFulfillmentHandler.code}"
  747. translations: [{ languageCode: en, name: "test" description: "test" }]
  748. customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
  749. }
  750. ) {
  751. id
  752. ${customFieldsSelection}
  753. }
  754. }
  755. `);
  756. assertCustomFieldIds(createShippingMethod.customFields, 'T_1', ['T_1', 'T_2']);
  757. shippingMethodId = createShippingMethod.id;
  758. });
  759. it('admin updateShippingMethod', async () => {
  760. const { updateShippingMethod } = await adminClient.query(gql`
  761. mutation {
  762. updateShippingMethod(
  763. input: {
  764. id: "${shippingMethodId}"
  765. translations: []
  766. customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
  767. }
  768. ) {
  769. id
  770. ${customFieldsSelection}
  771. }
  772. }
  773. `);
  774. assertCustomFieldIds(updateShippingMethod.customFields, 'T_2', ['T_3', 'T_4']);
  775. });
  776. });
  777. });
  778. it('null values', async () => {
  779. const { updateCustomerAddress } = await adminClient.query(gql`
  780. mutation {
  781. updateCustomerAddress(
  782. input: { id: "T_1", customFields: { singleId: null, multiIds: ["T_1", "null"] } }
  783. ) {
  784. id
  785. customFields {
  786. single {
  787. id
  788. }
  789. multi {
  790. id
  791. }
  792. }
  793. }
  794. }
  795. `);
  796. expect(updateCustomerAddress.customFields.single).toEqual(null);
  797. expect(updateCustomerAddress.customFields.multi).toEqual([{ id: 'T_1' }]);
  798. });
  799. });