| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- import { createTestEnvironment } from '@vendure/testing';
- import gql from 'graphql-tag';
- import path from 'path';
- 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 { omit } from '../../common/lib/omit';
- import { PRODUCT_OPTION_GROUP_FRAGMENT } from './graphql/fragments';
- import * as Codegen from './graphql/generated-e2e-admin-types';
- import { DeletionResult, LanguageCode } from './graphql/generated-e2e-admin-types';
- import {
- ADD_OPTION_GROUP_TO_PRODUCT,
- CREATE_PRODUCT,
- CREATE_PRODUCT_OPTION_GROUP,
- CREATE_PRODUCT_VARIANTS,
- DELETE_PRODUCT_VARIANT,
- } from './graphql/shared-definitions';
- import { assertThrowsWithMessage } from './utils/assert-throws-with-message';
- /* eslint-disable @typescript-eslint/no-non-null-assertion */
- describe('ProductOption resolver', () => {
- const { server, adminClient } = createTestEnvironment(testConfig());
- let sizeGroup: Codegen.ProductOptionGroupFragment;
- let mediumOption: Codegen.CreateProductOptionMutation['createProductOption'];
- beforeAll(async () => {
- await server.init({
- initialData,
- customerCount: 1,
- productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-minimal.csv'),
- });
- await adminClient.asSuperAdmin();
- }, TEST_SETUP_TIMEOUT_MS);
- afterAll(async () => {
- await server.destroy();
- });
- it('createProductOptionGroup', async () => {
- const { createProductOptionGroup } = await adminClient.query<
- Codegen.CreateProductOptionGroupMutation,
- Codegen.CreateProductOptionGroupMutationVariables
- >(CREATE_PRODUCT_OPTION_GROUP, {
- input: {
- code: 'size',
- translations: [
- { languageCode: LanguageCode.en, name: 'Size' },
- { languageCode: LanguageCode.de, name: 'Größe' },
- ],
- options: [
- {
- code: 'small',
- translations: [
- { languageCode: LanguageCode.en, name: 'Small' },
- { languageCode: LanguageCode.de, name: 'Klein' },
- ],
- },
- {
- code: 'large',
- translations: [
- { languageCode: LanguageCode.en, name: 'Large' },
- { languageCode: LanguageCode.de, name: 'Groß' },
- ],
- },
- ],
- },
- });
- expect(omit(createProductOptionGroup, ['options', 'translations'])).toEqual({
- id: 'T_3',
- name: 'Size',
- code: 'size',
- });
- sizeGroup = createProductOptionGroup;
- });
- it('updateProductOptionGroup', async () => {
- const { updateProductOptionGroup } = await adminClient.query<
- Codegen.UpdateProductOptionGroupMutation,
- Codegen.UpdateProductOptionGroupMutationVariables
- >(UPDATE_PRODUCT_OPTION_GROUP, {
- input: {
- id: sizeGroup.id,
- translations: [
- { id: sizeGroup.translations[0].id, languageCode: LanguageCode.en, name: 'Bigness' },
- ],
- },
- });
- expect(updateProductOptionGroup.name).toBe('Bigness');
- });
- it(
- 'createProductOption throws with invalid productOptionGroupId',
- assertThrowsWithMessage(async () => {
- const { createProductOption } = await adminClient.query<
- Codegen.CreateProductOptionMutation,
- Codegen.CreateProductOptionMutationVariables
- >(CREATE_PRODUCT_OPTION, {
- input: {
- productOptionGroupId: 'T_999',
- code: 'medium',
- translations: [
- { languageCode: LanguageCode.en, name: 'Medium' },
- { languageCode: LanguageCode.de, name: 'Mittel' },
- ],
- },
- });
- }, 'No ProductOptionGroup with the id "999" could be found'),
- );
- it('createProductOption', async () => {
- const { createProductOption } = await adminClient.query<
- Codegen.CreateProductOptionMutation,
- Codegen.CreateProductOptionMutationVariables
- >(CREATE_PRODUCT_OPTION, {
- input: {
- productOptionGroupId: sizeGroup.id,
- code: 'medium',
- translations: [
- { languageCode: LanguageCode.en, name: 'Medium' },
- { languageCode: LanguageCode.de, name: 'Mittel' },
- ],
- },
- });
- expect(omit(createProductOption, ['translations'])).toEqual({
- id: 'T_7',
- groupId: sizeGroup.id,
- code: 'medium',
- name: 'Medium',
- });
- mediumOption = createProductOption;
- });
- it('updateProductOption', async () => {
- const { updateProductOption } = await adminClient.query<
- Codegen.UpdateProductOptionMutation,
- Codegen.UpdateProductOptionMutationVariables
- >(UPDATE_PRODUCT_OPTION, {
- input: {
- id: 'T_7',
- translations: [
- { id: mediumOption.translations[0].id, languageCode: LanguageCode.en, name: 'Middling' },
- ],
- },
- });
- expect(updateProductOption.name).toBe('Middling');
- });
- describe('deletion', () => {
- let sizeOptionGroupWithOptions: NonNullable<Codegen.GetProductOptionGroupQuery['productOptionGroup']>;
- let variants: Codegen.CreateProductVariantsMutation['createProductVariants'];
- beforeAll(async () => {
- // Create a new product with a variant in each size option
- const { createProduct } = await adminClient.query<
- Codegen.CreateProductMutation,
- Codegen.CreateProductMutationVariables
- >(CREATE_PRODUCT, {
- input: {
- translations: [
- {
- languageCode: LanguageCode.en,
- name: 'T-shirt',
- slug: 't-shirt',
- description: 'A television set',
- },
- ],
- },
- });
- const result = await adminClient.query<
- Codegen.AddOptionGroupToProductMutation,
- Codegen.AddOptionGroupToProductMutationVariables
- >(ADD_OPTION_GROUP_TO_PRODUCT, {
- optionGroupId: sizeGroup.id,
- productId: createProduct.id,
- });
- const { productOptionGroup } = await adminClient.query<
- Codegen.GetProductOptionGroupQuery,
- Codegen.GetProductOptionGroupQueryVariables
- >(GET_PRODUCT_OPTION_GROUP, {
- id: sizeGroup.id,
- });
- const variantInput: Codegen.CreateProductVariantsMutationVariables['input'] =
- productOptionGroup!.options.map((option, i) => ({
- productId: createProduct.id,
- sku: `TS-${option.code}`,
- optionIds: [option.id],
- translations: [{ languageCode: LanguageCode.en, name: `T-shirt ${option.code}` }],
- }));
- const { createProductVariants } = await adminClient.query<
- Codegen.CreateProductVariantsMutation,
- Codegen.CreateProductVariantsMutationVariables
- >(CREATE_PRODUCT_VARIANTS, {
- input: variantInput,
- });
- variants = createProductVariants;
- sizeOptionGroupWithOptions = productOptionGroup!;
- });
- it(
- 'attempting to delete a non-existent id throws',
- assertThrowsWithMessage(
- () =>
- adminClient.query<
- Codegen.DeleteProductOptionMutation,
- Codegen.DeleteProductOptionMutationVariables
- >(DELETE_PRODUCT_OPTION, {
- id: '999999',
- }),
- 'No ProductOption with the id "999999" could be found',
- ),
- );
- it('cannot delete ProductOption that is used by a ProductVariant', async () => {
- const { deleteProductOption } = await adminClient.query<
- Codegen.DeleteProductOptionMutation,
- Codegen.DeleteProductOptionMutationVariables
- >(DELETE_PRODUCT_OPTION, {
- id: sizeOptionGroupWithOptions.options.find(o => o.code === 'medium')!.id,
- });
- expect(deleteProductOption.result).toBe(DeletionResult.NOT_DELETED);
- expect(deleteProductOption.message).toBe(
- 'Cannot delete the option "medium" as it is being used by 1 ProductVariant',
- );
- });
- it('can delete ProductOption after deleting associated ProductVariant', async () => {
- const { deleteProductVariant } = await adminClient.query<
- Codegen.DeleteProductVariantMutation,
- Codegen.DeleteProductVariantMutationVariables
- >(DELETE_PRODUCT_VARIANT, {
- id: variants.find(v => v!.name.includes('medium'))!.id,
- });
- expect(deleteProductVariant.result).toBe(DeletionResult.DELETED);
- const { deleteProductOption } = await adminClient.query<
- Codegen.DeleteProductOptionMutation,
- Codegen.DeleteProductOptionMutationVariables
- >(DELETE_PRODUCT_OPTION, {
- id: sizeOptionGroupWithOptions.options.find(o => o.code === 'medium')!.id,
- });
- expect(deleteProductOption.result).toBe(DeletionResult.DELETED);
- });
- it('deleted ProductOptions not included in query result', async () => {
- const { productOptionGroup } = await adminClient.query<
- Codegen.GetProductOptionGroupQuery,
- Codegen.GetProductOptionGroupQueryVariables
- >(GET_PRODUCT_OPTION_GROUP, {
- id: sizeGroup.id,
- });
- expect(productOptionGroup?.options.length).toBe(2);
- expect(productOptionGroup?.options.findIndex(o => o.code === 'medium')).toBe(-1);
- });
- });
- });
- const GET_PRODUCT_OPTION_GROUP = gql`
- query GetProductOptionGroup($id: ID!) {
- productOptionGroup(id: $id) {
- id
- code
- name
- options {
- id
- code
- name
- }
- }
- }
- `;
- const UPDATE_PRODUCT_OPTION_GROUP = gql`
- mutation UpdateProductOptionGroup($input: UpdateProductOptionGroupInput!) {
- updateProductOptionGroup(input: $input) {
- ...ProductOptionGroup
- }
- }
- ${PRODUCT_OPTION_GROUP_FRAGMENT}
- `;
- const CREATE_PRODUCT_OPTION = gql`
- mutation CreateProductOption($input: CreateProductOptionInput!) {
- createProductOption(input: $input) {
- id
- code
- name
- groupId
- translations {
- id
- languageCode
- name
- }
- }
- }
- `;
- const UPDATE_PRODUCT_OPTION = gql`
- mutation UpdateProductOption($input: UpdateProductOptionInput!) {
- updateProductOption(input: $input) {
- id
- code
- name
- groupId
- }
- }
- `;
- const DELETE_PRODUCT_OPTION = gql`
- mutation DeleteProductOption($id: ID!) {
- deleteProductOption(id: $id) {
- result
- message
- }
- }
- `;
|