import gql from 'graphql-tag'; import { getUser, startSessionAnonymously } from 'test/graphql'; import { getCustomRepository } from 'typeorm'; import { AggregateProductVariantSavesListRepository } from '@/repositories/AggregateProductVariantSavesListRepository'; import { AggregateProduct, AggregateProductVariant } from '@/entities'; describe('Query:savesLists', () => { const query = gql` query { savesLists { nodes { id variants { id } collaborators { id } createdBy { id } } } } `; test('should get all lists', async () => { const { execute, user } = await startSessionAnonymously(); const otherUser = await getUser(); const listRepo = getCustomRepository( AggregateProductVariantSavesListRepository ); const aggregateProduct = await AggregateProduct.save( AggregateProduct.create({ identifiers: ['test'], asin: 'asin', colorCode: 'colorCode', annotations: 'annotation', price: 100, description: 'description', dimensions: 'dimensions', discoverable: true, distributor: 'distributor', distributorSKU: 'distributor', imageUrls: ['http://test.com/test.jpg'], isAvailable: true, name: 'test', }) ); const aggregateProductVariant1 = await AggregateProductVariant.save( AggregateProductVariant.create({ identifiers: ['test'], product: aggregateProduct, asin: 'asin', colorCode: 'colorCode', annotations: 'annotation', price: 100, description: 'description', dimensions: 'dimensions', discoverable: true, distributor: 'distributor', distributorSKU: 'distributor', imageUrls: ['http://test.com/test1.jpg'], isAvailable: true, name: 'test', }) ); const aggregateProductVariant2 = await AggregateProductVariant.save( AggregateProductVariant.create({ identifiers: ['test1'], product: aggregateProduct, asin: 'asin', colorCode: 'otherColorCode', annotations: 'annotation', price: 5000, description: 'description', dimensions: 'dimensions', discoverable: true, distributor: 'distributor', distributorSKU: 'distributor', imageUrls: ['http://test.com/test2.jpg'], isAvailable: true, name: 'test', }) ); const list1 = await listRepo.create( { variantIds: [aggregateProductVariant1.id], }, user ); const list2 = await listRepo.create( { variantIds: [aggregateProductVariant2.id], collaboratorIds: [user.id], }, otherUser ); const response = await execute({ query: query, }); expect(response.errors?.length).toBeFalsy(); expect(response.data?.savesLists?.nodes).toHaveLength(2); expect(response.data?.savesLists?.nodes[0].id).toBe(list1.id); expect(response.data?.savesLists?.nodes[0].variants).toHaveLength(1); expect(response.data?.savesLists?.nodes[0].variants[0].id).toBe( aggregateProductVariant1.id ); expect(response.data?.savesLists?.nodes[0].collaborators).toHaveLength(0); expect(response.data?.savesLists?.nodes[0].createdBy.id).toBe(user.id); expect(response.data?.savesLists?.nodes[1].id).toBe(list2.id); expect(response.data?.savesLists?.nodes[1].variants).toHaveLength(1); expect(response.data?.savesLists?.nodes[1].variants[0].id).toBe( aggregateProductVariant2.id ); expect(response.data?.savesLists?.nodes[1].collaborators).toHaveLength(1); expect(response.data?.savesLists?.nodes[1].collaborators[0].id).toBe( user.id ); expect(response.data?.savesLists?.nodes[1].createdBy.id).toBe(otherUser.id); }); }); describe('Query:savedProducts', () => { const query = gql` query ($input: SavedProductsInput) { savedProducts(input: $input) { edges { node { id } } } } `; test('should return aggregate product variants of given aggregateProductVariantSavesList id', async () => { const { execute, user } = await startSessionAnonymously(); const listRepo = getCustomRepository( AggregateProductVariantSavesListRepository ); const aggregateProduct = await AggregateProduct.save( AggregateProduct.create({ identifiers: ['test'], asin: 'asin', colorCode: 'colorCode', annotations: 'annotation', price: 100, description: 'description', dimensions: 'dimensions', discoverable: true, distributor: 'distributor', distributorSKU: 'distributor', imageUrls: ['http://test.com/test.jpg'], isAvailable: true, name: 'test', }) ); const aggregateProductVariant = await AggregateProductVariant.save( AggregateProductVariant.create({ identifiers: ['test'], product: aggregateProduct, asin: 'asin', colorCode: 'colorCode', annotations: 'annotation', price: 100, description: 'description', dimensions: 'dimensions', discoverable: true, distributor: 'distributor', distributorSKU: 'distributor', imageUrls: ['http://test.com/test.jpg'], isAvailable: true, name: 'test', }) ); const list = await listRepo.create( { variantIds: [aggregateProductVariant.id], }, user ); const response = await execute({ query: query, variables: { input: { listId: list.id, }, }, }); expect(response.errors?.length).toBeFalsy(); expect(response.data?.savedProducts?.edges).toHaveLength(1); const ids = response.data?.savedProducts?.edges?.map((e: any) => e.node.id); expect(ids).toContain(aggregateProductVariant.id); const response1 = await execute({ query: query, variables: { input: {}, }, }); expect(response1.errors?.length).toBeFalsy(); expect(response1.data?.savedProducts?.edges).toHaveLength(1); const otherIds = response1.data?.savedProducts?.edges?.map( (e: any) => e.node.id ); expect(otherIds).toContain(aggregateProductVariant.id); }); }); describe('Mutation:createSavesList', () => { const query = gql` mutation ($input: CreateSavesListInput!) { createSavesList(input: $input) { savesList { id createdBy { id } variants { id } collaborators { id } viewerCanEdit } } } `; it('creates saves list', async () => { const { execute, user } = await startSessionAnonymously(); const anotherUser = await getUser(); const aggregateProduct = await AggregateProduct.save( AggregateProduct.create({ identifiers: ['test'], asin: 'asin', colorCode: 'colorCode', annotations: 'annotation', price: 100, description: 'description', dimensions: 'dimensions', discoverable: true, distributor: 'distributor', distributorSKU: 'distributor', imageUrls: ['http://test.com/test.jpg'], isAvailable: true, name: 'test', }) ); const aggregateProductVariant = await AggregateProductVariant.save( AggregateProductVariant.create({ identifiers: ['test'], product: aggregateProduct, asin: 'asin', colorCode: 'colorCode', annotations: 'annotation', price: 100, description: 'description', dimensions: 'dimensions', discoverable: true, distributor: 'distributor', distributorSKU: 'distributor', imageUrls: ['http://test.com/test.jpg'], isAvailable: true, name: 'test', }) ); const response = await execute({ query, variables: { input: { variantIds: [aggregateProductVariant.id], collaboratorIds: [anotherUser.id], }, }, }); expect(response.errors).toBeFalsy(); expect(response.data?.createSavesList.savesList.createdBy.id).toBe(user.id); expect(response.data?.createSavesList.savesList.viewerCanEdit).toBe(true); expect(response.data?.createSavesList.savesList.variants).toHaveLength(1); expect(response.data?.createSavesList.savesList.variants[0].id).toBe( aggregateProductVariant.id ); expect(response.data?.createSavesList.savesList.collaborators).toHaveLength( 1 ); expect(response.data?.createSavesList.savesList.collaborators[0].id).toBe( anotherUser.id ); }); }); describe('Mutation:updateSavesList', () => { const query = gql` mutation ($input: UpdateSavesListInput!) { updateSavesList(input: $input) { savesList { id createdBy { id } variants { id } collaborators { id } viewerCanEdit } } } `; it('updates saves list', async () => { const { execute, user } = await startSessionAnonymously(); const { user: otherUser, execute: executeAsOtherUser } = await startSessionAnonymously(); const aggregateProduct = await AggregateProduct.save( AggregateProduct.create({ identifiers: ['test'], asin: 'asin', colorCode: 'colorCode', annotations: 'annotation', price: 100, description: 'description', dimensions: 'dimensions', discoverable: true, distributor: 'distributor', distributorSKU: 'distributor', imageUrls: ['http://test.com/test.jpg'], isAvailable: true, name: 'test', }) ); const aggregateProductVariant = await AggregateProductVariant.save( AggregateProductVariant.create({ identifiers: ['test'], product: aggregateProduct, asin: 'asin', colorCode: 'colorCode', annotations: 'annotation', price: 100, description: 'description', dimensions: 'dimensions', discoverable: true, distributor: 'distributor', distributorSKU: 'distributor', imageUrls: ['http://test.com/test.jpg'], isAvailable: true, name: 'test', }) ); const list = await getCustomRepository( AggregateProductVariantSavesListRepository ).create( { variantIds: [aggregateProductVariant.id], }, user ); const response1 = await execute({ query, variables: { input: { listId: list.id, variantIds: [], collaboratorIds: [otherUser.id], }, }, }); expect(response1.errors).toBeFalsy(); expect(response1.data?.updateSavesList.savesList.createdBy.id).toBe( user.id ); expect(response1.data?.updateSavesList.savesList.viewerCanEdit).toBe(true); expect(response1.data?.updateSavesList.savesList.variants).toHaveLength(0); expect( response1.data?.updateSavesList.savesList.collaborators ).toHaveLength(1); expect(response1.data?.updateSavesList.savesList.collaborators[0].id).toBe( otherUser.id ); // collaborator can edit list const response2 = await executeAsOtherUser({ query, variables: { input: { listId: list.id, variantIds: [aggregateProductVariant.id], }, }, }); expect(response2.errors).toBeFalsy(); expect(response2.data?.updateSavesList.savesList.createdBy.id).toBe( user.id ); expect(response2.data?.updateSavesList.savesList.viewerCanEdit).toBe(true); expect(response2.data?.updateSavesList.savesList.variants).toHaveLength(1); expect(response2.data?.updateSavesList.savesList.variants[0].id).toBe( aggregateProductVariant.id ); expect( response2.data?.updateSavesList.savesList.collaborators ).toHaveLength(1); expect(response2.data?.updateSavesList.savesList.collaborators[0].id).toBe( otherUser.id ); const { execute: executeAsNonCollaborator } = await startSessionAnonymously(); // non collaborator cannot edit list const response3 = await executeAsNonCollaborator({ query, variables: { input: { listId: list.id, variantIds: [aggregateProductVariant.id], }, }, }); expect(response3.errors).toHaveLength(1); expect(response3.errors?.[0].message).toMatchInlineSnapshot( `"You must be a collaborator to update this product list."` ); expect(response3.data).toBeFalsy(); }); }); describe('Mutation:updateVariantsInList', () => { const query = gql` mutation ($input: UpdateVariantsInListInput!) { updateVariantsInList(input: $input) { savesList { id createdBy { id } variants { id } collaborators { id } viewerCanEdit } } } `; it('updates saves list', async () => { const { execute, user } = await startSessionAnonymously(); const aggregateProduct = await AggregateProduct.save( AggregateProduct.create({ identifiers: ['test'], asin: 'asin', colorCode: 'colorCode', annotations: 'annotation', price: 100, description: 'description', dimensions: 'dimensions', discoverable: true, distributor: 'distributor', distributorSKU: 'distributor', imageUrls: ['http://test.com/test.jpg'], isAvailable: true, name: 'test', }) ); const aggregateProductVariant1 = await AggregateProductVariant.save( AggregateProductVariant.create({ identifiers: ['test'], product: aggregateProduct, asin: 'asin', colorCode: 'colorCode', annotations: 'annotation', price: 100, description: 'description', dimensions: 'dimensions', discoverable: true, distributor: 'distributor', distributorSKU: 'distributor', imageUrls: ['http://test.com/test.jpg'], isAvailable: true, name: 'test', }) ); const aggregateProductVariant2 = await AggregateProductVariant.save( AggregateProductVariant.create({ identifiers: ['test2'], product: aggregateProduct, asin: 'asin', colorCode: 'colorCode', annotations: 'annotation', price: 100, description: 'description', dimensions: 'dimensions', discoverable: true, distributor: 'distributor', distributorSKU: 'distributor', imageUrls: ['http://test.com/test.jpg'], isAvailable: true, name: 'test', }) ); // creates new list if id is not given const response1 = await execute({ query, variables: { input: { variantIdsToAdd: [aggregateProductVariant1.id], }, }, }); expect(response1.errors).toBeFalsy(); expect(response1.data?.updateVariantsInList.savesList.id).toBeTruthy(); expect(response1.data?.updateVariantsInList.savesList.createdBy.id).toBe( user.id ); expect( response1.data?.updateVariantsInList.savesList.variants ).toHaveLength(1); expect(response1.data?.updateVariantsInList.savesList.variants[0].id).toBe( aggregateProductVariant1.id ); const list = await getCustomRepository( AggregateProductVariantSavesListRepository ).create( { variantIds: [aggregateProductVariant1.id], }, user ); // add variants ids const response2 = await execute({ query, variables: { listId: list.id, input: { variantIdsToAdd: [aggregateProductVariant2.id], }, }, }); expect(response2.errors).toBeFalsy(); expect(response2.data?.updateVariantsInList.savesList.id).toBe(list.id); expect(response2.data?.updateVariantsInList.savesList.createdBy.id).toBe( user.id ); expect(response2.data?.updateVariantsInList.savesList.viewerCanEdit).toBe( true ); expect( response2.data?.updateVariantsInList.savesList.variants ).toHaveLength(2); expect( response2.data?.updateVariantsInList.savesList.variants.find( (v: any) => v.id === aggregateProductVariant1.id ) ).toBeTruthy(); expect( response2.data?.updateVariantsInList.savesList.variants.find( (v: any) => v.id === aggregateProductVariant2.id ) ).toBeTruthy(); // remove variant ids const response3 = await execute({ query, variables: { input: { listId: list.id, variantIdsToRemove: [aggregateProductVariant1.id], }, }, }); expect(response3.errors).toBeFalsy(); expect(response3.data?.updateVariantsInList.savesList.id).toBe(list.id); expect(response3.data?.updateVariantsInList.savesList.createdBy.id).toBe( user.id ); expect(response3.data?.updateVariantsInList.savesList.viewerCanEdit).toBe( true ); expect( response3.data?.updateVariantsInList.savesList.variants ).toHaveLength(1); expect(response3.data?.updateVariantsInList.savesList.variants[0].id).toBe( aggregateProductVariant2.id ); }); it('lets user update another saves list', async () => { const { execute, user } = await startSessionAnonymously(); const anotherUser = await getUser(); const aggregateProduct = await AggregateProduct.save( AggregateProduct.create({ identifiers: ['test'], asin: 'asin', colorCode: 'colorCode', annotations: 'annotation', price: 100, description: 'description', dimensions: 'dimensions', discoverable: true, distributor: 'distributor', distributorSKU: 'distributor', imageUrls: ['http://test.com/test.jpg'], isAvailable: true, name: 'test', }) ); const aggregateProductVariant1 = await AggregateProductVariant.save( AggregateProductVariant.create({ identifiers: ['test'], product: aggregateProduct, asin: 'asin', colorCode: 'colorCode', annotations: 'annotation', price: 100, description: 'description', dimensions: 'dimensions', discoverable: true, distributor: 'distributor', distributorSKU: 'distributor', imageUrls: ['http://test.com/test.jpg'], isAvailable: true, name: 'test', }) ); const aggregateProductVariant2 = await AggregateProductVariant.save( AggregateProductVariant.create({ identifiers: ['test2'], product: aggregateProduct, asin: 'asin', colorCode: 'colorCode', annotations: 'annotation', price: 100, description: 'description', dimensions: 'dimensions', discoverable: true, distributor: 'distributor', distributorSKU: 'distributor', imageUrls: ['http://test.com/test.jpg'], isAvailable: true, name: 'test', }) ); const list = await getCustomRepository( AggregateProductVariantSavesListRepository ).create( { variantIds: [aggregateProductVariant1.id], }, anotherUser ); // cannot access list if not a collaborator const response1 = await execute({ query, variables: { input: { listId: list.id, variantIdsToAdd: [aggregateProductVariant2.id], }, }, }); expect(response1.errors).toHaveLength(1); expect(response1.errors?.[0].message).toMatchInlineSnapshot( `"You must be a collaborator to update this product list."` ); expect(response1.data).toBeFalsy(); // can access list if user is a collaborator await getCustomRepository( AggregateProductVariantSavesListRepository ).update( { id: list.id, collaboratorIds: [user.id], }, anotherUser ); const response2 = await execute({ query, variables: { input: { listId: list.id, variantIdsToAdd: [aggregateProductVariant2.id], }, }, }); expect(response2.errors).toBeFalsy(); expect(response2.data?.updateVariantsInList.savesList.id).toBe(list.id); expect(response2.data?.updateVariantsInList.savesList.createdBy.id).toBe( anotherUser.id ); expect(response2.data?.updateVariantsInList.savesList.viewerCanEdit).toBe( true ); expect( response2.data?.updateVariantsInList.savesList.variants ).toHaveLength(2); expect( response2.data?.updateVariantsInList.savesList.variants.find( (v: any) => v.id === aggregateProductVariant1.id ) ).toBeTruthy(); expect( response2.data?.updateVariantsInList.savesList.variants.find( (v: any) => v.id === aggregateProductVariant2.id ) ).toBeTruthy(); expect( response2.data?.updateVariantsInList.savesList.collaborators ).toHaveLength(1); expect( response2.data?.updateVariantsInList.savesList.collaborators[0].id ).toBe(user.id); }); });