| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278 |
- import {
- assertFound,
- Asset,
- Collection,
- Country,
- CustomFields,
- DefaultLogger,
- defaultShippingCalculator,
- defaultShippingEligibilityChecker,
- Facet,
- FacetValue,
- LogLevel,
- manualFulfillmentHandler,
- mergeConfig,
- PluginCommonModule,
- Product,
- ProductOption,
- ProductOptionGroup,
- ProductVariant,
- RequestContext,
- ShippingMethod,
- TransactionalConnection,
- VendureEntity,
- VendurePlugin,
- } from '@vendure/core';
- import { createTestEnvironment } from '@vendure/testing';
- import gql from 'graphql-tag';
- import path from 'path';
- import { Repository } from 'typeorm';
- import { afterAll, beforeAll, describe, expect, it } from 'vitest';
- import { initialData } from '../../../e2e-common/e2e-initial-data';
- import { testConfig, TEST_SETUP_TIMEOUT_MS } from '../../../e2e-common/test-config';
- import { testSuccessfulPaymentMethod } from './fixtures/test-payment-methods';
- import { TestPlugin1636_1664 } from './fixtures/test-plugins/issue-1636-1664/issue-1636-1664-plugin';
- import { PluginIssue2453 } from './fixtures/test-plugins/issue-2453/plugin-issue2453';
- import { TestCustomEntity, WithCustomEntity } from './fixtures/test-plugins/with-custom-entity';
- import { AddItemToOrderMutationVariables } from './graphql/generated-e2e-shop-types';
- import { ADD_ITEM_TO_ORDER } from './graphql/shop-definitions';
- import { sortById } from './utils/test-order-utils';
- // From https://github.com/microsoft/TypeScript/issues/13298#issuecomment-654906323
- // to ensure that we _always_ test all entities which support custom fields
- type ValueOf<T> = T[keyof T];
- type NonEmptyArray<T> = [T, ...T[]];
- type MustInclude<T, U extends T[]> = [T] extends [ValueOf<U>] ? U : never;
- const enumerate =
- <T>() =>
- <U extends NonEmptyArray<T>>(...elements: MustInclude<T, U>) =>
- elements;
- const entitiesWithCustomFields = enumerate<keyof CustomFields>()(
- 'Address',
- 'Administrator',
- 'Asset',
- 'Channel',
- 'Collection',
- 'Customer',
- 'CustomerGroup',
- 'Facet',
- 'FacetValue',
- 'Fulfillment',
- 'GlobalSettings',
- 'Order',
- 'OrderLine',
- 'PaymentMethod',
- 'Product',
- 'ProductOption',
- 'ProductOptionGroup',
- 'ProductVariant',
- 'Promotion',
- 'Region',
- 'Seller',
- 'ShippingMethod',
- 'TaxCategory',
- 'TaxRate',
- 'User',
- 'Zone',
- );
- const customFieldConfig: CustomFields = {};
- for (const entity of entitiesWithCustomFields) {
- customFieldConfig[entity] = [
- { name: 'single', type: 'relation', entity: Asset, graphQLType: 'Asset', list: false },
- { name: 'multi', type: 'relation', entity: Asset, graphQLType: 'Asset', list: true },
- ];
- }
- customFieldConfig.Product?.push(
- { name: 'cfCollection', type: 'relation', entity: Collection, list: false },
- { name: 'cfCountry', type: 'relation', entity: Country, list: false },
- { name: 'cfFacetValue', type: 'relation', entity: FacetValue, list: false },
- { name: 'cfFacet', type: 'relation', entity: Facet, list: false },
- { name: 'cfProductOptionGroup', type: 'relation', entity: ProductOptionGroup, list: false },
- { name: 'cfProductOption', type: 'relation', entity: ProductOption, list: false },
- { name: 'cfProductVariant', type: 'relation', entity: ProductVariant, list: false },
- { name: 'cfProduct', type: 'relation', entity: Product, list: false },
- { name: 'cfShippingMethod', type: 'relation', entity: ShippingMethod, list: false },
- { name: 'cfInternalAsset', type: 'relation', entity: Asset, list: false, internal: true },
- );
- customFieldConfig.ProductVariant?.push({
- name: 'cfRelatedProducts',
- type: 'relation',
- entity: Product,
- list: true,
- internal: false,
- public: true,
- });
- const customConfig = mergeConfig(testConfig(), {
- paymentOptions: {
- paymentMethodHandlers: [testSuccessfulPaymentMethod],
- },
- // logger: new DefaultLogger({ level: LogLevel.Debug }),
- dbConnectionOptions: {
- timezone: 'Z',
- },
- customFields: customFieldConfig,
- plugins: [TestPlugin1636_1664, WithCustomEntity, PluginIssue2453],
- });
- describe('Custom field relations', () => {
- const { server, adminClient, shopClient } = createTestEnvironment(customConfig);
- beforeAll(async () => {
- await server.init({
- initialData,
- productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-full.csv'),
- customerCount: 3,
- });
- await adminClient.asSuperAdmin();
- }, TEST_SETUP_TIMEOUT_MS);
- afterAll(async () => {
- await server.destroy();
- });
- it('customFieldConfig query returns entity and scalar fields', async () => {
- const { globalSettings } = await adminClient.query(gql`
- query {
- globalSettings {
- serverConfig {
- customFieldConfig {
- Customer {
- ... on RelationCustomFieldConfig {
- name
- entity
- scalarFields
- }
- }
- }
- }
- }
- }
- `);
- const single = globalSettings.serverConfig.customFieldConfig.Customer[0];
- expect(single.entity).toBe('Asset');
- expect(single.scalarFields).toEqual([
- 'id',
- 'createdAt',
- 'updatedAt',
- 'name',
- 'type',
- 'fileSize',
- 'mimeType',
- 'width',
- 'height',
- 'source',
- 'preview',
- ]);
- });
- describe('special data resolution', () => {
- let productId: string;
- const productCustomFieldRelationsSelection = `
- id
- customFields {
- cfCollection {
- languageCode
- name
- }
- cfCountry {
- languageCode
- name
- }
- cfFacetValue {
- languageCode
- name
- }
- cfFacet {
- languageCode
- name
- }
- cfProductOptionGroup {
- languageCode
- name
- }
- cfProductOption {
- languageCode
- name
- }
- cfProductVariant {
- languageCode
- name
- }
- cfProduct {
- languageCode
- name
- }
- cfShippingMethod {
- languageCode
- name
- }
- }`;
- function assertTranslatableCustomFieldValues(product: { customFields: any }) {
- expect(product.customFields.cfCollection).toEqual({
- languageCode: 'en',
- name: '__root_collection__',
- });
- expect(product.customFields.cfCountry).toEqual({ languageCode: 'en', name: 'Australia' });
- expect(product.customFields.cfFacetValue).toEqual({
- languageCode: 'en',
- name: 'electronics',
- });
- expect(product.customFields.cfFacet).toEqual({ languageCode: 'en', name: 'category' });
- expect(product.customFields.cfProductOptionGroup).toEqual({
- languageCode: 'en',
- name: 'screen size',
- });
- expect(product.customFields.cfProductOption).toEqual({
- languageCode: 'en',
- name: '13 inch',
- });
- expect(product.customFields.cfProductVariant).toEqual({
- languageCode: 'en',
- name: 'Laptop 13 inch 8GB',
- });
- expect(product.customFields.cfProduct).toEqual({ languageCode: 'en', name: 'Laptop' });
- expect(product.customFields.cfShippingMethod).toEqual({
- languageCode: 'en',
- name: 'Standard Shipping',
- });
- }
- it('translatable entities get translated', async () => {
- const { createProduct } = await adminClient.query(gql`
- mutation {
- createProduct(
- input: {
- translations: [
- {
- languageCode: en
- name: "Test product"
- description: ""
- slug: "test-product"
- }
- ]
- customFields: {
- cfCollectionId: "T_1"
- cfCountryId: "T_1"
- cfFacetValueId: "T_1"
- cfFacetId: "T_1"
- cfProductOptionGroupId: "T_1"
- cfProductOptionId: "T_1"
- cfProductVariantId: "T_1"
- cfProductId: "T_1"
- cfShippingMethodId: "T_1"
- }
- }
- ) { ${productCustomFieldRelationsSelection} }
- }
- `);
- productId = createProduct.id;
- assertTranslatableCustomFieldValues(createProduct);
- });
- it('translatable entities get translated on findOneInChannel', async () => {
- const { product } = await adminClient.query(gql`
- query {
- product(id: "${productId}") { ${productCustomFieldRelationsSelection} }
- }
- `);
- assertTranslatableCustomFieldValues(product);
- });
- // https://github.com/vendure-ecommerce/vendure/issues/2453
- it('translatable eager-loaded relation works (issue 2453)', async () => {
- const { collections } = await adminClient.query(gql`
- query {
- collections(options: { sort: { name: DESC } }) {
- totalItems
- items {
- id
- name
- customFields {
- campaign {
- name
- languageCode
- }
- }
- }
- }
- }
- `);
- expect(collections.totalItems).toBe(3);
- expect(collections.items.find((c: any) => c.id === 'T_3')).toEqual({
- customFields: {
- campaign: {
- languageCode: 'en',
- name: 'Clearance Up to 70% Off frames',
- },
- },
- id: 'T_3',
- name: 'children collection',
- });
- });
- it('ProductVariant prices get resolved', async () => {
- const { product } = await adminClient.query(gql`
- query {
- product(id: "${productId}") {
- id
- customFields {
- cfProductVariant {
- price
- currencyCode
- priceWithTax
- }
- }
- }
- }`);
- expect(product.customFields.cfProductVariant).toEqual({
- price: 129900,
- currencyCode: 'USD',
- priceWithTax: 155880,
- });
- });
- });
- describe('entity-specific implementation', () => {
- function assertCustomFieldIds(customFields: any, single: string, multi: string[]) {
- expect(customFields.single).toEqual({ id: single });
- expect(customFields.multi.sort(sortById)).toEqual(multi.map(id => ({ id })));
- }
- const customFieldsSelection = `
- customFields {
- single {
- id
- }
- multi {
- id
- }
- }`;
- describe('Address entity', () => {
- it('admin createCustomerAddress', async () => {
- const { createCustomerAddress } = await adminClient.query(gql`
- mutation {
- createCustomerAddress(
- customerId: "T_1"
- input: {
- countryCode: "GB"
- streetLine1: "Test Street"
- customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(createCustomerAddress.customFields, 'T_1', ['T_1', 'T_2']);
- });
- it('shop createCustomerAddress', async () => {
- await shopClient.asUserWithCredentials('hayden.zieme12@hotmail.com', 'test');
- const { createCustomerAddress } = await shopClient.query(gql`
- mutation {
- createCustomerAddress(
- input: {
- countryCode: "GB"
- streetLine1: "Test Street"
- customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(createCustomerAddress.customFields, 'T_1', ['T_1', 'T_2']);
- });
- it('admin updateCustomerAddress', async () => {
- const { updateCustomerAddress } = await adminClient.query(gql`
- mutation {
- updateCustomerAddress(
- input: { id: "T_1", customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] } }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(updateCustomerAddress.customFields, 'T_2', ['T_3', 'T_4']);
- });
- it('shop updateCustomerAddress', async () => {
- const { updateCustomerAddress } = await shopClient.query(gql`
- mutation {
- updateCustomerAddress(
- input: { id: "T_1", customFields: { singleId: "T_3", multiIds: ["T_4", "T_2"] } }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(updateCustomerAddress.customFields, 'T_3', ['T_2', 'T_4']);
- });
- });
- describe('Collection entity', () => {
- let collectionId: string;
- it('admin createCollection', async () => {
- const { createCollection } = await adminClient.query(gql`
- mutation {
- createCollection(
- input: {
- translations: [
- { languageCode: en, name: "Test", description: "test", slug: "test" }
- ]
- filters: []
- customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(createCollection.customFields, 'T_1', ['T_1', 'T_2']);
- collectionId = createCollection.id;
- });
- it('admin updateCollection', async () => {
- const { updateCollection } = await adminClient.query(gql`
- mutation {
- updateCollection(
- input: {
- id: "${collectionId}"
- customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(updateCollection.customFields, 'T_2', ['T_3', 'T_4']);
- });
- });
- describe('Customer entity', () => {
- let customerId: string;
- it('admin createCustomer', async () => {
- const { createCustomer } = await adminClient.query(gql`
- mutation {
- createCustomer(
- input: {
- emailAddress: "test@test.com"
- firstName: "Test"
- lastName: "Person"
- customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
- }
- ) {
- ... on Customer {
- id
- ${customFieldsSelection}
- }
- }
- }
- `);
- assertCustomFieldIds(createCustomer.customFields, 'T_1', ['T_1', 'T_2']);
- customerId = createCustomer.id;
- });
- it('admin updateCustomer', async () => {
- const { updateCustomer } = await adminClient.query(gql`
- mutation {
- updateCustomer(
- input: {
- id: "${customerId}"
- customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
- }
- ) {
- ...on Customer {
- id
- ${customFieldsSelection}
- }
- }
- }
- `);
- assertCustomFieldIds(updateCustomer.customFields, 'T_2', ['T_3', 'T_4']);
- });
- it('shop updateCustomer', async () => {
- const { updateCustomer } = await shopClient.query(gql`
- mutation {
- updateCustomer(input: { customFields: { singleId: "T_4", multiIds: ["T_2", "T_4"] } }) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(updateCustomer.customFields, 'T_4', ['T_2', 'T_4']);
- });
- });
- describe('Facet entity', () => {
- let facetId: string;
- it('admin createFacet', async () => {
- const { createFacet } = await adminClient.query(gql`
- mutation {
- createFacet(
- input: {
- code: "test"
- isPrivate: false
- translations: [{ languageCode: en, name: "test" }]
- customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(createFacet.customFields, 'T_1', ['T_1', 'T_2']);
- facetId = createFacet.id;
- });
- it('admin updateFacet', async () => {
- const { updateFacet } = await adminClient.query(gql`
- mutation {
- updateFacet(
- input: {
- id: "${facetId}"
- customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(updateFacet.customFields, 'T_2', ['T_3', 'T_4']);
- });
- });
- describe('FacetValue entity', () => {
- let facetValueId: string;
- it('admin createFacetValues', async () => {
- const { createFacetValues } = await adminClient.query(gql`
- mutation {
- createFacetValues(
- input: {
- code: "test"
- facetId: "T_1"
- translations: [{ languageCode: en, name: "test" }]
- customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(createFacetValues[0].customFields, 'T_1', ['T_1', 'T_2']);
- facetValueId = createFacetValues[0].id;
- });
- it('admin updateFacetValues', async () => {
- const { updateFacetValues } = await adminClient.query(gql`
- mutation {
- updateFacetValues(
- input: {
- id: "${facetValueId}"
- customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(updateFacetValues[0].customFields, 'T_2', ['T_3', 'T_4']);
- });
- });
- // describe('Fulfillment entity', () => {
- // // Currently no GraphQL API to set customFields on fulfillments
- // });
- describe('GlobalSettings entity', () => {
- it('admin updateGlobalSettings', async () => {
- const { updateGlobalSettings } = await adminClient.query(gql`
- mutation {
- updateGlobalSettings(
- input: {
- customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
- }
- ) {
- ... on GlobalSettings {
- id
- ${customFieldsSelection}
- }
- }
- }
- `);
- assertCustomFieldIds(updateGlobalSettings.customFields, 'T_2', ['T_3', 'T_4']);
- });
- });
- describe('Order entity', () => {
- let orderId: string;
- beforeAll(async () => {
- const { addItemToOrder } = await shopClient.query<any, AddItemToOrderMutationVariables>(
- ADD_ITEM_TO_ORDER,
- {
- productVariantId: 'T_1',
- quantity: 1,
- },
- );
- orderId = addItemToOrder.id;
- });
- it('shop setOrderCustomFields', async () => {
- const { setOrderCustomFields } = await shopClient.query(gql`
- mutation {
- setOrderCustomFields(
- input: {
- customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
- }
- ) {
- ... on Order {
- id
- ${customFieldsSelection}
- }
- }
- }
- `);
- assertCustomFieldIds(setOrderCustomFields.customFields, 'T_2', ['T_3', 'T_4']);
- });
- it('admin setOrderCustomFields', async () => {
- const { setOrderCustomFields } = await adminClient.query(gql`
- mutation {
- setOrderCustomFields(
- input: {
- id: "${orderId}"
- customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
- }
- ) {
- ... on Order {
- id
- ${customFieldsSelection}
- }
- }
- }
- `);
- assertCustomFieldIds(setOrderCustomFields.customFields, 'T_1', ['T_1', 'T_2']);
- });
- // https://github.com/vendure-ecommerce/vendure/issues/1664#issuecomment-1320872627
- it('admin order query with eager-loaded custom field relation', async () => {
- const { order } = await adminClient.query(gql`
- query {
- order(id: 1) {
- id
- customFields {
- productOwner {
- id
- }
- }
- }
- }
- `);
- // we're just making sure it does not throw here.
- expect(order).toEqual({
- customFields: {
- productOwner: null,
- },
- id: 'T_1',
- });
- });
- });
- describe('OrderLine entity', () => {
- it('shop addItemToOrder', async () => {
- const { addItemToOrder } = await shopClient.query(
- gql`mutation {
- addItemToOrder(productVariantId: "T_1", quantity: 1, customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }) {
- ... on Order {
- id
- ${customFieldsSelection}
- }
- }
- }`,
- );
- assertCustomFieldIds(addItemToOrder.customFields, 'T_1', ['T_1', 'T_2']);
- });
- });
- describe('Product, ProductVariant entity', () => {
- let productId: string;
- it('admin createProduct', async () => {
- const { createProduct } = await adminClient.query(gql`
- mutation {
- createProduct(
- input: {
- translations: [{ languageCode: en, name: "test" slug: "test" description: "test" }]
- customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(createProduct.customFields, 'T_1', ['T_1', 'T_2']);
- productId = createProduct.id;
- });
- it('admin updateProduct', async () => {
- const { updateProduct } = await adminClient.query(gql`
- mutation {
- updateProduct(
- input: {
- id: "${productId}"
- customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(updateProduct.customFields, 'T_2', ['T_3', 'T_4']);
- });
- let productVariantId: string;
- it('admin createProductVariant', async () => {
- const { createProductVariants } = await adminClient.query(gql`
- mutation {
- createProductVariants(
- input: [{
- sku: "TEST01"
- productId: "${productId}"
- translations: [{ languageCode: en, name: "test" }]
- customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
- }]
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(createProductVariants[0].customFields, 'T_1', ['T_1', 'T_2']);
- productVariantId = createProductVariants[0].id;
- });
- it('admin updateProductVariant', async () => {
- const { updateProductVariants } = await adminClient.query(gql`
- mutation {
- updateProductVariants(
- input: [{
- id: "${productVariantId}"
- customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
- }]
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(updateProductVariants[0].customFields, 'T_2', ['T_3', 'T_4']);
- });
- describe('issue 1664', () => {
- // https://github.com/vendure-ecommerce/vendure/issues/1664
- it('successfully gets product by id with eager-loading custom field relation', async () => {
- const { product } = await shopClient.query(gql`
- query {
- product(id: "T_1") {
- id
- customFields {
- cfVendor {
- featuredProduct {
- id
- }
- }
- }
- }
- }
- `);
- expect(product).toBeDefined();
- });
- // https://github.com/vendure-ecommerce/vendure/issues/1664
- it('successfully gets product by id with nested eager-loading custom field relation', async () => {
- const { customer } = await adminClient.query(gql`
- query {
- customer(id: "T_1") {
- id
- firstName
- lastName
- emailAddress
- phoneNumber
- user {
- customFields {
- cfVendor {
- id
- }
- }
- }
- }
- }
- `);
- expect(customer).toBeDefined();
- });
- // https://github.com/vendure-ecommerce/vendure/issues/1664
- it('successfully gets product.variants with nested custom field relation', async () => {
- await adminClient.query(gql`
- mutation {
- updateProductVariants(
- input: [{ id: "T_1", customFields: { cfRelatedProductsIds: ["T_2"] } }]
- ) {
- id
- }
- }
- `);
- const { product } = await adminClient.query(gql`
- query {
- product(id: "T_1") {
- variants {
- id
- customFields {
- cfRelatedProducts {
- featuredAsset {
- id
- }
- }
- }
- }
- }
- }
- `);
- expect(product).toBeDefined();
- expect(product.variants[0].customFields.cfRelatedProducts).toEqual([
- {
- featuredAsset: { id: 'T_2' },
- },
- ]);
- });
- it('successfully gets product by slug with eager-loading custom field relation', async () => {
- const { product } = await shopClient.query(gql`
- query {
- product(slug: "laptop") {
- id
- customFields {
- cfVendor {
- featuredProduct {
- id
- }
- }
- }
- }
- }
- `);
- expect(product).toBeDefined();
- });
- it('does not error on custom field relation with eager custom field relation', async () => {
- const { product } = await adminClient.query(gql`
- query {
- product(slug: "laptop") {
- name
- customFields {
- owner {
- id
- code
- customFields {
- profile {
- id
- name
- }
- }
- }
- }
- }
- }
- `);
- expect(product).toBeDefined();
- });
- });
- });
- describe('ProductOptionGroup, ProductOption entity', () => {
- let productOptionGroupId: string;
- it('admin createProductOptionGroup', async () => {
- const { createProductOptionGroup } = await adminClient.query(gql`
- mutation {
- createProductOptionGroup(
- input: {
- code: "test"
- options: []
- translations: [{ languageCode: en, name: "test" }]
- customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(createProductOptionGroup.customFields, 'T_1', ['T_1', 'T_2']);
- productOptionGroupId = createProductOptionGroup.id;
- });
- it('admin updateProductOptionGroup', async () => {
- const { updateProductOptionGroup } = await adminClient.query(gql`
- mutation {
- updateProductOptionGroup(
- input: {
- id: "${productOptionGroupId}"
- customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(updateProductOptionGroup.customFields, 'T_2', ['T_3', 'T_4']);
- });
- let productOptionId: string;
- it('admin createProductOption', async () => {
- const { createProductOption } = await adminClient.query(gql`
- mutation {
- createProductOption(
- input: {
- productOptionGroupId: "${productOptionGroupId}"
- code: "test-option"
- translations: [{ languageCode: en, name: "test-option" }]
- customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(createProductOption.customFields, 'T_1', ['T_1', 'T_2']);
- productOptionId = createProductOption.id;
- });
- it('admin updateProductOption', async () => {
- const { updateProductOption } = await adminClient.query(gql`
- mutation {
- updateProductOption(
- input: {
- id: "${productOptionId}"
- customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(updateProductOption.customFields, 'T_2', ['T_3', 'T_4']);
- });
- });
- // describe('User entity', () => {
- // // Currently no GraphQL API to set User custom fields
- // });
- describe('ShippingMethod entity', () => {
- let shippingMethodId: string;
- it('admin createShippingMethod', async () => {
- const { createShippingMethod } = await adminClient.query(gql`
- mutation {
- createShippingMethod(
- input: {
- code: "test"
- calculator: {
- code: "${defaultShippingCalculator.code}"
- arguments: [
- { name: "rate" value: "10"},
- { name: "includesTax" value: "true"},
- { name: "taxRate" value: "10"},
- ]
- }
- checker: {
- code: "${defaultShippingEligibilityChecker.code}"
- arguments: [
- { name: "orderMinimum" value: "0"},
- ]
- }
- fulfillmentHandler: "${manualFulfillmentHandler.code}"
- translations: [{ languageCode: en, name: "test" description: "test" }]
- customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] }
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(createShippingMethod.customFields, 'T_1', ['T_1', 'T_2']);
- shippingMethodId = createShippingMethod.id;
- });
- it('admin updateShippingMethod', async () => {
- const { updateShippingMethod } = await adminClient.query(gql`
- mutation {
- updateShippingMethod(
- input: {
- id: "${shippingMethodId}"
- translations: []
- customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(updateShippingMethod.customFields, 'T_2', ['T_3', 'T_4']);
- });
- it('shop eligibleShippingMethods (ShippingMethodQuote)', async () => {
- const { eligibleShippingMethods } = await shopClient.query(gql`
- query {
- eligibleShippingMethods {
- id
- name
- code
- description
- ${customFieldsSelection}
- }
- }
- `);
- const testShippingMethodQuote = eligibleShippingMethods.find(
- (quote: any) => quote.code === 'test',
- );
- assertCustomFieldIds(testShippingMethodQuote.customFields, 'T_2', ['T_3', 'T_4']);
- });
- });
- describe('PaymentMethod entity', () => {
- let paymentMethodId: string;
- it('admin createShippingMethod', async () => {
- const { createPaymentMethod } = await adminClient.query(gql`
- mutation {
- createPaymentMethod(
- input: {
- code: "test"
- enabled: true
- handler: {
- code: "${testSuccessfulPaymentMethod.code}"
- arguments: []
- }
- customFields: { singleId: "T_1", multiIds: ["T_1", "T_2"] },
- translations: [{ languageCode: en, name: "test" }]
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(createPaymentMethod.customFields, 'T_1', ['T_1', 'T_2']);
- paymentMethodId = createPaymentMethod.id;
- });
- it('admin updatePaymentMethod', async () => {
- const { updatePaymentMethod } = await adminClient.query(gql`
- mutation {
- updatePaymentMethod(
- input: {
- id: "${paymentMethodId}"
- customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] },
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(updatePaymentMethod.customFields, 'T_2', ['T_3', 'T_4']);
- });
- it('shop eligiblePaymentMethods (PaymentMethodQuote)', async () => {
- const { eligiblePaymentMethods } = await shopClient.query(gql`
- query {
- eligiblePaymentMethods {
- id
- name
- description
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(eligiblePaymentMethods[0].customFields, 'T_2', ['T_3', 'T_4']);
- });
- });
- describe('Asset entity', () => {
- it('set custom field relations on Asset', async () => {
- const { updateAsset } = await adminClient.query(gql`
- mutation {
- updateAsset(
- input: {
- id: "T_1",
- customFields: { singleId: "T_2", multiIds: ["T_3", "T_4"] }
- }
- ) {
- id
- ${customFieldsSelection}
- }
- }
- `);
- assertCustomFieldIds(updateAsset.customFields, 'T_2', ['T_3', 'T_4']);
- });
- it('findOne on Asset', async () => {
- const { asset } = await adminClient.query(gql`
- query {
- asset(id: "T_1") {
- id
- ${customFieldsSelection}
- }
- }
- `);
- expect(asset.customFields.single.id).toBe('T_2');
- expect(asset.customFields.multi.length).toEqual(2);
- });
- // https://github.com/vendure-ecommerce/vendure/issues/1636
- it('calling TransactionalConnection.findOneInChannel() returns custom field relations', async () => {
- TestPlugin1636_1664.testResolverSpy.mockReset();
- await shopClient.query(gql`
- query {
- getAssetTest(id: "T_1")
- }
- `);
- const args = TestPlugin1636_1664.testResolverSpy.mock.calls[0];
- expect(args[0].customFields.single.id).toEqual(2);
- expect(args[0].customFields.multi.length).toEqual(2);
- });
- });
- });
- it('null values', async () => {
- const { updateCustomerAddress } = await adminClient.query(gql`
- mutation {
- updateCustomerAddress(
- input: { id: "T_1", customFields: { singleId: null, multiIds: ["T_1", "null"] } }
- ) {
- id
- customFields {
- single {
- id
- }
- multi {
- id
- }
- }
- }
- }
- `);
- expect(updateCustomerAddress.customFields.single).toEqual(null);
- expect(updateCustomerAddress.customFields.multi).toEqual([{ id: 'T_1' }]);
- });
- describe('bi-direction relations', () => {
- let customEntityRepository: Repository<TestCustomEntity>;
- let customEntity: TestCustomEntity;
- let collectionIdInternal: number;
- beforeAll(async () => {
- customEntityRepository = server.app
- .get(TransactionalConnection)
- .getRepository(RequestContext.empty(), TestCustomEntity);
- const customEntityId = (await customEntityRepository.save({})).id;
- const { createCollection } = await adminClient.query(gql`
- mutation {
- createCollection(
- input: {
- translations: [
- { languageCode: en, name: "Test", description: "test", slug: "test" }
- ]
- filters: []
- customFields: { customEntityListIds: [${customEntityId}] customEntityId: ${customEntityId} }
- }
- ) {
- id
- }
- }
- `);
- collectionIdInternal = parseInt(createCollection.id.replace('T_', ''), 10);
- customEntity = await assertFound(
- customEntityRepository.findOne({
- where: { id: customEntityId },
- relations: {
- customEntityInverse: true,
- customEntityListInverse: true,
- },
- }),
- );
- });
- it('can create inverse relation for list=false', () => {
- expect(customEntity.customEntityInverse).toEqual([
- expect.objectContaining({ id: collectionIdInternal }),
- ]);
- });
- it('can create inverse relation for list=true', () => {
- expect(customEntity.customEntityListInverse).toEqual([
- expect.objectContaining({ id: collectionIdInternal }),
- ]);
- });
- });
- });
|