Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add strongly typed response for listing variants by type #271

Merged
merged 4 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Kontent.Ai.Management.Tests/Data/ElementsData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ private static dynamic GetRichTextAsDynamic(Guid? elementId, string value, IEnum
dynamic element = new ExpandoObject();
element.element = GetElement(elementId.Value.ToString("d"));
element.value = value;
element.components = compoments.Select(x => GetRichTextComponentAsDynamic(x));
element.components = compoments.Select(GetRichTextComponentAsDynamic);

return element;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public async Task ListAssetsAsync_DynamicallyTyped_WithMorePages_ListsAssets()
"00000000-0000-0000-0000-000000000000",
"10000000-0000-0000-0000-000000000000",
"20000000-0000-0000-0000-000000000000"
}.Select(x => GetExpectedDynamicAssetModel(assetId: x));
}.Select(GetExpectedDynamicAssetModel);

var response = await client.ListAssetsAsync().GetAllAsync();

Expand All @@ -49,7 +49,7 @@ public async Task ListAssetsAsync_StronglyTyped_WithMorePages_ListsAssets()
"00000000-0000-0000-0000-000000000000",
"10000000-0000-0000-0000-000000000000",
"20000000-0000-0000-0000-000000000000"
}.Select(x => GetExpectedStronglyTypedAssetModel(assetId: x));
}.Select(GetExpectedStronglyTypedAssetModel);

var response = await client.ListAssetsAsync<ComplexTestModel>().GetAllAsync();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,43 @@ await client.Invoking(x => x.ListLanguageVariantsByItemAsync(null))
.Should().ThrowExactlyAsync<ArgumentNullException>();
}

[Fact]
public async Task ListLanguageVariantsByTypeAsync_StronglyTyped_ListsVariants()
{
var client = _scenario
.WithResponses("LanguageVariantsPage1.json", "LanguageVariantsPage2.json", "LanguageVariantsPage3.json")
.CreateManagementClient();

var expected = new[]
{
(itemId: "00000000-0000-0000-0000-000000000000", languageId: "00000000-0000-0000-0000-000000000000"),
(itemId: "00000000-0000-0000-0000-000000000000", languageId: "10000000-0000-0000-0000-000000000000"),
(itemId: "10000000-0000-0000-0000-000000000000", languageId: "00000000-0000-0000-0000-000000000000"),
(itemId: "10000000-0000-0000-0000-000000000000", languageId: "10000000-0000-0000-0000-000000000000"),
(itemId: "20000000-0000-0000-0000-000000000000", languageId: "00000000-0000-0000-0000-000000000000"),
(itemId: "20000000-0000-0000-0000-000000000000", languageId: "10000000-0000-0000-0000-000000000000")
}.Select(x => GetExpectedComplexTestModel(x.languageId, x.itemId));

var identifier = Reference.ById(Guid.Parse("17ff8a28-ebe6-5c9d-95ea-18fe1ff86d2d"));
var response = await client.ListLanguageVariantsByTypeAsync<ComplexTestModel>(identifier).GetAllAsync();

_scenario
.CreateExpectations()
.HttpMethod(HttpMethod.Get)
.Response(response, expected)
.Url($"{Endpoint}/projects/{ENVIRONMENT_ID}/types/{identifier.Id}/variants")
.Validate();
}

[Fact]
public async Task ListLanguageVariantsByTypeAsync_StronglyTyped_IdentifierIsNull_Throws()
{
var client = _scenario.CreateManagementClient();

await client.Invoking(x => x.ListLanguageVariantsByTypeAsync<ComplexTestModel>(null))
.Should().ThrowExactlyAsync<ArgumentNullException>();
}

[Fact]
public async void ListLanguageVariantsByTypeAsync_DynamicallyTyped_ListsVariants()
{
Expand Down Expand Up @@ -120,7 +157,6 @@ await client.Invoking(x => x.ListLanguageVariantsByTypeAsync(null))
.Should().ThrowExactlyAsync<ArgumentNullException>();
}


