From 97600f5730c8cb2a8b8c41b99177d73cdac7e5f0 Mon Sep 17 00:00:00 2001 From: Nhu Dinh Date: Fri, 29 Aug 2025 11:46:55 +0700 Subject: [PATCH 01/14] Added tests for media delivery api --- .../DeliveryApi/MediaDeliveryApi.spec.ts | 435 ++++++++++++++++++ 1 file changed, 435 insertions(+) create mode 100644 tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/MediaDeliveryApi.spec.ts diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/MediaDeliveryApi.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/MediaDeliveryApi.spec.ts new file mode 100644 index 000000000000..4aecadd2965d --- /dev/null +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/MediaDeliveryApi.spec.ts @@ -0,0 +1,435 @@ +import {expect} from '@playwright/test'; +import {AliasHelper} from '@umbraco/json-models-builders'; +import {test} from '@umbraco/playwright-testhelpers'; + +// Media Folder +const rootMediaFolderName = 'RootMediaFolder'; +const childMediaFolderName = 'ChildMediaFolder'; +// Media Items +const rootImageName = 'RootImage'; +const rootArticleName = 'RootArticle'; +const rootAudioName = 'RootAudio'; +const rootSVGName = 'RootSVG'; +const rootCustomMediaName = 'TestCustomMedia' +const fileName = 'TestFile'; +const videoName = 'TestVideo'; +const imageSizeNamePrefix = 'Test Image Size'; +const rootImageSizeNamePrefix = 'Root Test Image Size'; +const specialCharacterImageName = ', . ! ? # $ % & * @ é ü ă đ 漢字' +// Media Type +const customMediaTypeName = 'CustomMediaType'; +// Data Type +const textStringDataType = 'Textstring'; +const textStringValue = 'This is a test textstring'; +// Constant +const imageSize = 3; +const rootImageSize = 5; + +test.describe('Media Delivery API', () => { + test.beforeAll(async ({umbracoApi}) => { + // Create a root level folder + const rootFolderId = await umbracoApi.media.createDefaultMediaFolder(rootMediaFolderName); + // Create child folder + const childFolderId = await umbracoApi.media.createDefaultMediaFolderAndParentId(childMediaFolderName, rootFolderId); + // Create an image item at root level + await umbracoApi.media.createDefaultMediaWithImage(rootImageName); + // Create a article file item at root level + await umbracoApi.media.createDefaultMediaWithArticle(rootArticleName); + // Create an audio item at root level + await umbracoApi.media.createDefaultMediaWithAudio(rootAudioName); + // Create an vector graphic item at root level + await umbracoApi.media.createDefaultMediaWithSVG(rootSVGName); + // Create a file item in the child folder + await umbracoApi.media.createDefaultMediaFileAndParentId(fileName, childFolderId); + // Create a video item in the child folder + await umbracoApi.media.createDefaultMediaWithVideoAndParentId(videoName, childFolderId); + // Create multiple image items in the child folder, named have prefix imageSizeNamePrefix + for (let i = 1; i <= imageSize; i++) { + await umbracoApi.media.createDefaultMediaWithImageAndParentId(imageSizeNamePrefix + i, childFolderId); + } + // Create multiple image items in the root folder, named have prefix rootImageSizeNamePrefix + for (let i = 1; i <= rootImageSize; i++) { + await umbracoApi.media.createDefaultMediaWithImage(rootImageSizeNamePrefix + i); + } + // Create custom media item at root level + await umbracoApi.media.createDefaultMediaWithTextstring(rootCustomMediaName, customMediaTypeName, textStringValue, textStringDataType); + // Create an image item at root level and its name has special characters + await umbracoApi.media.createDefaultMediaWithImage(specialCharacterImageName); + }); + + test.afterAll(async ({umbracoApi}) => { + await umbracoApi.media.ensureNameNotExists(rootMediaFolderName); + await umbracoApi.media.ensureNameNotExists(childMediaFolderName); + await umbracoApi.media.ensureNameNotExists(rootImageName); + await umbracoApi.media.ensureNameNotExists(rootArticleName); + await umbracoApi.media.ensureNameNotExists(rootAudioName); + await umbracoApi.media.ensureNameNotExists(rootSVGName); + await umbracoApi.media.ensureNameNotExists(fileName); + await umbracoApi.media.ensureNameNotExists(videoName); + await umbracoApi.media.ensureNameNotExists(specialCharacterImageName); + for (let i = 1; i <= imageSize; i++) { + await umbracoApi.media.ensureNameNotExists(imageSizeNamePrefix + i); + } + for (let i = 1; i <= rootImageSize; i++) { + await umbracoApi.media.ensureNameNotExists(rootImageSizeNamePrefix + i); + } + await umbracoApi.media.ensureNameNotExists(rootCustomMediaName); + await umbracoApi.mediaType.ensureNameNotExists(customMediaTypeName); + }); + + // Gets a media item by id + test('can fetch an image item by its ID', async ({umbracoApi}) => { + // Arrange + const mediaTypeName = 'Image'; + const mediaData = await umbracoApi.media.getByName(rootImageName); + const mediaPath = '/' + rootImageName.toLowerCase() + '/'; + + // Act + const mediaItem = await umbracoApi.mediaDeliveryApi.getMediaItemWithId(mediaData.id); + + // Assert + expect(mediaItem.status()).toBe(200); + const mediaItemJson = await mediaItem.json(); + await umbracoApi.mediaDeliveryApi.verifyDefaultMediaItemJson(rootImageName, mediaItemJson, mediaPath, mediaTypeName); + }); + + test('can fetch an audio item by its ID', async ({umbracoApi}) => { + // Arrange + const mediaTypeName = 'Audio'; + const mediaData = await umbracoApi.media.getByName(rootAudioName); + const mediaPath = '/' + rootAudioName.toLowerCase() + '/'; + + // Act + const mediaItem = await umbracoApi.mediaDeliveryApi.getMediaItemWithId(mediaData.id); + + // Assert + expect(mediaItem.status()).toBe(200); + const mediaItemJson = await mediaItem.json(); + await umbracoApi.mediaDeliveryApi.verifyDefaultMediaItemJson(rootAudioName, mediaItemJson, mediaPath, mediaTypeName); + }); + + test('can fetch a vector graphics item by its ID', async ({umbracoApi}) => { + // Arrange + const mediaTypeName = 'Vector Graphics (SVG)'; + const mediaData = await umbracoApi.media.getByName(rootSVGName); + const mediaPath = '/' + rootSVGName.toLowerCase() + '/'; + + // Act + const mediaItem = await umbracoApi.mediaDeliveryApi.getMediaItemWithId(mediaData.id); + + // Assert + expect(mediaItem.status()).toBe(200); + const mediaItemJson = await mediaItem.json(); + await umbracoApi.mediaDeliveryApi.verifyDefaultMediaItemJson(rootSVGName, mediaItemJson, mediaPath, mediaTypeName); + }); + + test('can fetch a media folder by its ID', async ({umbracoApi}) => { + // Arrange + const mediaTypeName = 'Folder'; + const mediaData = await umbracoApi.media.getByName(rootMediaFolderName); + const mediaPath = '/' + rootMediaFolderName.toLowerCase() + '/'; + + // Act + const mediaItem = await umbracoApi.mediaDeliveryApi.getMediaItemWithId(mediaData.id); + + // Assert + expect(mediaItem.status()).toBe(200); + const mediaItemJson = await mediaItem.json(); + await umbracoApi.mediaDeliveryApi.verifyDefaultMediaItemJson(rootMediaFolderName, mediaItemJson, mediaPath, mediaTypeName); + }); + + test('can fetch a media item in a folder in a folder by its ID', async ({umbracoApi}) => { + // Arrange + const mediaTypeName = 'File'; + const mediaData = await umbracoApi.media.getByName(fileName); + const mediaPath = '/' + rootMediaFolderName.toLowerCase() + '/' + childMediaFolderName.toLowerCase() + '/' + fileName.toLowerCase() + '/'; + + // Act + const mediaItem = await umbracoApi.mediaDeliveryApi.getMediaItemWithId(mediaData.id); + + // Assert + expect(mediaItem.status()).toBe(200); + const mediaItemJson = await mediaItem.json(); + await umbracoApi.mediaDeliveryApi.verifyDefaultMediaItemJson(fileName, mediaItemJson, mediaPath, mediaTypeName); + }); + + test('can fetch an custom media item by its ID', async ({umbracoApi}) => { + // Arrange + const mediaData = await umbracoApi.media.getByName(rootCustomMediaName); + const mediaPath = '/' + rootCustomMediaName.toLowerCase() + '/'; + + // Act + const mediaItem = await umbracoApi.mediaDeliveryApi.getMediaItemWithId(mediaData.id); + + // Assert + expect(mediaItem.status()).toBe(200); + const mediaItemJson = await mediaItem.json(); + await umbracoApi.mediaDeliveryApi.verifyDefaultMediaItemJson(rootCustomMediaName, mediaItemJson, mediaPath, customMediaTypeName); + expect(mediaItemJson.properties[AliasHelper.toAlias(textStringDataType)]).toBe(textStringValue); + }); + + test('returns 404 when fetching a non-existent media item', async ({umbracoApi}) => { + // Arrange + const nonExistentMediaId = '00000000-0000-0000-0000-000000000000'; + + // Act + const mediaItem = await umbracoApi.mediaDeliveryApi.getMediaItemWithId(nonExistentMediaId); + + // Assert + expect(mediaItem.status()).toBe(404); + }); + + test('returns 401 when fetching a media item without proper authorization', async ({umbracoApi}) => { + }); + + // Gets a media item by path + test('can fetch an media item by its path', async ({umbracoApi}) => { + // Arrange + const mediaTypeName = 'Article'; + const mediaPath = '/' + rootArticleName.toLowerCase() + '/'; + + // Act + const mediaItem = await umbracoApi.mediaDeliveryApi.getMediaItemWithPath(mediaPath); + + // Assert + expect(mediaItem.status()).toBe(200); + const mediaItemJson = await mediaItem.json(); + await umbracoApi.mediaDeliveryApi.verifyDefaultMediaItemJson(rootArticleName, mediaItemJson, mediaPath, mediaTypeName); + }); + + // This test fails because it will return 404 error if the path includes # or ? + test('can fetch an media item by its path with special character', async ({umbracoApi}) => { + // Arrange + const mediaTypeName = 'Image'; + const mediaPath = '/' + specialCharacterImageName.toLowerCase() + '/'; + + // Act + const mediaItem = await umbracoApi.mediaDeliveryApi.getMediaItemWithPath(mediaPath); + + // Assert + expect(mediaItem.status()).toBe(200); + const mediaItemJson = await mediaItem.json(); + await umbracoApi.mediaDeliveryApi.verifyDefaultMediaItemJson(specialCharacterImageName, mediaItemJson, mediaPath, mediaTypeName); + }); + + test('can fetch a media folder in a folder by its path', async ({umbracoApi}) => { + // Arrange + const mediaTypeName = 'Folder'; + const mediaPath = '/' + rootMediaFolderName.toLowerCase() + '/' + childMediaFolderName.toLowerCase() + '/'; + + // Act + const mediaItem = await umbracoApi.mediaDeliveryApi.getMediaItemWithPath(mediaPath); + + // Assert + expect(mediaItem.status()).toBe(200); + const mediaItemJson = await mediaItem.json(); + await umbracoApi.mediaDeliveryApi.verifyDefaultMediaItemJson(childMediaFolderName, mediaItemJson, mediaPath, mediaTypeName); + }); + + test('can fetch a media item in a folder in a folder by its path', async ({umbracoApi}) => { + // Arrange + const mediaTypeName = 'Video'; + const mediaPath = '/' + rootMediaFolderName.toLowerCase() + '/' + childMediaFolderName.toLowerCase() + '/' + videoName.toLowerCase() + '/'; + + // Act + const mediaItem = await umbracoApi.mediaDeliveryApi.getMediaItemWithId(mediaPath); + + // Assert + expect(mediaItem.status()).toBe(200); + const mediaItemJson = await mediaItem.json(); + await umbracoApi.mediaDeliveryApi.verifyDefaultMediaItemJson(videoName, mediaItemJson, mediaPath, mediaTypeName); + }); + + test('returns 404 when fetching a non-existent media path', async ({umbracoApi}) => { + // Arrange + const nonExistentMediaPath = '/non-existent-media-path/'; + + // Act + const mediaItem = await umbracoApi.mediaDeliveryApi.getMediaItemWithPath(nonExistentMediaPath); + + // Assert + expect(mediaItem.status()).toBe(404); + }); + + test('returns 401 when fetching a media item by path without proper authorization', async ({umbracoApi}) => { + }); + + // Gets media item(s) by id + test('can fetch multiple media items by their IDs', async ({umbracoApi}) => { + // Arrange + const firstMediaName = rootImageSizeNamePrefix + '1'; + const secondMediaName = childMediaFolderName; + const mediaNames = [firstMediaName, secondMediaName]; + const firstMediaPath = '/' + firstMediaName.toLowerCase() + '/'; + const secondMediaPath = '/' + rootMediaFolderName.toLowerCase() + '/' + childMediaFolderName.toLowerCase() + '/'; + const mediaPaths = [firstMediaPath, secondMediaPath]; + const mediaTypeNames = ['Image', 'Folder']; + const firstMediaData = await umbracoApi.media.getByName(firstMediaName); + const secondMediaData = await umbracoApi.media.getByName(secondMediaName); + const mediaIds = [firstMediaData.id, secondMediaData.id]; + + // Act + const mediaItems = await umbracoApi.mediaDeliveryApi.getMediaItemsWithIds(mediaIds); + + // Assert + expect(mediaItems.status()).toBe(200); + const mediaItemsJson = await mediaItems.json(); + await umbracoApi.mediaDeliveryApi.verifyMutipleMediaItemsJson(mediaNames, mediaItemsJson, mediaPaths, mediaTypeNames); + }); + + test('returns only valid media items when some IDs are invalid', async ({umbracoApi}) => { + // Arrange + const validMediaName = rootArticleName; + const validMediaPath = '/' + validMediaName.toLowerCase() + '/'; + const validMediaTypeName = 'Article'; + const validMediaId = await umbracoApi.media.getByName(validMediaName); + const nonExistentMediaId = '00000000-0000-0000-0000-000000000000'; + const mediaIds = [validMediaId.id, nonExistentMediaId]; + + // Act + const mediaItems = await umbracoApi.mediaDeliveryApi.getMediaItemsWithIds(mediaIds); + + // Assert + expect(mediaItems.status()).toBe(200); + const mediaItemsJson = await mediaItems.json(); + await umbracoApi.mediaDeliveryApi.verifyMutipleMediaItemsJson([validMediaName], mediaItemsJson, [validMediaPath], [validMediaTypeName]); + }); + + // Gets media item(s) from a query + test('can fetch children at root', async ({umbracoApi}) => { + // Arrange + const fetch = 'children:/'; + const rootItems = await umbracoApi.media.getAllAtRoot(); + const rootItemsJson = await rootItems.json(); + + // Act + const mediaItems = await umbracoApi.mediaDeliveryApi.getMediaItemsFromAQuery(fetch); + + // Assert + expect(mediaItems).not.toBeNull(); + if (mediaItems !== null) { + expect(mediaItems.status()).toBe(200); + const mediaItemsJson = await mediaItems.json(); + expect(mediaItemsJson.total).toBe(rootItemsJson.total); + } + }); + + test('can fetch children of a media folder', async ({umbracoApi}) => { + // Arrange + const mediaFolderData = await umbracoApi.media.getByName(childMediaFolderName); + const fetch = 'children:/' + rootMediaFolderName.toLowerCase() + '/' + childMediaFolderName.toLowerCase() + '/'; + const childrenItems = await umbracoApi.media.getChildren(mediaFolderData.id); + + // Act + const mediaItems = await umbracoApi.mediaDeliveryApi.getMediaItemsFromAQuery(fetch); + + // Assert + expect(mediaItems).not.toBeNull(); + if (mediaItems !== null) { + expect(mediaItems.status()).toBe(200); + const mediaItemsJson = await mediaItems.json(); + expect(mediaItemsJson.total).toBe(childrenItems.length); + } + }); + + test('can filter media items', async ({umbracoApi}) => { + // Arrange + const fetch = 'children:/' + rootMediaFolderName.toLowerCase() + '/' + childMediaFolderName.toLowerCase() + '/'; + const filter = 'name:' + imageSizeNamePrefix; + + // Act + const mediaItems = await umbracoApi.mediaDeliveryApi.getMediaItemsFromAQuery(fetch, filter); + + // Assert + expect(mediaItems).not.toBeNull(); + if (mediaItems !== null) { + expect(mediaItems.status()).toBe(200); + const mediaItemsJson = await mediaItems.json(); + expect(mediaItemsJson.total).toBe(imageSize); + } + }); + + test('can sort media items', async ({umbracoApi}) => { + // Arrange + const fetch = 'children:/' + rootMediaFolderName.toLowerCase() + '/' + childMediaFolderName.toLowerCase() + '/'; + const filter = 'name:' + imageSizeNamePrefix; + const sort = 'name:desc'; + + // Act + const mediaItems = await umbracoApi.mediaDeliveryApi.getMediaItemsFromAQuery(fetch, filter, sort); + + // Assert + expect(mediaItems).not.toBeNull(); + if (mediaItems !== null) { + expect(mediaItems.status()).toBe(200); + const mediaItemsJson = await mediaItems.json(); + for (let i = 0; i < mediaItemsJson.items.length; i++) { + expect(mediaItemsJson.items[i].name).toBe(imageSizeNamePrefix + (imageSize - i)); + } + } + }); + + // This test fails because it still returns all media items and ignores the 'take' parameter. + test('can paginate media items', async ({umbracoApi}) => { + // Arrange + const fetch = 'children:/'; + const filter = 'mediaType:' + 'Image'; + const skip = 0; + const take = rootImageSize; + + // Act + const mediaItems = await umbracoApi.mediaDeliveryApi.getMediaItemsFromAQuery(fetch, filter, undefined, skip, take); + + // Assert + expect(mediaItems).not.toBeNull(); + if (mediaItems !== null) { + expect(mediaItems.status()).toBe(200); + const mediaItemsJson = await mediaItems.json(); + expect(mediaItemsJson.total).toBe(take); + } + }); + + test('returns 400 when using an invalid sort parameter', async ({umbracoApi}) => { + // Arrange + const fetch = 'children:/'; + const invalidSort= 'invalidSort'; + + // Act + const mediaItems = await umbracoApi.mediaDeliveryApi.getMediaItemsFromAQuery(fetch, undefined, invalidSort); + + // Assert + expect(mediaItems).not.toBeNull(); + if (mediaItems !== null) { + expect(mediaItems.status()).toBe(400); + } + }); + + test('returns 400 when using an invalid filter parameter', async ({umbracoApi}) => { + // Arrange + const fetch = 'children:/'; + const invalidFilter = 'invalidFilter'; + + // Act + const mediaItems = await umbracoApi.mediaDeliveryApi.getMediaItemsFromAQuery(fetch, invalidFilter); + + // Assert + expect(mediaItems).not.toBeNull(); + if (mediaItems !== null) { + expect(mediaItems.status()).toBe(400); + } + }); + + test('returns 400 when using an invalid fetch type', async ({umbracoApi}) => { + // Arrange + const fetch = 'invalid:/'; + + // Act + const mediaItems = await umbracoApi.mediaDeliveryApi.getMediaItemsFromAQuery(fetch); + + // Assert + expect(mediaItems).not.toBeNull(); + if (mediaItems !== null) { + expect(mediaItems.status()).toBe(400); + } + }); +}); \ No newline at end of file From 1013a04972b2bff2a8e62fedbdfae135166840d5 Mon Sep 17 00:00:00 2001 From: Nhu Dinh Date: Fri, 29 Aug 2025 11:47:09 +0700 Subject: [PATCH 02/14] Added tests for content delivery api --- .../DeliveryApi/ContentDeliveryApi.spec.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts new file mode 100644 index 000000000000..ffbcf96d4572 --- /dev/null +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts @@ -0,0 +1,27 @@ +import {expect} from '@playwright/test'; +import {AliasHelper, test} from '@umbraco/playwright-testhelpers'; + +test('can get content from delivery api', async ({umbracoApi}) => { + // Arrange + const documentTypeName = 'TestDocumentType'; + const contentName = 'TestContent'; + const dataTypeName = 'Textstring'; + const textStringValue = 'This is a test text string value'; + await umbracoApi.documentType.ensureNameNotExists(documentTypeName); + const dataType = await umbracoApi.dataType.getByName(dataTypeName); + const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, dataTypeName, dataType.id, 'TestGroup'); + const documentId = await umbracoApi.document.createDocumentWithTextContent(contentName, documentTypeId, textStringValue, dataTypeName); + const propertyValue = { + dataTypeName: AliasHelper.toAlias(dataTypeName), + dataTypeValue: textStringValue + } + + // Act + await umbracoApi.document.publish(documentId); + + // Assert + expect(await umbracoApi.contentDeliveryApi.doesContentItemWithIdContainValues(documentId, contentName, AliasHelper.toAlias(documentTypeName), [propertyValue])).toBeTruthy(); + + // Clean + await umbracoApi.documentType.ensureNameNotExists(documentTypeName); +}); From b36f7c6f07acd75438f2410f8345c34cdaa27f46 Mon Sep 17 00:00:00 2001 From: Nhu Dinh Date: Fri, 29 Aug 2025 11:48:30 +0700 Subject: [PATCH 03/14] Fixed import --- .../tests/DeliveryApi/MediaDeliveryApi.spec.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/MediaDeliveryApi.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/MediaDeliveryApi.spec.ts index 4aecadd2965d..50525aac413f 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/MediaDeliveryApi.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/MediaDeliveryApi.spec.ts @@ -1,6 +1,5 @@ import {expect} from '@playwright/test'; -import {AliasHelper} from '@umbraco/json-models-builders'; -import {test} from '@umbraco/playwright-testhelpers'; +import {test, AliasHelper} from '@umbraco/playwright-testhelpers'; // Media Folder const rootMediaFolderName = 'RootMediaFolder'; From 46275d9e7d652d5811e7a62fd169112c369977b1 Mon Sep 17 00:00:00 2001 From: Nhu Dinh Date: Fri, 5 Sep 2025 16:49:06 +0700 Subject: [PATCH 04/14] Added tests for Content Delivery API --- .../DeliveryApi/ContentDeliveryApi.spec.ts | 545 +++++++++++++++++- 1 file changed, 520 insertions(+), 25 deletions(-) diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts index ffbcf96d4572..e7e3b28d6067 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts @@ -1,27 +1,522 @@ import {expect} from '@playwright/test'; -import {AliasHelper, test} from '@umbraco/playwright-testhelpers'; - -test('can get content from delivery api', async ({umbracoApi}) => { - // Arrange - const documentTypeName = 'TestDocumentType'; - const contentName = 'TestContent'; - const dataTypeName = 'Textstring'; - const textStringValue = 'This is a test text string value'; - await umbracoApi.documentType.ensureNameNotExists(documentTypeName); - const dataType = await umbracoApi.dataType.getByName(dataTypeName); - const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, dataTypeName, dataType.id, 'TestGroup'); - const documentId = await umbracoApi.document.createDocumentWithTextContent(contentName, documentTypeId, textStringValue, dataTypeName); - const propertyValue = { - dataTypeName: AliasHelper.toAlias(dataTypeName), - dataTypeValue: textStringValue - } - - // Act - await umbracoApi.document.publish(documentId); - - // Assert - expect(await umbracoApi.contentDeliveryApi.doesContentItemWithIdContainValues(documentId, contentName, AliasHelper.toAlias(documentTypeName), [propertyValue])).toBeTruthy(); - - // Clean - await umbracoApi.documentType.ensureNameNotExists(documentTypeName); +import {test} from '@umbraco/playwright-testhelpers'; +import { text } from 'stream/consumers'; + +// Document +const publishInvRootContent = 'Publish Invariant Root'; +const publishInvParentContent = 'Publish Invariant Parent'; +const childPublishInvContentPrefix = 'Child Publish Invariant'; +const publishInvContentWithTextstring = 'Publish Invariant With Textstring'; +const publishInvContentWithNumeric = 'Publish Invariant With Numeric'; +const publishInvContentWithTrueFalse = 'Publish Invariant With True/False'; +const publishInvContentWithMultiUrlPicker = 'Publish Invariant With Multi URL Picker'; +const unpublishInvRootContent = 'Unpublish Invariant Root'; +const publishVariantRootContent = 'Publish Variant Root'; +const publishInvContentWithSpecialCharacters = 'Test Content, . ! ? # $ % & * @ é ü ă đ 漢字'; +// Document Type +const invariantDocumentType = 'Invariant Document Type'; +const collectionDocumentType = 'Collection Document Type'; +const invariantDocumentTypeWithTextString = 'Invariant Document Type With Textstring'; +const invariantDocumentTypeWithTrueFalse = 'Invariant Document Type With True False'; +const invariantDocumentTypeWithNumeric = 'Invariant Document Type With Numeric'; +const invariantDocumentTypeWithMultiUrlPicker = 'Invariant Document Type With Multi URL Picker Property'; +const variantDocumentTypeWithTextstring = 'Variant Document Type With Textstring'; +// Data Type +const textstringDataTypeName = 'Textstring'; +const trueFalseDataTypeName = 'True/false'; +const numericDataTypeName = 'Numeric'; +const listViewContentTypeName = 'List View - Content'; +const multiUrlPickerDataTypeName = 'Multi URL Picker'; +// Property Values +const textPropertyValue = 'This is an invariant text string value'; +const numericPropertyValue = '1234'; +const trueFalsePropertyValue = true; +// Template +const templateName = 'TestTemplateForContentDeliveryApi'; +let templateId = null; +// Others +const childContentAmount = 5; + + +test.describe('Content Delivery API tests', () => { + // test.beforeAll(async ({umbracoApi}) => { + // //Create a template + // templateId = await umbracoApi.template.createDefaultTemplate(templateName); + // // Create 3 languges (en-US, da, vi) + // await umbracoApi.language.createDanishLanguage(); + // await umbracoApi.language.createVietnameseLanguage(); + // //Get data types + // const listViewDataType = await umbracoApi.dataType.getByName(listViewContentTypeName); + // // Create document types + // const invariantDocTypeId = await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(invariantDocumentType); + // const collectionDocTypeId = await umbracoApi.documentType.createDocumentTypeWithAllowedChildNodeAndCollectionId(collectionDocumentType, invariantDocTypeId, listViewDataType.id); + // // Create a publish invariant content item at root + // const publishInvRootId = await umbracoApi.document.createDefaultDocument(publishInvRootContent, invariantDocTypeId); + // await umbracoApi.document.publish(publishInvRootId); + // // Create a publish invariant parent item at root + // const publishInvParentId = await umbracoApi.document.createDefaultDocument(publishInvParentContent, collectionDocTypeId);; + // await umbracoApi.document.publish(publishInvParentId); + // // Create publish invariant child items + // for (let i = 1; i <= childContentAmount; i++) { + // const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvContentPrefix + i, invariantDocTypeId, publishInvParentId); + // await umbracoApi.document.publish(childId); + // } + // // Create an unpublish invariant content item at root + // await umbracoApi.document.createDefaultDocument(unpublishInvRootContent, invariantDocTypeId); + // // Create a publish invariant content item with special characters at root + // const publishInvContentWithSpecialCharactersId = await umbracoApi.document.createDefaultDocument(publishInvContentWithSpecialCharacters, invariantDocTypeId); + // await umbracoApi.document.publish(publishInvContentWithSpecialCharactersId); + // // Create a publish variant content item at root + // const textStringDataType = await umbracoApi.dataType.getByName(textstringDataTypeName); + // const variantDocTypeId = await umbracoApi.documentType.createVariantDocumentTypeWithInvariantPropertyEditor(variantDocumentTypeWithTextstring, textstringDataTypeName, textStringDataType.id); + // const publishVariantRootId = await umbracoApi.document.createDocumentWithEnglishCultureAndTextContent(publishVariantRootContent, variantDocTypeId, textPropertyValue, textstringDataTypeName); + // await umbracoApi.document.publishDocumentWithCulture(publishVariantRootId, 'en-US'); + // }); + + test.afterAll(async ({umbracoApi}) => { + // await umbracoApi.document.ensureNameNotExists(publishInvRootContent); + // await umbracoApi.document.ensureNameNotExists(publishInvParentContent); + // for (let i = 1; i <= childContentAmount; i++) { + // await umbracoApi.document.ensureNameNotExists(childPublishInvContentPrefix + i); + // } + // await umbracoApi.document.ensureNameNotExists(unpublishInvRootContent); + // await umbracoApi.documentType.ensureNameNotExists(invariantDocumentType); + // await umbracoApi.documentType.ensureNameNotExists(collectionDocumentType); + // await umbracoApi.template.ensureNameNotExists(templateName); + // await umbracoApi.language.ensureIsoCodeNotExists('da'); + // await umbracoApi.language.ensureIsoCodeNotExists('vi'); + }); + + // Gets a content item by id + test('can fetch an content item at root by its ID', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvRootContent; + const contentData = await umbracoApi.document.getByName(contentName); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + }); + + test('can fetch a child content item by its ID', async ({umbracoApi}) => { + // Arrange + const contentName = childPublishInvContentPrefix + '2'; + const contentData = await umbracoApi.document.getByName(contentName); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + }); + + test('can fetch a content item that has children by its ID', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvParentContent; + const contentData = await umbracoApi.document.getByName(contentName); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + }); + + test('cannot fetch an unpublished content item without preview by its ID', async ({umbracoApi}) => { + // Arrange + const contentName = unpublishInvRootContent; + const contentData = await umbracoApi.document.getByName(contentName); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); + + // Assert + expect(contentItem.status()).toBe(404); + }); + + test('can fetch a content item with textstring property', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvContentWithTextstring; + const textstringDataType = await umbracoApi.dataType.getByName(textstringDataTypeName); + const contentId = await umbracoApi.document.createPublishedDocumentWithValue(contentName, textPropertyValue, textstringDataType.id, templateId, textstringDataTypeName, invariantDocumentTypeWithTextString); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithTextString); + }); + + test('can fetch a content item with true/false property', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvContentWithTrueFalse; + const trueFalseDataType = await umbracoApi.dataType.getByName(trueFalseDataTypeName); + const contentId = await umbracoApi.document.createPublishedDocumentWithValue(contentName, trueFalsePropertyValue, trueFalseDataType.id, templateId, 'Test TrueFalse', invariantDocumentTypeWithTrueFalse); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithTrueFalse); + }); + + test('can fetch a content item with numeric property', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvContentWithNumeric; + const numericDataType = await umbracoApi.dataType.getByName(numericDataTypeName); + const contentId = await umbracoApi.document.createPublishedDocumentWithValue(contentName, numericPropertyValue, numericDataType.id, templateId, numericDataTypeName, invariantDocumentTypeWithNumeric); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithNumeric); + }); + + test('can fetch a content item with multi URL picker property', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvContentWithMultiUrlPicker; + const pickerName = childPublishInvContentPrefix + '2'; + const pickerNameData = await umbracoApi.document.getByName(pickerName); + const multiUrlPickerDataType = await umbracoApi.dataType.getByName(multiUrlPickerDataTypeName); + const contentId = await umbracoApi.document.createPublishedDocumentWithDocumentLinkURLPicker(contentName, pickerName, pickerNameData.id, multiUrlPickerDataType.id, templateId, multiUrlPickerDataTypeName, invariantDocumentTypeWithMultiUrlPicker); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItemWithMultiURLPicker(contentName, contentItemJson, 'Content'); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithMultiUrlPicker); + }); + + test('can fetch a variant content item by its ID', async ({umbracoApi}) => { + // Arrange + const contentName = publishVariantRootContent; + const contentData = await umbracoApi.document.getByName(contentName); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson, true); + }); + + test('returns 404 when fetching a non-existent content item', async ({umbracoApi}) => { + // Arrange + const nonExistentContentId = '00000000-0000-0000-0000-000000000000'; + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(nonExistentContentId); + + // Assert + expect(contentItem.status()).toBe(404); + }); + + // Gets a content item by route + test('can fetch a content item by its route', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvRootContent; + const contentData = await umbracoApi.document.getByName(contentName); + const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithRoute(contentURL); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + }); + + test('can fetch a child content item by its route', async ({umbracoApi}) => { + // Arrange + const contentName = childPublishInvContentPrefix + '1'; + const contentData = await umbracoApi.document.getByName(contentName); + const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentURL); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + }); + + test('can fetch a content item by its route with special character', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvContentWithSpecialCharacters; + const contentData = await umbracoApi.document.getByName(contentName); + const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentURL); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + }); + + test('returns 404 when fetching a non-existent content route', async ({umbracoApi}) => { + // Arrange + const nonExistentContentPath = '/non-existent-path'; + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithRoute(nonExistentContentPath); + + // Assert + expect(contentItem.status()).toBe(404); + }); + + // Gets content item(s) by id + test('can fetch multiple content items by their IDs', async ({umbracoApi}) => { + // Arrange + const contentName1 = publishInvRootContent; + const contentData1 = await umbracoApi.document.getByName(contentName1); + const contentName2 = childPublishInvContentPrefix + '3'; + const contentData2 = await umbracoApi.document.getByName(contentName2); + const contentNames = [contentName1, contentName2]; + const contentIds = [contentData1.id, contentData2.id]; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsWithIds(contentIds); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.length).toBe(2); + for (let i = 0; i < contentNames.length; i++) { + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentNames[i], contentItemsJson[i]); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentNames[i], contentItemsJson[i]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentNames[i], contentItemsJson[i]); + } + }); + + test('returns only valid content items when some IDs are invalid', async ({umbracoApi}) => { + // Arrange + const contentName = childPublishInvContentPrefix + '4'; + const contentData = await umbracoApi.document.getByName(contentName); + const nonExistentContentId = '00000000-0000-0000-0000-000000000000'; + const contentIds = [contentData.id, nonExistentContentId]; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsWithIds(contentIds); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.length).toBe(1); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemsJson[0]); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemsJson[0]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemsJson[0]); + }); + + test('returns only publish content items when some IDs are unpublish', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvRootContent; + const contentData = await umbracoApi.document.getByName(contentName); + const unpublishContent = unpublishInvRootContent; + const unpublishContentData = await umbracoApi.document.getByName(unpublishContent); + const contentIds = [contentData.id, unpublishContentData.id]; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsWithIds(contentIds); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.length).toBe(1); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemsJson[0]); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemsJson[0]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemsJson[0]); + }); + + // Gets content item(s) from a query + test('can fetch children of a content', async ({umbracoApi}) => { + // Arrange + const parentContentName = publishInvParentContent; + const parentContentData = await umbracoApi.document.getByName(parentContentName); + const parentContentId = parentContentData.id; + const fetch = 'children:' + parentContentId; + const totalChildrenItems = await umbracoApi.document.getChildrenAmount(parentContentId); + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(fetch); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.total).toBe(totalChildrenItems); + }); + + test('can fetch ancestors of a content item', async ({umbracoApi}) => { + // Arrange + const childContentName = childPublishInvContentPrefix + '1'; + const expectedParentContentName = publishInvParentContent; + const childContentData = await umbracoApi.document.getByName(childContentName); + const childContentId = childContentData.id; + const fetch = 'ancestors:' + childContentId; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(fetch); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.total).toBe(1); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(expectedParentContentName, contentItemsJson.items[0]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(expectedParentContentName, contentItemsJson.items[0]); + }); + + test('can filter content items', async ({umbracoApi}) => { + // Arrange + const contentType = collectionDocumentType; + const expectedContentName = publishInvParentContent; + const contentTypeData = await umbracoApi.documentType.getByName(contentType); + const filter = 'contentType:' + contentTypeData.alias; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, filter); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.total).toBe(1); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(expectedContentName, contentItemsJson.items[0]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(expectedContentName, contentItemsJson.items[0]); + }); + + test('can sort content items', async ({umbracoApi}) => { + // Arrange + const sort = 'name:desc'; + const filter = 'name:' + 'Child'; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, filter, sort); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.total).toBe(childContentAmount); + for (let i = 0; i < childContentAmount; i++) { + expect(contentItemsJson.items[i].name).toBe(childPublishInvContentPrefix + ' ' + (i + 1)); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(childPublishInvContentPrefix + i, contentItemsJson.items[childContentAmount -i]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(childPublishInvContentPrefix + i, contentItemsJson.items[childContentAmount -i]); + } + }); + + test('can paginate content items', async ({umbracoApi}) => { + // Arrange + const sort = 'name:asc'; + const filter = 'name:' + 'Child'; + const skip = 0; + const take = childContentAmount - 1; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, filter, sort, skip, take); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.total).toBe(childContentAmount); + expect(contentItemsJson.items.length).toBe(take); + }); + + test('returns 400 when using an invalid sort parameter', async ({umbracoApi}) => { + // Arrange + const invalidSort= 'invalidSort'; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, invalidSort); + + // Assert + expect(contentItems).not.toBeNull(); + if (contentItems !== null) { + expect(contentItems.status()).toBe(400); + } + }); + + test('returns 400 when using an invalid filter parameter', async ({umbracoApi}) => { + // Arrange + const invalidFilter = 'invalidFilter'; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, invalidFilter); + + // Assert + expect(contentItems).not.toBeNull(); + if (contentItems !== null) { + expect(contentItems.status()).toBe(400); + } + }); + + test('returns 400 when using an invalid fetch type', async ({umbracoApi}) => { + // Arrange + const fetch = 'invalid'; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(fetch); + + // Assert + expect(contentItems).not.toBeNull(); + if (contentItems !== null) { + expect(contentItems.status()).toBe(400); + } + }); }); From a14e3ddc3941bacea7950aa06026a76353c8b758 Mon Sep 17 00:00:00 2001 From: Nhu Dinh Date: Tue, 9 Sep 2025 11:00:02 +0200 Subject: [PATCH 05/14] Updated skip tag and issue link for the failing tests --- .../tests/DeliveryApi/MediaDeliveryApi.spec.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/MediaDeliveryApi.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/MediaDeliveryApi.spec.ts index 50525aac413f..119e9fff25c5 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/MediaDeliveryApi.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/MediaDeliveryApi.spec.ts @@ -196,8 +196,9 @@ test.describe('Media Delivery API', () => { await umbracoApi.mediaDeliveryApi.verifyDefaultMediaItemJson(rootArticleName, mediaItemJson, mediaPath, mediaTypeName); }); - // This test fails because it will return 404 error if the path includes # or ? - test('can fetch an media item by its path with special character', async ({umbracoApi}) => { + // Skip this because it will return 404 error if the path includes # or ? + // Issue link: https://github.com/umbraco/Umbraco-CMS/issues/20024 + test.skip('can fetch an media item by its path with special character', async ({umbracoApi}) => { // Arrange const mediaTypeName = 'Image'; const mediaPath = '/' + specialCharacterImageName.toLowerCase() + '/'; @@ -273,7 +274,7 @@ test.describe('Media Delivery API', () => { // Assert expect(mediaItems.status()).toBe(200); const mediaItemsJson = await mediaItems.json(); - await umbracoApi.mediaDeliveryApi.verifyMutipleMediaItemsJson(mediaNames, mediaItemsJson, mediaPaths, mediaTypeNames); + await umbracoApi.mediaDeliveryApi.verifyMultipleMediaItemsJson(mediaNames, mediaItemsJson, mediaPaths, mediaTypeNames); }); test('returns only valid media items when some IDs are invalid', async ({umbracoApi}) => { @@ -291,7 +292,7 @@ test.describe('Media Delivery API', () => { // Assert expect(mediaItems.status()).toBe(200); const mediaItemsJson = await mediaItems.json(); - await umbracoApi.mediaDeliveryApi.verifyMutipleMediaItemsJson([validMediaName], mediaItemsJson, [validMediaPath], [validMediaTypeName]); + await umbracoApi.mediaDeliveryApi.verifyMultipleMediaItemsJson([validMediaName], mediaItemsJson, [validMediaPath], [validMediaTypeName]); }); // Gets media item(s) from a query @@ -368,13 +369,12 @@ test.describe('Media Delivery API', () => { } }); - // This test fails because it still returns all media items and ignores the 'take' parameter. test('can paginate media items', async ({umbracoApi}) => { // Arrange const fetch = 'children:/'; - const filter = 'mediaType:' + 'Image'; + const filter = 'name:' + rootImageSizeNamePrefix; const skip = 0; - const take = rootImageSize; + const take = rootImageSize - 2; // Act const mediaItems = await umbracoApi.mediaDeliveryApi.getMediaItemsFromAQuery(fetch, filter, undefined, skip, take); @@ -384,7 +384,8 @@ test.describe('Media Delivery API', () => { if (mediaItems !== null) { expect(mediaItems.status()).toBe(200); const mediaItemsJson = await mediaItems.json(); - expect(mediaItemsJson.total).toBe(take); + expect(mediaItemsJson.total).toBe(rootImageSize); + expect(mediaItemsJson.items.length).toBe(take); } }); From 19a232a0568d5896d1752438c2dca20c3a45c309 Mon Sep 17 00:00:00 2001 From: Nhu Dinh Date: Tue, 9 Sep 2025 11:00:19 +0200 Subject: [PATCH 06/14] Bumped version --- .../package-lock.json | 16 ++++++++-------- tests/Umbraco.Tests.AcceptanceTest/package.json | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/Umbraco.Tests.AcceptanceTest/package-lock.json b/tests/Umbraco.Tests.AcceptanceTest/package-lock.json index 478655791d2b..b198a5194c09 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/package-lock.json +++ b/tests/Umbraco.Tests.AcceptanceTest/package-lock.json @@ -8,7 +8,7 @@ "hasInstallScript": true, "dependencies": { "@umbraco/json-models-builders": "^2.0.38", - "@umbraco/playwright-testhelpers": "^16.0.42", + "@umbraco/playwright-testhelpers": "^16.0.44", "camelize": "^1.0.0", "dotenv": "^16.3.1", "node-fetch": "^2.6.7" @@ -58,21 +58,21 @@ } }, "node_modules/@umbraco/json-models-builders": { - "version": "2.0.38", - "resolved": "https://registry.npmjs.org/@umbraco/json-models-builders/-/json-models-builders-2.0.38.tgz", - "integrity": "sha512-6nC1Y1xn+8zyqU3iqHubRo18L53TdZkhHIY4z68VSLcA6YoAzdxtjw+zx7yDIMV+epoQ4NCG2ooAa0gBhHqQgg==", + "version": "2.0.39", + "resolved": "https://registry.npmjs.org/@umbraco/json-models-builders/-/json-models-builders-2.0.39.tgz", + "integrity": "sha512-YcgZ+WJ3HANBUaffSzZVRlJNLjXOaWOQNIuGf/A0lGH1khd5Kkv2JGln1bq2bNzIbIYQM+f2vYAnmYXmJFN7Vg==", "license": "MIT", "dependencies": { "camelize": "^1.0.1" } }, "node_modules/@umbraco/playwright-testhelpers": { - "version": "16.0.42", - "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-16.0.42.tgz", - "integrity": "sha512-ePKl8gtELoIMEV57E3N4VumfKNkuOTFo/LYH7ePhseCcm5oUh1Cc/RVqvlXYsdfBTiMfZ7x7Nu4lOSv15D2Z3Q==", + "version": "16.0.44", + "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-16.0.44.tgz", + "integrity": "sha512-ngdJHtynS+61fs8mWyjHrJtAP8m+PGIZyDqUGPlFOwnEeyDI5LVLmoSVOkB8kBnmg++luUwDn1jocFjEzC7tlg==", "license": "MIT", "dependencies": { - "@umbraco/json-models-builders": "2.0.38", + "@umbraco/json-models-builders": "2.0.39", "node-fetch": "^2.6.7" } }, diff --git a/tests/Umbraco.Tests.AcceptanceTest/package.json b/tests/Umbraco.Tests.AcceptanceTest/package.json index adda20995116..e322dd9d1046 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/package.json +++ b/tests/Umbraco.Tests.AcceptanceTest/package.json @@ -22,7 +22,7 @@ }, "dependencies": { "@umbraco/json-models-builders": "^2.0.38", - "@umbraco/playwright-testhelpers": "^16.0.42", + "@umbraco/playwright-testhelpers": "^16.0.44", "camelize": "^1.0.0", "dotenv": "^16.3.1", "node-fetch": "^2.6.7" From a34032d4ef131700495f31ec820579be7b389e14 Mon Sep 17 00:00:00 2001 From: Nhu Dinh Date: Fri, 5 Dec 2025 15:02:40 +0700 Subject: [PATCH 07/14] Refactor code for content delivery api tests --- .../DeliveryApi/ContentDeliveryApi.spec.ts | 1088 +++++++++-------- 1 file changed, 606 insertions(+), 482 deletions(-) diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts index 9262c9d60bd9..6bdc375bdb32 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts @@ -32,490 +32,614 @@ const numericPropertyValue = '1234'; const trueFalsePropertyValue = true; // Template const templateName = 'TestTemplateForContentDeliveryApi'; -let templateId = null; // Others const childContentAmount = 5; +let templateId: string | null = null; +let invariantDocTypeId = ''; +let collectionDocTypeId = ''; + +test.beforeEach(async ({umbracoApi}) => { + // Create a template + const createdTemplateId = await umbracoApi.template.createDefaultTemplate(templateName); + templateId = createdTemplateId ?? null; + // Create 3 languages (en-US, da, vi) + await umbracoApi.language.createDanishLanguage(); + await umbracoApi.language.createVietnameseLanguage(); + // Get data types + const listViewDataType = await umbracoApi.dataType.getByName(listViewContentTypeName); + // Create document types + invariantDocTypeId = await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(invariantDocumentType) ?? ''; + collectionDocTypeId = await umbracoApi.documentType.createDocumentTypeWithAllowedChildNodeAndCollectionId(collectionDocumentType, invariantDocTypeId, listViewDataType.id) ?? ''; +}); + +test.afterEach(async ({umbracoApi}) => { + // await umbracoApi.documentType.ensureNameNotExists(invariantDocumentType); + // await umbracoApi.documentType.ensureNameNotExists(collectionDocumentType); + // await umbracoApi.template.ensureNameNotExists(templateName); + // await umbracoApi.language.ensureIsoCodeNotExists('da'); + // await umbracoApi.language.ensureIsoCodeNotExists('vi'); +}); + +// Gets a content item by id +test('can fetch an content item at root by its ID', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvRootContent; + const publishInvRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); + await umbracoApi.document.publish(publishInvRootId); + const contentData = await umbracoApi.document.getByName(contentName); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); +}); + +test('can fetch a child content item by its ID', async ({umbracoApi}) => { + // Arrange + const publishInvParentId = await umbracoApi.document.createDefaultDocument(publishInvParentContent, collectionDocTypeId); + await umbracoApi.document.publish(publishInvParentId); + const contentName = childPublishInvContentPrefix + '2'; + const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvParentId); + await umbracoApi.document.publish(childId); + const contentData = await umbracoApi.document.getByName(contentName); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.document.ensureNameNotExists(publishInvParentContent); +}); + +test('can fetch a content item that has children by its ID', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvParentContent; + const publishInvParentId = await umbracoApi.document.createDefaultDocument(contentName, collectionDocTypeId); + await umbracoApi.document.publish(publishInvParentId); + // Create child items + for (let i = 1; i <= childContentAmount; i++) { + const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvContentPrefix + i, invariantDocTypeId, publishInvParentId); + await umbracoApi.document.publish(childId); + } + const contentData = await umbracoApi.document.getByName(contentName); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + for (let i = 1; i <= childContentAmount; i++) { + await umbracoApi.document.ensureNameNotExists(childPublishInvContentPrefix + i); + } + await umbracoApi.document.ensureNameNotExists(contentName); +}); + +test('cannot fetch an unpublished content item without preview by its ID', async ({umbracoApi}) => { + // Arrange + const contentName = unpublishInvRootContent; + await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); + const contentData = await umbracoApi.document.getByName(contentName); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); + + // Assert + expect(contentItem.status()).toBe(404); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); +}); + +test('can fetch a content item with textstring property', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvContentWithTextstring; + const textstringDataType = await umbracoApi.dataType.getByName(textstringDataTypeName); + const contentId = await umbracoApi.document.createPublishedDocumentWithValue(contentName, textPropertyValue, textstringDataType.id, templateId!, textstringDataTypeName, invariantDocumentTypeWithTextString); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithTextString); +}); + +test('can fetch a content item with true/false property', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvContentWithTrueFalse; + const trueFalseDataType = await umbracoApi.dataType.getByName(trueFalseDataTypeName); + const contentId = await umbracoApi.document.createPublishedDocumentWithValue(contentName, trueFalsePropertyValue, trueFalseDataType.id, templateId!, 'Test TrueFalse', invariantDocumentTypeWithTrueFalse); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithTrueFalse); +}); + +test('can fetch a content item with numeric property', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvContentWithNumeric; + const numericDataType = await umbracoApi.dataType.getByName(numericDataTypeName); + const contentId = await umbracoApi.document.createPublishedDocumentWithValue(contentName, numericPropertyValue, numericDataType.id, templateId!, numericDataTypeName, invariantDocumentTypeWithNumeric); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithNumeric); +}); + +test('can fetch a content item with multi URL picker property', async ({umbracoApi}) => { + // Arrange + // Create parent and child content first + const publishInvParentId = await umbracoApi.document.createDefaultDocument(publishInvParentContent, collectionDocTypeId); + await umbracoApi.document.publish(publishInvParentId); + const pickerName = childPublishInvContentPrefix + '2'; + const pickerId = await umbracoApi.document.createDefaultDocumentWithParent(pickerName, invariantDocTypeId, publishInvParentId); + await umbracoApi.document.publish(pickerId); + const pickerNameData = await umbracoApi.document.getByName(pickerName); + + const contentName = publishInvContentWithMultiUrlPicker; + const multiUrlPickerDataType = await umbracoApi.dataType.getByName(multiUrlPickerDataTypeName); + const contentId = await umbracoApi.document.createPublishedDocumentWithDocumentLinkURLPicker(contentName, pickerName, pickerNameData.id, multiUrlPickerDataType.id, templateId!, multiUrlPickerDataTypeName, invariantDocumentTypeWithMultiUrlPicker); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItemWithMultiURLPicker(contentName, contentItemJson, 'Content'); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.document.ensureNameNotExists(pickerName); + await umbracoApi.document.ensureNameNotExists(publishInvParentContent); + await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithMultiUrlPicker); +}); + +test('can fetch a variant content item by its ID', async ({umbracoApi}) => { + // Arrange + const contentName = publishVariantRootContent; + const textStringDataType = await umbracoApi.dataType.getByName(textstringDataTypeName); + const variantDocTypeId = await umbracoApi.documentType.createVariantDocumentTypeWithInvariantPropertyEditor(variantDocumentTypeWithTextstring, textstringDataTypeName, textStringDataType.id); + const publishVariantRootId = await umbracoApi.document.createDocumentWithEnglishCultureAndTextContent(contentName, variantDocTypeId, textPropertyValue, textstringDataTypeName); + await umbracoApi.document.publishDocumentWithCulture(publishVariantRootId, 'en-US'); + const contentData = await umbracoApi.document.getByName(contentName); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson, true); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(variantDocumentTypeWithTextstring); +}); + +test('returns 404 when fetching a non-existent content item', async ({umbracoApi}) => { + // Arrange + const nonExistentContentId = '00000000-0000-0000-0000-000000000000'; + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(nonExistentContentId); + + // Assert + expect(contentItem.status()).toBe(404); +}); + +// Gets a content item by route +test('can fetch a content item by its route', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvRootContent; + const publishInvRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); + await umbracoApi.document.publish(publishInvRootId); + const contentData = await umbracoApi.document.getByName(contentName); + const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithRoute(contentURL); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); +}); + +test('can fetch a child content item by its route', async ({umbracoApi}) => { + // Arrange + const publishInvParentId = await umbracoApi.document.createDefaultDocument(publishInvParentContent, collectionDocTypeId); + await umbracoApi.document.publish(publishInvParentId); + const contentName = childPublishInvContentPrefix + '1'; + const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvParentId); + await umbracoApi.document.publish(childId); + const contentData = await umbracoApi.document.getByName(contentName); + const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentURL); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.document.ensureNameNotExists(publishInvParentContent); +}); + +test('can fetch a content item by its route with special character', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvContentWithSpecialCharacters; + const publishInvContentWithSpecialCharactersId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); + await umbracoApi.document.publish(publishInvContentWithSpecialCharactersId); + const contentData = await umbracoApi.document.getByName(contentName); + const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentURL); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); +}); + +test('returns 404 when fetching a non-existent content route', async ({umbracoApi}) => { + // Arrange + const nonExistentContentPath = '/non-existent-path'; + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithRoute(nonExistentContentPath); + + // Assert + expect(contentItem.status()).toBe(404); +}); + +// Gets content item(s) by id +test('can fetch multiple content items by their IDs', async ({umbracoApi}) => { + // Arrange + const contentName1 = publishInvRootContent; + const publishInvRootId = await umbracoApi.document.createDefaultDocument(contentName1, invariantDocTypeId); + await umbracoApi.document.publish(publishInvRootId); + + const publishInvParentId = await umbracoApi.document.createDefaultDocument(publishInvParentContent, collectionDocTypeId); + await umbracoApi.document.publish(publishInvParentId); + const contentName2 = childPublishInvContentPrefix + '3'; + const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName2, invariantDocTypeId, publishInvParentId); + await umbracoApi.document.publish(childId); + + const contentData1 = await umbracoApi.document.getByName(contentName1); + const contentData2 = await umbracoApi.document.getByName(contentName2); + const contentNames = [contentName1, contentName2]; + const contentIds = [contentData1.id, contentData2.id]; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsWithIds(contentIds); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.length).toBe(2); + for (let i = 0; i < contentNames.length; i++) { + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentNames[i], contentItemsJson[i]); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentNames[i], contentItemsJson[i]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentNames[i], contentItemsJson[i]); + } + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName2); + await umbracoApi.document.ensureNameNotExists(publishInvParentContent); + await umbracoApi.document.ensureNameNotExists(contentName1); +}); + +test('returns only valid content items when some IDs are invalid', async ({umbracoApi}) => { + // Arrange + const publishInvParentId = await umbracoApi.document.createDefaultDocument(publishInvParentContent, collectionDocTypeId); + await umbracoApi.document.publish(publishInvParentId); + const contentName = childPublishInvContentPrefix + '4'; + const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvParentId); + await umbracoApi.document.publish(childId); + + const contentData = await umbracoApi.document.getByName(contentName); + const nonExistentContentId = '00000000-0000-0000-0000-000000000000'; + const contentIds = [contentData.id, nonExistentContentId]; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsWithIds(contentIds); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.length).toBe(1); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemsJson[0]); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemsJson[0]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemsJson[0]); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.document.ensureNameNotExists(publishInvParentContent); +}); + +test('returns only publish content items when some IDs are unpublish', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvRootContent; + const publishInvRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); + await umbracoApi.document.publish(publishInvRootId); + + const unpublishContent = unpublishInvRootContent; + await umbracoApi.document.createDefaultDocument(unpublishContent, invariantDocTypeId); + + const contentData = await umbracoApi.document.getByName(contentName); + const unpublishContentData = await umbracoApi.document.getByName(unpublishContent); + const contentIds = [contentData.id, unpublishContentData.id]; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsWithIds(contentIds); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.length).toBe(1); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemsJson[0]); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemsJson[0]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemsJson[0]); + + // Clean + await umbracoApi.document.ensureNameNotExists(unpublishContent); + await umbracoApi.document.ensureNameNotExists(contentName); +}); + +// Gets content item(s) from a query +test('can fetch children of a content', async ({umbracoApi}) => { + // Arrange + const parentContentName = publishInvParentContent; + const publishInvParentId = await umbracoApi.document.createDefaultDocument(parentContentName, collectionDocTypeId); + await umbracoApi.document.publish(publishInvParentId); + // Create child items + for (let i = 1; i <= childContentAmount; i++) { + const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvContentPrefix + i, invariantDocTypeId, publishInvParentId); + await umbracoApi.document.publish(childId); + } + + const parentContentData = await umbracoApi.document.getByName(parentContentName); + const parentContentId = parentContentData.id; + const fetch = 'children:' + parentContentId; + const totalChildrenItems = await umbracoApi.document.getChildrenAmount(parentContentId); + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, fetch); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.total).toBe(totalChildrenItems); + + // Clean + for (let i = 1; i <= childContentAmount; i++) { + await umbracoApi.document.ensureNameNotExists(childPublishInvContentPrefix + i); + } + await umbracoApi.document.ensureNameNotExists(parentContentName); +}); + +test('can fetch ancestors of a content item', async ({umbracoApi}) => { + // Arrange + const expectedParentContentName = publishInvParentContent; + const publishInvParentId = await umbracoApi.document.createDefaultDocument(expectedParentContentName, collectionDocTypeId); + await umbracoApi.document.publish(publishInvParentId); + const childContentName = childPublishInvContentPrefix + '1'; + const childId = await umbracoApi.document.createDefaultDocumentWithParent(childContentName, invariantDocTypeId, publishInvParentId); + await umbracoApi.document.publish(childId); + + const fetch = 'ancestors:' + childId; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, fetch); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.total).toBe(1); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(expectedParentContentName, contentItemsJson.items[0]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(expectedParentContentName, contentItemsJson.items[0]); + + // Clean + await umbracoApi.document.ensureNameNotExists(childContentName); + await umbracoApi.document.ensureNameNotExists(expectedParentContentName); +}); + +test('can filter content items', async ({umbracoApi}) => { + // Arrange + const expectedContentName = publishInvParentContent; + const publishInvParentId = await umbracoApi.document.createDefaultDocument(expectedContentName, collectionDocTypeId); + await umbracoApi.document.publish(publishInvParentId); + + const contentType = collectionDocumentType; + const contentTypeData = await umbracoApi.documentType.getByName(contentType); + const filter = 'contentType:' + contentTypeData.alias; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, filter); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.total).toBe(1); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(expectedContentName, contentItemsJson.items[0]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(expectedContentName, contentItemsJson.items[0]); + + // Clean + await umbracoApi.document.ensureNameNotExists(expectedContentName); +}); + +test('can sort content items', async ({umbracoApi}) => { + // Arrange + const publishInvParentId = await umbracoApi.document.createDefaultDocument(publishInvParentContent, collectionDocTypeId); + await umbracoApi.document.publish(publishInvParentId); + // Create child items + for (let i = 1; i <= childContentAmount; i++) { + const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvContentPrefix + i, invariantDocTypeId, publishInvParentId); + await umbracoApi.document.publish(childId); + } + + const sort = 'name:desc'; + const filter = 'name:' + 'Child'; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, filter, sort); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.total).toBe(childContentAmount); + for (let i = 0; i < childContentAmount; i++) { + expect(contentItemsJson.items[i].name).toBe(childPublishInvContentPrefix + ' ' + (i + 1)); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(childPublishInvContentPrefix + i, contentItemsJson.items[childContentAmount - i]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(childPublishInvContentPrefix + i, contentItemsJson.items[childContentAmount - i]); + } + + // Clean + for (let i = 1; i <= childContentAmount; i++) { + await umbracoApi.document.ensureNameNotExists(childPublishInvContentPrefix + i); + } + await umbracoApi.document.ensureNameNotExists(publishInvParentContent); +}); + +test('can paginate content items', async ({umbracoApi}) => { + // Arrange + const publishInvParentId = await umbracoApi.document.createDefaultDocument(publishInvParentContent, collectionDocTypeId); + await umbracoApi.document.publish(publishInvParentId); + // Create child items + for (let i = 1; i <= childContentAmount; i++) { + const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvContentPrefix + i, invariantDocTypeId, publishInvParentId); + await umbracoApi.document.publish(childId); + } + + const sort = 'name:asc'; + const filter = 'name:' + 'Child'; + const skip = 0; + const take = childContentAmount - 1; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, filter, sort, skip, take); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.total).toBe(childContentAmount); + expect(contentItemsJson.items.length).toBe(take); + + // Clean + for (let i = 1; i <= childContentAmount; i++) { + await umbracoApi.document.ensureNameNotExists(childPublishInvContentPrefix + i); + } + await umbracoApi.document.ensureNameNotExists(publishInvParentContent); +}); + +test('returns 400 when using an invalid sort parameter', async ({umbracoApi}) => { + // Arrange + const invalidSort = 'invalidSort'; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, undefined, invalidSort); + + // Assert + expect(contentItems).not.toBeNull(); + if (contentItems !== null) { + expect(contentItems.status()).toBe(400); + } +}); + +test('returns 400 when using an invalid filter parameter', async ({umbracoApi}) => { + // Arrange + const invalidFilter = 'invalidFilter'; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, invalidFilter); + + // Assert + expect(contentItems).not.toBeNull(); + if (contentItems !== null) { + expect(contentItems.status()).toBe(400); + } +}); + +test('returns 400 when using an invalid fetch type', async ({umbracoApi}) => { + // Arrange + const invalidFetch = 'invalid'; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, invalidFetch); -test.describe('Content Delivery API tests', () => { - // test.beforeAll(async ({umbracoApi}) => { - // //Create a template - // templateId = await umbracoApi.template.createDefaultTemplate(templateName); - // // Create 3 languges (en-US, da, vi) - // await umbracoApi.language.createDanishLanguage(); - // await umbracoApi.language.createVietnameseLanguage(); - // //Get data types - // const listViewDataType = await umbracoApi.dataType.getByName(listViewContentTypeName); - // // Create document types - // const invariantDocTypeId = await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(invariantDocumentType); - // const collectionDocTypeId = await umbracoApi.documentType.createDocumentTypeWithAllowedChildNodeAndCollectionId(collectionDocumentType, invariantDocTypeId, listViewDataType.id); - // // Create a publish invariant content item at root - // const publishInvRootId = await umbracoApi.document.createDefaultDocument(publishInvRootContent, invariantDocTypeId); - // await umbracoApi.document.publish(publishInvRootId); - // // Create a publish invariant parent item at root - // const publishInvParentId = await umbracoApi.document.createDefaultDocument(publishInvParentContent, collectionDocTypeId);; - // await umbracoApi.document.publish(publishInvParentId); - // // Create publish invariant child items - // for (let i = 1; i <= childContentAmount; i++) { - // const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvContentPrefix + i, invariantDocTypeId, publishInvParentId); - // await umbracoApi.document.publish(childId); - // } - // // Create an unpublish invariant content item at root - // await umbracoApi.document.createDefaultDocument(unpublishInvRootContent, invariantDocTypeId); - // // Create a publish invariant content item with special characters at root - // const publishInvContentWithSpecialCharactersId = await umbracoApi.document.createDefaultDocument(publishInvContentWithSpecialCharacters, invariantDocTypeId); - // await umbracoApi.document.publish(publishInvContentWithSpecialCharactersId); - // // Create a publish variant content item at root - // const textStringDataType = await umbracoApi.dataType.getByName(textstringDataTypeName); - // const variantDocTypeId = await umbracoApi.documentType.createVariantDocumentTypeWithInvariantPropertyEditor(variantDocumentTypeWithTextstring, textstringDataTypeName, textStringDataType.id); - // const publishVariantRootId = await umbracoApi.document.createDocumentWithEnglishCultureAndTextContent(publishVariantRootContent, variantDocTypeId, textPropertyValue, textstringDataTypeName); - // await umbracoApi.document.publishDocumentWithCulture(publishVariantRootId, 'en-US'); - // }); - - test.afterAll(async ({umbracoApi}) => { - // await umbracoApi.document.ensureNameNotExists(publishInvRootContent); - // await umbracoApi.document.ensureNameNotExists(publishInvParentContent); - // for (let i = 1; i <= childContentAmount; i++) { - // await umbracoApi.document.ensureNameNotExists(childPublishInvContentPrefix + i); - // } - // await umbracoApi.document.ensureNameNotExists(unpublishInvRootContent); - // await umbracoApi.documentType.ensureNameNotExists(invariantDocumentType); - // await umbracoApi.documentType.ensureNameNotExists(collectionDocumentType); - // await umbracoApi.template.ensureNameNotExists(templateName); - // await umbracoApi.language.ensureIsoCodeNotExists('da'); - // await umbracoApi.language.ensureIsoCodeNotExists('vi'); - }); - - // Gets a content item by id - test('can fetch an content item at root by its ID', async ({umbracoApi}) => { - // Arrange - const contentName = publishInvRootContent; - const contentData = await umbracoApi.document.getByName(contentName); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - }); - - test('can fetch a child content item by its ID', async ({umbracoApi}) => { - // Arrange - const contentName = childPublishInvContentPrefix + '2'; - const contentData = await umbracoApi.document.getByName(contentName); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - }); - - test('can fetch a content item that has children by its ID', async ({umbracoApi}) => { - // Arrange - const contentName = publishInvParentContent; - const contentData = await umbracoApi.document.getByName(contentName); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - }); - - test('cannot fetch an unpublished content item without preview by its ID', async ({umbracoApi}) => { - // Arrange - const contentName = unpublishInvRootContent; - const contentData = await umbracoApi.document.getByName(contentName); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); - - // Assert - expect(contentItem.status()).toBe(404); - }); - - test('can fetch a content item with textstring property', async ({umbracoApi}) => { - // Arrange - const contentName = publishInvContentWithTextstring; - const textstringDataType = await umbracoApi.dataType.getByName(textstringDataTypeName); - const contentId = await umbracoApi.document.createPublishedDocumentWithValue(contentName, textPropertyValue, textstringDataType.id, templateId, textstringDataTypeName, invariantDocumentTypeWithTextString); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - - // Clean - await umbracoApi.document.ensureNameNotExists(contentName); - await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithTextString); - }); - - test('can fetch a content item with true/false property', async ({umbracoApi}) => { - // Arrange - const contentName = publishInvContentWithTrueFalse; - const trueFalseDataType = await umbracoApi.dataType.getByName(trueFalseDataTypeName); - const contentId = await umbracoApi.document.createPublishedDocumentWithValue(contentName, trueFalsePropertyValue, trueFalseDataType.id, templateId, 'Test TrueFalse', invariantDocumentTypeWithTrueFalse); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - - // Clean - await umbracoApi.document.ensureNameNotExists(contentName); - await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithTrueFalse); - }); - - test('can fetch a content item with numeric property', async ({umbracoApi}) => { - // Arrange - const contentName = publishInvContentWithNumeric; - const numericDataType = await umbracoApi.dataType.getByName(numericDataTypeName); - const contentId = await umbracoApi.document.createPublishedDocumentWithValue(contentName, numericPropertyValue, numericDataType.id, templateId, numericDataTypeName, invariantDocumentTypeWithNumeric); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - - // Clean - await umbracoApi.document.ensureNameNotExists(contentName); - await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithNumeric); - }); - - test('can fetch a content item with multi URL picker property', async ({umbracoApi}) => { - // Arrange - const contentName = publishInvContentWithMultiUrlPicker; - const pickerName = childPublishInvContentPrefix + '2'; - const pickerNameData = await umbracoApi.document.getByName(pickerName); - const multiUrlPickerDataType = await umbracoApi.dataType.getByName(multiUrlPickerDataTypeName); - const contentId = await umbracoApi.document.createPublishedDocumentWithDocumentLinkURLPicker(contentName, pickerName, pickerNameData.id, multiUrlPickerDataType.id, templateId, multiUrlPickerDataTypeName, invariantDocumentTypeWithMultiUrlPicker); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItemWithMultiURLPicker(contentName, contentItemJson, 'Content'); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - - // Clean - await umbracoApi.document.ensureNameNotExists(contentName); - await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithMultiUrlPicker); - }); - - test('can fetch a variant content item by its ID', async ({umbracoApi}) => { - // Arrange - const contentName = publishVariantRootContent; - const contentData = await umbracoApi.document.getByName(contentName); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson, true); - }); - - test('returns 404 when fetching a non-existent content item', async ({umbracoApi}) => { - // Arrange - const nonExistentContentId = '00000000-0000-0000-0000-000000000000'; - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(nonExistentContentId); - - // Assert - expect(contentItem.status()).toBe(404); - }); - - // Gets a content item by route - test('can fetch a content item by its route', async ({umbracoApi}) => { - // Arrange - const contentName = publishInvRootContent; - const contentData = await umbracoApi.document.getByName(contentName); - const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithRoute(contentURL); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - }); - - test('can fetch a child content item by its route', async ({umbracoApi}) => { - // Arrange - const contentName = childPublishInvContentPrefix + '1'; - const contentData = await umbracoApi.document.getByName(contentName); - const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentURL); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - }); - - test('can fetch a content item by its route with special character', async ({umbracoApi}) => { - // Arrange - const contentName = publishInvContentWithSpecialCharacters; - const contentData = await umbracoApi.document.getByName(contentName); - const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentURL); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - }); - - test('returns 404 when fetching a non-existent content route', async ({umbracoApi}) => { - // Arrange - const nonExistentContentPath = '/non-existent-path'; - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithRoute(nonExistentContentPath); - - // Assert - expect(contentItem.status()).toBe(404); - }); - - // Gets content item(s) by id - test('can fetch multiple content items by their IDs', async ({umbracoApi}) => { - // Arrange - const contentName1 = publishInvRootContent; - const contentData1 = await umbracoApi.document.getByName(contentName1); - const contentName2 = childPublishInvContentPrefix + '3'; - const contentData2 = await umbracoApi.document.getByName(contentName2); - const contentNames = [contentName1, contentName2]; - const contentIds = [contentData1.id, contentData2.id]; - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsWithIds(contentIds); - - // Assert - expect(contentItems.status()).toBe(200); - const contentItemsJson = await contentItems.json(); - expect(contentItemsJson.length).toBe(2); - for (let i = 0; i < contentNames.length; i++) { - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentNames[i], contentItemsJson[i]); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentNames[i], contentItemsJson[i]); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentNames[i], contentItemsJson[i]); - } - }); - - test('returns only valid content items when some IDs are invalid', async ({umbracoApi}) => { - // Arrange - const contentName = childPublishInvContentPrefix + '4'; - const contentData = await umbracoApi.document.getByName(contentName); - const nonExistentContentId = '00000000-0000-0000-0000-000000000000'; - const contentIds = [contentData.id, nonExistentContentId]; - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsWithIds(contentIds); - - // Assert - expect(contentItems.status()).toBe(200); - const contentItemsJson = await contentItems.json(); - expect(contentItemsJson.length).toBe(1); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemsJson[0]); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemsJson[0]); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemsJson[0]); - }); - - test('returns only publish content items when some IDs are unpublish', async ({umbracoApi}) => { - // Arrange - const contentName = publishInvRootContent; - const contentData = await umbracoApi.document.getByName(contentName); - const unpublishContent = unpublishInvRootContent; - const unpublishContentData = await umbracoApi.document.getByName(unpublishContent); - const contentIds = [contentData.id, unpublishContentData.id]; - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsWithIds(contentIds); - - // Assert - expect(contentItems.status()).toBe(200); - const contentItemsJson = await contentItems.json(); - expect(contentItemsJson.length).toBe(1); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemsJson[0]); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItem(contentName, contentItemsJson[0]); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemsJson[0]); - }); - - // Gets content item(s) from a query - test('can fetch children of a content', async ({umbracoApi}) => { - // Arrange - const parentContentName = publishInvParentContent; - const parentContentData = await umbracoApi.document.getByName(parentContentName); - const parentContentId = parentContentData.id; - const fetch = 'children:' + parentContentId; - const totalChildrenItems = await umbracoApi.document.getChildrenAmount(parentContentId); - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(fetch); - - // Assert - expect(contentItems.status()).toBe(200); - const contentItemsJson = await contentItems.json(); - expect(contentItemsJson.total).toBe(totalChildrenItems); - }); - - test('can fetch ancestors of a content item', async ({umbracoApi}) => { - // Arrange - const childContentName = childPublishInvContentPrefix + '1'; - const expectedParentContentName = publishInvParentContent; - const childContentData = await umbracoApi.document.getByName(childContentName); - const childContentId = childContentData.id; - const fetch = 'ancestors:' + childContentId; - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(fetch); - - // Assert - expect(contentItems.status()).toBe(200); - const contentItemsJson = await contentItems.json(); - expect(contentItemsJson.total).toBe(1); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(expectedParentContentName, contentItemsJson.items[0]); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(expectedParentContentName, contentItemsJson.items[0]); - }); - - test('can filter content items', async ({umbracoApi}) => { - // Arrange - const contentType = collectionDocumentType; - const expectedContentName = publishInvParentContent; - const contentTypeData = await umbracoApi.documentType.getByName(contentType); - const filter = 'contentType:' + contentTypeData.alias; - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, filter); - - // Assert - expect(contentItems.status()).toBe(200); - const contentItemsJson = await contentItems.json(); - expect(contentItemsJson.total).toBe(1); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(expectedContentName, contentItemsJson.items[0]); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(expectedContentName, contentItemsJson.items[0]); - }); - - test('can sort content items', async ({umbracoApi}) => { - // Arrange - const sort = 'name:desc'; - const filter = 'name:' + 'Child'; - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, filter, sort); - - // Assert - expect(contentItems.status()).toBe(200); - const contentItemsJson = await contentItems.json(); - expect(contentItemsJson.total).toBe(childContentAmount); - for (let i = 0; i < childContentAmount; i++) { - expect(contentItemsJson.items[i].name).toBe(childPublishInvContentPrefix + ' ' + (i + 1)); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(childPublishInvContentPrefix + i, contentItemsJson.items[childContentAmount -i]); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(childPublishInvContentPrefix + i, contentItemsJson.items[childContentAmount -i]); - } - }); - - test('can paginate content items', async ({umbracoApi}) => { - // Arrange - const sort = 'name:asc'; - const filter = 'name:' + 'Child'; - const skip = 0; - const take = childContentAmount - 1; - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, filter, sort, skip, take); - - // Assert - expect(contentItems.status()).toBe(200); - const contentItemsJson = await contentItems.json(); - expect(contentItemsJson.total).toBe(childContentAmount); - expect(contentItemsJson.items.length).toBe(take); - }); - - test('returns 400 when using an invalid sort parameter', async ({umbracoApi}) => { - // Arrange - const invalidSort= 'invalidSort'; - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, invalidSort); - - // Assert - expect(contentItems).not.toBeNull(); - if (contentItems !== null) { - expect(contentItems.status()).toBe(400); - } - }); - - test('returns 400 when using an invalid filter parameter', async ({umbracoApi}) => { - // Arrange - const invalidFilter = 'invalidFilter'; - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, invalidFilter); - - // Assert - expect(contentItems).not.toBeNull(); - if (contentItems !== null) { - expect(contentItems.status()).toBe(400); - } - }); - - test('returns 400 when using an invalid fetch type', async ({umbracoApi}) => { - // Arrange - const fetch = 'invalid'; - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(fetch); - - // Assert - expect(contentItems).not.toBeNull(); - if (contentItems !== null) { - expect(contentItems.status()).toBe(400); - } - }); + // Assert + expect(contentItems).not.toBeNull(); + if (contentItems !== null) { + expect(contentItems.status()).toBe(400); + } }); From caa1ea2dada3ab9156cd3b5f4ac2ea30a2133494 Mon Sep 17 00:00:00 2001 From: Nhu Dinh Date: Tue, 9 Dec 2025 03:58:00 +0700 Subject: [PATCH 08/14] Moved repeat steps to beforeEach and added more waits --- .../DeliveryApi/ContentDeliveryApi.spec.ts | 72 ++++++------------- 1 file changed, 21 insertions(+), 51 deletions(-) diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts index 6bdc375bdb32..557d56bb3daf 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts @@ -38,6 +38,7 @@ const childContentAmount = 5; let templateId: string | null = null; let invariantDocTypeId = ''; let collectionDocTypeId = ''; +let publishInvParentId = ''; test.beforeEach(async ({umbracoApi}) => { // Create a template @@ -51,14 +52,17 @@ test.beforeEach(async ({umbracoApi}) => { // Create document types invariantDocTypeId = await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(invariantDocumentType) ?? ''; collectionDocTypeId = await umbracoApi.documentType.createDocumentTypeWithAllowedChildNodeAndCollectionId(collectionDocumentType, invariantDocTypeId, listViewDataType.id) ?? ''; + publishInvParentId = await umbracoApi.document.createDefaultDocument(publishInvParentContent, collectionDocTypeId) ?? ''; + await umbracoApi.document.publish(publishInvParentId); }); test.afterEach(async ({umbracoApi}) => { - // await umbracoApi.documentType.ensureNameNotExists(invariantDocumentType); - // await umbracoApi.documentType.ensureNameNotExists(collectionDocumentType); - // await umbracoApi.template.ensureNameNotExists(templateName); - // await umbracoApi.language.ensureIsoCodeNotExists('da'); - // await umbracoApi.language.ensureIsoCodeNotExists('vi'); + await umbracoApi.document.ensureNameNotExists(publishInvParentContent); + await umbracoApi.documentType.ensureNameNotExists(invariantDocumentType); + await umbracoApi.documentType.ensureNameNotExists(collectionDocumentType); + await umbracoApi.template.ensureNameNotExists(templateName); + await umbracoApi.language.ensureIsoCodeNotExists('da'); + await umbracoApi.language.ensureIsoCodeNotExists('vi'); }); // Gets a content item by id @@ -85,8 +89,6 @@ test('can fetch an content item at root by its ID', async ({umbracoApi}) => { test('can fetch a child content item by its ID', async ({umbracoApi}) => { // Arrange - const publishInvParentId = await umbracoApi.document.createDefaultDocument(publishInvParentContent, collectionDocTypeId); - await umbracoApi.document.publish(publishInvParentId); const contentName = childPublishInvContentPrefix + '2'; const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvParentId); await umbracoApi.document.publish(childId); @@ -104,14 +106,11 @@ test('can fetch a child content item by its ID', async ({umbracoApi}) => { // Clean await umbracoApi.document.ensureNameNotExists(contentName); - await umbracoApi.document.ensureNameNotExists(publishInvParentContent); }); test('can fetch a content item that has children by its ID', async ({umbracoApi}) => { // Arrange const contentName = publishInvParentContent; - const publishInvParentId = await umbracoApi.document.createDefaultDocument(contentName, collectionDocTypeId); - await umbracoApi.document.publish(publishInvParentId); // Create child items for (let i = 1; i <= childContentAmount; i++) { const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvContentPrefix + i, invariantDocTypeId, publishInvParentId); @@ -133,7 +132,6 @@ test('can fetch a content item that has children by its ID', async ({umbracoApi} for (let i = 1; i <= childContentAmount; i++) { await umbracoApi.document.ensureNameNotExists(childPublishInvContentPrefix + i); } - await umbracoApi.document.ensureNameNotExists(contentName); }); test('cannot fetch an unpublished content item without preview by its ID', async ({umbracoApi}) => { @@ -217,9 +215,7 @@ test('can fetch a content item with numeric property', async ({umbracoApi}) => { test('can fetch a content item with multi URL picker property', async ({umbracoApi}) => { // Arrange - // Create parent and child content first - const publishInvParentId = await umbracoApi.document.createDefaultDocument(publishInvParentContent, collectionDocTypeId); - await umbracoApi.document.publish(publishInvParentId); + // Create child content const pickerName = childPublishInvContentPrefix + '2'; const pickerId = await umbracoApi.document.createDefaultDocumentWithParent(pickerName, invariantDocTypeId, publishInvParentId); await umbracoApi.document.publish(pickerId); @@ -242,7 +238,6 @@ test('can fetch a content item with multi URL picker property', async ({umbracoA // Clean await umbracoApi.document.ensureNameNotExists(contentName); await umbracoApi.document.ensureNameNotExists(pickerName); - await umbracoApi.document.ensureNameNotExists(publishInvParentContent); await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithMultiUrlPicker); }); @@ -306,8 +301,6 @@ test('can fetch a content item by its route', async ({umbracoApi}) => { test('can fetch a child content item by its route', async ({umbracoApi}) => { // Arrange - const publishInvParentId = await umbracoApi.document.createDefaultDocument(publishInvParentContent, collectionDocTypeId); - await umbracoApi.document.publish(publishInvParentId); const contentName = childPublishInvContentPrefix + '1'; const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvParentId); await umbracoApi.document.publish(childId); @@ -326,7 +319,6 @@ test('can fetch a child content item by its route', async ({umbracoApi}) => { // Clean await umbracoApi.document.ensureNameNotExists(contentName); - await umbracoApi.document.ensureNameNotExists(publishInvParentContent); }); test('can fetch a content item by its route with special character', async ({umbracoApi}) => { @@ -369,8 +361,6 @@ test('can fetch multiple content items by their IDs', async ({umbracoApi}) => { const publishInvRootId = await umbracoApi.document.createDefaultDocument(contentName1, invariantDocTypeId); await umbracoApi.document.publish(publishInvRootId); - const publishInvParentId = await umbracoApi.document.createDefaultDocument(publishInvParentContent, collectionDocTypeId); - await umbracoApi.document.publish(publishInvParentId); const contentName2 = childPublishInvContentPrefix + '3'; const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName2, invariantDocTypeId, publishInvParentId); await umbracoApi.document.publish(childId); @@ -395,14 +385,11 @@ test('can fetch multiple content items by their IDs', async ({umbracoApi}) => { // Clean await umbracoApi.document.ensureNameNotExists(contentName2); - await umbracoApi.document.ensureNameNotExists(publishInvParentContent); await umbracoApi.document.ensureNameNotExists(contentName1); }); test('returns only valid content items when some IDs are invalid', async ({umbracoApi}) => { // Arrange - const publishInvParentId = await umbracoApi.document.createDefaultDocument(publishInvParentContent, collectionDocTypeId); - await umbracoApi.document.publish(publishInvParentId); const contentName = childPublishInvContentPrefix + '4'; const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvParentId); await umbracoApi.document.publish(childId); @@ -424,7 +411,6 @@ test('returns only valid content items when some IDs are invalid', async ({umbra // Clean await umbracoApi.document.ensureNameNotExists(contentName); - await umbracoApi.document.ensureNameNotExists(publishInvParentContent); }); test('returns only publish content items when some IDs are unpublish', async ({umbracoApi}) => { @@ -460,8 +446,6 @@ test('returns only publish content items when some IDs are unpublish', async ({u test('can fetch children of a content', async ({umbracoApi}) => { // Arrange const parentContentName = publishInvParentContent; - const publishInvParentId = await umbracoApi.document.createDefaultDocument(parentContentName, collectionDocTypeId); - await umbracoApi.document.publish(publishInvParentId); // Create child items for (let i = 1; i <= childContentAmount; i++) { const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvContentPrefix + i, invariantDocTypeId, publishInvParentId); @@ -485,18 +469,15 @@ test('can fetch children of a content', async ({umbracoApi}) => { for (let i = 1; i <= childContentAmount; i++) { await umbracoApi.document.ensureNameNotExists(childPublishInvContentPrefix + i); } - await umbracoApi.document.ensureNameNotExists(parentContentName); }); test('can fetch ancestors of a content item', async ({umbracoApi}) => { // Arrange const expectedParentContentName = publishInvParentContent; - const publishInvParentId = await umbracoApi.document.createDefaultDocument(expectedParentContentName, collectionDocTypeId); - await umbracoApi.document.publish(publishInvParentId); const childContentName = childPublishInvContentPrefix + '1'; const childId = await umbracoApi.document.createDefaultDocumentWithParent(childContentName, invariantDocTypeId, publishInvParentId); await umbracoApi.document.publish(childId); - + await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed const fetch = 'ancestors:' + childId; // Act @@ -511,18 +492,15 @@ test('can fetch ancestors of a content item', async ({umbracoApi}) => { // Clean await umbracoApi.document.ensureNameNotExists(childContentName); - await umbracoApi.document.ensureNameNotExists(expectedParentContentName); }); test('can filter content items', async ({umbracoApi}) => { // Arrange const expectedContentName = publishInvParentContent; - const publishInvParentId = await umbracoApi.document.createDefaultDocument(expectedContentName, collectionDocTypeId); - await umbracoApi.document.publish(publishInvParentId); - const contentType = collectionDocumentType; const contentTypeData = await umbracoApi.documentType.getByName(contentType); const filter = 'contentType:' + contentTypeData.alias; + await umbracoApi.page.waitForTimeout(500); // Wait is needed to ensure content is indexed // Act const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, filter); @@ -533,21 +511,16 @@ test('can filter content items', async ({umbracoApi}) => { expect(contentItemsJson.total).toBe(1); await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(expectedContentName, contentItemsJson.items[0]); await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(expectedContentName, contentItemsJson.items[0]); - - // Clean - await umbracoApi.document.ensureNameNotExists(expectedContentName); }); test('can sort content items', async ({umbracoApi}) => { // Arrange - const publishInvParentId = await umbracoApi.document.createDefaultDocument(publishInvParentContent, collectionDocTypeId); - await umbracoApi.document.publish(publishInvParentId); // Create child items - for (let i = 1; i <= childContentAmount; i++) { + for (let i = 0; i < childContentAmount; i++) { const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvContentPrefix + i, invariantDocTypeId, publishInvParentId); await umbracoApi.document.publish(childId); } - + await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed const sort = 'name:desc'; const filter = 'name:' + 'Child'; @@ -559,32 +532,29 @@ test('can sort content items', async ({umbracoApi}) => { const contentItemsJson = await contentItems.json(); expect(contentItemsJson.total).toBe(childContentAmount); for (let i = 0; i < childContentAmount; i++) { - expect(contentItemsJson.items[i].name).toBe(childPublishInvContentPrefix + ' ' + (i + 1)); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(childPublishInvContentPrefix + i, contentItemsJson.items[childContentAmount - i]); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(childPublishInvContentPrefix + i, contentItemsJson.items[childContentAmount - i]); + expect(contentItemsJson.items[i].name).toBe(childPublishInvContentPrefix + (childContentAmount - 1 - i)); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(childPublishInvContentPrefix + i, contentItemsJson.items[childContentAmount - 1 - i]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(childPublishInvContentPrefix + i, contentItemsJson.items[childContentAmount - 1 - i]); } // Clean - for (let i = 1; i <= childContentAmount; i++) { + for (let i = 0; i < childContentAmount; i++) { await umbracoApi.document.ensureNameNotExists(childPublishInvContentPrefix + i); } - await umbracoApi.document.ensureNameNotExists(publishInvParentContent); }); test('can paginate content items', async ({umbracoApi}) => { // Arrange - const publishInvParentId = await umbracoApi.document.createDefaultDocument(publishInvParentContent, collectionDocTypeId); - await umbracoApi.document.publish(publishInvParentId); // Create child items for (let i = 1; i <= childContentAmount; i++) { const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvContentPrefix + i, invariantDocTypeId, publishInvParentId); await umbracoApi.document.publish(childId); } - + await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed const sort = 'name:asc'; const filter = 'name:' + 'Child'; const skip = 0; - const take = childContentAmount - 1; + const take = childContentAmount - 2; // Act const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, filter, sort, skip, take); @@ -592,6 +562,7 @@ test('can paginate content items', async ({umbracoApi}) => { // Assert expect(contentItems.status()).toBe(200); const contentItemsJson = await contentItems.json(); + console.log(contentItemsJson); expect(contentItemsJson.total).toBe(childContentAmount); expect(contentItemsJson.items.length).toBe(take); @@ -599,7 +570,6 @@ test('can paginate content items', async ({umbracoApi}) => { for (let i = 1; i <= childContentAmount; i++) { await umbracoApi.document.ensureNameNotExists(childPublishInvContentPrefix + i); } - await umbracoApi.document.ensureNameNotExists(publishInvParentContent); }); test('returns 400 when using an invalid sort parameter', async ({umbracoApi}) => { From 9c8869dc32a22ff235cd8e46e84f1387ac318dd2 Mon Sep 17 00:00:00 2001 From: Nhu Dinh Date: Tue, 9 Dec 2025 15:06:11 +0700 Subject: [PATCH 09/14] Bumped version --- tests/Umbraco.Tests.AcceptanceTest/package-lock.json | 8 ++++---- tests/Umbraco.Tests.AcceptanceTest/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/Umbraco.Tests.AcceptanceTest/package-lock.json b/tests/Umbraco.Tests.AcceptanceTest/package-lock.json index d31a2f2f0d6b..eec3a5721a6e 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/package-lock.json +++ b/tests/Umbraco.Tests.AcceptanceTest/package-lock.json @@ -8,7 +8,7 @@ "hasInstallScript": true, "dependencies": { "@umbraco/json-models-builders": "^2.0.42", - "@umbraco/playwright-testhelpers": "^17.0.15", + "@umbraco/playwright-testhelpers": "^17.0.17", "camelize": "^1.0.0", "dotenv": "^16.3.1", "node-fetch": "^2.6.7" @@ -67,9 +67,9 @@ } }, "node_modules/@umbraco/playwright-testhelpers": { - "version": "17.0.15", - "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-17.0.15.tgz", - "integrity": "sha512-aV31VbzkSGTH0q8AloB6aWQuYIxvKrH613DOFBhO0Ccw99Xv1NB9ZsE/HrG2QO//Si6p9y8aWv4mfQKcUfQ41w==", + "version": "17.0.17", + "resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-17.0.17.tgz", + "integrity": "sha512-5WqByhAnp0WUVay0MI0C1eEmAled5YuRmooq5DuXIhKA/B7F99fNKbGLU4YdlYKDjcTMzSlTV5oByvaiVhpIog==", "license": "MIT", "dependencies": { "@umbraco/json-models-builders": "2.0.42", diff --git a/tests/Umbraco.Tests.AcceptanceTest/package.json b/tests/Umbraco.Tests.AcceptanceTest/package.json index a5f31426cf88..a12019aa4102 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/package.json +++ b/tests/Umbraco.Tests.AcceptanceTest/package.json @@ -23,7 +23,7 @@ }, "dependencies": { "@umbraco/json-models-builders": "^2.0.42", - "@umbraco/playwright-testhelpers": "^17.0.15", + "@umbraco/playwright-testhelpers": "^17.0.17", "camelize": "^1.0.0", "dotenv": "^16.3.1", "node-fetch": "^2.6.7" From 9fbef79b2a8c29f0dd15cc8a6e0b54fb63d8fcb3 Mon Sep 17 00:00:00 2001 From: Nhu Dinh Date: Tue, 9 Dec 2025 17:22:47 +0700 Subject: [PATCH 10/14] Added more waits --- .../tests/DeliveryApi/ContentDeliveryApi.spec.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts index 557d56bb3daf..24a25ccd137e 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts @@ -451,7 +451,7 @@ test('can fetch children of a content', async ({umbracoApi}) => { const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvContentPrefix + i, invariantDocTypeId, publishInvParentId); await umbracoApi.document.publish(childId); } - + await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed const parentContentData = await umbracoApi.document.getByName(parentContentName); const parentContentId = parentContentData.id; const fetch = 'children:' + parentContentId; @@ -500,7 +500,7 @@ test('can filter content items', async ({umbracoApi}) => { const contentType = collectionDocumentType; const contentTypeData = await umbracoApi.documentType.getByName(contentType); const filter = 'contentType:' + contentTypeData.alias; - await umbracoApi.page.waitForTimeout(500); // Wait is needed to ensure content is indexed + await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed // Act const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, filter); @@ -562,7 +562,6 @@ test('can paginate content items', async ({umbracoApi}) => { // Assert expect(contentItems.status()).toBe(200); const contentItemsJson = await contentItems.json(); - console.log(contentItemsJson); expect(contentItemsJson.total).toBe(childContentAmount); expect(contentItemsJson.items.length).toBe(take); From 3e29a4fbfb3a764dc64340c6d9b3b52d04776f71 Mon Sep 17 00:00:00 2001 From: Nhu Dinh Date: Mon, 15 Dec 2025 16:56:47 +0700 Subject: [PATCH 11/14] Updated variable names --- .../DeliveryApi/ContentDeliveryApi.spec.ts | 129 +++++++++--------- 1 file changed, 65 insertions(+), 64 deletions(-) diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts index 24a25ccd137e..aa39ac9b5a34 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts @@ -2,16 +2,16 @@ import {expect} from '@playwright/test'; import {test} from '@umbraco/playwright-testhelpers'; // Document -const publishInvRootContent = 'Publish Invariant Root'; -const publishInvParentContent = 'Publish Invariant Parent'; -const childPublishInvContentPrefix = 'Child Publish Invariant'; -const publishInvContentWithTextstring = 'Publish Invariant With Textstring'; -const publishInvContentWithNumeric = 'Publish Invariant With Numeric'; -const publishInvContentWithTrueFalse = 'Publish Invariant With True/False'; -const publishInvContentWithMultiUrlPicker = 'Publish Invariant With Multi URL Picker'; -const unpublishInvRootContent = 'Unpublish Invariant Root'; +const publishInvariantRootContent = 'Publish Invariant Root'; +const publishInvariantParentContent = 'Publish Invariant Parent'; +const childPublishInvariantContentPrefix = 'Child Publish Invariant'; +const publishInvariantContentWithTextstring = 'Publish Invariant With Textstring'; +const publishInvariantContentWithNumeric = 'Publish Invariant With Numeric'; +const publishInvariantContentWithTrueFalse = 'Publish Invariant With True/False'; +const publishInvariantContentWithMultiUrlPicker = 'Publish Invariant With Multi URL Picker'; +const unpublishInvariantRootContent = 'Unpublish Invariant Root'; const publishVariantRootContent = 'Publish Variant Root'; -const publishInvContentWithSpecialCharacters = 'Test Content, . ! ? # $ % & * @ é ü ă đ 漢字'; +const publishInvariantContentWithSpecialCharacters = 'Test Content, . ! ? # $ % & * @ é ü ă đ 漢字'; // Document Type const invariantDocumentType = 'Invariant Document Type'; const collectionDocumentType = 'Collection Document Type'; @@ -38,26 +38,27 @@ const childContentAmount = 5; let templateId: string | null = null; let invariantDocTypeId = ''; let collectionDocTypeId = ''; -let publishInvParentId = ''; +let publishInvariantParentId = ''; test.beforeEach(async ({umbracoApi}) => { // Create a template const createdTemplateId = await umbracoApi.template.createDefaultTemplate(templateName); templateId = createdTemplateId ?? null; - // Create 3 languages (en-US, da, vi) + // Create 2 languages (da, vi) await umbracoApi.language.createDanishLanguage(); await umbracoApi.language.createVietnameseLanguage(); - // Get data types + // Get data type const listViewDataType = await umbracoApi.dataType.getByName(listViewContentTypeName); // Create document types invariantDocTypeId = await umbracoApi.documentType.createDefaultDocumentTypeWithAllowAsRoot(invariantDocumentType) ?? ''; collectionDocTypeId = await umbracoApi.documentType.createDocumentTypeWithAllowedChildNodeAndCollectionId(collectionDocumentType, invariantDocTypeId, listViewDataType.id) ?? ''; - publishInvParentId = await umbracoApi.document.createDefaultDocument(publishInvParentContent, collectionDocTypeId) ?? ''; - await umbracoApi.document.publish(publishInvParentId); + // Create document + publishInvariantParentId = await umbracoApi.document.createDefaultDocument(publishInvariantParentContent, collectionDocTypeId) ?? ''; + await umbracoApi.document.publish(publishInvariantParentId); }); test.afterEach(async ({umbracoApi}) => { - await umbracoApi.document.ensureNameNotExists(publishInvParentContent); + await umbracoApi.document.ensureNameNotExists(publishInvariantParentContent); await umbracoApi.documentType.ensureNameNotExists(invariantDocumentType); await umbracoApi.documentType.ensureNameNotExists(collectionDocumentType); await umbracoApi.template.ensureNameNotExists(templateName); @@ -68,9 +69,9 @@ test.afterEach(async ({umbracoApi}) => { // Gets a content item by id test('can fetch an content item at root by its ID', async ({umbracoApi}) => { // Arrange - const contentName = publishInvRootContent; - const publishInvRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); - await umbracoApi.document.publish(publishInvRootId); + const contentName = publishInvariantRootContent; + const publishInvariantRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); + await umbracoApi.document.publish(publishInvariantRootId); const contentData = await umbracoApi.document.getByName(contentName); // Act @@ -89,8 +90,8 @@ test('can fetch an content item at root by its ID', async ({umbracoApi}) => { test('can fetch a child content item by its ID', async ({umbracoApi}) => { // Arrange - const contentName = childPublishInvContentPrefix + '2'; - const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvParentId); + const contentName = childPublishInvariantContentPrefix + '2'; + const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvariantParentId); await umbracoApi.document.publish(childId); const contentData = await umbracoApi.document.getByName(contentName); @@ -110,10 +111,10 @@ test('can fetch a child content item by its ID', async ({umbracoApi}) => { test('can fetch a content item that has children by its ID', async ({umbracoApi}) => { // Arrange - const contentName = publishInvParentContent; + const contentName = publishInvariantParentContent; // Create child items for (let i = 1; i <= childContentAmount; i++) { - const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvContentPrefix + i, invariantDocTypeId, publishInvParentId); + const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvariantContentPrefix + i, invariantDocTypeId, publishInvariantParentId); await umbracoApi.document.publish(childId); } const contentData = await umbracoApi.document.getByName(contentName); @@ -130,13 +131,13 @@ test('can fetch a content item that has children by its ID', async ({umbracoApi} // Clean for (let i = 1; i <= childContentAmount; i++) { - await umbracoApi.document.ensureNameNotExists(childPublishInvContentPrefix + i); + await umbracoApi.document.ensureNameNotExists(childPublishInvariantContentPrefix + i); } }); test('cannot fetch an unpublished content item without preview by its ID', async ({umbracoApi}) => { // Arrange - const contentName = unpublishInvRootContent; + const contentName = unpublishInvariantRootContent; await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); const contentData = await umbracoApi.document.getByName(contentName); @@ -152,7 +153,7 @@ test('cannot fetch an unpublished content item without preview by its ID', async test('can fetch a content item with textstring property', async ({umbracoApi}) => { // Arrange - const contentName = publishInvContentWithTextstring; + const contentName = publishInvariantContentWithTextstring; const textstringDataType = await umbracoApi.dataType.getByName(textstringDataTypeName); const contentId = await umbracoApi.document.createPublishedDocumentWithValue(contentName, textPropertyValue, textstringDataType.id, templateId!, textstringDataTypeName, invariantDocumentTypeWithTextString); @@ -173,7 +174,7 @@ test('can fetch a content item with textstring property', async ({umbracoApi}) = test('can fetch a content item with true/false property', async ({umbracoApi}) => { // Arrange - const contentName = publishInvContentWithTrueFalse; + const contentName = publishInvariantContentWithTrueFalse; const trueFalseDataType = await umbracoApi.dataType.getByName(trueFalseDataTypeName); const contentId = await umbracoApi.document.createPublishedDocumentWithValue(contentName, trueFalsePropertyValue, trueFalseDataType.id, templateId!, 'Test TrueFalse', invariantDocumentTypeWithTrueFalse); @@ -194,7 +195,7 @@ test('can fetch a content item with true/false property', async ({umbracoApi}) = test('can fetch a content item with numeric property', async ({umbracoApi}) => { // Arrange - const contentName = publishInvContentWithNumeric; + const contentName = publishInvariantContentWithNumeric; const numericDataType = await umbracoApi.dataType.getByName(numericDataTypeName); const contentId = await umbracoApi.document.createPublishedDocumentWithValue(contentName, numericPropertyValue, numericDataType.id, templateId!, numericDataTypeName, invariantDocumentTypeWithNumeric); @@ -216,12 +217,12 @@ test('can fetch a content item with numeric property', async ({umbracoApi}) => { test('can fetch a content item with multi URL picker property', async ({umbracoApi}) => { // Arrange // Create child content - const pickerName = childPublishInvContentPrefix + '2'; - const pickerId = await umbracoApi.document.createDefaultDocumentWithParent(pickerName, invariantDocTypeId, publishInvParentId); + const pickerName = childPublishInvariantContentPrefix + '2'; + const pickerId = await umbracoApi.document.createDefaultDocumentWithParent(pickerName, invariantDocTypeId, publishInvariantParentId); await umbracoApi.document.publish(pickerId); const pickerNameData = await umbracoApi.document.getByName(pickerName); - const contentName = publishInvContentWithMultiUrlPicker; + const contentName = publishInvariantContentWithMultiUrlPicker; const multiUrlPickerDataType = await umbracoApi.dataType.getByName(multiUrlPickerDataTypeName); const contentId = await umbracoApi.document.createPublishedDocumentWithDocumentLinkURLPicker(contentName, pickerName, pickerNameData.id, multiUrlPickerDataType.id, templateId!, multiUrlPickerDataTypeName, invariantDocumentTypeWithMultiUrlPicker); @@ -279,9 +280,9 @@ test('returns 404 when fetching a non-existent content item', async ({umbracoApi // Gets a content item by route test('can fetch a content item by its route', async ({umbracoApi}) => { // Arrange - const contentName = publishInvRootContent; - const publishInvRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); - await umbracoApi.document.publish(publishInvRootId); + const contentName = publishInvariantRootContent; + const publishInvariantRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); + await umbracoApi.document.publish(publishInvariantRootId); const contentData = await umbracoApi.document.getByName(contentName); const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); @@ -301,8 +302,8 @@ test('can fetch a content item by its route', async ({umbracoApi}) => { test('can fetch a child content item by its route', async ({umbracoApi}) => { // Arrange - const contentName = childPublishInvContentPrefix + '1'; - const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvParentId); + const contentName = childPublishInvariantContentPrefix + '1'; + const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvariantParentId); await umbracoApi.document.publish(childId); const contentData = await umbracoApi.document.getByName(contentName); const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); @@ -323,9 +324,9 @@ test('can fetch a child content item by its route', async ({umbracoApi}) => { test('can fetch a content item by its route with special character', async ({umbracoApi}) => { // Arrange - const contentName = publishInvContentWithSpecialCharacters; - const publishInvContentWithSpecialCharactersId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); - await umbracoApi.document.publish(publishInvContentWithSpecialCharactersId); + const contentName = publishInvariantContentWithSpecialCharacters; + const publishInvariantContentWithSpecialCharactersId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); + await umbracoApi.document.publish(publishInvariantContentWithSpecialCharactersId); const contentData = await umbracoApi.document.getByName(contentName); const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); @@ -357,12 +358,12 @@ test('returns 404 when fetching a non-existent content route', async ({umbracoAp // Gets content item(s) by id test('can fetch multiple content items by their IDs', async ({umbracoApi}) => { // Arrange - const contentName1 = publishInvRootContent; - const publishInvRootId = await umbracoApi.document.createDefaultDocument(contentName1, invariantDocTypeId); - await umbracoApi.document.publish(publishInvRootId); + const contentName1 = publishInvariantRootContent; + const publishInvariantRootId = await umbracoApi.document.createDefaultDocument(contentName1, invariantDocTypeId); + await umbracoApi.document.publish(publishInvariantRootId); - const contentName2 = childPublishInvContentPrefix + '3'; - const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName2, invariantDocTypeId, publishInvParentId); + const contentName2 = childPublishInvariantContentPrefix + '3'; + const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName2, invariantDocTypeId, publishInvariantParentId); await umbracoApi.document.publish(childId); const contentData1 = await umbracoApi.document.getByName(contentName1); @@ -390,8 +391,8 @@ test('can fetch multiple content items by their IDs', async ({umbracoApi}) => { test('returns only valid content items when some IDs are invalid', async ({umbracoApi}) => { // Arrange - const contentName = childPublishInvContentPrefix + '4'; - const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvParentId); + const contentName = childPublishInvariantContentPrefix + '4'; + const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvariantParentId); await umbracoApi.document.publish(childId); const contentData = await umbracoApi.document.getByName(contentName); @@ -413,13 +414,13 @@ test('returns only valid content items when some IDs are invalid', async ({umbra await umbracoApi.document.ensureNameNotExists(contentName); }); -test('returns only publish content items when some IDs are unpublish', async ({umbracoApi}) => { +test('returns only published content items when some IDs are unpublished', async ({umbracoApi}) => { // Arrange - const contentName = publishInvRootContent; - const publishInvRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); - await umbracoApi.document.publish(publishInvRootId); + const contentName = publishInvariantRootContent; + const publishInvariantRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); + await umbracoApi.document.publish(publishInvariantRootId); - const unpublishContent = unpublishInvRootContent; + const unpublishContent = unpublishInvariantRootContent; await umbracoApi.document.createDefaultDocument(unpublishContent, invariantDocTypeId); const contentData = await umbracoApi.document.getByName(contentName); @@ -445,10 +446,10 @@ test('returns only publish content items when some IDs are unpublish', async ({u // Gets content item(s) from a query test('can fetch children of a content', async ({umbracoApi}) => { // Arrange - const parentContentName = publishInvParentContent; + const parentContentName = publishInvariantParentContent; // Create child items for (let i = 1; i <= childContentAmount; i++) { - const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvContentPrefix + i, invariantDocTypeId, publishInvParentId); + const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvariantContentPrefix + i, invariantDocTypeId, publishInvariantParentId); await umbracoApi.document.publish(childId); } await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed @@ -467,15 +468,15 @@ test('can fetch children of a content', async ({umbracoApi}) => { // Clean for (let i = 1; i <= childContentAmount; i++) { - await umbracoApi.document.ensureNameNotExists(childPublishInvContentPrefix + i); + await umbracoApi.document.ensureNameNotExists(childPublishInvariantContentPrefix + i); } }); test('can fetch ancestors of a content item', async ({umbracoApi}) => { // Arrange - const expectedParentContentName = publishInvParentContent; - const childContentName = childPublishInvContentPrefix + '1'; - const childId = await umbracoApi.document.createDefaultDocumentWithParent(childContentName, invariantDocTypeId, publishInvParentId); + const expectedParentContentName = publishInvariantParentContent; + const childContentName = childPublishInvariantContentPrefix + '1'; + const childId = await umbracoApi.document.createDefaultDocumentWithParent(childContentName, invariantDocTypeId, publishInvariantParentId); await umbracoApi.document.publish(childId); await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed const fetch = 'ancestors:' + childId; @@ -496,7 +497,7 @@ test('can fetch ancestors of a content item', async ({umbracoApi}) => { test('can filter content items', async ({umbracoApi}) => { // Arrange - const expectedContentName = publishInvParentContent; + const expectedContentName = publishInvariantParentContent; const contentType = collectionDocumentType; const contentTypeData = await umbracoApi.documentType.getByName(contentType); const filter = 'contentType:' + contentTypeData.alias; @@ -517,7 +518,7 @@ test('can sort content items', async ({umbracoApi}) => { // Arrange // Create child items for (let i = 0; i < childContentAmount; i++) { - const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvContentPrefix + i, invariantDocTypeId, publishInvParentId); + const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvariantContentPrefix + i, invariantDocTypeId, publishInvariantParentId); await umbracoApi.document.publish(childId); } await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed @@ -532,14 +533,14 @@ test('can sort content items', async ({umbracoApi}) => { const contentItemsJson = await contentItems.json(); expect(contentItemsJson.total).toBe(childContentAmount); for (let i = 0; i < childContentAmount; i++) { - expect(contentItemsJson.items[i].name).toBe(childPublishInvContentPrefix + (childContentAmount - 1 - i)); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(childPublishInvContentPrefix + i, contentItemsJson.items[childContentAmount - 1 - i]); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(childPublishInvContentPrefix + i, contentItemsJson.items[childContentAmount - 1 - i]); + expect(contentItemsJson.items[i].name).toBe(childPublishInvariantContentPrefix + (childContentAmount - 1 - i)); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(childPublishInvariantContentPrefix + i, contentItemsJson.items[childContentAmount - 1 - i]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(childPublishInvariantContentPrefix + i, contentItemsJson.items[childContentAmount - 1 - i]); } // Clean for (let i = 0; i < childContentAmount; i++) { - await umbracoApi.document.ensureNameNotExists(childPublishInvContentPrefix + i); + await umbracoApi.document.ensureNameNotExists(childPublishInvariantContentPrefix + i); } }); @@ -547,7 +548,7 @@ test('can paginate content items', async ({umbracoApi}) => { // Arrange // Create child items for (let i = 1; i <= childContentAmount; i++) { - const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvContentPrefix + i, invariantDocTypeId, publishInvParentId); + const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvariantContentPrefix + i, invariantDocTypeId, publishInvariantParentId); await umbracoApi.document.publish(childId); } await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed @@ -567,7 +568,7 @@ test('can paginate content items', async ({umbracoApi}) => { // Clean for (let i = 1; i <= childContentAmount; i++) { - await umbracoApi.document.ensureNameNotExists(childPublishInvContentPrefix + i); + await umbracoApi.document.ensureNameNotExists(childPublishInvariantContentPrefix + i); } }); From fb37d5b84a113586a857ce9002508623e1d67189 Mon Sep 17 00:00:00 2001 From: Nhu Dinh Date: Mon, 15 Dec 2025 17:03:47 +0700 Subject: [PATCH 12/14] Grouped tests --- .../DeliveryApi/ContentDeliveryApi.spec.ts | 1072 +++++++++-------- 1 file changed, 538 insertions(+), 534 deletions(-) diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts index aa39ac9b5a34..7ba967629e85 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts @@ -66,550 +66,554 @@ test.afterEach(async ({umbracoApi}) => { await umbracoApi.language.ensureIsoCodeNotExists('vi'); }); -// Gets a content item by id -test('can fetch an content item at root by its ID', async ({umbracoApi}) => { - // Arrange - const contentName = publishInvariantRootContent; - const publishInvariantRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); - await umbracoApi.document.publish(publishInvariantRootId); - const contentData = await umbracoApi.document.getByName(contentName); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - - // Clean - await umbracoApi.document.ensureNameNotExists(contentName); -}); - -test('can fetch a child content item by its ID', async ({umbracoApi}) => { - // Arrange - const contentName = childPublishInvariantContentPrefix + '2'; - const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvariantParentId); - await umbracoApi.document.publish(childId); - const contentData = await umbracoApi.document.getByName(contentName); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - - // Clean - await umbracoApi.document.ensureNameNotExists(contentName); -}); - -test('can fetch a content item that has children by its ID', async ({umbracoApi}) => { - // Arrange - const contentName = publishInvariantParentContent; - // Create child items - for (let i = 1; i <= childContentAmount; i++) { - const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvariantContentPrefix + i, invariantDocTypeId, publishInvariantParentId); +test.describe('fetch a content item by id', () => { + test('can fetch an content item at root by its ID', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvariantRootContent; + const publishInvariantRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); + await umbracoApi.document.publish(publishInvariantRootId); + const contentData = await umbracoApi.document.getByName(contentName); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + }); + + test('can fetch a child content item by its ID', async ({umbracoApi}) => { + // Arrange + const contentName = childPublishInvariantContentPrefix + '2'; + const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvariantParentId); await umbracoApi.document.publish(childId); - } - const contentData = await umbracoApi.document.getByName(contentName); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - - // Clean - for (let i = 1; i <= childContentAmount; i++) { - await umbracoApi.document.ensureNameNotExists(childPublishInvariantContentPrefix + i); - } -}); - -test('cannot fetch an unpublished content item without preview by its ID', async ({umbracoApi}) => { - // Arrange - const contentName = unpublishInvariantRootContent; - await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); - const contentData = await umbracoApi.document.getByName(contentName); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); - - // Assert - expect(contentItem.status()).toBe(404); - - // Clean - await umbracoApi.document.ensureNameNotExists(contentName); -}); - -test('can fetch a content item with textstring property', async ({umbracoApi}) => { - // Arrange - const contentName = publishInvariantContentWithTextstring; - const textstringDataType = await umbracoApi.dataType.getByName(textstringDataTypeName); - const contentId = await umbracoApi.document.createPublishedDocumentWithValue(contentName, textPropertyValue, textstringDataType.id, templateId!, textstringDataTypeName, invariantDocumentTypeWithTextString); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - - // Clean - await umbracoApi.document.ensureNameNotExists(contentName); - await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithTextString); -}); - -test('can fetch a content item with true/false property', async ({umbracoApi}) => { - // Arrange - const contentName = publishInvariantContentWithTrueFalse; - const trueFalseDataType = await umbracoApi.dataType.getByName(trueFalseDataTypeName); - const contentId = await umbracoApi.document.createPublishedDocumentWithValue(contentName, trueFalsePropertyValue, trueFalseDataType.id, templateId!, 'Test TrueFalse', invariantDocumentTypeWithTrueFalse); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - - // Clean - await umbracoApi.document.ensureNameNotExists(contentName); - await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithTrueFalse); -}); - -test('can fetch a content item with numeric property', async ({umbracoApi}) => { - // Arrange - const contentName = publishInvariantContentWithNumeric; - const numericDataType = await umbracoApi.dataType.getByName(numericDataTypeName); - const contentId = await umbracoApi.document.createPublishedDocumentWithValue(contentName, numericPropertyValue, numericDataType.id, templateId!, numericDataTypeName, invariantDocumentTypeWithNumeric); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - - // Clean - await umbracoApi.document.ensureNameNotExists(contentName); - await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithNumeric); -}); - -test('can fetch a content item with multi URL picker property', async ({umbracoApi}) => { - // Arrange - // Create child content - const pickerName = childPublishInvariantContentPrefix + '2'; - const pickerId = await umbracoApi.document.createDefaultDocumentWithParent(pickerName, invariantDocTypeId, publishInvariantParentId); - await umbracoApi.document.publish(pickerId); - const pickerNameData = await umbracoApi.document.getByName(pickerName); - - const contentName = publishInvariantContentWithMultiUrlPicker; - const multiUrlPickerDataType = await umbracoApi.dataType.getByName(multiUrlPickerDataTypeName); - const contentId = await umbracoApi.document.createPublishedDocumentWithDocumentLinkURLPicker(contentName, pickerName, pickerNameData.id, multiUrlPickerDataType.id, templateId!, multiUrlPickerDataTypeName, invariantDocumentTypeWithMultiUrlPicker); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItemWithMultiURLPicker(contentName, contentItemJson, 'Content'); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - - // Clean - await umbracoApi.document.ensureNameNotExists(contentName); - await umbracoApi.document.ensureNameNotExists(pickerName); - await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithMultiUrlPicker); -}); - -test('can fetch a variant content item by its ID', async ({umbracoApi}) => { - // Arrange - const contentName = publishVariantRootContent; - const textStringDataType = await umbracoApi.dataType.getByName(textstringDataTypeName); - const variantDocTypeId = await umbracoApi.documentType.createVariantDocumentTypeWithInvariantPropertyEditor(variantDocumentTypeWithTextstring, textstringDataTypeName, textStringDataType.id); - const publishVariantRootId = await umbracoApi.document.createDocumentWithEnglishCultureAndTextContent(contentName, variantDocTypeId, textPropertyValue, textstringDataTypeName); - await umbracoApi.document.publishDocumentWithCulture(publishVariantRootId, 'en-US'); - const contentData = await umbracoApi.document.getByName(contentName); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson, true); - - // Clean - await umbracoApi.document.ensureNameNotExists(contentName); - await umbracoApi.documentType.ensureNameNotExists(variantDocumentTypeWithTextstring); -}); - -test('returns 404 when fetching a non-existent content item', async ({umbracoApi}) => { - // Arrange - const nonExistentContentId = '00000000-0000-0000-0000-000000000000'; - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(nonExistentContentId); - - // Assert - expect(contentItem.status()).toBe(404); -}); - -// Gets a content item by route -test('can fetch a content item by its route', async ({umbracoApi}) => { - // Arrange - const contentName = publishInvariantRootContent; - const publishInvariantRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); - await umbracoApi.document.publish(publishInvariantRootId); - const contentData = await umbracoApi.document.getByName(contentName); - const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithRoute(contentURL); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - - // Clean - await umbracoApi.document.ensureNameNotExists(contentName); -}); - -test('can fetch a child content item by its route', async ({umbracoApi}) => { - // Arrange - const contentName = childPublishInvariantContentPrefix + '1'; - const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvariantParentId); - await umbracoApi.document.publish(childId); - const contentData = await umbracoApi.document.getByName(contentName); - const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentURL); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - - // Clean - await umbracoApi.document.ensureNameNotExists(contentName); + const contentData = await umbracoApi.document.getByName(contentName); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + }); + + test('can fetch a content item that has children by its ID', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvariantParentContent; + // Create child items + for (let i = 1; i <= childContentAmount; i++) { + const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvariantContentPrefix + i, invariantDocTypeId, publishInvariantParentId); + await umbracoApi.document.publish(childId); + } + const contentData = await umbracoApi.document.getByName(contentName); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + for (let i = 1; i <= childContentAmount; i++) { + await umbracoApi.document.ensureNameNotExists(childPublishInvariantContentPrefix + i); + } + }); + + test('cannot fetch an unpublished content item without preview by its ID', async ({umbracoApi}) => { + // Arrange + const contentName = unpublishInvariantRootContent; + await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); + const contentData = await umbracoApi.document.getByName(contentName); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); + + // Assert + expect(contentItem.status()).toBe(404); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + }); + + test('can fetch a content item with textstring property', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvariantContentWithTextstring; + const textstringDataType = await umbracoApi.dataType.getByName(textstringDataTypeName); + const contentId = await umbracoApi.document.createPublishedDocumentWithValue(contentName, textPropertyValue, textstringDataType.id, templateId!, textstringDataTypeName, invariantDocumentTypeWithTextString); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithTextString); + }); + + test('can fetch a content item with true/false property', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvariantContentWithTrueFalse; + const trueFalseDataType = await umbracoApi.dataType.getByName(trueFalseDataTypeName); + const contentId = await umbracoApi.document.createPublishedDocumentWithValue(contentName, trueFalsePropertyValue, trueFalseDataType.id, templateId!, 'Test TrueFalse', invariantDocumentTypeWithTrueFalse); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithTrueFalse); + }); + + test('can fetch a content item with numeric property', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvariantContentWithNumeric; + const numericDataType = await umbracoApi.dataType.getByName(numericDataTypeName); + const contentId = await umbracoApi.document.createPublishedDocumentWithValue(contentName, numericPropertyValue, numericDataType.id, templateId!, numericDataTypeName, invariantDocumentTypeWithNumeric); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithNumeric); + }); + + test('can fetch a content item with multi URL picker property', async ({umbracoApi}) => { + // Arrange + // Create child content + const pickerName = childPublishInvariantContentPrefix + '2'; + const pickerId = await umbracoApi.document.createDefaultDocumentWithParent(pickerName, invariantDocTypeId, publishInvariantParentId); + await umbracoApi.document.publish(pickerId); + const pickerNameData = await umbracoApi.document.getByName(pickerName); + + const contentName = publishInvariantContentWithMultiUrlPicker; + const multiUrlPickerDataType = await umbracoApi.dataType.getByName(multiUrlPickerDataTypeName); + const contentId = await umbracoApi.document.createPublishedDocumentWithDocumentLinkURLPicker(contentName, pickerName, pickerNameData.id, multiUrlPickerDataType.id, templateId!, multiUrlPickerDataTypeName, invariantDocumentTypeWithMultiUrlPicker); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentId); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForContentItemWithMultiURLPicker(contentName, contentItemJson, 'Content'); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.document.ensureNameNotExists(pickerName); + await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithMultiUrlPicker); + }); + + test('can fetch a variant content item by its ID', async ({umbracoApi}) => { + // Arrange + const contentName = publishVariantRootContent; + const textStringDataType = await umbracoApi.dataType.getByName(textstringDataTypeName); + const variantDocTypeId = await umbracoApi.documentType.createVariantDocumentTypeWithInvariantPropertyEditor(variantDocumentTypeWithTextstring, textstringDataTypeName, textStringDataType.id); + const publishVariantRootId = await umbracoApi.document.createDocumentWithEnglishCultureAndTextContent(contentName, variantDocTypeId, textPropertyValue, textstringDataTypeName); + await umbracoApi.document.publishDocumentWithCulture(publishVariantRootId, 'en-US'); + const contentData = await umbracoApi.document.getByName(contentName); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentData.id); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson, true); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + await umbracoApi.documentType.ensureNameNotExists(variantDocumentTypeWithTextstring); + }); + + test('returns 404 when fetching a non-existent content item', async ({umbracoApi}) => { + // Arrange + const nonExistentContentId = '00000000-0000-0000-0000-000000000000'; + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(nonExistentContentId); + + // Assert + expect(contentItem.status()).toBe(404); + }); }); -test('can fetch a content item by its route with special character', async ({umbracoApi}) => { - // Arrange - const contentName = publishInvariantContentWithSpecialCharacters; - const publishInvariantContentWithSpecialCharactersId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); - await umbracoApi.document.publish(publishInvariantContentWithSpecialCharactersId); - const contentData = await umbracoApi.document.getByName(contentName); - const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentURL); - - // Assert - expect(contentItem.status()).toBe(200); - const contentItemJson = await contentItem.json(); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); - - // Clean - await umbracoApi.document.ensureNameNotExists(contentName); -}); - -test('returns 404 when fetching a non-existent content route', async ({umbracoApi}) => { - // Arrange - const nonExistentContentPath = '/non-existent-path'; - - // Act - const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithRoute(nonExistentContentPath); - - // Assert - expect(contentItem.status()).toBe(404); -}); - -// Gets content item(s) by id -test('can fetch multiple content items by their IDs', async ({umbracoApi}) => { - // Arrange - const contentName1 = publishInvariantRootContent; - const publishInvariantRootId = await umbracoApi.document.createDefaultDocument(contentName1, invariantDocTypeId); - await umbracoApi.document.publish(publishInvariantRootId); - - const contentName2 = childPublishInvariantContentPrefix + '3'; - const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName2, invariantDocTypeId, publishInvariantParentId); - await umbracoApi.document.publish(childId); - - const contentData1 = await umbracoApi.document.getByName(contentName1); - const contentData2 = await umbracoApi.document.getByName(contentName2); - const contentNames = [contentName1, contentName2]; - const contentIds = [contentData1.id, contentData2.id]; - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsWithIds(contentIds); - - // Assert - expect(contentItems.status()).toBe(200); - const contentItemsJson = await contentItems.json(); - expect(contentItemsJson.length).toBe(2); - for (let i = 0; i < contentNames.length; i++) { - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentNames[i], contentItemsJson[i]); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentNames[i], contentItemsJson[i]); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentNames[i], contentItemsJson[i]); - } - - // Clean - await umbracoApi.document.ensureNameNotExists(contentName2); - await umbracoApi.document.ensureNameNotExists(contentName1); -}); - -test('returns only valid content items when some IDs are invalid', async ({umbracoApi}) => { - // Arrange - const contentName = childPublishInvariantContentPrefix + '4'; - const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvariantParentId); - await umbracoApi.document.publish(childId); - - const contentData = await umbracoApi.document.getByName(contentName); - const nonExistentContentId = '00000000-0000-0000-0000-000000000000'; - const contentIds = [contentData.id, nonExistentContentId]; - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsWithIds(contentIds); - - // Assert - expect(contentItems.status()).toBe(200); - const contentItemsJson = await contentItems.json(); - expect(contentItemsJson.length).toBe(1); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemsJson[0]); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemsJson[0]); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemsJson[0]); - - // Clean - await umbracoApi.document.ensureNameNotExists(contentName); -}); - -test('returns only published content items when some IDs are unpublished', async ({umbracoApi}) => { - // Arrange - const contentName = publishInvariantRootContent; - const publishInvariantRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); - await umbracoApi.document.publish(publishInvariantRootId); - - const unpublishContent = unpublishInvariantRootContent; - await umbracoApi.document.createDefaultDocument(unpublishContent, invariantDocTypeId); - - const contentData = await umbracoApi.document.getByName(contentName); - const unpublishContentData = await umbracoApi.document.getByName(unpublishContent); - const contentIds = [contentData.id, unpublishContentData.id]; - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsWithIds(contentIds); - - // Assert - expect(contentItems.status()).toBe(200); - const contentItemsJson = await contentItems.json(); - expect(contentItemsJson.length).toBe(1); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemsJson[0]); - await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemsJson[0]); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemsJson[0]); - - // Clean - await umbracoApi.document.ensureNameNotExists(unpublishContent); - await umbracoApi.document.ensureNameNotExists(contentName); -}); - -// Gets content item(s) from a query -test('can fetch children of a content', async ({umbracoApi}) => { - // Arrange - const parentContentName = publishInvariantParentContent; - // Create child items - for (let i = 1; i <= childContentAmount; i++) { - const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvariantContentPrefix + i, invariantDocTypeId, publishInvariantParentId); +test.describe('fetch a content item by route', () => { + test('can fetch a content item by its route', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvariantRootContent; + const publishInvariantRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); + await umbracoApi.document.publish(publishInvariantRootId); + const contentData = await umbracoApi.document.getByName(contentName); + const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithRoute(contentURL); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + }); + + test('can fetch a child content item by its route', async ({umbracoApi}) => { + // Arrange + const contentName = childPublishInvariantContentPrefix + '1'; + const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvariantParentId); await umbracoApi.document.publish(childId); - } - await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed - const parentContentData = await umbracoApi.document.getByName(parentContentName); - const parentContentId = parentContentData.id; - const fetch = 'children:' + parentContentId; - const totalChildrenItems = await umbracoApi.document.getChildrenAmount(parentContentId); - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, fetch); - - // Assert - expect(contentItems.status()).toBe(200); - const contentItemsJson = await contentItems.json(); - expect(contentItemsJson.total).toBe(totalChildrenItems); - - // Clean - for (let i = 1; i <= childContentAmount; i++) { - await umbracoApi.document.ensureNameNotExists(childPublishInvariantContentPrefix + i); - } + const contentData = await umbracoApi.document.getByName(contentName); + const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentURL); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + }); + + test('can fetch a content item by its route with special character', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvariantContentWithSpecialCharacters; + const publishInvariantContentWithSpecialCharactersId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); + await umbracoApi.document.publish(publishInvariantContentWithSpecialCharactersId); + const contentData = await umbracoApi.document.getByName(contentName); + const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentURL); + + // Assert + expect(contentItem.status()).toBe(200); + const contentItemJson = await contentItem.json(); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemJson); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemJson); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + }); + + test('returns 404 when fetching a non-existent content route', async ({umbracoApi}) => { + // Arrange + const nonExistentContentPath = '/non-existent-path'; + + // Act + const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithRoute(nonExistentContentPath); + + // Assert + expect(contentItem.status()).toBe(404); + }); }); -test('can fetch ancestors of a content item', async ({umbracoApi}) => { - // Arrange - const expectedParentContentName = publishInvariantParentContent; - const childContentName = childPublishInvariantContentPrefix + '1'; - const childId = await umbracoApi.document.createDefaultDocumentWithParent(childContentName, invariantDocTypeId, publishInvariantParentId); - await umbracoApi.document.publish(childId); - await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed - const fetch = 'ancestors:' + childId; - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, fetch); - - // Assert - expect(contentItems.status()).toBe(200); - const contentItemsJson = await contentItems.json(); - expect(contentItemsJson.total).toBe(1); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(expectedParentContentName, contentItemsJson.items[0]); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(expectedParentContentName, contentItemsJson.items[0]); - - // Clean - await umbracoApi.document.ensureNameNotExists(childContentName); -}); +test.describe('fetch content items by ids', () => { + test('can fetch multiple content items by their IDs', async ({umbracoApi}) => { + // Arrange + const contentName1 = publishInvariantRootContent; + const publishInvariantRootId = await umbracoApi.document.createDefaultDocument(contentName1, invariantDocTypeId); + await umbracoApi.document.publish(publishInvariantRootId); -test('can filter content items', async ({umbracoApi}) => { - // Arrange - const expectedContentName = publishInvariantParentContent; - const contentType = collectionDocumentType; - const contentTypeData = await umbracoApi.documentType.getByName(contentType); - const filter = 'contentType:' + contentTypeData.alias; - await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, filter); - - // Assert - expect(contentItems.status()).toBe(200); - const contentItemsJson = await contentItems.json(); - expect(contentItemsJson.total).toBe(1); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(expectedContentName, contentItemsJson.items[0]); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(expectedContentName, contentItemsJson.items[0]); -}); - -test('can sort content items', async ({umbracoApi}) => { - // Arrange - // Create child items - for (let i = 0; i < childContentAmount; i++) { - const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvariantContentPrefix + i, invariantDocTypeId, publishInvariantParentId); + const contentName2 = childPublishInvariantContentPrefix + '3'; + const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName2, invariantDocTypeId, publishInvariantParentId); await umbracoApi.document.publish(childId); - } - await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed - const sort = 'name:desc'; - const filter = 'name:' + 'Child'; - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, filter, sort); - - // Assert - expect(contentItems.status()).toBe(200); - const contentItemsJson = await contentItems.json(); - expect(contentItemsJson.total).toBe(childContentAmount); - for (let i = 0; i < childContentAmount; i++) { - expect(contentItemsJson.items[i].name).toBe(childPublishInvariantContentPrefix + (childContentAmount - 1 - i)); - await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(childPublishInvariantContentPrefix + i, contentItemsJson.items[childContentAmount - 1 - i]); - await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(childPublishInvariantContentPrefix + i, contentItemsJson.items[childContentAmount - 1 - i]); - } - - // Clean - for (let i = 0; i < childContentAmount; i++) { - await umbracoApi.document.ensureNameNotExists(childPublishInvariantContentPrefix + i); - } -}); -test('can paginate content items', async ({umbracoApi}) => { - // Arrange - // Create child items - for (let i = 1; i <= childContentAmount; i++) { - const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvariantContentPrefix + i, invariantDocTypeId, publishInvariantParentId); + const contentData1 = await umbracoApi.document.getByName(contentName1); + const contentData2 = await umbracoApi.document.getByName(contentName2); + const contentNames = [contentName1, contentName2]; + const contentIds = [contentData1.id, contentData2.id]; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsWithIds(contentIds); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.length).toBe(2); + for (let i = 0; i < contentNames.length; i++) { + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentNames[i], contentItemsJson[i]); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentNames[i], contentItemsJson[i]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentNames[i], contentItemsJson[i]); + } + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName2); + await umbracoApi.document.ensureNameNotExists(contentName1); + }); + + test('returns only valid content items when some IDs are invalid', async ({umbracoApi}) => { + // Arrange + const contentName = childPublishInvariantContentPrefix + '4'; + const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvariantParentId); await umbracoApi.document.publish(childId); - } - await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed - const sort = 'name:asc'; - const filter = 'name:' + 'Child'; - const skip = 0; - const take = childContentAmount - 2; - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, filter, sort, skip, take); - - // Assert - expect(contentItems.status()).toBe(200); - const contentItemsJson = await contentItems.json(); - expect(contentItemsJson.total).toBe(childContentAmount); - expect(contentItemsJson.items.length).toBe(take); - - // Clean - for (let i = 1; i <= childContentAmount; i++) { - await umbracoApi.document.ensureNameNotExists(childPublishInvariantContentPrefix + i); - } -}); - -test('returns 400 when using an invalid sort parameter', async ({umbracoApi}) => { - // Arrange - const invalidSort = 'invalidSort'; - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, undefined, invalidSort); - - // Assert - expect(contentItems).not.toBeNull(); - if (contentItems !== null) { - expect(contentItems.status()).toBe(400); - } + const contentData = await umbracoApi.document.getByName(contentName); + const nonExistentContentId = '00000000-0000-0000-0000-000000000000'; + const contentIds = [contentData.id, nonExistentContentId]; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsWithIds(contentIds); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.length).toBe(1); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemsJson[0]); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemsJson[0]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemsJson[0]); + + // Clean + await umbracoApi.document.ensureNameNotExists(contentName); + }); + + test('returns only published content items when some IDs are unpublished', async ({umbracoApi}) => { + // Arrange + const contentName = publishInvariantRootContent; + const publishInvariantRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); + await umbracoApi.document.publish(publishInvariantRootId); + + const unpublishContent = unpublishInvariantRootContent; + await umbracoApi.document.createDefaultDocument(unpublishContent, invariantDocTypeId); + + const contentData = await umbracoApi.document.getByName(contentName); + const unpublishContentData = await umbracoApi.document.getByName(unpublishContent); + const contentIds = [contentData.id, unpublishContentData.id]; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsWithIds(contentIds); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.length).toBe(1); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(contentName, contentItemsJson[0]); + await umbracoApi.contentDeliveryApi.verifyEditorialPropertiesForInvariantContentItem(contentName, contentItemsJson[0]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(contentName, contentItemsJson[0]); + + // Clean + await umbracoApi.document.ensureNameNotExists(unpublishContent); + await umbracoApi.document.ensureNameNotExists(contentName); + }); }); -test('returns 400 when using an invalid filter parameter', async ({umbracoApi}) => { - // Arrange - const invalidFilter = 'invalidFilter'; - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, invalidFilter); - - // Assert - expect(contentItems).not.toBeNull(); - if (contentItems !== null) { - expect(contentItems.status()).toBe(400); - } -}); - -test('returns 400 when using an invalid fetch type', async ({umbracoApi}) => { - // Arrange - const invalidFetch = 'invalid'; - - // Act - const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, invalidFetch); - - // Assert - expect(contentItems).not.toBeNull(); - if (contentItems !== null) { - expect(contentItems.status()).toBe(400); - } -}); +test.describe('fetch content items from a query', () => { + test('can fetch children of a content', async ({umbracoApi}) => { + // Arrange + const parentContentName = publishInvariantParentContent; + // Create child items + for (let i = 1; i <= childContentAmount; i++) { + const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvariantContentPrefix + i, invariantDocTypeId, publishInvariantParentId); + await umbracoApi.document.publish(childId); + } + await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed + const parentContentData = await umbracoApi.document.getByName(parentContentName); + const parentContentId = parentContentData.id; + const fetch = 'children:' + parentContentId; + const totalChildrenItems = await umbracoApi.document.getChildrenAmount(parentContentId); + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, fetch); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.total).toBe(totalChildrenItems); + + // Clean + for (let i = 1; i <= childContentAmount; i++) { + await umbracoApi.document.ensureNameNotExists(childPublishInvariantContentPrefix + i); + } + }); + + test('can fetch ancestors of a content item', async ({umbracoApi}) => { + // Arrange + const expectedParentContentName = publishInvariantParentContent; + const childContentName = childPublishInvariantContentPrefix + '1'; + const childId = await umbracoApi.document.createDefaultDocumentWithParent(childContentName, invariantDocTypeId, publishInvariantParentId); + await umbracoApi.document.publish(childId); + await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed + const fetch = 'ancestors:' + childId; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, fetch); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.total).toBe(1); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(expectedParentContentName, contentItemsJson.items[0]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(expectedParentContentName, contentItemsJson.items[0]); + + // Clean + await umbracoApi.document.ensureNameNotExists(childContentName); + }); + + test('can filter content items', async ({umbracoApi}) => { + // Arrange + const expectedContentName = publishInvariantParentContent; + const contentType = collectionDocumentType; + const contentTypeData = await umbracoApi.documentType.getByName(contentType); + const filter = 'contentType:' + contentTypeData.alias; + await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, filter); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.total).toBe(1); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(expectedContentName, contentItemsJson.items[0]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(expectedContentName, contentItemsJson.items[0]); + }); + + test('can sort content items', async ({umbracoApi}) => { + // Arrange + // Create child items + for (let i = 0; i < childContentAmount; i++) { + const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvariantContentPrefix + i, invariantDocTypeId, publishInvariantParentId); + await umbracoApi.document.publish(childId); + } + await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed + const sort = 'name:desc'; + const filter = 'name:' + 'Child'; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, filter, sort); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.total).toBe(childContentAmount); + for (let i = 0; i < childContentAmount; i++) { + expect(contentItemsJson.items[i].name).toBe(childPublishInvariantContentPrefix + (childContentAmount - 1 - i)); + await umbracoApi.contentDeliveryApi.verifyBasicPropertiesForContentItem(childPublishInvariantContentPrefix + i, contentItemsJson.items[childContentAmount - 1 - i]); + await umbracoApi.contentDeliveryApi.verifyCulturePropertyForContentItem(childPublishInvariantContentPrefix + i, contentItemsJson.items[childContentAmount - 1 - i]); + } + + // Clean + for (let i = 0; i < childContentAmount; i++) { + await umbracoApi.document.ensureNameNotExists(childPublishInvariantContentPrefix + i); + } + }); + + test('can paginate content items', async ({umbracoApi}) => { + // Arrange + // Create child items + for (let i = 1; i <= childContentAmount; i++) { + const childId = await umbracoApi.document.createDefaultDocumentWithParent(childPublishInvariantContentPrefix + i, invariantDocTypeId, publishInvariantParentId); + await umbracoApi.document.publish(childId); + } + await umbracoApi.page.waitForTimeout(1000); // Wait is needed to ensure content is indexed + const sort = 'name:asc'; + const filter = 'name:' + 'Child'; + const skip = 0; + const take = childContentAmount - 2; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, filter, sort, skip, take); + + // Assert + expect(contentItems.status()).toBe(200); + const contentItemsJson = await contentItems.json(); + expect(contentItemsJson.total).toBe(childContentAmount); + expect(contentItemsJson.items.length).toBe(take); + + // Clean + for (let i = 1; i <= childContentAmount; i++) { + await umbracoApi.document.ensureNameNotExists(childPublishInvariantContentPrefix + i); + } + }); + + test('returns 400 when using an invalid sort parameter', async ({umbracoApi}) => { + // Arrange + const invalidSort = 'invalidSort'; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, undefined, invalidSort); + + // Assert + expect(contentItems).not.toBeNull(); + if (contentItems !== null) { + expect(contentItems.status()).toBe(400); + } + }); + + test('returns 400 when using an invalid filter parameter', async ({umbracoApi}) => { + // Arrange + const invalidFilter = 'invalidFilter'; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, undefined, invalidFilter); + + // Assert + expect(contentItems).not.toBeNull(); + if (contentItems !== null) { + expect(contentItems.status()).toBe(400); + } + }); + + test('returns 400 when using an invalid fetch type', async ({umbracoApi}) => { + // Arrange + const invalidFetch = 'invalid'; + + // Act + const contentItems = await umbracoApi.contentDeliveryApi.getContentItemsFromAQuery(undefined, invalidFetch); + + // Assert + expect(contentItems).not.toBeNull(); + if (contentItems !== null) { + expect(contentItems.status()).toBe(400); + } + }); +}); \ No newline at end of file From daeee8dee49dc5c6c402d4bf2aa5239aad740ef1 Mon Sep 17 00:00:00 2001 From: Nhu Dinh Date: Mon, 15 Dec 2025 17:38:00 +0700 Subject: [PATCH 13/14] Renamed --- .../tests/DeliveryApi/ContentDeliveryApi.spec.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts index 7ba967629e85..964cc4d6d0fc 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts @@ -67,7 +67,7 @@ test.afterEach(async ({umbracoApi}) => { }); test.describe('fetch a content item by id', () => { - test('can fetch an content item at root by its ID', async ({umbracoApi}) => { + test('can fetch an content item at root by its id', async ({umbracoApi}) => { // Arrange const contentName = publishInvariantRootContent; const publishInvariantRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); @@ -88,7 +88,7 @@ test.describe('fetch a content item by id', () => { await umbracoApi.document.ensureNameNotExists(contentName); }); - test('can fetch a child content item by its ID', async ({umbracoApi}) => { + test('can fetch a child content item by its id', async ({umbracoApi}) => { // Arrange const contentName = childPublishInvariantContentPrefix + '2'; const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvariantParentId); @@ -109,7 +109,7 @@ test.describe('fetch a content item by id', () => { await umbracoApi.document.ensureNameNotExists(contentName); }); - test('can fetch a content item that has children by its ID', async ({umbracoApi}) => { + test('can fetch a content item that has children by its id', async ({umbracoApi}) => { // Arrange const contentName = publishInvariantParentContent; // Create child items @@ -135,7 +135,7 @@ test.describe('fetch a content item by id', () => { } }); - test('cannot fetch an unpublished content item without preview by its ID', async ({umbracoApi}) => { + test('cannot fetch an unpublished content item without preview by its id', async ({umbracoApi}) => { // Arrange const contentName = unpublishInvariantRootContent; await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); @@ -242,7 +242,7 @@ test.describe('fetch a content item by id', () => { await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithMultiUrlPicker); }); - test('can fetch a variant content item by its ID', async ({umbracoApi}) => { + test('can fetch a variant content item by its id', async ({umbracoApi}) => { // Arrange const contentName = publishVariantRootContent; const textStringDataType = await umbracoApi.dataType.getByName(textstringDataTypeName); From d0a0903651c3fd040fedc8f407d30dc304ea404b Mon Sep 17 00:00:00 2001 From: Nhu Dinh Date: Fri, 19 Dec 2025 16:39:54 +0700 Subject: [PATCH 14/14] Fixed names --- .../DeliveryApi/ContentDeliveryApi.spec.ts | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts index 964cc4d6d0fc..455899479eb6 100644 --- a/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts +++ b/tests/Umbraco.Tests.AcceptanceTest/tests/DeliveryApi/ContentDeliveryApi.spec.ts @@ -67,7 +67,7 @@ test.afterEach(async ({umbracoApi}) => { }); test.describe('fetch a content item by id', () => { - test('can fetch an content item at root by its id', async ({umbracoApi}) => { + test('can fetch an content item at root', async ({umbracoApi}) => { // Arrange const contentName = publishInvariantRootContent; const publishInvariantRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); @@ -88,7 +88,7 @@ test.describe('fetch a content item by id', () => { await umbracoApi.document.ensureNameNotExists(contentName); }); - test('can fetch a child content item by its id', async ({umbracoApi}) => { + test('can fetch a child content item', async ({umbracoApi}) => { // Arrange const contentName = childPublishInvariantContentPrefix + '2'; const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvariantParentId); @@ -109,7 +109,7 @@ test.describe('fetch a content item by id', () => { await umbracoApi.document.ensureNameNotExists(contentName); }); - test('can fetch a content item that has children by its id', async ({umbracoApi}) => { + test('can fetch a content item that has children', async ({umbracoApi}) => { // Arrange const contentName = publishInvariantParentContent; // Create child items @@ -135,7 +135,7 @@ test.describe('fetch a content item by id', () => { } }); - test('cannot fetch an unpublished content item without preview by its id', async ({umbracoApi}) => { + test('cannot fetch an unpublished content item without preview', async ({umbracoApi}) => { // Arrange const contentName = unpublishInvariantRootContent; await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); @@ -242,7 +242,7 @@ test.describe('fetch a content item by id', () => { await umbracoApi.documentType.ensureNameNotExists(invariantDocumentTypeWithMultiUrlPicker); }); - test('can fetch a variant content item by its id', async ({umbracoApi}) => { + test('can fetch a variant content item', async ({umbracoApi}) => { // Arrange const contentName = publishVariantRootContent; const textStringDataType = await umbracoApi.dataType.getByName(textstringDataTypeName); @@ -279,7 +279,7 @@ test.describe('fetch a content item by id', () => { }); test.describe('fetch a content item by route', () => { - test('can fetch a content item by its route', async ({umbracoApi}) => { + test('can fetch a content item', async ({umbracoApi}) => { // Arrange const contentName = publishInvariantRootContent; const publishInvariantRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); @@ -301,7 +301,7 @@ test.describe('fetch a content item by route', () => { await umbracoApi.document.ensureNameNotExists(contentName); }); - test('can fetch a child content item by its route', async ({umbracoApi}) => { + test('can fetch a child content item', async ({umbracoApi}) => { // Arrange const contentName = childPublishInvariantContentPrefix + '1'; const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvariantParentId); @@ -323,14 +323,13 @@ test.describe('fetch a content item by route', () => { await umbracoApi.document.ensureNameNotExists(contentName); }); - test('can fetch a content item by its route with special character', async ({umbracoApi}) => { + test('can fetch a content item with a special character route', async ({umbracoApi}) => { // Arrange const contentName = publishInvariantContentWithSpecialCharacters; const publishInvariantContentWithSpecialCharactersId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId); await umbracoApi.document.publish(publishInvariantContentWithSpecialCharactersId); const contentData = await umbracoApi.document.getByName(contentName); const contentURL = await umbracoApi.document.getDocumentUrl(contentData.id); - // Act const contentItem = await umbracoApi.contentDeliveryApi.getContentItemWithId(contentURL); @@ -358,7 +357,7 @@ test.describe('fetch a content item by route', () => { }); test.describe('fetch content items by ids', () => { - test('can fetch multiple content items by their IDs', async ({umbracoApi}) => { + test('can fetch multiple content items', async ({umbracoApi}) => { // Arrange const contentName1 = publishInvariantRootContent; const publishInvariantRootId = await umbracoApi.document.createDefaultDocument(contentName1, invariantDocTypeId); @@ -391,7 +390,7 @@ test.describe('fetch content items by ids', () => { await umbracoApi.document.ensureNameNotExists(contentName1); }); - test('returns only valid content items when some IDs are invalid', async ({umbracoApi}) => { + test('returns only valid content items when some ids are invalid', async ({umbracoApi}) => { // Arrange const contentName = childPublishInvariantContentPrefix + '4'; const childId = await umbracoApi.document.createDefaultDocumentWithParent(contentName, invariantDocTypeId, publishInvariantParentId); @@ -416,7 +415,7 @@ test.describe('fetch content items by ids', () => { await umbracoApi.document.ensureNameNotExists(contentName); }); - test('returns only published content items when some IDs are unpublished', async ({umbracoApi}) => { + test('returns only published content items when some ids are unpublished', async ({umbracoApi}) => { // Arrange const contentName = publishInvariantRootContent; const publishInvariantRootId = await umbracoApi.document.createDefaultDocument(contentName, invariantDocTypeId);