[Fact]
public async Task ListLanguageVariantsOfContentTypeWithComponentsAsync_DynamicallyTyped_ListsVariants()
{
Expand Down Expand Up @@ -496,18 +532,20 @@ private static LanguageVariantModel GetExpectedLanguageVariantModel(
};

private static List<LanguageVariantModel<ComplexTestModel>> GetExpectedComplexTestModels(params string[] languageIds)
=> languageIds.Select(GetExpectedComplexTestModel).ToList();
=> languageIds.Select(x => GetExpectedComplexTestModel(x)).ToList();

private static LanguageVariantModel<ComplexTestModel> GetExpectedComplexTestModel(string languageId = "78dbefe8-831b-457e-9352-f4c4eacd5024") => new()
{
Item = Reference.ById(Guid.Parse("4b628214-e4fe-4fe0-b1ff-955df33e1515")),
Language = Reference.ById(Guid.Parse(languageId)),
LastModified = DateTimeOffset.Parse("2021-11-06T13:57:26.7069564Z").UtcDateTime,
Workflow = new WorkflowStepIdentifier(Reference.ById(Guid.Parse("00000000-0000-0000-0000-000000000000")), Reference.ById(Guid.Parse("eee6db3b-545a-4785-8e86-e3772c8756f9"))),
Schedule = GetExpectedScheduleResponseModel(),
DueDate = GetExpectedDueDateModel(),
Elements = ElementsData.GetExpectedStronglyTypedElementsModel(),
};
private static LanguageVariantModel<ComplexTestModel> GetExpectedComplexTestModel(
string languageId = "78dbefe8-831b-457e-9352-f4c4eacd5024",
string itemId = "4b628214-e4fe-4fe0-b1ff-955df33e1515") => new()
{
Item = Reference.ById(Guid.Parse(itemId)),
Language = Reference.ById(Guid.Parse(languageId)),
LastModified = DateTimeOffset.Parse("2021-11-06T13:57:26.7069564Z").UtcDateTime,
Workflow = new WorkflowStepIdentifier(Reference.ById(Guid.Parse("00000000-0000-0000-0000-000000000000")), Reference.ById(Guid.Parse("eee6db3b-545a-4785-8e86-e3772c8756f9"))),
Schedule = GetExpectedScheduleResponseModel(),
DueDate = GetExpectedDueDateModel(),
Elements = ElementsData.GetExpectedStronglyTypedElementsModel(),
};

private static ScheduleResponseModel GetExpectedScheduleResponseModel() => new()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public void GetKontentElementCodename_ThrowsIfNoAttribute()
{
var property = typeof(PropertyInfoExtensionsTestsSampleClass).GetProperty("Property1");

Assert.Throws<InvalidOperationException>(() => property.GetKontentElementCodename());
Assert.Throws<InvalidOperationException>(property.GetKontentElementCodename);
}

[Fact]
Expand Down
60 changes: 12 additions & 48 deletions Kontent.Ai.Management/Extensions/ManagementClientExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,9 @@ public static class ManagementClientExtensions
/// <returns>The <see cref="ContentItemModel"/> instance that represents updated content item.</returns>
public async static Task<ContentItemModel> UpsertContentItemAsync(this IManagementClient client, Reference identifier, ContentItemModel contentItem)
{
if (identifier == null)
{
throw new ArgumentNullException(nameof(identifier));
}
ArgumentNullException.ThrowIfNull(identifier);

if (contentItem == null)
{
throw new ArgumentNullException(nameof(contentItem));
}
ArgumentNullException.ThrowIfNull(contentItem);

var contentItemUpdateModel = new ContentItemUpsertModel
{
Expand All @@ -52,14 +46,8 @@ public async static Task<ContentItemModel> UpsertContentItemAsync(this IManageme
/// <param name="assetCreateModel">Updated values for the asset.</param>
public async static Task<AssetModel> CreateAssetAsync(this IManagementClient client, FileContentSource fileContent, AssetCreateModel assetCreateModel)
{
if (fileContent == null)
{
throw new ArgumentNullException(nameof(fileContent));
}
if (assetCreateModel == null)
{
throw new ArgumentNullException(nameof(assetCreateModel));
}
ArgumentNullException.ThrowIfNull(fileContent);
ArgumentNullException.ThrowIfNull(assetCreateModel);

var fileResult = await client.UploadFileAsync(fileContent);

Expand All @@ -78,14 +66,8 @@ public async static Task<AssetModel> CreateAssetAsync(this IManagementClient cli
/// <param name="assetCreateModel">Updated values for the strongly typed asset.</param>
public async static Task<AssetModel<T>> CreateAssetAsync<T>(this IManagementClient client, FileContentSource fileContent, AssetCreateModel<T> assetCreateModel) where T : new()
{
if (fileContent == null)
{
throw new ArgumentNullException(nameof(fileContent));
}
if (assetCreateModel == null)
{
throw new ArgumentNullException(nameof(assetCreateModel));
}
ArgumentNullException.ThrowIfNull(fileContent);
ArgumentNullException.ThrowIfNull(assetCreateModel);

var fileResult = await client.UploadFileAsync(fileContent);

Expand All @@ -106,20 +88,11 @@ public async static Task<AssetModel> CreateAssetAsync(this IManagementClient cli
/// <returns>The <see cref="AssetModel"/> instance that represents created or updated asset.</returns>
public async static Task<AssetModel> UpsertAssetAsync(this IManagementClient client, Reference identifier, FileContentSource fileContent, AssetUpsertModel upsertModel)
{
if (identifier == null)
{
throw new ArgumentNullException(nameof(identifier));
}
ArgumentNullException.ThrowIfNull(identifier);

if (fileContent == null)
{
throw new ArgumentNullException(nameof(fileContent));
}
ArgumentNullException.ThrowIfNull(fileContent);

if (upsertModel == null)
{
throw new ArgumentNullException(nameof(upsertModel));
}
ArgumentNullException.ThrowIfNull(upsertModel);

var fileResult = await client.UploadFileAsync(fileContent);

Expand All @@ -140,20 +113,11 @@ public async static Task<AssetModel> UpsertAssetAsync(this IManagementClient cli
/// <returns>The <see cref="AssetModel{T}"/> instance that represents created or updated strongly typed asset.</returns>
public async static Task<AssetModel<T>> UpsertAssetAsync<T>(this IManagementClient client, Reference identifier, FileContentSource fileContent, AssetUpsertModel<T> upsertModel) where T : new()
{
if (identifier == null)
{
throw new ArgumentNullException(nameof(identifier));
}
ArgumentNullException.ThrowIfNull(identifier);

if (fileContent == null)
{
throw new ArgumentNullException(nameof(fileContent));
}
ArgumentNullException.ThrowIfNull(fileContent);

if (upsertModel == null)
{
throw new ArgumentNullException(nameof(upsertModel));
}
ArgumentNullException.ThrowIfNull(upsertModel);

var fileResult = await client.UploadFileAsync(fileContent);

Expand Down
11 changes: 11 additions & 0 deletions Kontent.Ai.Management/IManagementClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,17 @@ public interface IManagementClient
/// <returns>The <see cref="IEnumerable{LanguageVariantModel}"/> instance that represents the listing of language variants.</returns>
Task<IListingResponseModel<LanguageVariantModel>> ListLanguageVariantsByTypeAsync(Reference identifier);

/// <summary>
/// Returns strongly typed listing of language variants with strongly typed elements for the specified content type.
/// The Content management API returns a dynamically paginated listing response limited to up to 100 objects.
/// To check if the next page is available use <see cref="IListingResponseModel{T}.HasNextPage"/>.
/// For getting next page use <see cref="IListingResponseModel{T}.GetNextPage"/>.
/// </summary>
/// <typeparam name="T">Type of the content item elements</typeparam>
/// <param name="identifier">The identifier of the content type.</param>
/// <returns>The <see cref="IEnumerable{LanguageVariantModel}"/> instance that represents the listing of language variants.</returns>
Task<IListingResponseModel<LanguageVariantModel<T>>> ListLanguageVariantsByTypeAsync<T>(Reference identifier) where T : new();

/// <summary>
/// Returns strongly typed listing of language variants containing components by type.
/// The Content management API returns a dynamically paginated listing response limited to up to 100 objects.
Expand Down
40 changes: 8 additions & 32 deletions Kontent.Ai.Management/ManagementClient.Asset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,7 @@ public async Task<IListingResponseModel<AssetModel>> ListAssetsAsync()
/// <inheritdoc />
public async Task<AssetModel> GetAssetAsync(Reference identifier)
{
if (identifier == null)
{
throw new ArgumentNullException(nameof(identifier));
}
ArgumentNullException.ThrowIfNull(identifier);

var endpointUrl = _urlBuilder.BuildAssetsUrl(identifier);
var response = await _actionInvoker.InvokeReadOnlyMethodAsync<AssetModel>(endpointUrl, HttpMethod.Get);
Expand All @@ -61,15 +58,9 @@ public async Task<AssetModel> GetAssetAsync(Reference identifier)
/// <inheritdoc />
public async Task<AssetModel> UpsertAssetAsync(Reference identifier, AssetUpsertModel asset)
{
if (identifier == null)
{
throw new ArgumentNullException(nameof(identifier));
}
ArgumentNullException.ThrowIfNull(identifier);

if (asset == null)
{
throw new ArgumentNullException(nameof(asset));
}
ArgumentNullException.ThrowIfNull(asset);

var endpointUrl = _urlBuilder.BuildAssetsUrl(identifier);
var response = await _actionInvoker.InvokeMethodAsync<AssetUpsertModel, AssetModel>(endpointUrl, HttpMethod.Put, asset);
Expand All @@ -80,10 +71,7 @@ public async Task<AssetModel> UpsertAssetAsync(Reference identifier, AssetUpsert
/// <inheritdoc />
public async Task<AssetModel<T>> UpsertAssetAsync<T>(Reference identifier, AssetUpsertModel<T> asset) where T : new()
{
if (asset == null)
{
throw new ArgumentNullException(nameof(asset));
}
ArgumentNullException.ThrowIfNull(asset);

var result = await UpsertAssetAsync(identifier, _modelProvider.GetAssetUpsertModel(asset));

Expand All @@ -93,10 +81,7 @@ public async Task<AssetModel> UpsertAssetAsync(Reference identifier, AssetUpsert
/// <inheritdoc />
public async Task<AssetModel> CreateAssetAsync(AssetCreateModel asset)
{
if (asset == null)
{
throw new ArgumentNullException(nameof(asset));
}
ArgumentNullException.ThrowIfNull(asset);

var endpointUrl = _urlBuilder.BuildAssetsUrl();
var response = await _actionInvoker.InvokeMethodAsync<AssetCreateModel, AssetModel>(endpointUrl, HttpMethod.Post, asset);
Expand All @@ -107,10 +92,7 @@ public async Task<AssetModel> CreateAssetAsync(AssetCreateModel asset)
/// <inheritdoc />
public async Task<AssetModel<T>> CreateAssetAsync<T>(AssetCreateModel<T> asset) where T : new()
{
if (asset == null)
{
throw new ArgumentNullException(nameof(asset));
}
ArgumentNullException.ThrowIfNull(asset);

var result = await CreateAssetAsync(_modelProvider.GetAssetCreateModel(asset));

Expand All @@ -120,10 +102,7 @@ public async Task<AssetModel> CreateAssetAsync(AssetCreateModel asset)
/// <inheritdoc />
public async Task DeleteAssetAsync(Reference identifier)
{
if (identifier == null)
{
throw new ArgumentNullException(nameof(identifier));
}
ArgumentNullException.ThrowIfNull(identifier);

var endpointUrl = _urlBuilder.BuildAssetsUrl(identifier);
await _actionInvoker.InvokeMethodAsync(endpointUrl, HttpMethod.Delete);
Expand All @@ -132,10 +111,7 @@ public async Task DeleteAssetAsync(Reference identifier)
/// <inheritdoc />
public async Task<FileReference> UploadFileAsync(FileContentSource fileContent)
{
if (fileContent == null)
{
throw new ArgumentNullException(nameof(fileContent));
}
ArgumentNullException.ThrowIfNull(fileContent);

var stream = fileContent.OpenReadStream();
try
Expand Down
10 changes: 2 additions & 8 deletions Kontent.Ai.Management/ManagementClient.AssetFolder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,7 @@ public async Task<AssetFoldersModel> GetAssetFoldersAsync()
/// <inheritdoc />
public async Task<AssetFoldersModel> CreateAssetFoldersAsync(AssetFolderCreateModel folder)
{
if (folder == null)
{
throw new ArgumentNullException(nameof(folder));
}
ArgumentNullException.ThrowIfNull(folder);

var endpointUrl = _urlBuilder.BuildAssetFoldersUrl();
var response = await _actionInvoker.InvokeMethodAsync<AssetFolderCreateModel, AssetFoldersModel>(endpointUrl, HttpMethod.Post, folder);
Expand All @@ -35,10 +32,7 @@ public async Task<AssetFoldersModel> CreateAssetFoldersAsync(AssetFolderCreateMo
/// <inheritdoc />
public async Task<AssetFoldersModel> ModifyAssetFoldersAsync(IEnumerable<AssetFolderOperationBaseModel> changes)
{
if (changes == null)
{
throw new ArgumentNullException(nameof(changes));
}
ArgumentNullException.ThrowIfNull(changes);

var endpointUrl = _urlBuilder.BuildAssetFoldersUrl();
var response = await _actionInvoker.InvokeMethodAsync<IEnumerable<AssetFolderOperationBaseModel>, AssetFoldersModel>(endpointUrl, new HttpMethod("PATCH"), changes);
Expand Down
Loading
Loading