From e3cbe5e465f81a6596638c2ce30d2c67d6a7571c Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Fri, 16 Aug 2024 18:43:56 -0500 Subject: [PATCH 01/35] Add the sorting in the queries before paging --- .../Features/Actions/ReadActions.cs | 5 +- .../Features/Applications/ReadApplication.cs | 20 +------ .../ReadAuthorizationStrategy.cs | 2 +- .../Features/ClaimSets/ReadClaimSets.cs | 5 +- .../Features/OdsInstances/ReadOdsInstance.cs | 2 +- .../Features/Profiles/ProfileModel.cs | 2 +- .../Features/Profiles/ReadProfile.cs | 2 +- .../ResourceClaims/ReadResourceClaims.cs | 5 +- .../Features/Vendors/ReadVendor.cs | 2 +- .../Infrastructure/CommonQueryParams.cs | 15 +---- .../Database/Queries/GetAllActionsQuery.cs | 21 +++++-- .../Queries/GetAllApplicationsQuery.cs | 60 +++++++++++++++++++ .../Database/Queries/GetAllClaimSetsQuery.cs | 19 +++++- .../Queries/GetAuthStrategiesQuery.cs | 24 ++++++-- .../Queries/GetOdsInstanceContextsQuery.cs | 17 +++++- .../Queries/GetOdsInstanceDerivativesQuery.cs | 18 +++++- .../Database/Queries/GetOdsInstancesQuery.cs | 18 +++++- .../Database/Queries/GetProfilesQuery.cs | 17 ++++-- .../Queries/GetResourceClaimsQuery.cs | 43 +++++++++---- .../Database/Queries/GetVendorsQuery.cs | 15 ++++- .../Extensions/QueryExtensions.cs | 17 ++++++ .../Helpers/QueryStringMappingHelper.cs | 32 ++++++++++ .../Helpers/SortingDirectionHelper.cs | 26 ++++---- 23 files changed, 289 insertions(+), 98 deletions(-) create mode 100644 Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllApplicationsQuery.cs create mode 100644 Application/EdFi.Ods.AdminApi/Infrastructure/Helpers/QueryStringMappingHelper.cs diff --git a/Application/EdFi.Ods.AdminApi/Features/Actions/ReadActions.cs b/Application/EdFi.Ods.AdminApi/Features/Actions/ReadActions.cs index 12a4bd1d2..a05ef8115 100644 --- a/Application/EdFi.Ods.AdminApi/Features/Actions/ReadActions.cs +++ b/Application/EdFi.Ods.AdminApi/Features/Actions/ReadActions.cs @@ -28,9 +28,6 @@ internal Task GetActions(IGetAllActionsQuery getAllActionsQuery, IMappe new CommonQueryParams(offset, limit, orderBy, direction), id, name)); - var result = actions.Sort( - orderBy ?? string.Empty, - SortingDirectionHelper.GetNonEmptyOrDefault(direction)); - return Task.FromResult(Results.Ok(result)); + return Task.FromResult(Results.Ok(actions)); } } diff --git a/Application/EdFi.Ods.AdminApi/Features/Applications/ReadApplication.cs b/Application/EdFi.Ods.AdminApi/Features/Applications/ReadApplication.cs index 2bd1074aa..066326f11 100644 --- a/Application/EdFi.Ods.AdminApi/Features/Applications/ReadApplication.cs +++ b/Application/EdFi.Ods.AdminApi/Features/Applications/ReadApplication.cs @@ -33,27 +33,13 @@ public void MapEndpoints(IEndpointRouteBuilder endpoints) } internal Task GetApplications( - IGetVendorsQuery getVendorsAndApplicationsQuery, + IGetAllApplicationsQuery getAllApplicationsQuery, IMapper mapper, IOptions settings, [AsParameters] CommonQueryParams commonQueryParams, int? id, string? applicationName, string? claimsetName) { - var vendors = getVendorsAndApplicationsQuery.Execute(); - var applications = new List(); - foreach (var vendor in vendors) - { - applications.AddRange(mapper.Map>(vendor.Applications)); - } - var filteredApplications = applications - .AsEnumerable() - .Where(a => id == null || a.Id == id) - .Where(a => applicationName == null || a.ApplicationName == applicationName) - .Where(a => claimsetName == null || a.ClaimSetName == claimsetName) - .Paginate(commonQueryParams.Offset, commonQueryParams.Limit, settings); - - var applicationsReturned = mapper.Map>(filteredApplications); - applicationsReturned = applicationsReturned.Sort(commonQueryParams.OrderBy ?? string.Empty, SortingDirectionHelper.GetNonEmptyOrDefault(commonQueryParams.Direction)); - return Task.FromResult(Results.Ok(applicationsReturned)); + var applications = mapper.Map>(getAllApplicationsQuery.Execute(commonQueryParams, id, applicationName, claimsetName)); + return Task.FromResult(Results.Ok(applications)); } internal Task GetApplication(GetApplicationByIdQuery getApplicationByIdQuery, IMapper mapper, int id) diff --git a/Application/EdFi.Ods.AdminApi/Features/AuthorizationStrategies/ReadAuthorizationStrategy.cs b/Application/EdFi.Ods.AdminApi/Features/AuthorizationStrategies/ReadAuthorizationStrategy.cs index 0d1571748..cd0a48b33 100644 --- a/Application/EdFi.Ods.AdminApi/Features/AuthorizationStrategies/ReadAuthorizationStrategy.cs +++ b/Application/EdFi.Ods.AdminApi/Features/AuthorizationStrategies/ReadAuthorizationStrategy.cs @@ -24,6 +24,6 @@ public void MapEndpoints(IEndpointRouteBuilder endpoints) internal Task GetAuthStrategies(IGetAuthStrategiesQuery getAuthStrategiesQuery, IMapper mapper, [AsParameters] CommonQueryParams commonQueryParams) { var authStrategyList = mapper.Map>(getAuthStrategiesQuery.Execute(commonQueryParams)); - return Task.FromResult(Results.Ok(authStrategyList.Sort(commonQueryParams.OrderBy ?? string.Empty, SortingDirectionHelper.GetNonEmptyOrDefault(commonQueryParams.Direction)))); + return Task.FromResult(Results.Ok(authStrategyList)); } } diff --git a/Application/EdFi.Ods.AdminApi/Features/ClaimSets/ReadClaimSets.cs b/Application/EdFi.Ods.AdminApi/Features/ClaimSets/ReadClaimSets.cs index e44dc5eed..c2b57024c 100644 --- a/Application/EdFi.Ods.AdminApi/Features/ClaimSets/ReadClaimSets.cs +++ b/Application/EdFi.Ods.AdminApi/Features/ClaimSets/ReadClaimSets.cs @@ -36,12 +36,11 @@ internal Task GetClaimSets( commonQueryParams, id, name)); - var model = claimSets.Sort(commonQueryParams.OrderBy ?? string.Empty, SortingDirectionHelper.GetNonEmptyOrDefault(commonQueryParams.Direction)); - foreach (var claimSet in model) + foreach (var claimSet in claimSets) { claimSet.Applications = mapper.Map>(getApplications.Execute(claimSet.Id)); } - return Task.FromResult(Results.Ok(model)); + return Task.FromResult(Results.Ok(claimSets)); } internal Task GetClaimSet(IGetClaimSetByIdQuery getClaimSetByIdQuery, diff --git a/Application/EdFi.Ods.AdminApi/Features/OdsInstances/ReadOdsInstance.cs b/Application/EdFi.Ods.AdminApi/Features/OdsInstances/ReadOdsInstance.cs index 8d51c7cb6..79181f7d7 100644 --- a/Application/EdFi.Ods.AdminApi/Features/OdsInstances/ReadOdsInstance.cs +++ b/Application/EdFi.Ods.AdminApi/Features/OdsInstances/ReadOdsInstance.cs @@ -33,7 +33,7 @@ internal Task GetOdsInstances(IGetOdsInstancesQuery getOdsInstancesQuer id, name, instanceType)); - return Task.FromResult(Results.Ok(odsInstances.Sort(commonQueryParams.OrderBy ?? string.Empty, SortingDirectionHelper.GetNonEmptyOrDefault(commonQueryParams.Direction)))); + return Task.FromResult(Results.Ok(odsInstances)); } internal Task GetOdsInstance(IGetOdsInstanceQuery getOdsInstanceQuery, IMapper mapper, int id) diff --git a/Application/EdFi.Ods.AdminApi/Features/Profiles/ProfileModel.cs b/Application/EdFi.Ods.AdminApi/Features/Profiles/ProfileModel.cs index 3aa73926a..4b813d0eb 100644 --- a/Application/EdFi.Ods.AdminApi/Features/Profiles/ProfileModel.cs +++ b/Application/EdFi.Ods.AdminApi/Features/Profiles/ProfileModel.cs @@ -16,6 +16,6 @@ public class ProfileModel [SwaggerSchema(Title = "ProfileDetails")] public class ProfileDetailsModel : ProfileModel -{ +{ public string? Definition { get; set; } } diff --git a/Application/EdFi.Ods.AdminApi/Features/Profiles/ReadProfile.cs b/Application/EdFi.Ods.AdminApi/Features/Profiles/ReadProfile.cs index d7816d932..45bda7288 100644 --- a/Application/EdFi.Ods.AdminApi/Features/Profiles/ReadProfile.cs +++ b/Application/EdFi.Ods.AdminApi/Features/Profiles/ReadProfile.cs @@ -32,7 +32,7 @@ internal Task GetProfiles(IGetProfilesQuery getProfilesQuery, IMapper m var profileList = mapper.Map>(getProfilesQuery.Execute( commonQueryParams, id, name)); - return Task.FromResult(Results.Ok(profileList.Sort(commonQueryParams.OrderBy ?? string.Empty, SortingDirectionHelper.GetNonEmptyOrDefault(commonQueryParams.Direction)))); + return Task.FromResult(Results.Ok(profileList)); } internal Task GetProfile(IGetProfileByIdQuery getProfileByIdQuery, IMapper mapper, int id) diff --git a/Application/EdFi.Ods.AdminApi/Features/ResourceClaims/ReadResourceClaims.cs b/Application/EdFi.Ods.AdminApi/Features/ResourceClaims/ReadResourceClaims.cs index 45aa9fb76..7553985b7 100644 --- a/Application/EdFi.Ods.AdminApi/Features/ResourceClaims/ReadResourceClaims.cs +++ b/Application/EdFi.Ods.AdminApi/Features/ResourceClaims/ReadResourceClaims.cs @@ -32,10 +32,9 @@ internal Task GetResourceClaims(IGetResourceClaimsQuery getResourceClai { var resourceClaims = mapper.Map>(getResourceClaimsQuery.Execute( commonQueryParams, - id, name).ToList()); - var model = resourceClaims.Sort(commonQueryParams.OrderBy ?? string.Empty, SortingDirectionHelper.GetNonEmptyOrDefault(commonQueryParams.Direction)); + id, name)); - return Task.FromResult(Results.Ok(model)); + return Task.FromResult(Results.Ok(resourceClaims)); } internal Task GetResourceClaim(IGetResourceClaimByResourceClaimIdQuery getResourceClaimByResourceClaimIdQuery, IMapper mapper, int id) diff --git a/Application/EdFi.Ods.AdminApi/Features/Vendors/ReadVendor.cs b/Application/EdFi.Ods.AdminApi/Features/Vendors/ReadVendor.cs index 9ce29f9c7..090ee917a 100644 --- a/Application/EdFi.Ods.AdminApi/Features/Vendors/ReadVendor.cs +++ b/Application/EdFi.Ods.AdminApi/Features/Vendors/ReadVendor.cs @@ -33,7 +33,7 @@ internal Task GetVendors( var vendorList = mapper.Map>(getVendorsQuery.Execute( commonQueryParams, id, company, namespacePrefixes, contactName, contactEmailAddress)); - return Task.FromResult(Results.Ok(vendorList.Sort(commonQueryParams.OrderBy ?? string.Empty, SortingDirectionHelper.GetNonEmptyOrDefault(commonQueryParams.Direction)))); + return Task.FromResult(Results.Ok(vendorList)); } internal Task GetVendor(IGetVendorByIdQuery getVendorByIdQuery, IMapper mapper, int id) diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/CommonQueryParams.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/CommonQueryParams.cs index 528156549..337d0d534 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/CommonQueryParams.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/CommonQueryParams.cs @@ -3,11 +3,9 @@ // The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. // See the LICENSE and NOTICES files in the project root for more information. -using EdFi.Ods.AdminApi.Helpers; using EdFi.Ods.AdminApi.Infrastructure.Helpers; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ModelBinding; -using Microsoft.Extensions.Options; namespace EdFi.Ods.AdminApi.Infrastructure; @@ -19,29 +17,22 @@ public struct CommonQueryParams public int? Limit { get; set; } [FromQuery(Name = "orderBy")] public string? OrderBy { get; set; } - [BindNever] - public string? OrderByDefault { get; set; } [FromQuery(Name = "direction")] public string? Direction { get; set; } [BindNever] - public bool? IsDescending { get; set; } + public bool IsDescending => SortingDirectionHelper.IsDescendingSorting(Direction); public CommonQueryParams() { } public CommonQueryParams(int? offset, int? limit) { Offset = offset; Limit = limit; } - public CommonQueryParams(int? offset, int? limit, string? orderBy, string? direction, string? orderByDefault = "") + public CommonQueryParams(int? offset, int? limit, string? orderBy, string? direction) { Offset = offset; Limit = limit; OrderBy = orderBy; - OrderByDefault = orderByDefault; - if (!string.IsNullOrEmpty(direction)) - { - Direction = SortingDirectionHelper.GetNonEmptyOrDefault(direction); - IsDescending = SortingDirectionHelper.IsDescendingSorting(Direction); - } + Direction = SortingDirectionHelper.GetNonEmptyOrDefault(direction); } } diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllActionsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllActionsQuery.cs index 91a1e6258..48a05c2ca 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllActionsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllActionsQuery.cs @@ -3,8 +3,10 @@ // The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. // See the LICENSE and NOTICES files in the project root for more information. +using System.Linq.Expressions; using EdFi.Ods.AdminApi.Helpers; using EdFi.Ods.AdminApi.Infrastructure.Extensions; +using EdFi.Ods.AdminApi.Infrastructure.Helpers; using EdFi.Security.DataAccess.Contexts; using Microsoft.Extensions.Options; using Action = EdFi.Security.DataAccess.Models.Action; @@ -21,6 +23,14 @@ public class GetAllActionsQuery : IGetAllActionsQuery { private readonly ISecurityContext _securityContext; private readonly IOptions _options; + private static readonly Dictionary>> _orderByColumnActions = + new Dictionary>> + (StringComparer.OrdinalIgnoreCase) + { + { "name", x => x.ActionName }, + { "uri", x => x.ActionUri }, + { "id", x => x.ActionId } + }; public GetAllActionsQuery(ISecurityContext securityContext, IOptions options) { @@ -35,10 +45,13 @@ public IReadOnlyList Execute() public IReadOnlyList Execute(CommonQueryParams commonQueryParams, int? id, string? name) { + Expression> columnToOrderBy = _orderByColumnActions.GetColumnToOrderBy(commonQueryParams.OrderBy); + return _securityContext.Actions - .Where(a => id == null || a.ActionId == id) - .Where(a => name == null || a.ActionName == name) - .Paginate(commonQueryParams.Offset, commonQueryParams.Limit, _options) - .ToList(); + .Where(a => id == null || a.ActionId == id) + .Where(a => name == null || a.ActionName == name) + .OrderByColumn(columnToOrderBy, commonQueryParams.IsDescending) + .Paginate(commonQueryParams.Offset, commonQueryParams.Limit, _options) + .ToList(); } } diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllApplicationsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllApplicationsQuery.cs new file mode 100644 index 000000000..5faba0be6 --- /dev/null +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllApplicationsQuery.cs @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using System.Linq.Expressions; +using EdFi.Admin.DataAccess.Contexts; +using EdFi.Admin.DataAccess.Models; +using EdFi.Ods.AdminApi.Helpers; +using EdFi.Ods.AdminApi.Infrastructure.Extensions; +using EdFi.Ods.AdminApi.Infrastructure.Helpers; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Options; + +namespace EdFi.Ods.AdminApi.Infrastructure.Database.Queries; + + +public interface IGetAllApplicationsQuery +{ + IReadOnlyList Execute(CommonQueryParams commonQueryParams, int? id, string? applicationName, string? claimsetName); +} + +public class GetAllApplicationsQuery : IGetAllApplicationsQuery +{ + private readonly IUsersContext _context; + private readonly IOptions _options; + private static readonly Dictionary>> _orderByColumnApplications = + new Dictionary>> + (StringComparer.OrdinalIgnoreCase) + { + { "name", x => x.ApplicationName }, + { "claimsetName", x => x.ClaimSetName }, + { "id", x => x.ApplicationId } + }; + + public GetAllApplicationsQuery(IUsersContext context, IOptions options) + { + _context = context; + _options = options; + } + + public IReadOnlyList Execute(CommonQueryParams commonQueryParams, int? id, string? applicationName, string? claimsetName) + { + Expression> columnToOrderBy = _orderByColumnApplications.GetColumnToOrderBy(commonQueryParams.OrderBy); + + var applications = _context.Applications + .Include(a => a.ApplicationEducationOrganizations) + .Include(a => a.Profiles) + .Include(a => a.Vendor) + .Include(a => a.ApiClients) + .Where(a => id == null || a.ApplicationId == id) + .Where(a => applicationName == null || a.ApplicationName == applicationName) + .Where(a => claimsetName == null || a.ClaimSetName == claimsetName) + .OrderByColumn(columnToOrderBy, commonQueryParams.IsDescending) + .Paginate(commonQueryParams.Offset, commonQueryParams.Limit, _options) + .ToList(); + + return applications; + } +} diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllClaimSetsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllClaimSetsQuery.cs index 2df1d5ea5..14aaa8649 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllClaimSetsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllClaimSetsQuery.cs @@ -3,8 +3,10 @@ // The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. // See the LICENSE and NOTICES files in the project root for more information. +using System.Linq.Expressions; using EdFi.Ods.AdminApi.Helpers; using EdFi.Ods.AdminApi.Infrastructure.Extensions; +using EdFi.Ods.AdminApi.Infrastructure.Helpers; using EdFi.Security.DataAccess.Contexts; using Microsoft.Extensions.Options; using ClaimSet = EdFi.Ods.AdminApi.Infrastructure.ClaimSetEditor.ClaimSet; @@ -20,7 +22,16 @@ public interface IGetAllClaimSetsQuery public class GetAllClaimSetsQuery : IGetAllClaimSetsQuery { private readonly ISecurityContext _securityContext; - private readonly IOptions _options; + private readonly IOptions _options; + private static readonly Dictionary>> _orderByColumnClaimSet = + new Dictionary>> + (StringComparer.OrdinalIgnoreCase) + { +#pragma warning disable CS8603 // Possible null reference return. + { "name", x => x.Name }, +#pragma warning restore CS8603 // Possible null reference return. + { "id", x => x.Id } + }; public GetAllClaimSetsQuery(ISecurityContext securityContext, IOptions options) { _securityContext = securityContext; @@ -42,7 +53,9 @@ public IReadOnlyList Execute() } public IReadOnlyList Execute(CommonQueryParams commonQueryParams, int? id, string? name) - { + { + Expression> columnToOrderBy = _orderByColumnClaimSet.GetColumnToOrderBy(commonQueryParams.OrderBy); + return _securityContext.ClaimSets .Where(c => id == null || c.ClaimSetId == id) .Where(c => name == null || c.ClaimSetName == name) @@ -53,7 +66,7 @@ public IReadOnlyList Execute(CommonQueryParams commonQueryParams, int? IsEditable = !x.IsEdfiPreset && !x.ForApplicationUseOnly }) .Distinct() - .OrderBy(x => x.Name) + .OrderByColumn(columnToOrderBy, commonQueryParams.IsDescending) .Paginate(commonQueryParams.Offset, commonQueryParams.Limit, _options) .ToList(); } diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAuthStrategiesQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAuthStrategiesQuery.cs index 917ada932..e1ae0ebfc 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAuthStrategiesQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAuthStrategiesQuery.cs @@ -3,8 +3,10 @@ // The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. // See the LICENSE and NOTICES files in the project root for more information. +using System.Linq.Expressions; using EdFi.Ods.AdminApi.Helpers; using EdFi.Ods.AdminApi.Infrastructure.Extensions; +using EdFi.Ods.AdminApi.Infrastructure.Helpers; using EdFi.Security.DataAccess.Contexts; using EdFi.Security.DataAccess.Models; using Microsoft.Extensions.Options; @@ -20,7 +22,14 @@ public interface IGetAuthStrategiesQuery public class GetAuthStrategiesQuery : IGetAuthStrategiesQuery { private readonly ISecurityContext _context; - private readonly IOptions _options; + private readonly IOptions _options; + private static readonly Dictionary>> _orderByColumnAuthorizationStrategies = + new Dictionary>>(StringComparer.OrdinalIgnoreCase) + { + { "name", x => x.AuthorizationStrategyName }, + { "displayName", x => x.DisplayName }, + { "id", x => x.AuthorizationStrategyId } + }; public GetAuthStrategiesQuery(ISecurityContext context, IOptions options) { @@ -29,15 +38,18 @@ public GetAuthStrategiesQuery(ISecurityContext context, IOptions op } public List Execute() - { + { return _context.AuthorizationStrategies.OrderBy(v => v.AuthorizationStrategyName).ToList(); } public List Execute(CommonQueryParams commonQueryParams) - { + { + Expression> columnToOrderBy = _orderByColumnAuthorizationStrategies.GetColumnToOrderBy(commonQueryParams.OrderBy); + return _context.AuthorizationStrategies - .OrderBy(v => v.AuthorizationStrategyName) - .Paginate(commonQueryParams.Offset, commonQueryParams.Limit, _options) - .ToList(); + .OrderByColumn(columnToOrderBy, commonQueryParams.IsDescending) + .Paginate(commonQueryParams.Offset, commonQueryParams.Limit, _options) + .ToList(); } } + diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceContextsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceContextsQuery.cs index d28d3aa53..71765d14e 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceContextsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceContextsQuery.cs @@ -3,10 +3,12 @@ // The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. // See the LICENSE and NOTICES files in the project root for more information. +using System.Linq.Expressions; using EdFi.Admin.DataAccess.Contexts; using EdFi.Admin.DataAccess.Models; using EdFi.Ods.AdminApi.Helpers; using EdFi.Ods.AdminApi.Infrastructure.Extensions; +using EdFi.Ods.AdminApi.Infrastructure.Helpers; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; @@ -23,7 +25,14 @@ public class GetOdsInstanceContextsQuery : IGetOdsInstanceContextsQuery { private readonly IUsersContext _usersContext; private readonly IOptions _options; - + private static readonly Dictionary>> _orderByColumnOds = + new Dictionary>> + (StringComparer.OrdinalIgnoreCase) + { + { "contextKey", x => x.ContextKey }, + { "contextValue", x => x.ContextValue }, + { "id", x => x.OdsInstanceContextId } + }; public GetOdsInstanceContextsQuery(IUsersContext usersContext, IOptions options) { _usersContext = usersContext; @@ -38,10 +47,12 @@ public List Execute() } public List Execute(CommonQueryParams commonQueryParams) - { + { + Expression> columnToOrderBy = _orderByColumnOds.GetColumnToOrderBy(commonQueryParams.OrderBy); + return _usersContext.OdsInstanceContexts .Include(oid => oid.OdsInstance) - .OrderBy(p => p.ContextKey) + .OrderByColumn(columnToOrderBy, commonQueryParams.IsDescending) .Paginate(commonQueryParams.Offset, commonQueryParams.Limit, _options) .ToList(); } diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceDerivativesQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceDerivativesQuery.cs index 08bab2ce6..4e0c4af30 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceDerivativesQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceDerivativesQuery.cs @@ -3,10 +3,12 @@ // The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. // See the LICENSE and NOTICES files in the project root for more information. +using System.Linq.Expressions; using EdFi.Admin.DataAccess.Contexts; using EdFi.Admin.DataAccess.Models; using EdFi.Ods.AdminApi.Helpers; using EdFi.Ods.AdminApi.Infrastructure.Extensions; +using EdFi.Ods.AdminApi.Infrastructure.Helpers; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; @@ -21,7 +23,15 @@ public interface IGetOdsInstanceDerivativesQuery public class GetOdsInstanceDerivativesQuery : IGetOdsInstanceDerivativesQuery { private readonly IUsersContext _usersContext; - private readonly IOptions _options; + private readonly IOptions _options; + private static readonly Dictionary>> _orderByColumnOds = + new Dictionary>> + (StringComparer.OrdinalIgnoreCase) + { + { "derivativeType", x => x.DerivativeType }, + { "odsInstanceId", x => x.OdsInstance.OdsInstanceId }, + { "id", x => x.OdsInstanceDerivativeId } + }; public GetOdsInstanceDerivativesQuery(IUsersContext usersContext, IOptions options) { @@ -37,10 +47,12 @@ public List Execute() } public List Execute(CommonQueryParams commonQueryParams) - { + { + Expression> columnToOrderBy = _orderByColumnOds.GetColumnToOrderBy(commonQueryParams.OrderBy); + return _usersContext.OdsInstanceDerivatives .Include(oid => oid.OdsInstance) - .OrderBy(p => p.DerivativeType) + .OrderByColumn(columnToOrderBy, commonQueryParams.IsDescending) .Paginate(commonQueryParams.Offset, commonQueryParams.Limit, _options) .ToList(); } diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs index 2d8150ac1..1025a60c3 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs @@ -3,10 +3,12 @@ // The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. // See the LICENSE and NOTICES files in the project root for more information. +using System.Linq.Expressions; using EdFi.Admin.DataAccess.Contexts; using EdFi.Admin.DataAccess.Models; using EdFi.Ods.AdminApi.Helpers; using EdFi.Ods.AdminApi.Infrastructure.Extensions; +using EdFi.Ods.AdminApi.Infrastructure.Helpers; using Microsoft.Extensions.Options; namespace EdFi.Ods.AdminApi.Infrastructure.Database.Queries; @@ -21,7 +23,15 @@ public interface IGetOdsInstancesQuery public class GetOdsInstancesQuery : IGetOdsInstancesQuery { private readonly IUsersContext _usersContext; - private readonly IOptions _options; + private readonly IOptions _options; + private static readonly Dictionary>> _orderByColumnOds = + new Dictionary>> + (StringComparer.OrdinalIgnoreCase) + { + { "name", x => x.Name }, + { "instanceType", x => x.InstanceType }, + { "id", x => x.OdsInstanceId } + }; public GetOdsInstancesQuery(IUsersContext userContext, IOptions options) { @@ -35,12 +45,14 @@ public List Execute() } public List Execute(CommonQueryParams commonQueryParams, int? id, string? name, string? instanceType) - { + { + Expression> columnToOrderBy = _orderByColumnOds.GetColumnToOrderBy(commonQueryParams.OrderBy); + return _usersContext.OdsInstances .Where(o => id == null || o.OdsInstanceId == id) .Where(o => name == null || o.Name == name) .Where(o => instanceType == null || o.InstanceType == instanceType) - .OrderBy(odsInstance => odsInstance.Name) + .OrderByColumn(columnToOrderBy, commonQueryParams.IsDescending) .Paginate(commonQueryParams.Offset, commonQueryParams.Limit, _options) .ToList(); } diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetProfilesQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetProfilesQuery.cs index b114f8b18..7bd57723c 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetProfilesQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetProfilesQuery.cs @@ -3,10 +3,12 @@ // The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. // See the LICENSE and NOTICES files in the project root for more information. +using System.Linq.Expressions; using EdFi.Admin.DataAccess.Contexts; using EdFi.Admin.DataAccess.Models; using EdFi.Ods.AdminApi.Helpers; using EdFi.Ods.AdminApi.Infrastructure.Extensions; +using EdFi.Ods.AdminApi.Infrastructure.Helpers; using Microsoft.Extensions.Options; namespace EdFi.Ods.AdminApi.Infrastructure.Database.Queries; @@ -21,7 +23,13 @@ public class GetProfilesQuery : IGetProfilesQuery { private readonly IUsersContext _usersContext; private readonly IOptions _options; - + private static readonly Dictionary>> _orderByColumnProfiles = + new Dictionary>> + (StringComparer.OrdinalIgnoreCase) + { + { "name", x => x.ProfileName }, + { "id", x => x.ProfileId } + }; public GetProfilesQuery(IUsersContext usersContext, IOptions options) { _usersContext = usersContext; @@ -32,13 +40,14 @@ public List Execute() { return _usersContext.Profiles.OrderBy(p => p.ProfileName).ToList(); } - public List Execute(CommonQueryParams commonQueryParams, int? id, string? name) - { + { + Expression> columnToOrderBy = _orderByColumnProfiles.GetColumnToOrderBy(commonQueryParams.OrderBy); + return _usersContext.Profiles .Where(p => id == null || p.ProfileId == id) .Where(p => name == null || p.ProfileName == name) - .OrderBy(p => p.ProfileName) + .OrderByColumn(columnToOrderBy, commonQueryParams.IsDescending) .Paginate(commonQueryParams.Offset, commonQueryParams.Limit, _options) .ToList(); } diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetResourceClaimsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetResourceClaimsQuery.cs index 37977fd30..b9b59c6ef 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetResourceClaimsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetResourceClaimsQuery.cs @@ -3,8 +3,10 @@ // The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. // See the LICENSE and NOTICES files in the project root for more information. +using System.Linq.Expressions; using EdFi.Ods.AdminApi.Helpers; using EdFi.Ods.AdminApi.Infrastructure.ClaimSetEditor; +using EdFi.Ods.AdminApi.Infrastructure.Extensions; using EdFi.Ods.AdminApi.Infrastructure.Helpers; using EdFi.Security.DataAccess.Contexts; using Microsoft.Extensions.Options; @@ -21,7 +23,17 @@ public class GetResourceClaimsQuery : IGetResourceClaimsQuery { private readonly ISecurityContext _securityContext; private readonly IOptions _options; - + private static readonly Dictionary>> _orderByColumnResourceClaims = + new Dictionary>> + (StringComparer.OrdinalIgnoreCase) + { + { "name", x => x.ResourceName }, + { "parentName", x => x.ParentResourceClaim.ResourceName }, +#pragma warning disable CS8603 // Possible null reference return. + { "parentId", x => x.ParentResourceClaimId }, +#pragma warning restore CS8603 // Possible null reference return. + { "id", x => x.ResourceClaimId } + }; public GetResourceClaimsQuery(ISecurityContext securityContext, IOptions options) { _securityContext = securityContext; @@ -34,20 +46,28 @@ public IEnumerable Execute() } public IEnumerable Execute(CommonQueryParams commonQueryParams, int? id, string? name) - { - return Query() + { + return Query(commonQueryParams) .Where(c => id == null || c.Id == id) - .Where(c => name == null || c.Name == name) - .Paginate(commonQueryParams.Offset, commonQueryParams.Limit, _options) + .Where(c => name == null || c.Name == name) .ToList(); } - private IEnumerable Query() - { + private IEnumerable Query(CommonQueryParams? commonQueryParams = null) + { + Expression> columnToOrderBy = _orderByColumnResourceClaims.GetColumnToOrderBy(commonQueryParams != null ? commonQueryParams.Value.OrderBy : string.Empty); var resources = new List(); - var parentResources = _securityContext.ResourceClaims.Where(x => x.ParentResourceClaim == null).ToList(); - var childResources = _securityContext.ResourceClaims.Where(x => x.ParentResourceClaim != null).ToList(); - foreach (var parentResource in parentResources) + + var parentResources = _securityContext.ResourceClaims + .Where(x => x.ParentResourceClaim == null) + .OrderByColumn(columnToOrderBy, commonQueryParams.GetValueOrDefault().IsDescending); + + if (commonQueryParams != null) + parentResources = parentResources.Paginate(commonQueryParams.Value.Offset, commonQueryParams.Value.Limit, _options); + + var childResources = _securityContext.ResourceClaims.Where(x => x.ParentResourceClaim != null).ToList(); + + foreach (var parentResource in parentResources.ToList()) { var children = childResources.Where(x => x.ParentResourceClaimId == parentResource.ResourceClaimId); resources.Add(new ResourceClaim @@ -64,7 +84,6 @@ private IEnumerable Query() }); } return resources - .Distinct() - .OrderBy(x => x.Name); + .Distinct(); } } diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs index c15690c70..344025035 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs @@ -3,11 +3,13 @@ // The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. // See the LICENSE and NOTICES files in the project root for more information. +using System.Linq.Expressions; using EdFi.Admin.DataAccess.Contexts; using EdFi.Admin.DataAccess.Models; using EdFi.Ods.AdminApi.Helpers; using EdFi.Ods.AdminApi.Infrastructure; using EdFi.Ods.AdminApi.Infrastructure.Extensions; +using EdFi.Ods.AdminApi.Infrastructure.Helpers; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; @@ -23,7 +25,13 @@ public class GetVendorsQuery : IGetVendorsQuery { private readonly IUsersContext _context; private readonly IOptions _options; - + private static readonly Dictionary>> _orderByColumnVendors = + new Dictionary>> + (StringComparer.OrdinalIgnoreCase) + { + { "company", x => x.VendorName }, + { "id", x => x.VendorId } + }; public GetVendorsQuery(IUsersContext context, IOptions options) { _context = context; @@ -45,7 +53,9 @@ public List Execute() } public List Execute(CommonQueryParams commonQueryParams, int? id, string? company, string? namespacePrefixes, string? contactName, string? contactEmailAddress) - { + { + Expression> columnToOrderBy = _orderByColumnVendors.GetColumnToOrderBy(commonQueryParams.OrderBy); + return _context.Vendors .Where(c => id == null || id < 1 || c.VendorId == id) .Where(c => company == null || c.VendorName == company) @@ -61,6 +71,7 @@ public List Execute(CommonQueryParams commonQueryParams, int? id, string .Include(v => v.Users) .Include(v => v.VendorNamespacePrefixes) .Where(v => !VendorExtensions.ReservedNames.Contains(v.VendorName.Trim())) + .OrderByColumn(columnToOrderBy, commonQueryParams.IsDescending) .Paginate(commonQueryParams.Offset, commonQueryParams.Limit, _options) .ToList(); } diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Extensions/QueryExtensions.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Extensions/QueryExtensions.cs index e5693d2c0..3e1f6b399 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Extensions/QueryExtensions.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Extensions/QueryExtensions.cs @@ -56,6 +56,23 @@ public static IQueryable OrderByColumn(this IQueryable source, string o } } + /// + /// Ordering the IQueryable base in the expression + /// + /// Entity type + /// DBSet that contains the data + /// Expression function that contains the column to order + /// Indicate if it is descending + /// + public static IQueryable OrderByColumn(this IQueryable source, Expression> orderBy, bool isDescending) + { + if (isDescending) + source = source.OrderByDescending(orderBy); + else + source = source.OrderBy(orderBy); + return source; + } + /// /// Apply pagination based on the offset and limit /// diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Helpers/QueryStringMappingHelper.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Helpers/QueryStringMappingHelper.cs new file mode 100644 index 000000000..f74ae4722 --- /dev/null +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Helpers/QueryStringMappingHelper.cs @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using System.Linq.Expressions; +using FluentValidation; +using FluentValidation.Results; + +namespace EdFi.Ods.AdminApi.Infrastructure.Helpers; + +public static class QueryStringMappingHelper +{ + public static Expression> GetColumnToOrderBy(this Dictionary>> mapping, string? orderBy) + { + orderBy = orderBy ?? string.Empty; + Expression>? result; + + if (mapping == null) + throw new ArgumentNullException(nameof(mapping)); + + if (string.IsNullOrEmpty(orderBy)) + return mapping.First().Value; + + if (!mapping.TryGetValue(orderBy.ToLowerInvariant(), out result)) + { + throw new ValidationException([new ValidationFailure(nameof(orderBy), $"The orderBy value {orderBy} is not allowed. The allowed values are {string.Join(",", mapping.Keys)}")]); + } + + return result; + } +} diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Helpers/SortingDirectionHelper.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Helpers/SortingDirectionHelper.cs index 101edd793..f51e20b45 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Helpers/SortingDirectionHelper.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Helpers/SortingDirectionHelper.cs @@ -21,26 +21,24 @@ public enum Direction Descending } - public static bool IsDescendingSorting(string input) - { - switch (input.ToLowerInvariant()) - { - case "asc": - case "ascending": - return false; - case "desc": - case "descending": - default: - return true; - } + public static bool IsDescendingSorting(string? direction) + { + direction = GetNonEmptyOrDefault(direction); + + bool result = direction.ToLowerInvariant() switch + { + "asc" or "ascending" => false, + "desc" or "descending" => true, + _ => false, + }; + + return result; } public static string GetNonEmptyOrDefault(string? direction) { if (!string.IsNullOrEmpty(direction)) - { return direction; - } return Direction.Ascending.ToString(); } } From 4cc0160f3cf5e7fd324ea1b9beaaa50d620a4f6f Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Fri, 16 Aug 2024 18:47:58 -0500 Subject: [PATCH 02/35] Remove the unused SortableList class --- .../Features/SortableListTests.cs | 121 ------------------ .../Extensions/ListExtensions.cs | 46 ------- .../Extensions/QueryExtensions.cs | 44 ------- 3 files changed, 211 deletions(-) delete mode 100644 Application/EdFi.Ods.AdminApi.UnitTests/Features/SortableListTests.cs delete mode 100644 Application/EdFi.Ods.AdminApi/Infrastructure/Extensions/ListExtensions.cs diff --git a/Application/EdFi.Ods.AdminApi.UnitTests/Features/SortableListTests.cs b/Application/EdFi.Ods.AdminApi.UnitTests/Features/SortableListTests.cs deleted file mode 100644 index ff212773d..000000000 --- a/Application/EdFi.Ods.AdminApi.UnitTests/Features/SortableListTests.cs +++ /dev/null @@ -1,121 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Licensed to the Ed-Fi Alliance under one or more agreements. -// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. -// See the LICENSE and NOTICES files in the project root for more information. - -using System.Collections.Generic; -using System.Linq; -using EdFi.Ods.AdminApi.Features.Vendors; -using EdFi.Ods.AdminApi.Infrastructure.Extensions; -using EdFi.Ods.AdminApi.Infrastructure.Helpers; -using NUnit.Framework; -using Shouldly; - -namespace EdFi.Ods.AdminApi.UnitTests.Features -{ - [TestFixture] - public class SortableListTests - { - [Test] - public void Should_retrieve_vendors_with_sorting() - { - var vendors = new List(); - - vendors.AddRange(new List{ new VendorModel - { - Company = "test vendor 2", - NamespacePrefixes = "http://testvendor2.net", - ContactName = "test user 2", - ContactEmailAddress = "testuser@test.com" - }, { new VendorModel - { - Company = "test vendor 3", - NamespacePrefixes = "http://testvendor3.net", - ContactName = "test user 3", - ContactEmailAddress = "testuser@test.com" } - }, { new VendorModel - { - Company = "test vendor 1", - NamespacePrefixes = "http://testvendor1.net", - ContactName = "test user 1", - ContactEmailAddress = "testuser@test.com" } - }}); - - /// ContactName - string orderBy = "ContactName"; - var sortedList = vendors.Sort(orderBy); - - sortedList.ElementAt(0).Company.ShouldBe("test vendor 1"); - sortedList.ElementAt(1).Company.ShouldBe("test vendor 2"); - sortedList.ElementAt(2).Company.ShouldBe("test vendor 3"); - } - - [Test] - public void Should_retrieve_vendors_with_descending_sorting() - { - var vendors = new List(); - - vendors.AddRange(new List{ new VendorModel - { - Company = "test vendor 2", - NamespacePrefixes = "http://testvendor2.net", - ContactName = "test user 2", - ContactEmailAddress = "testuser@test.com" - }, { new VendorModel - { - Company = "test vendor 3", - NamespacePrefixes = "http://testvendor3.net", - ContactName = "test user 3", - ContactEmailAddress = "testuser@test.com" } - }, { new VendorModel - { - Company = "test vendor 1", - NamespacePrefixes = "http://testvendor1.net", - ContactName = "test user 1", - ContactEmailAddress = "testuser@test.com" } - }}); - - /// ContactName - string orderBy = "ContactName"; - var sortedList = vendors.Sort(orderBy, SortingDirectionHelper.Direction.Descending.ToString()); - - sortedList.ElementAt(0).Company.ShouldBe("test vendor 3"); - sortedList.ElementAt(1).Company.ShouldBe("test vendor 2"); - sortedList.ElementAt(2).Company.ShouldBe("test vendor 1"); - } - - [Test] - public void Should_retrieve_vendors_with_sorting_by_default_column() - { - var vendors = new List(); - - vendors.AddRange(new List{ new VendorModel - { - Company = "test vendor 2", - NamespacePrefixes = "http://testvendor2.net", - ContactName = "test user 2", - ContactEmailAddress = "testuser@test.com" - }, { new VendorModel - { - Company = "test vendor 3", - NamespacePrefixes = "http://testvendor3.net", - ContactName = "test user 3", - ContactEmailAddress = "testuser@test.com" } - }, { new VendorModel - { - Company = "test vendor 1", - NamespacePrefixes = "http://testvendor1.net", - ContactName = "test user 1", - ContactEmailAddress = "testuser@test.com" } - }}); - - /// ContactName - string orderBy = "notExistingColumn"; - var sortedList = vendors.Sort(orderBy); - - sortedList.ElementAt(0).Company.ShouldBe("test vendor 1"); - sortedList.ElementAt(1).Company.ShouldBe("test vendor 2"); - sortedList.ElementAt(2).Company.ShouldBe("test vendor 3"); - } - } -} diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Extensions/ListExtensions.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Extensions/ListExtensions.cs deleted file mode 100644 index 13c46ec42..000000000 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Extensions/ListExtensions.cs +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Licensed to the Ed-Fi Alliance under one or more agreements. -// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. -// See the LICENSE and NOTICES files in the project root for more information. - -using EdFi.Ods.AdminApi.Features.ClaimSets; -using EdFi.Ods.AdminApi.Features.ODSInstances; -using EdFi.Ods.AdminApi.Features.Profiles; -using EdFi.Ods.AdminApi.Features.Vendors; -using EdFi.Ods.AdminApi.Features; -using EdFi.Ods.AdminApi.Features.Actions; -using EdFi.Ods.AdminApi.Features.Applications; -using EdFi.Ods.AdminApi.Infrastructure.Helpers; - -namespace EdFi.Ods.AdminApi.Infrastructure.Extensions; - -public static class ListExtensions -{ - public static List Sort(this List source, string orderBy, string direction = "asc") - { - var descending = SortingDirectionHelper.IsDescendingSorting(direction); - var defaultSortColumn = string.Empty; - - if (typeof(ActionModel) == typeof(T)) - defaultSortColumn = FeatureConstants.ActionDefaultSorting; - else if (typeof(ApplicationModel) == typeof(T)) - defaultSortColumn = FeatureConstants.ApplicationsDefaultSorting; - else if (typeof(ClaimSetModel) == typeof(T)) - defaultSortColumn = FeatureConstants.ClaimsetDefaultSorting; - else if (typeof(OdsInstanceModel) == typeof(T)) - defaultSortColumn = FeatureConstants.OdsInstanceDefaultSorting; - else if (typeof(ProfileModel) == typeof(T)) - defaultSortColumn = FeatureConstants.ProfileDefaultSorting; - else if (typeof(ResourceClaimModel) == typeof(T)) - defaultSortColumn = FeatureConstants.ProfileDefaultSorting; - else if (typeof(VendorModel) == typeof(T)) - defaultSortColumn = FeatureConstants.VendorDefaultSorting; - - if (!string.IsNullOrEmpty(defaultSortColumn)) - { - var queriable = source.AsQueryable().OrderByColumn(orderBy, defaultSortColumn, descending); - return queriable.ToList(); - } - return source; - } -} diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Extensions/QueryExtensions.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Extensions/QueryExtensions.cs index 3e1f6b399..f2beb2290 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Extensions/QueryExtensions.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Extensions/QueryExtensions.cs @@ -12,50 +12,6 @@ namespace EdFi.Ods.AdminApi.Infrastructure.Extensions { public static class QueryExtensions { - /// - /// Custom function for sorting. - /// We initially try to fix by orderBy. If this column does not exist, we try to sort by orderByDefault. - /// - /// Any entity from the model - /// - /// Try to fix by this column - /// In case orderBy column does not exist, we sort by this column - /// asc or desc - /// - public static IQueryable OrderByColumn(this IQueryable source, string orderBy, string orderByDefault, bool descending = false) - { - try - { - var type = typeof(T); - var property = type.GetProperty(orderBy, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); - if (property == null) - property = type.GetProperty(orderByDefault, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); - - if (property != null) - { - var parameter = Expression.Parameter(type, "p"); - var propertyAccess = Expression.MakeMemberAccess(parameter, property); - var orderByExp = Expression.Lambda(propertyAccess, parameter); - - var resultExp = Expression.Call( - typeof(Queryable), - descending ? "OrderByDescending" : "OrderBy", - new Type[] { type, property.PropertyType }, - source.Expression, - Expression.Quote(orderByExp) - ); - - return source.Provider.CreateQuery(resultExp); - } - return source; - } - catch (Exception) - { - /// If this throws an exception simply don't sort. - return source; - } - } - /// /// Ordering the IQueryable base in the expression /// From b9d8d3b1b25662536c57b97c823773ce7c6fe702 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Fri, 16 Aug 2024 20:07:47 -0500 Subject: [PATCH 03/35] Add a couple of integration tests to the GetAllApplicationsQuery --- .../QueryTests/GetAllApplicationsQuery.cs | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 Application/EdFi.Ods.AdminApi.DBTests/Database/QueryTests/GetAllApplicationsQuery.cs diff --git a/Application/EdFi.Ods.AdminApi.DBTests/Database/QueryTests/GetAllApplicationsQuery.cs b/Application/EdFi.Ods.AdminApi.DBTests/Database/QueryTests/GetAllApplicationsQuery.cs new file mode 100644 index 000000000..049e4474d --- /dev/null +++ b/Application/EdFi.Ods.AdminApi.DBTests/Database/QueryTests/GetAllApplicationsQuery.cs @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using System; +using System.Threading.Tasks; +using EdFi.Admin.DataAccess.Models; +using EdFi.Ods.AdminApi.Helpers; +using EdFi.Ods.AdminApi.Infrastructure; +using EdFi.Ods.AdminApi.Infrastructure.Database.Queries; +using Microsoft.Extensions.Options; +using NUnit.Framework; +using Shouldly; +using VendorUser = EdFi.Admin.DataAccess.Models.User; + + +namespace EdFi.Ods.AdminApi.DBTests.Database.QueryTests; + +[TestFixture] +public class GetAllApplicationsQueryTests : PlatformUsersContextTestBase +{ + private IOptions _options { get; set; } + + [OneTimeSetUp] + public virtual async Task FixtureSetup() + { + _options = Testing.GetAppSettings(); + _options.Value.PreventDuplicateApplications = false; + LoadApplications(3); + await Task.Yield(); + } + + [Test] + public void ShouldGetAllApplications() + { + Transaction(usersContext => + { + var query = new GetAllApplicationsQuery(usersContext, _options); + var result = query.Execute( + new CommonQueryParams(null, null, null, null), null, null, null); + + result.Count.ShouldBeGreaterThan(0); + }); + } + + [Test] + public void ShouldGetAllApplications_With_Offset_and_Limit() + { + var offset = 1; + var limit = 2; + Transaction(usersContext => + { + var query = new GetAllApplicationsQuery(usersContext, _options); + var result = query.Execute( + new CommonQueryParams(offset, limit, null, null), null, null, null); + + result.Count.ShouldBeGreaterThan(0); + result.Count.ShouldBe(2); + }); + } + + private void LoadApplications(int count = 1) + { + for (int i = 0; i < count; i++) + { + var vendor = new Vendor { VendorName = $"test vendor {Guid.NewGuid().ToString()}" }; + var odsInstance = new OdsInstance + { + Name = $"Test Instance {Guid.NewGuid().ToString()}", + InstanceType = "Ods", + ConnectionString = "Data Source=(local);Initial Catalog=EdFi_Ods;Integrated Security=True;Encrypt=False" + }; + + var application = new Application + { + ApplicationName = $"test application {Guid.NewGuid().ToString()}", + ClaimSetName = "test claim set", + Vendor = vendor, + OperationalContextUri = OperationalContext.DefaultOperationalContextUri, + }; + var user = new VendorUser + { + Email = "", + FullName = application.ApplicationName, + Vendor = vendor + }; + + var apiClient = new ApiClient + { + Application = application, + Key = "key", + Secret = "secret", + Name = application.ApplicationName, + IsApproved = true, + UseSandbox = false, + KeyStatus = "Active", + User = user, + }; + + var apiClientOdsIntance = new ApiClientOdsInstance + { + ApiClient = apiClient, + OdsInstance = odsInstance, + }; + + Save(odsInstance, vendor, application, apiClient, apiClientOdsIntance); + } + } +} From 17e586899d73b77b0663c9f99af01d5ee8b53c56 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Tue, 20 Aug 2024 10:01:01 -0500 Subject: [PATCH 04/35] Fix the property name in the orderby applications --- .../Infrastructure/Database/Queries/GetAllApplicationsQuery.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllApplicationsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllApplicationsQuery.cs index 5faba0be6..c410338bc 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllApplicationsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllApplicationsQuery.cs @@ -14,7 +14,6 @@ namespace EdFi.Ods.AdminApi.Infrastructure.Database.Queries; - public interface IGetAllApplicationsQuery { IReadOnlyList Execute(CommonQueryParams commonQueryParams, int? id, string? applicationName, string? claimsetName); @@ -28,7 +27,7 @@ public class GetAllApplicationsQuery : IGetAllApplicationsQuery new Dictionary>> (StringComparer.OrdinalIgnoreCase) { - { "name", x => x.ApplicationName }, + { "applicationName", x => x.ApplicationName }, { "claimsetName", x => x.ClaimSetName }, { "id", x => x.ApplicationId } }; From 74c4cb6fbd1b99947e18876abea7b19f7bde8e36 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Tue, 20 Aug 2024 11:40:23 -0500 Subject: [PATCH 05/35] Fix the orderby in vendors to include contactname, contactemail and nameprefixes --- .../Database/Queries/GetVendorsQuery.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs index 344025035..5d0867043 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs @@ -4,6 +4,7 @@ // See the LICENSE and NOTICES files in the project root for more information. using System.Linq.Expressions; +using System.Numerics; using EdFi.Admin.DataAccess.Contexts; using EdFi.Admin.DataAccess.Models; using EdFi.Ods.AdminApi.Helpers; @@ -30,6 +31,13 @@ public class GetVendorsQuery : IGetVendorsQuery (StringComparer.OrdinalIgnoreCase) { { "company", x => x.VendorName }, +#pragma warning disable CS8602 // Dereference of a possibly null reference. + { "contactName", x => x.Users.FirstOrDefault().FullName }, +#pragma warning restore CS8602 // Dereference of a possibly null reference. +#pragma warning disable CS8602 // Dereference of a possibly null reference. + { "contactEmail", x => x.Users.FirstOrDefault().Email }, +#pragma warning restore CS8602 // Dereference of a possibly null reference. + { "namespacePrefixes", x => string.Join(",", x.VendorNamespacePrefixes.Select(p=> p.NamespacePrefix)) }, { "id", x => x.VendorId } }; public GetVendorsQuery(IUsersContext context, IOptions options) @@ -57,11 +65,6 @@ public List Execute(CommonQueryParams commonQueryParams, int? id, string Expression> columnToOrderBy = _orderByColumnVendors.GetColumnToOrderBy(commonQueryParams.OrderBy); return _context.Vendors - .Where(c => id == null || id < 1 || c.VendorId == id) - .Where(c => company == null || c.VendorName == company) - .Where(c => c.VendorNamespacePrefixes.Any(v => namespacePrefixes == null || v.NamespacePrefix == namespacePrefixes)) - .Where(c => c.Users.Any(u => contactName == null || u.FullName == contactName)) - .Where(c => c.Users.Any(u => contactEmailAddress == null || u.Email == contactEmailAddress)) .Include(v => v.Applications) .ThenInclude(a => a.Profiles) .Include(v => v.Applications) @@ -71,6 +74,11 @@ public List Execute(CommonQueryParams commonQueryParams, int? id, string .Include(v => v.Users) .Include(v => v.VendorNamespacePrefixes) .Where(v => !VendorExtensions.ReservedNames.Contains(v.VendorName.Trim())) + .Where(c => id == null || id < 1 || c.VendorId == id) + .Where(c => company == null || c.VendorName == company) + .Where(c => c.VendorNamespacePrefixes.Any(v => namespacePrefixes == null || v.NamespacePrefix == namespacePrefixes)) + .Where(c => c.Users.Any(u => contactName == null || u.FullName == contactName)) + .Where(c => c.Users.Any(u => contactEmailAddress == null || u.Email == contactEmailAddress)) .OrderByColumn(columnToOrderBy, commonQueryParams.IsDescending) .Paginate(commonQueryParams.Offset, commonQueryParams.Limit, _options) .ToList(); From 4bf358a0f199dfcdb693a1e60aae342e2531df5a Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Tue, 20 Aug 2024 15:17:27 -0500 Subject: [PATCH 06/35] Add new constants in order to use it in the sorting implementation --- .../Features/FeatureConstants.cs | 10 +---- .../Database/Queries/GetAllActionsQuery.cs | 6 +-- .../Queries/GetAllApplicationsQuery.cs | 6 +-- .../Database/Queries/GetAllClaimSetsQuery.cs | 4 +- .../Queries/GetAuthStrategiesQuery.cs | 6 +-- .../Queries/GetOdsInstanceContextsQuery.cs | 6 +-- .../Queries/GetOdsInstanceDerivativesQuery.cs | 6 +-- .../Database/Queries/GetOdsInstancesQuery.cs | 6 +-- .../Database/Queries/GetProfilesQuery.cs | 4 +- .../Queries/GetResourceClaimsQuery.cs | 8 ++-- .../Database/Queries/GetVendorsQuery.cs | 11 +++-- .../Infrastructure/SortingConstants.cs | 41 +++++++++++++++++++ 12 files changed, 73 insertions(+), 41 deletions(-) create mode 100644 Application/EdFi.Ods.AdminApi/Infrastructure/SortingConstants.cs diff --git a/Application/EdFi.Ods.AdminApi/Features/FeatureConstants.cs b/Application/EdFi.Ods.AdminApi/Features/FeatureConstants.cs index 0f3eeb056..72c5ca8f1 100644 --- a/Application/EdFi.Ods.AdminApi/Features/FeatureConstants.cs +++ b/Application/EdFi.Ods.AdminApi/Features/FeatureConstants.cs @@ -61,13 +61,5 @@ public static class FeatureConstants public const string ActionIdDescription = "Action id"; public const string ActionNameDescription = "Action name"; - /// Default columns to filter for each entity: - public const string ActionDefaultSorting = "Name"; - public const string ApplicationsDefaultSorting = "ApplicationName"; - public const string ClaimsetDefaultSorting = "Name"; - public const string OdsInstanceDefaultSorting = "Name"; - public const string ProfileDefaultSorting = "Name"; - public const string ResourceDefaultSorting = "Name"; - public const string ResourceClaimsDefaultSorting = "Name"; - public const string VendorDefaultSorting = "Company"; + } diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllActionsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllActionsQuery.cs index 48a05c2ca..7ee4bb47e 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllActionsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllActionsQuery.cs @@ -27,9 +27,9 @@ public class GetAllActionsQuery : IGetAllActionsQuery new Dictionary>> (StringComparer.OrdinalIgnoreCase) { - { "name", x => x.ActionName }, - { "uri", x => x.ActionUri }, - { "id", x => x.ActionId } + { SortingColumns.DefaultNameColumn, x => x.ActionName }, + { SortingColumns.ActionUriColumn, x => x.ActionUri }, + { SortingColumns.DefaultIdColumn, x => x.ActionId } }; public GetAllActionsQuery(ISecurityContext securityContext, IOptions options) diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllApplicationsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllApplicationsQuery.cs index c410338bc..39bf2dc1e 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllApplicationsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllApplicationsQuery.cs @@ -27,9 +27,9 @@ public class GetAllApplicationsQuery : IGetAllApplicationsQuery new Dictionary>> (StringComparer.OrdinalIgnoreCase) { - { "applicationName", x => x.ApplicationName }, - { "claimsetName", x => x.ClaimSetName }, - { "id", x => x.ApplicationId } + { SortingColumns.ApplicationNameColumn, x => x.ApplicationName }, + { SortingColumns.ApplicationClaimSetNameColumn, x => x.ClaimSetName }, + { SortingColumns.DefaultIdColumn, x => x.ApplicationId } }; public GetAllApplicationsQuery(IUsersContext context, IOptions options) diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllClaimSetsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllClaimSetsQuery.cs index 14aaa8649..918fbe17b 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllClaimSetsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllClaimSetsQuery.cs @@ -28,9 +28,9 @@ public class GetAllClaimSetsQuery : IGetAllClaimSetsQuery (StringComparer.OrdinalIgnoreCase) { #pragma warning disable CS8603 // Possible null reference return. - { "name", x => x.Name }, + { SortingColumns.DefaultNameColumn, x => x.Name }, #pragma warning restore CS8603 // Possible null reference return. - { "id", x => x.Id } + { SortingColumns.DefaultIdColumn, x => x.Id } }; public GetAllClaimSetsQuery(ISecurityContext securityContext, IOptions options) { diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAuthStrategiesQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAuthStrategiesQuery.cs index e1ae0ebfc..4d634a942 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAuthStrategiesQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAuthStrategiesQuery.cs @@ -26,9 +26,9 @@ public class GetAuthStrategiesQuery : IGetAuthStrategiesQuery private static readonly Dictionary>> _orderByColumnAuthorizationStrategies = new Dictionary>>(StringComparer.OrdinalIgnoreCase) { - { "name", x => x.AuthorizationStrategyName }, - { "displayName", x => x.DisplayName }, - { "id", x => x.AuthorizationStrategyId } + { SortingColumns.DefaultNameColumn, x => x.AuthorizationStrategyName }, + { SortingColumns.AuthorizationStrategyDisplayNameColumn, x => x.DisplayName }, + { SortingColumns.DefaultIdColumn, x => x.AuthorizationStrategyId } }; public GetAuthStrategiesQuery(ISecurityContext context, IOptions options) diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceContextsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceContextsQuery.cs index 71765d14e..bae55f923 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceContextsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceContextsQuery.cs @@ -29,9 +29,9 @@ public class GetOdsInstanceContextsQuery : IGetOdsInstanceContextsQuery new Dictionary>> (StringComparer.OrdinalIgnoreCase) { - { "contextKey", x => x.ContextKey }, - { "contextValue", x => x.ContextValue }, - { "id", x => x.OdsInstanceContextId } + { SortingColumns.OdsInstanceContextKeyColumn, x => x.ContextKey }, + { SortingColumns.OdsInstanceContextValueColumn, x => x.ContextValue }, + { SortingColumns.DefaultIdColumn, x => x.OdsInstanceContextId } }; public GetOdsInstanceContextsQuery(IUsersContext usersContext, IOptions options) { diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceDerivativesQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceDerivativesQuery.cs index 4e0c4af30..3d2b286db 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceDerivativesQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceDerivativesQuery.cs @@ -28,9 +28,9 @@ public class GetOdsInstanceDerivativesQuery : IGetOdsInstanceDerivativesQuery new Dictionary>> (StringComparer.OrdinalIgnoreCase) { - { "derivativeType", x => x.DerivativeType }, - { "odsInstanceId", x => x.OdsInstance.OdsInstanceId }, - { "id", x => x.OdsInstanceDerivativeId } + { SortingColumns.OdsInstanceDerivativeTypeColumn, x => x.DerivativeType }, + { SortingColumns.OdsInstanceDerivativeOdsInstanceIdColumn, x => x.OdsInstance.OdsInstanceId }, + { SortingColumns.DefaultIdColumn, x => x.OdsInstanceDerivativeId } }; public GetOdsInstanceDerivativesQuery(IUsersContext usersContext, IOptions options) diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs index 1025a60c3..f3e7244ce 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs @@ -28,9 +28,9 @@ public class GetOdsInstancesQuery : IGetOdsInstancesQuery new Dictionary>> (StringComparer.OrdinalIgnoreCase) { - { "name", x => x.Name }, - { "instanceType", x => x.InstanceType }, - { "id", x => x.OdsInstanceId } + { SortingColumns.DefaultNameColumn, x => x.Name }, + { SortingColumns.OdsInstanceInstanceTypeColumn, x => x.InstanceType }, + { SortingColumns.DefaultIdColumn, x => x.OdsInstanceId } }; public GetOdsInstancesQuery(IUsersContext userContext, IOptions options) diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetProfilesQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetProfilesQuery.cs index 7bd57723c..eb7358cd2 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetProfilesQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetProfilesQuery.cs @@ -27,8 +27,8 @@ public class GetProfilesQuery : IGetProfilesQuery new Dictionary>> (StringComparer.OrdinalIgnoreCase) { - { "name", x => x.ProfileName }, - { "id", x => x.ProfileId } + { SortingColumns.DefaultNameColumn, x => x.ProfileName }, + { SortingColumns.DefaultIdColumn, x => x.ProfileId } }; public GetProfilesQuery(IUsersContext usersContext, IOptions options) { diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetResourceClaimsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetResourceClaimsQuery.cs index b9b59c6ef..0d7325c13 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetResourceClaimsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetResourceClaimsQuery.cs @@ -27,12 +27,12 @@ public class GetResourceClaimsQuery : IGetResourceClaimsQuery new Dictionary>> (StringComparer.OrdinalIgnoreCase) { - { "name", x => x.ResourceName }, - { "parentName", x => x.ParentResourceClaim.ResourceName }, + { SortingColumns.DefaultNameColumn, x => x.ResourceName }, + { SortingColumns.ResourceClaimParentNameColumn, x => x.ParentResourceClaim.ResourceName }, #pragma warning disable CS8603 // Possible null reference return. - { "parentId", x => x.ParentResourceClaimId }, + { SortingColumns.ResourceClaimParentIdColumn, x => x.ParentResourceClaimId }, #pragma warning restore CS8603 // Possible null reference return. - { "id", x => x.ResourceClaimId } + { SortingColumns.DefaultIdColumn, x => x.ResourceClaimId } }; public GetResourceClaimsQuery(ISecurityContext securityContext, IOptions options) { diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs index 5d0867043..4f66033af 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs @@ -4,7 +4,6 @@ // See the LICENSE and NOTICES files in the project root for more information. using System.Linq.Expressions; -using System.Numerics; using EdFi.Admin.DataAccess.Contexts; using EdFi.Admin.DataAccess.Models; using EdFi.Ods.AdminApi.Helpers; @@ -30,15 +29,15 @@ public class GetVendorsQuery : IGetVendorsQuery new Dictionary>> (StringComparer.OrdinalIgnoreCase) { - { "company", x => x.VendorName }, + { SortingColumns.VendorCompanyColumn, x => x.VendorName }, #pragma warning disable CS8602 // Dereference of a possibly null reference. - { "contactName", x => x.Users.FirstOrDefault().FullName }, + { SortingColumns.VendorContactNameColumn, x => x.Users.FirstOrDefault().FullName }, #pragma warning restore CS8602 // Dereference of a possibly null reference. #pragma warning disable CS8602 // Dereference of a possibly null reference. - { "contactEmail", x => x.Users.FirstOrDefault().Email }, + { SortingColumns.VendorContactEmailColumn, x => x.Users.FirstOrDefault().Email }, #pragma warning restore CS8602 // Dereference of a possibly null reference. - { "namespacePrefixes", x => string.Join(",", x.VendorNamespacePrefixes.Select(p=> p.NamespacePrefix)) }, - { "id", x => x.VendorId } + { SortingColumns.VendorNamespacePrefixesColumn, x => string.Join(",", x.VendorNamespacePrefixes.Select(p=> p.NamespacePrefix)) }, + { SortingColumns.DefaultIdColumn, x => x.VendorId } }; public GetVendorsQuery(IUsersContext context, IOptions options) { diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/SortingConstants.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/SortingConstants.cs new file mode 100644 index 000000000..885a1d50d --- /dev/null +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/SortingConstants.cs @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: Apache-2.0 +// Licensed to the Ed-Fi Alliance under one or more agreements. +// The Ed-Fi Alliance licenses this file to you under the Apache License, Version 2.0. +// See the LICENSE and NOTICES files in the project root for more information. + +using EdFi.Ods.AdminApi.Features.Actions; +using EdFi.Ods.AdminApi.Features.Applications; +using EdFi.Ods.AdminApi.Features.AuthorizationStrategies; +using EdFi.Ods.AdminApi.Features.ClaimSets; +using EdFi.Ods.AdminApi.Features.OdsInstanceContext; +using EdFi.Ods.AdminApi.Features.OdsInstanceDerivative; +using EdFi.Ods.AdminApi.Features.ODSInstances; +using EdFi.Ods.AdminApi.Features.Vendors; + +namespace EdFi.Ods.AdminApi.Infrastructure; + +public static class SortingColumns +{ + /// Default columns to filter for each entity: + public const string DefaultNameColumn = "Name"; + public const string DefaultIdColumn = "Id"; + public const string ApplicationNameColumn = nameof(ApplicationModel.ApplicationName); + public const string ApplicationClaimSetNameColumn = nameof(ApplicationModel.ClaimSetName); + public const string ActionUriColumn = nameof(ActionModel.Uri); + public const string AuthorizationStrategyDisplayNameColumn = nameof(AuthorizationStrategyModel.DisplayName); + public const string OdsInstanceContextKeyColumn = nameof(OdsInstanceContextModel.ContextKey); + public const string OdsInstanceContextValueColumn = nameof(OdsInstanceContextModel.ContextValue); + public const string OdsInstanceDerivativeTypeColumn = nameof(OdsInstanceDerivativeModel.DerivativeType); + public const string OdsInstanceDerivativeOdsInstanceIdColumn = nameof(OdsInstanceDerivativeModel.OdsInstanceId); + public const string OdsInstanceInstanceTypeColumn = nameof(OdsInstanceModel.InstanceType); + public const string ResourceClaimParentNameColumn = nameof(ResourceClaimModel.ParentName); + public const string ResourceClaimParentIdColumn = nameof(ResourceClaimModel.ParentId); + public const string VendorCompanyColumn = nameof(VendorModel.Company); + public const string VendorContactNameColumn = nameof(VendorModel.ContactName); + public const string VendorContactEmailColumn = nameof(VendorModel.ContactEmailAddress); + public const string VendorNamespacePrefixesColumn = nameof(VendorModel.NamespacePrefixes); + + + + +} From dbe9862386a47fa22dbde12493d93a895d948e65 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Tue, 20 Aug 2024 15:44:40 -0500 Subject: [PATCH 07/35] Fix the orderby namespaceprefixes in vendors --- .../Infrastructure/Database/Queries/GetVendorsQuery.cs | 2 +- .../Infrastructure/Helpers/IEnumerableExtensions.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs index 4f66033af..4fadb5752 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs @@ -36,7 +36,7 @@ public class GetVendorsQuery : IGetVendorsQuery #pragma warning disable CS8602 // Dereference of a possibly null reference. { SortingColumns.VendorContactEmailColumn, x => x.Users.FirstOrDefault().Email }, #pragma warning restore CS8602 // Dereference of a possibly null reference. - { SortingColumns.VendorNamespacePrefixesColumn, x => string.Join(",", x.VendorNamespacePrefixes.Select(p=> p.NamespacePrefix)) }, + { SortingColumns.VendorNamespacePrefixesColumn, x => x.VendorNamespacePrefixes.OrderBy(p => p.NamespacePrefix).First().NamespacePrefix }, { SortingColumns.DefaultIdColumn, x => x.VendorId } }; public GetVendorsQuery(IUsersContext context, IOptions options) diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Helpers/IEnumerableExtensions.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Helpers/IEnumerableExtensions.cs index eaeead4b7..e2b320082 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Helpers/IEnumerableExtensions.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Helpers/IEnumerableExtensions.cs @@ -15,7 +15,7 @@ public static class IEnumerableExtensions public static string ToCommaSeparated(this IEnumerable vendorNamespacePrefixes) { return vendorNamespacePrefixes != null && vendorNamespacePrefixes.Any() - ? ToDelimiterSeparated(vendorNamespacePrefixes.Select(x => x.NamespacePrefix)) + ? ToDelimiterSeparated([.. vendorNamespacePrefixes.Select(x => x.NamespacePrefix).OrderBy(f => f)]) : string.Empty; } From c1b3dee3c3c85c8482726867e150cb105cf637de Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Wed, 21 Aug 2024 17:31:51 -0500 Subject: [PATCH 08/35] Replace from odsInstanceId to id in odsintances e2e --- ...ng - ODS Instances.postman_collection.json | 2235 +++++++++-------- 1 file changed, 1130 insertions(+), 1105 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json index 84b9007e7..b7f9271dd 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json @@ -1,1107 +1,1132 @@ { - "info": { - "_postman_id": "06cfccbc-ca75-4c23-9fc0-a358c43bcc19", - "name": "Admin API E2E 2.0 - Sorting and Filtering - ODS Instances", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "5260609" - }, - "item": [ - { - "name": "Get ODS Instances order by Default Asc", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var _ = require('lodash');\r", - "\r", - "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results.length).to.be.greaterThan(0); \r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result is ordered by Name asc\", function () {\r", - " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['asc']);\r", - " \r", - " pm.expect(results).to.eql(expectedSortedOrder);\r", - "});\r", - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&direction=ASC", - "host": [ - "{{API_URL}}" - ], - "path": [ - "v2", - "odsInstances" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "direction", - "value": "ASC" - } - ] - } - }, - "response": [] - }, - { - "name": "Get ODS Instances order by Default Desc", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var _ = require('lodash');\r", - "\r", - "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results.length).to.be.greaterThan(0); \r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result is ordered by Namne desc\", function () {\r", - " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", - " \r", - " pm.expect(results).to.eql(expectedSortedOrder);\r", - "});\r", - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&direction=desc", - "host": [ - "{{API_URL}}" - ], - "path": [ - "v2", - "odsInstances" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "direction", - "value": "desc" - } - ] - } - }, - "response": [] - }, - { - "name": "Get ODS Instances order by Id Asc", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var _ = require('lodash');\r", - "\r", - "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results.length).to.be.greaterThan(0); \r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result is ordered by Id asc\", function () {\r", - " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.id],['asc']);\r", - " \r", - " pm.expect(results).to.eql(expectedSortedOrder);\r", - "});\r", - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&orderBy=odsInstanceId&direction=ASC", - "host": [ - "{{API_URL}}" - ], - "path": [ - "v2", - "odsInstances" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "orderBy", - "value": "odsInstanceId" - }, - { - "key": "direction", - "value": "ASC" - } - ] - } - }, - "response": [] - }, - { - "name": "Get ODS Instances order by Id Desc", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var _ = require('lodash');\r", - "\r", - "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results.length).to.be.greaterThan(0); \r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result is ordered by Id desc\", function () {\r", - " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.id],['desc']);\r", - " \r", - " pm.expect(results).to.eql(expectedSortedOrder);\r", - "});\r", - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&orderBy=odsInstanceId&direction=desc", - "host": [ - "{{API_URL}}" - ], - "path": [ - "v2", - "odsInstances" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "orderBy", - "value": "odsInstanceId" - }, - { - "key": "direction", - "value": "desc" - } - ] - } - }, - "response": [] - }, - { - "name": "Get ODS Instances order by Name Asc", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var _ = require('lodash');\r", - "\r", - "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results.length).to.be.greaterThan(0); \r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result is ordered by Name asc\", function () {\r", - " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['asc']);\r", - " \r", - " pm.expect(results).to.eql(expectedSortedOrder);\r", - "});\r", - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&orderBy=name&direction=ASC", - "host": [ - "{{API_URL}}" - ], - "path": [ - "v2", - "odsInstances" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "orderBy", - "value": "name" - }, - { - "key": "direction", - "value": "ASC" - } - ] - } - }, - "response": [] - }, - { - "name": "Get ODS Instances order by Name Desc", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var _ = require('lodash');\r", - "\r", - "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results.length).to.be.greaterThan(0); \r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result is ordered by Name desc\", function () {\r", - " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", - " \r", - " pm.expect(results).to.eql(expectedSortedOrder);\r", - "});\r", - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&orderBy=Name&direction=desc", - "host": [ - "{{API_URL}}" - ], - "path": [ - "v2", - "odsInstances" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "orderBy", - "value": "Name" - }, - { - "key": "direction", - "value": "desc" - } - ] - } - }, - "response": [] - }, - { - "name": "Get ODS Instances order by InstanceType Asc", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var _ = require('lodash');\r", - "\r", - "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results.length).to.be.greaterThan(0); \r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result is ordered by InstanceType asc\", function () {\r", - " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType.toLowerCase()],['asc']);\r", - " \r", - " pm.expect(results).to.eql(expectedSortedOrder);\r", - "});\r", - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&orderBy=instanceType&direction=ASC", - "host": [ - "{{API_URL}}" - ], - "path": [ - "v2", - "odsInstances" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "orderBy", - "value": "instanceType" - }, - { - "key": "direction", - "value": "ASC" - } - ] - } - }, - "response": [] - }, - { - "name": "Get ODS Instances order by InstanceType Desc", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var _ = require('lodash');\r", - "\r", - "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results.length).to.be.greaterThan(0); \r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result is ordered by InstanceType desc\", function () {\r", - " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType.toLowerCase()],['desc']);\r", - " \r", - " pm.expect(results).to.eql(expectedSortedOrder);\r", - "});\r", - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&orderBy=instanceType&direction=desc", - "host": [ - "{{API_URL}}" - ], - "path": [ - "v2", - "odsInstances" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "orderBy", - "value": "instanceType" - }, - { - "key": "direction", - "value": "desc" - } - ] - } - }, - "response": [] - }, - { - "name": "Get ODS Instances filter by Name", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"GET Ods Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET Ods Instances: Response result includes Ods instance\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results).to.have.lengthOf(1);\r", - "});\r", - "\r", - "pm.test(\"GET Ods Instances: Response result contains requested Ods instance\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results[0].name).to.eql(pm.collectionVariables.get(\"FILTERNAME\"));\r", - "});\r", - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&name={{FILTERNAME}}", - "host": [ - "{{API_URL}}" - ], - "path": [ - "v2", - "odsInstances" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "name", - "value": "{{FILTERNAME}}" - } - ] - } - }, - "response": [] - }, - { - "name": "Get ODS Instances filter by InstanceType", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "pm.test(\"GET Ods Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET Ods Instances: Response result includes Ods Instance\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results).to.have.lengthOf(1);\r", - "});\r", - "\r", - "pm.test(\"GET Ods Instances: Response result contains requested Ods Instance\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results[0].instanceType).to.eql(pm.collectionVariables.get(\"FILTERINSTANCETYPE\"));\r", - "});\r", - "" - ], - "type": "text/javascript", - "packages": {} - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript", - "packages": {} - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - }, - "request": { - "method": "GET", - "header": [], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&instanceType={{FILTERINSTANCETYPE}}", - "host": [ - "{{API_URL}}" - ], - "path": [ - "v2", - "odsInstances" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "instanceType", - "value": "{{FILTERINSTANCETYPE}}" - } - ] - } - }, - "response": [] - } - ], - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "{{TOKEN}}", - "type": "string" - } - ] - }, - "event": [ - { - "listen": "prerequest", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "/// -------\r", - "/// Authentication\r", - "/// -------\r", - "\r", - "let header = {};\r", - "\r", - "function generateClientSecret() {\r", - " const minLength = 32;\r", - " const maxLength = 128;\r", - " let result = '';\r", - " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r", - " const specialCharacters = '!@#$%^&*()_+{}:\"<>?|[];\\',./`~';\r", - " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;\r", - "\r", - " result += randomChar('abcdefghijklmnopqrstuvwxyz');\r", - " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');\r", - " result += randomChar('0123456789');\r", - " result += randomChar(specialCharacters);\r", - "\r", - " for (let i = result.length; i < length; i++) {\r", - " const charactersPlusSpecial = characters + specialCharacters;\r", - " result += charactersPlusSpecial.charAt(Math.floor(Math.random() * charactersPlusSpecial.length));\r", - " }\r", - "\r", - " return shuffleString(result);\r", - "}\r", - "\r", - "function randomChar(str) {\r", - " return str.charAt(Math.floor(Math.random() * str.length));\r", - "}\r", - "\r", - "function shuffleString(str) {\r", - " const array = str.split('');\r", - " for (let i = array.length - 1; i > 0; i--) {\r", - " const j = Math.floor(Math.random() * (i + 1));\r", - " [array[i], array[j]] = [array[j], array[i]];\r", - " }\r", - " return array.join('');\r", - "}\r", - "\r", - "const RegisterAndGetToken = () => new Promise((resolve) => {\r", - " let guid = pm.variables.replaceIn('{{$guid}}');\r", - " let client_secret = generateClientSecret();\r", - "\r", - " let header = {\r", - " 'Content-Type': 'application/x-www-form-urlencoded'\r", - " };\r", - "\r", - " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", - " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", - " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", - " }\r", - "\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/connect/register`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'urlencoded',\r", - " urlencoded: [\r", - " {key: 'ClientId', value: guid },\r", - " {key: 'ClientSecret', value: client_secret },\r", - " {key: 'DisplayName', value: guid }\r", - " ]\r", - " }\r", - " },\r", - " (err, res) => {\r", - " error = res.json().error\r", - " if(error) {\r", - " throw res.json().error_description\r", - " }\r", - "\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/connect/token`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'urlencoded',\r", - " urlencoded: [\r", - " {key: 'client_id', value: guid },\r", - " {key: 'client_secret', value: client_secret },\r", - " {key: 'grant_type', value: \"client_credentials\"},\r", - " {key: 'scope', value: \"edfi_admin_api/full_access\"}\r", - " ]\r", - " }\r", - " },\r", - " (err, res) => {\r", - " error = res.json().error\r", - " if(error) {\r", - " throw res.json().error_description\r", - " }\r", - " pm.collectionVariables.set(\"TOKEN\", res.json().access_token);\r", - " resolve();\r", - " });\r", - " });\r", - "});\r", - "\r", - "/// -------\r", - "/// ODS Instances\r", - "/// -------\r", - "\r", - "function generateAlphanumericString() {\r", - " const minLength = 8;\r", - " const maxLength = 24;\r", - " let result = '';\r", - " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r", - " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;\r", - "\r", - " result += randomChar('abcdefghijklmnopqrstuvwxyz');\r", - " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');\r", - " result += randomChar('0123456789');\r", - "\r", - " for (let i = result.length; i < length; i++) {\r", - " result += characters.charAt(Math.floor(Math.random() * characters.length));\r", - " }\r", - "\r", - " return shuffleString(result);\r", - "}\r", - "\r", - "const createODSInstance = (name, instanceType) => new Promise((resolve) => {\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/v2/odsInstances`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'raw',\r", - " raw: JSON.stringify({ \"name\": `${name}`, \"instanceType\": `${instanceType}`, \"connectionString\": pm.variables.get(\"connectionString\") })\r", - " }\r", - " }, (err, res) => {\r", - " let location = res.headers.get('Location');\r", - " let matches = location.match(/(\\d+)/);\r", - " odsInstanceId = parseInt(matches[0], 10);\r", - " resolve(odsInstanceId);\r", - " });\r", - "});\r", - "\r", - "(async function () {\r", - " await RegisterAndGetToken();\r", - "\r", - " header = {\r", - " 'Content-Type': 'application/json',\r", - " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`\r", - " };\r", - "\r", - " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", - " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", - " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", - " }\r", - "\r", - " odsInstancesToDelete = [];\r", - " for (let i = 0; i < parseInt(pm.collectionVariables.get(\"ODSINSTANCECOUNT\"), 10); i++) {\r", - " let name = `TestOdsInstance${generateAlphanumericString()}`;\r", - " let instanceType = generateAlphanumericString();\r", - "\r", - " pm.collectionVariables.set(\"FILTERNAME\", name);\r", - " pm.collectionVariables.set(\"FILTERINSTANCETYPE\", instanceType);\r", - "\r", - " odsInstancesToDelete.push(await createODSInstance(name, instanceType).then(odsInstanceId => odsInstanceId));\r", - " }\r", - "\r", - " pm.collectionVariables.set(\"ODSINSTANCESTODELETE\", JSON.stringify(odsInstancesToDelete));\r", - "})();\r", - "" - ] - } - }, - { - "listen": "test", - "script": { - "type": "text/javascript", - "packages": {}, - "exec": [ - "header = {\r", - " 'Content-Type': 'application/json',\r", - " 'Accept': '*/*',\r", - " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`\r", - "};\r", - "\r", - "if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", - " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", - " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", - "}\r", - "\r", - "function deleteODSInstanceById(id) {\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/v2/odsInstances/${id}`,\r", - " method: 'DELETE',\r", - " header: header\r", - " }, function (err, res) {\r", - " if (err) {\r", - " console.log(err);\r", - " }\r", - " });\r", - "}\r", - "\r", - "function deleteODSInstances() {\r", - " let odsInstancesToDelete = JSON.parse(pm.variables.get(\"ODSINSTANCESTODELETE\"));\r", - " for (let i = 0; i < odsInstancesToDelete.length; i++) {\r", - " deleteODSInstanceById(odsInstancesToDelete[i]);\r", - " }\r", - "}\r", - "\r", - "deleteODSInstances();" - ] - } - } - ], - "variable": [ - { - "key": "TOKEN", - "value": "", - "type": "string" - }, - { - "key": "FILTERNAME", - "value": "", - "type": "string" - }, - { - "key": "FILTERINSTANCETYPE", - "value": "", - "type": "string" - }, - { - "key": "ODSINSTANCECOUNT", - "value": "4", - "type": "string" - }, - { - "key": "ODSINSTANCESTODELETE", - "value": "", - "type": "string" - } - ] + "_": { + "postman_id": "06cfccbc-ca75-4c23-9fc0-a358c43bcc19", + "exporter_id": "5260609" + }, + "item": [ + { + "id": "72bb60e8-7f83-4061-991f-8e006a330407", + "name": "Get ODS Instances order by Default Asc", + "request": { + "url": { + "path": [ + "v2", + "odsInstances" + ], + "host": [ + "{{API_URL}}" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "direction", + "value": "ASC" + } + ], + "variable": [] + }, + "method": "GET", + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "id": "3088ea09-b4ca-4b8c-a00c-71d335fa65c7", + "type": "text/javascript", + "packages": {}, + "exec": [ + "var _ = require('lodash');\r", + "\r", + "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results.length).to.be.greaterThan(0); \r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result is ordered by Name asc\", function () {\r", + " const results = pm.response.json();\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['asc']);\r", + " \r", + " pm.expect(results).to.eql(expectedSortedOrder);\r", + "});\r", + "" + ] + } + }, + { + "listen": "prerequest", + "script": { + "id": "dec3e5bd-f834-49f0-ac20-ebdd8b8fe839", + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "f11726b4-c77f-4cc2-80d1-459f86523636", + "name": "Get ODS Instances order by Default Desc", + "request": { + "url": { + "path": [ + "v2", + "odsInstances" + ], + "host": [ + "{{API_URL}}" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "direction", + "value": "desc" + } + ], + "variable": [] + }, + "method": "GET", + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "id": "995ebbc1-9862-48f3-8167-1be4b546515c", + "type": "text/javascript", + "packages": {}, + "exec": [ + "var _ = require('lodash');\r", + "\r", + "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results.length).to.be.greaterThan(0); \r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result is ordered by Namne desc\", function () {\r", + " const results = pm.response.json();\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", + " \r", + " pm.expect(results).to.eql(expectedSortedOrder);\r", + "});\r", + "" + ] + } + }, + { + "listen": "prerequest", + "script": { + "id": "779c9664-b8dc-4999-8364-5b982c839b8c", + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "e1d19eba-ccac-4d40-a3c4-9ebd3c3e6ca7", + "name": "Get ODS Instances order by Id Asc", + "request": { + "url": { + "path": [ + "v2", + "odsInstances" + ], + "host": [ + "{{API_URL}}" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "orderBy", + "value": "odsInstanceId" + }, + { + "key": "direction", + "value": "ASC" + } + ], + "variable": [] + }, + "method": "GET", + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "id": "a9152191-013c-4d2c-b005-93524be02047", + "type": "text/javascript", + "packages": {}, + "exec": [ + "var _ = require('lodash');\r", + "\r", + "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results.length).to.be.greaterThan(0); \r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result is ordered by Id asc\", function () {\r", + " const results = pm.response.json();\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.id],['asc']);\r", + " \r", + " pm.expect(results).to.eql(expectedSortedOrder);\r", + "});\r", + "" + ] + } + }, + { + "listen": "prerequest", + "script": { + "id": "3ffec75e-33d2-48f0-bb36-233d1d6e8966", + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "03342f89-0eba-457b-b657-f27f7b3f9a7c", + "name": "Get ODS Instances order by Id Desc", + "request": { + "url": { + "path": [ + "v2", + "odsInstances" + ], + "host": [ + "{{API_URL}}" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "orderBy", + "value": "odsInstanceId" + }, + { + "key": "direction", + "value": "desc" + } + ], + "variable": [] + }, + "method": "GET", + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "id": "e5704a9f-f1f6-4d60-b050-4a43a9d50bac", + "type": "text/javascript", + "packages": {}, + "exec": [ + "var _ = require('lodash');\r", + "\r", + "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results.length).to.be.greaterThan(0); \r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result is ordered by Id desc\", function () {\r", + " const results = pm.response.json();\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.id],['desc']);\r", + " \r", + " pm.expect(results).to.eql(expectedSortedOrder);\r", + "});\r", + "" + ] + } + }, + { + "listen": "prerequest", + "script": { + "id": "27dd9a02-b90c-4e60-bcfb-dcb7ef798661", + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "b7d7e327-55c5-463c-a27c-4b79e7bdb442", + "name": "Get ODS Instances order by Name Asc", + "request": { + "url": { + "path": [ + "v2", + "odsInstances" + ], + "host": [ + "{{API_URL}}" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "orderBy", + "value": "name" + }, + { + "key": "direction", + "value": "ASC" + } + ], + "variable": [] + }, + "method": "GET", + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "id": "9a904ae4-6c1d-41bb-ba76-516d3bf510e1", + "type": "text/javascript", + "packages": {}, + "exec": [ + "var _ = require('lodash');\r", + "\r", + "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results.length).to.be.greaterThan(0); \r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result is ordered by Name asc\", function () {\r", + " const results = pm.response.json();\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['asc']);\r", + " \r", + " pm.expect(results).to.eql(expectedSortedOrder);\r", + "});\r", + "" + ] + } + }, + { + "listen": "prerequest", + "script": { + "id": "69046ea4-796d-4798-b4a7-cd308f8c4e69", + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "cc30e600-abdb-4a4b-ba02-2d6bc9062e40", + "name": "Get ODS Instances order by Name Desc", + "request": { + "url": { + "path": [ + "v2", + "odsInstances" + ], + "host": [ + "{{API_URL}}" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "orderBy", + "value": "Name" + }, + { + "key": "direction", + "value": "desc" + } + ], + "variable": [] + }, + "method": "GET", + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "id": "fa2ddc76-5667-431b-a339-d074286a964d", + "type": "text/javascript", + "packages": {}, + "exec": [ + "var _ = require('lodash');\r", + "\r", + "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results.length).to.be.greaterThan(0); \r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result is ordered by Name desc\", function () {\r", + " const results = pm.response.json();\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", + " \r", + " pm.expect(results).to.eql(expectedSortedOrder);\r", + "});\r", + "" + ] + } + }, + { + "listen": "prerequest", + "script": { + "id": "76bb8ca0-2ac4-46eb-8a4a-ed11e972c432", + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "942a4f84-0369-458a-a105-ed319806ad88", + "name": "Get ODS Instances order by InstanceType Asc", + "request": { + "url": { + "path": [ + "v2", + "odsInstances" + ], + "host": [ + "{{API_URL}}" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "orderBy", + "value": "instanceType" + }, + { + "key": "direction", + "value": "ASC" + } + ], + "variable": [] + }, + "method": "GET", + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "id": "6dd9b8b5-ab0d-4024-8ee3-ace6d1bf7673", + "type": "text/javascript", + "packages": {}, + "exec": [ + "var _ = require('lodash');\r", + "\r", + "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results.length).to.be.greaterThan(0); \r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result is ordered by InstanceType asc\", function () {\r", + " const results = pm.response.json();\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType.toLowerCase()],['asc']);\r", + " \r", + " pm.expect(results).to.eql(expectedSortedOrder);\r", + "});\r", + "" + ] + } + }, + { + "listen": "prerequest", + "script": { + "id": "45e64f56-54d0-458f-b403-fa1e8ad8dd25", + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "5521d70a-cccf-4d5a-b2ae-30ade43c4572", + "name": "Get ODS Instances order by InstanceType Desc", + "request": { + "url": { + "path": [ + "v2", + "odsInstances" + ], + "host": [ + "{{API_URL}}" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "orderBy", + "value": "instanceType" + }, + { + "key": "direction", + "value": "desc" + } + ], + "variable": [] + }, + "method": "GET", + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "id": "e779263a-53cb-4b9e-a41e-fdb07f625e47", + "type": "text/javascript", + "packages": {}, + "exec": [ + "var _ = require('lodash');\r", + "\r", + "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results.length).to.be.greaterThan(0); \r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result is ordered by InstanceType desc\", function () {\r", + " const results = pm.response.json();\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType.toLowerCase()],['desc']);\r", + " \r", + " pm.expect(results).to.eql(expectedSortedOrder);\r", + "});\r", + "" + ] + } + }, + { + "listen": "prerequest", + "script": { + "id": "f9cbdfcc-88fb-469c-ad0e-2fc1954da1d9", + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "bb9ea0ee-ba7f-4da8-b668-d8101a4a9996", + "name": "Get ODS Instances filter by Name", + "request": { + "url": { + "path": [ + "v2", + "odsInstances" + ], + "host": [ + "{{API_URL}}" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "name", + "value": "{{FILTERNAME}}" + } + ], + "variable": [] + }, + "method": "GET", + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "id": "ccda89b9-197e-4ca7-9103-c2b7ccc15c39", + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"GET Ods Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET Ods Instances: Response result includes Ods instance\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results).to.have.lengthOf(1);\r", + "});\r", + "\r", + "pm.test(\"GET Ods Instances: Response result contains requested Ods instance\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results[0].name).to.eql(pm.collectionVariables.get(\"FILTERNAME\"));\r", + "});\r", + "" + ] + } + }, + { + "listen": "prerequest", + "script": { + "id": "c0ac9bad-126d-4cc7-bd83-58893569eaab", + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + }, + { + "id": "bcde38aa-65a7-4aca-a797-fd144f6d7885", + "name": "Get ODS Instances filter by InstanceType", + "request": { + "url": { + "path": [ + "v2", + "odsInstances" + ], + "host": [ + "{{API_URL}}" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "instanceType", + "value": "{{FILTERINSTANCETYPE}}" + } + ], + "variable": [] + }, + "method": "GET", + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + } + }, + "response": [], + "event": [ + { + "listen": "test", + "script": { + "id": "120cce70-1499-431f-9d89-b96f02929862", + "type": "text/javascript", + "packages": {}, + "exec": [ + "pm.test(\"GET Ods Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET Ods Instances: Response result includes Ods Instance\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results).to.have.lengthOf(1);\r", + "});\r", + "\r", + "pm.test(\"GET Ods Instances: Response result contains requested Ods Instance\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results[0].instanceType).to.eql(pm.collectionVariables.get(\"FILTERINSTANCETYPE\"));\r", + "});\r", + "" + ] + } + }, + { + "listen": "prerequest", + "script": { + "id": "5f842cbe-7bb0-4348-a8d9-59d68b1fcff1", + "type": "text/javascript", + "packages": {}, + "exec": [ + "" + ] + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + } + } + ], + "auth": { + "type": "bearer", + "bearer": [ + { + "type": "string", + "value": "{{TOKEN}}", + "key": "token" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "id": "3f416f72-e96e-4d51-8112-6cf2c10703ed", + "type": "text/javascript", + "packages": {}, + "exec": [ + "/// -------\r", + "/// Authentication\r", + "/// -------\r", + "\r", + "var header = {};\r", + "\r", + "function generateClientSecret() {\r", + " const minLength = 32;\r", + " const maxLength = 128;\r", + " let result = '';\r", + " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r", + " const specialCharacters = '!@#$%^&*()_+{}:\"<>?|[];\\',./`~';\r", + " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;\r", + "\r", + " result += randomChar('abcdefghijklmnopqrstuvwxyz');\r", + " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');\r", + " result += randomChar('0123456789');\r", + " result += randomChar(specialCharacters);\r", + "\r", + " for (let i = result.length; i < length; i++) {\r", + " const charactersPlusSpecial = characters + specialCharacters;\r", + " result += charactersPlusSpecial.charAt(Math.floor(Math.random() * charactersPlusSpecial.length));\r", + " }\r", + "\r", + " return shuffleString(result);\r", + "}\r", + "\r", + "function randomChar(str) {\r", + " return str.charAt(Math.floor(Math.random() * str.length));\r", + "}\r", + "\r", + "function shuffleString(str) {\r", + " const array = str.split('');\r", + " for (let i = array.length - 1; i > 0; i--) {\r", + " const j = Math.floor(Math.random() * (i + 1));\r", + " [array[i], array[j]] = [array[j], array[i]];\r", + " }\r", + " return array.join('');\r", + "}\r", + "\r", + "const RegisterAndGetToken = () => new Promise((resolve) => {\r", + " let guid = pm.variables.replaceIn('{{$guid}}');\r", + " let client_secret = generateClientSecret();\r", + "\r", + " let header = {\r", + " 'Content-Type': 'application/x-www-form-urlencoded'\r", + " };\r", + "\r", + " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", + " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", + " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", + " }\r", + "\r", + " pm.sendRequest({\r", + " url: `${pm.variables.get(\"API_URL\")}/connect/register`,\r", + " method: 'POST',\r", + " header: header,\r", + " body: {\r", + " mode: 'urlencoded',\r", + " urlencoded: [\r", + " {key: 'ClientId', value: guid },\r", + " {key: 'ClientSecret', value: client_secret },\r", + " {key: 'DisplayName', value: guid }\r", + " ]\r", + " }\r", + " },\r", + " (err, res) => {\r", + " error = res.json().error\r", + " if(error) {\r", + " throw res.json().error_description\r", + " }\r", + "\r", + " pm.sendRequest({\r", + " url: `${pm.variables.get(\"API_URL\")}/connect/token`,\r", + " method: 'POST',\r", + " header: header,\r", + " body: {\r", + " mode: 'urlencoded',\r", + " urlencoded: [\r", + " {key: 'client_id', value: guid },\r", + " {key: 'client_secret', value: client_secret },\r", + " {key: 'grant_type', value: \"client_credentials\"},\r", + " {key: 'scope', value: \"edfi_admin_api/full_access\"}\r", + " ]\r", + " }\r", + " },\r", + " (err, res) => {\r", + " error = res.json().error\r", + " if(error) {\r", + " throw res.json().error_description\r", + " }\r", + " pm.collectionVariables.set(\"TOKEN\", res.json().access_token);\r", + " resolve();\r", + " });\r", + " });\r", + "});\r", + "\r", + "/// -------\r", + "/// ODS Instances\r", + "/// -------\r", + "\r", + "function generateAlphanumericString() {\r", + " const minLength = 8;\r", + " const maxLength = 24;\r", + " let result = '';\r", + " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r", + " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;\r", + "\r", + " result += randomChar('abcdefghijklmnopqrstuvwxyz');\r", + " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');\r", + " result += randomChar('0123456789');\r", + "\r", + " for (let i = result.length; i < length; i++) {\r", + " result += characters.charAt(Math.floor(Math.random() * characters.length));\r", + " }\r", + "\r", + " return shuffleString(result);\r", + "}\r", + "\r", + "const createODSInstance = (name, instanceType) => new Promise((resolve) => {\r", + " pm.sendRequest({\r", + " url: `${pm.variables.get(\"API_URL\")}/v2/odsInstances`,\r", + " method: 'POST',\r", + " header: header,\r", + " body: {\r", + " mode: 'raw',\r", + " raw: JSON.stringify({ \"name\": `${name}`, \"instanceType\": `${instanceType}`, \"connectionString\": pm.variables.get(\"connectionString\") })\r", + " }\r", + " }, (err, res) => {\r", + " let location = res.headers.get('Location');\r", + " let matches = location.match(/(\\d+)/);\r", + " odsInstanceId = parseInt(matches[0], 10);\r", + " resolve(odsInstanceId);\r", + " });\r", + "});\r", + "\r", + "(async function () {\r", + " await RegisterAndGetToken();\r", + "\r", + " header = {\r", + " 'Content-Type': 'application/json',\r", + " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`\r", + " };\r", + "\r", + " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", + " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", + " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", + " }\r", + "\r", + " odsInstancesToDelete = [];\r", + " for (let i = 0; i < parseInt(pm.collectionVariables.get(\"ODSINSTANCECOUNT\"), 10); i++) {\r", + " let name = `TestOdsInstance${generateAlphanumericString()}`;\r", + " let instanceType = generateAlphanumericString();\r", + "\r", + " pm.collectionVariables.set(\"FILTERNAME\", name);\r", + " pm.collectionVariables.set(\"FILTERINSTANCETYPE\", instanceType);\r", + "\r", + " odsInstancesToDelete.push(await createODSInstance(name, instanceType).then(odsInstanceId => odsInstanceId));\r", + " }\r", + "\r", + " pm.collectionVariables.set(\"ODSINSTANCESTODELETE\", JSON.stringify(odsInstancesToDelete));\r", + "})();\r", + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "917541a7-acad-4f5b-affb-33a2368ad10f", + "type": "text/javascript", + "packages": {}, + "exec": [ + "header = {\r", + " 'Content-Type': 'application/json',\r", + " 'Accept': '*/*',\r", + " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`\r", + "};\r", + "\r", + "if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", + " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", + " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", + "}\r", + "\r", + "function deleteODSInstanceById(id) {\r", + " pm.sendRequest({\r", + " url: `${pm.variables.get(\"API_URL\")}/v2/odsInstances/${id}`,\r", + " method: 'DELETE',\r", + " header: header\r", + " }, function (err, res) {\r", + " if (err) {\r", + " console.log(err);\r", + " }\r", + " });\r", + "}\r", + "\r", + "function deleteODSInstances() {\r", + " let odsInstancesToDelete = JSON.parse(pm.variables.get(\"ODSINSTANCESTODELETE\"));\r", + " for (let i = 0; i < odsInstancesToDelete.length; i++) {\r", + " deleteODSInstanceById(odsInstancesToDelete[i]);\r", + " }\r", + "}\r", + "\r", + "deleteODSInstances();" + ] + } + } + ], + "variable": [ + { + "type": "string", + "value": "", + "key": "TOKEN" + }, + { + "type": "string", + "value": "", + "key": "FILTERNAME" + }, + { + "type": "string", + "value": "", + "key": "FILTERINSTANCETYPE" + }, + { + "type": "string", + "value": "4", + "key": "ODSINSTANCECOUNT" + }, + { + "type": "string", + "value": "", + "key": "ODSINSTANCESTODELETE" + } + ], + "info": { + "_postman_id": "06cfccbc-ca75-4c23-9fc0-a358c43bcc19", + "name": "Admin API E2E 2.0 - Sorting and Filtering - ODS Instances", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + } } \ No newline at end of file From bd4fd0b4071b478ba58672c3e08ef2658aaf63f6 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Wed, 21 Aug 2024 17:47:41 -0500 Subject: [PATCH 09/35] Add again the e2e file --- ...ng - ODS Instances.postman_collection.json | 2217 ++++++++--------- 1 file changed, 1087 insertions(+), 1130 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json index b7f9271dd..8a7d1f0d5 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json @@ -1,1132 +1,1089 @@ { - "_": { - "postman_id": "06cfccbc-ca75-4c23-9fc0-a358c43bcc19", - "exporter_id": "5260609" - }, - "item": [ - { - "id": "72bb60e8-7f83-4061-991f-8e006a330407", - "name": "Get ODS Instances order by Default Asc", - "request": { - "url": { - "path": [ - "v2", - "odsInstances" - ], - "host": [ - "{{API_URL}}" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "direction", - "value": "ASC" - } - ], - "variable": [] - }, - "method": "GET", - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - } - }, - "response": [], - "event": [ - { - "listen": "test", - "script": { - "id": "3088ea09-b4ca-4b8c-a00c-71d335fa65c7", - "type": "text/javascript", - "packages": {}, - "exec": [ - "var _ = require('lodash');\r", - "\r", - "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results.length).to.be.greaterThan(0); \r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result is ordered by Name asc\", function () {\r", - " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['asc']);\r", - " \r", - " pm.expect(results).to.eql(expectedSortedOrder);\r", - "});\r", - "" - ] - } - }, - { - "listen": "prerequest", - "script": { - "id": "dec3e5bd-f834-49f0-ac20-ebdd8b8fe839", - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - } - }, - { - "id": "f11726b4-c77f-4cc2-80d1-459f86523636", - "name": "Get ODS Instances order by Default Desc", - "request": { - "url": { - "path": [ - "v2", - "odsInstances" - ], - "host": [ - "{{API_URL}}" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "direction", - "value": "desc" - } - ], - "variable": [] - }, - "method": "GET", - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - } - }, - "response": [], - "event": [ - { - "listen": "test", - "script": { - "id": "995ebbc1-9862-48f3-8167-1be4b546515c", - "type": "text/javascript", - "packages": {}, - "exec": [ - "var _ = require('lodash');\r", - "\r", - "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results.length).to.be.greaterThan(0); \r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result is ordered by Namne desc\", function () {\r", - " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", - " \r", - " pm.expect(results).to.eql(expectedSortedOrder);\r", - "});\r", - "" - ] - } - }, - { - "listen": "prerequest", - "script": { - "id": "779c9664-b8dc-4999-8364-5b982c839b8c", - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - } - }, - { - "id": "e1d19eba-ccac-4d40-a3c4-9ebd3c3e6ca7", - "name": "Get ODS Instances order by Id Asc", - "request": { - "url": { - "path": [ - "v2", - "odsInstances" - ], - "host": [ - "{{API_URL}}" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "orderBy", - "value": "odsInstanceId" - }, - { - "key": "direction", - "value": "ASC" - } - ], - "variable": [] - }, - "method": "GET", - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - } - }, - "response": [], - "event": [ - { - "listen": "test", - "script": { - "id": "a9152191-013c-4d2c-b005-93524be02047", - "type": "text/javascript", - "packages": {}, - "exec": [ - "var _ = require('lodash');\r", - "\r", - "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results.length).to.be.greaterThan(0); \r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result is ordered by Id asc\", function () {\r", - " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.id],['asc']);\r", - " \r", - " pm.expect(results).to.eql(expectedSortedOrder);\r", - "});\r", - "" - ] - } - }, - { - "listen": "prerequest", - "script": { - "id": "3ffec75e-33d2-48f0-bb36-233d1d6e8966", - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - } - }, - { - "id": "03342f89-0eba-457b-b657-f27f7b3f9a7c", - "name": "Get ODS Instances order by Id Desc", - "request": { - "url": { - "path": [ - "v2", - "odsInstances" - ], - "host": [ - "{{API_URL}}" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "orderBy", - "value": "odsInstanceId" - }, - { - "key": "direction", - "value": "desc" - } - ], - "variable": [] - }, - "method": "GET", - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - } - }, - "response": [], - "event": [ - { - "listen": "test", - "script": { - "id": "e5704a9f-f1f6-4d60-b050-4a43a9d50bac", - "type": "text/javascript", - "packages": {}, - "exec": [ - "var _ = require('lodash');\r", - "\r", - "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results.length).to.be.greaterThan(0); \r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result is ordered by Id desc\", function () {\r", - " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.id],['desc']);\r", - " \r", - " pm.expect(results).to.eql(expectedSortedOrder);\r", - "});\r", - "" - ] - } - }, - { - "listen": "prerequest", - "script": { - "id": "27dd9a02-b90c-4e60-bcfb-dcb7ef798661", - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - } - }, - { - "id": "b7d7e327-55c5-463c-a27c-4b79e7bdb442", - "name": "Get ODS Instances order by Name Asc", - "request": { - "url": { - "path": [ - "v2", - "odsInstances" - ], - "host": [ - "{{API_URL}}" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "orderBy", - "value": "name" - }, - { - "key": "direction", - "value": "ASC" - } - ], - "variable": [] - }, - "method": "GET", - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - } - }, - "response": [], - "event": [ - { - "listen": "test", - "script": { - "id": "9a904ae4-6c1d-41bb-ba76-516d3bf510e1", - "type": "text/javascript", - "packages": {}, - "exec": [ - "var _ = require('lodash');\r", - "\r", - "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results.length).to.be.greaterThan(0); \r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result is ordered by Name asc\", function () {\r", - " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['asc']);\r", - " \r", - " pm.expect(results).to.eql(expectedSortedOrder);\r", - "});\r", - "" - ] - } - }, - { - "listen": "prerequest", - "script": { - "id": "69046ea4-796d-4798-b4a7-cd308f8c4e69", - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - } - }, - { - "id": "cc30e600-abdb-4a4b-ba02-2d6bc9062e40", - "name": "Get ODS Instances order by Name Desc", - "request": { - "url": { - "path": [ - "v2", - "odsInstances" - ], - "host": [ - "{{API_URL}}" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "orderBy", - "value": "Name" - }, - { - "key": "direction", - "value": "desc" - } - ], - "variable": [] - }, - "method": "GET", - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - } - }, - "response": [], - "event": [ - { - "listen": "test", - "script": { - "id": "fa2ddc76-5667-431b-a339-d074286a964d", - "type": "text/javascript", - "packages": {}, - "exec": [ - "var _ = require('lodash');\r", - "\r", - "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results.length).to.be.greaterThan(0); \r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result is ordered by Name desc\", function () {\r", - " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", - " \r", - " pm.expect(results).to.eql(expectedSortedOrder);\r", - "});\r", - "" - ] - } - }, - { - "listen": "prerequest", - "script": { - "id": "76bb8ca0-2ac4-46eb-8a4a-ed11e972c432", - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - } - }, - { - "id": "942a4f84-0369-458a-a105-ed319806ad88", - "name": "Get ODS Instances order by InstanceType Asc", - "request": { - "url": { - "path": [ - "v2", - "odsInstances" - ], - "host": [ - "{{API_URL}}" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "orderBy", - "value": "instanceType" - }, - { - "key": "direction", - "value": "ASC" - } - ], - "variable": [] - }, - "method": "GET", - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - } - }, - "response": [], - "event": [ - { - "listen": "test", - "script": { - "id": "6dd9b8b5-ab0d-4024-8ee3-ace6d1bf7673", - "type": "text/javascript", - "packages": {}, - "exec": [ - "var _ = require('lodash');\r", - "\r", - "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results.length).to.be.greaterThan(0); \r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result is ordered by InstanceType asc\", function () {\r", - " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType.toLowerCase()],['asc']);\r", - " \r", - " pm.expect(results).to.eql(expectedSortedOrder);\r", - "});\r", - "" - ] - } - }, - { - "listen": "prerequest", - "script": { - "id": "45e64f56-54d0-458f-b403-fa1e8ad8dd25", - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - } - }, - { - "id": "5521d70a-cccf-4d5a-b2ae-30ade43c4572", - "name": "Get ODS Instances order by InstanceType Desc", - "request": { - "url": { - "path": [ - "v2", - "odsInstances" - ], - "host": [ - "{{API_URL}}" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "orderBy", - "value": "instanceType" - }, - { - "key": "direction", - "value": "desc" - } - ], - "variable": [] - }, - "method": "GET", - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - } - }, - "response": [], - "event": [ - { - "listen": "test", - "script": { - "id": "e779263a-53cb-4b9e-a41e-fdb07f625e47", - "type": "text/javascript", - "packages": {}, - "exec": [ - "var _ = require('lodash');\r", - "\r", - "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results.length).to.be.greaterThan(0); \r", - "});\r", - "\r", - "pm.test(\"GET ODS Instances: Response result is ordered by InstanceType desc\", function () {\r", - " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType.toLowerCase()],['desc']);\r", - " \r", - " pm.expect(results).to.eql(expectedSortedOrder);\r", - "});\r", - "" - ] - } - }, - { - "listen": "prerequest", - "script": { - "id": "f9cbdfcc-88fb-469c-ad0e-2fc1954da1d9", - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - } - }, - { - "id": "bb9ea0ee-ba7f-4da8-b668-d8101a4a9996", - "name": "Get ODS Instances filter by Name", - "request": { - "url": { - "path": [ - "v2", - "odsInstances" - ], - "host": [ - "{{API_URL}}" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "name", - "value": "{{FILTERNAME}}" - } - ], - "variable": [] - }, - "method": "GET", - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - } - }, - "response": [], - "event": [ - { - "listen": "test", - "script": { - "id": "ccda89b9-197e-4ca7-9103-c2b7ccc15c39", - "type": "text/javascript", - "packages": {}, - "exec": [ - "pm.test(\"GET Ods Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET Ods Instances: Response result includes Ods instance\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results).to.have.lengthOf(1);\r", - "});\r", - "\r", - "pm.test(\"GET Ods Instances: Response result contains requested Ods instance\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results[0].name).to.eql(pm.collectionVariables.get(\"FILTERNAME\"));\r", - "});\r", - "" - ] - } - }, - { - "listen": "prerequest", - "script": { - "id": "c0ac9bad-126d-4cc7-bd83-58893569eaab", - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - } - }, - { - "id": "bcde38aa-65a7-4aca-a797-fd144f6d7885", - "name": "Get ODS Instances filter by InstanceType", - "request": { - "url": { - "path": [ - "v2", - "odsInstances" - ], - "host": [ - "{{API_URL}}" - ], - "query": [ - { - "key": "offset", - "value": "{{offset}}" - }, - { - "key": "limit", - "value": "{{limit}}" - }, - { - "key": "instanceType", - "value": "{{FILTERINSTANCETYPE}}" - } - ], - "variable": [] - }, - "method": "GET", - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - } - }, - "response": [], - "event": [ - { - "listen": "test", - "script": { - "id": "120cce70-1499-431f-9d89-b96f02929862", - "type": "text/javascript", - "packages": {}, - "exec": [ - "pm.test(\"GET Ods Instances: Status code is OK\", function () {\r", - " pm.response.to.have.status(200);\r", - "});\r", - "\r", - "pm.test(\"GET Ods Instances: Response result includes Ods Instance\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results).to.have.lengthOf(1);\r", - "});\r", - "\r", - "pm.test(\"GET Ods Instances: Response result contains requested Ods Instance\", function () {\r", - " const results = pm.response.json();\r", - " pm.expect(results[0].instanceType).to.eql(pm.collectionVariables.get(\"FILTERINSTANCETYPE\"));\r", - "});\r", - "" - ] - } - }, - { - "listen": "prerequest", - "script": { - "id": "5f842cbe-7bb0-4348-a8d9-59d68b1fcff1", - "type": "text/javascript", - "packages": {}, - "exec": [ - "" - ] - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true - } - } - ], - "auth": { - "type": "bearer", - "bearer": [ - { - "type": "string", - "value": "{{TOKEN}}", - "key": "token" - } - ] - }, - "event": [ - { - "listen": "prerequest", - "script": { - "id": "3f416f72-e96e-4d51-8112-6cf2c10703ed", - "type": "text/javascript", - "packages": {}, - "exec": [ - "/// -------\r", - "/// Authentication\r", - "/// -------\r", - "\r", - "var header = {};\r", - "\r", - "function generateClientSecret() {\r", - " const minLength = 32;\r", - " const maxLength = 128;\r", - " let result = '';\r", - " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r", - " const specialCharacters = '!@#$%^&*()_+{}:\"<>?|[];\\',./`~';\r", - " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;\r", - "\r", - " result += randomChar('abcdefghijklmnopqrstuvwxyz');\r", - " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');\r", - " result += randomChar('0123456789');\r", - " result += randomChar(specialCharacters);\r", - "\r", - " for (let i = result.length; i < length; i++) {\r", - " const charactersPlusSpecial = characters + specialCharacters;\r", - " result += charactersPlusSpecial.charAt(Math.floor(Math.random() * charactersPlusSpecial.length));\r", - " }\r", - "\r", - " return shuffleString(result);\r", - "}\r", - "\r", - "function randomChar(str) {\r", - " return str.charAt(Math.floor(Math.random() * str.length));\r", - "}\r", - "\r", - "function shuffleString(str) {\r", - " const array = str.split('');\r", - " for (let i = array.length - 1; i > 0; i--) {\r", - " const j = Math.floor(Math.random() * (i + 1));\r", - " [array[i], array[j]] = [array[j], array[i]];\r", - " }\r", - " return array.join('');\r", - "}\r", - "\r", - "const RegisterAndGetToken = () => new Promise((resolve) => {\r", - " let guid = pm.variables.replaceIn('{{$guid}}');\r", - " let client_secret = generateClientSecret();\r", - "\r", - " let header = {\r", - " 'Content-Type': 'application/x-www-form-urlencoded'\r", - " };\r", - "\r", - " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", - " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", - " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", - " }\r", - "\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/connect/register`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'urlencoded',\r", - " urlencoded: [\r", - " {key: 'ClientId', value: guid },\r", - " {key: 'ClientSecret', value: client_secret },\r", - " {key: 'DisplayName', value: guid }\r", - " ]\r", - " }\r", - " },\r", - " (err, res) => {\r", - " error = res.json().error\r", - " if(error) {\r", - " throw res.json().error_description\r", - " }\r", - "\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/connect/token`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'urlencoded',\r", - " urlencoded: [\r", - " {key: 'client_id', value: guid },\r", - " {key: 'client_secret', value: client_secret },\r", - " {key: 'grant_type', value: \"client_credentials\"},\r", - " {key: 'scope', value: \"edfi_admin_api/full_access\"}\r", - " ]\r", - " }\r", - " },\r", - " (err, res) => {\r", - " error = res.json().error\r", - " if(error) {\r", - " throw res.json().error_description\r", - " }\r", - " pm.collectionVariables.set(\"TOKEN\", res.json().access_token);\r", - " resolve();\r", - " });\r", - " });\r", - "});\r", - "\r", - "/// -------\r", - "/// ODS Instances\r", - "/// -------\r", - "\r", - "function generateAlphanumericString() {\r", - " const minLength = 8;\r", - " const maxLength = 24;\r", - " let result = '';\r", - " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r", - " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;\r", - "\r", - " result += randomChar('abcdefghijklmnopqrstuvwxyz');\r", - " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');\r", - " result += randomChar('0123456789');\r", - "\r", - " for (let i = result.length; i < length; i++) {\r", - " result += characters.charAt(Math.floor(Math.random() * characters.length));\r", - " }\r", - "\r", - " return shuffleString(result);\r", - "}\r", - "\r", - "const createODSInstance = (name, instanceType) => new Promise((resolve) => {\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/v2/odsInstances`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'raw',\r", - " raw: JSON.stringify({ \"name\": `${name}`, \"instanceType\": `${instanceType}`, \"connectionString\": pm.variables.get(\"connectionString\") })\r", - " }\r", - " }, (err, res) => {\r", - " let location = res.headers.get('Location');\r", - " let matches = location.match(/(\\d+)/);\r", - " odsInstanceId = parseInt(matches[0], 10);\r", - " resolve(odsInstanceId);\r", - " });\r", - "});\r", - "\r", - "(async function () {\r", - " await RegisterAndGetToken();\r", - "\r", - " header = {\r", - " 'Content-Type': 'application/json',\r", - " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`\r", - " };\r", - "\r", - " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", - " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", - " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", - " }\r", - "\r", - " odsInstancesToDelete = [];\r", - " for (let i = 0; i < parseInt(pm.collectionVariables.get(\"ODSINSTANCECOUNT\"), 10); i++) {\r", - " let name = `TestOdsInstance${generateAlphanumericString()}`;\r", - " let instanceType = generateAlphanumericString();\r", - "\r", - " pm.collectionVariables.set(\"FILTERNAME\", name);\r", - " pm.collectionVariables.set(\"FILTERINSTANCETYPE\", instanceType);\r", - "\r", - " odsInstancesToDelete.push(await createODSInstance(name, instanceType).then(odsInstanceId => odsInstanceId));\r", - " }\r", - "\r", - " pm.collectionVariables.set(\"ODSINSTANCESTODELETE\", JSON.stringify(odsInstancesToDelete));\r", - "})();\r", - "" - ] - } - }, - { - "listen": "test", - "script": { - "id": "917541a7-acad-4f5b-affb-33a2368ad10f", - "type": "text/javascript", - "packages": {}, - "exec": [ - "header = {\r", - " 'Content-Type': 'application/json',\r", - " 'Accept': '*/*',\r", - " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`\r", - "};\r", - "\r", - "if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", - " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", - " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", - "}\r", - "\r", - "function deleteODSInstanceById(id) {\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/v2/odsInstances/${id}`,\r", - " method: 'DELETE',\r", - " header: header\r", - " }, function (err, res) {\r", - " if (err) {\r", - " console.log(err);\r", - " }\r", - " });\r", - "}\r", - "\r", - "function deleteODSInstances() {\r", - " let odsInstancesToDelete = JSON.parse(pm.variables.get(\"ODSINSTANCESTODELETE\"));\r", - " for (let i = 0; i < odsInstancesToDelete.length; i++) {\r", - " deleteODSInstanceById(odsInstancesToDelete[i]);\r", - " }\r", - "}\r", - "\r", - "deleteODSInstances();" - ] - } - } - ], - "variable": [ - { - "type": "string", - "value": "", - "key": "TOKEN" - }, - { - "type": "string", - "value": "", - "key": "FILTERNAME" - }, - { - "type": "string", - "value": "", - "key": "FILTERINSTANCETYPE" - }, - { - "type": "string", - "value": "4", - "key": "ODSINSTANCECOUNT" - }, - { - "type": "string", - "value": "", - "key": "ODSINSTANCESTODELETE" - } - ], - "info": { - "_postman_id": "06cfccbc-ca75-4c23-9fc0-a358c43bcc19", - "name": "Admin API E2E 2.0 - Sorting and Filtering - ODS Instances", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" - } + "info": { + "_postman_id": "ee933872-22de-440c-ac3b-b79a8a7fc422", + "name": "Admin API E2E 2.0 - Sorting and Filtering - ODS Instances", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "Get ODS Instances order by Default Asc", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var _ = require('lodash');\r", + "\r", + "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results.length).to.be.greaterThan(0); \r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result is ordered by Name asc\", function () {\r", + " const results = pm.response.json();\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['asc']);\r", + " \r", + " pm.expect(results).to.eql(expectedSortedOrder);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&direction=ASC", + "host": [ + "{{API_URL}}" + ], + "path": [ + "v2", + "odsInstances" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "direction", + "value": "ASC" + } + ] + } + }, + "response": [] + }, + { + "name": "Get ODS Instances order by Default Desc", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var _ = require('lodash');\r", + "\r", + "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results.length).to.be.greaterThan(0); \r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result is ordered by Namne desc\", function () {\r", + " const results = pm.response.json();\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", + " \r", + " pm.expect(results).to.eql(expectedSortedOrder);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&direction=desc", + "host": [ + "{{API_URL}}" + ], + "path": [ + "v2", + "odsInstances" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "direction", + "value": "desc" + } + ] + } + }, + "response": [] + }, + { + "name": "Get ODS Instances order by Id Asc", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var _ = require('lodash');\r", + "\r", + "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results.length).to.be.greaterThan(0); \r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result is ordered by Id asc\", function () {\r", + " const results = pm.response.json();\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.id],['asc']);\r", + " \r", + " pm.expect(results).to.eql(expectedSortedOrder);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&orderBy=id&direction=ASC", + "host": [ + "{{API_URL}}" + ], + "path": [ + "v2", + "odsInstances" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "orderBy", + "value": "id" + }, + { + "key": "direction", + "value": "ASC" + } + ] + } + }, + "response": [] + }, + { + "name": "Get ODS Instances order by Id Desc", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var _ = require('lodash');\r", + "\r", + "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results.length).to.be.greaterThan(0); \r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result is ordered by Id desc\", function () {\r", + " const results = pm.response.json();\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.id],['desc']);\r", + " \r", + " pm.expect(results).to.eql(expectedSortedOrder);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&orderBy=id&direction=desc", + "host": [ + "{{API_URL}}" + ], + "path": [ + "v2", + "odsInstances" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "orderBy", + "value": "id" + }, + { + "key": "direction", + "value": "desc" + } + ] + } + }, + "response": [] + }, + { + "name": "Get ODS Instances order by Name Asc", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var _ = require('lodash');\r", + "\r", + "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results.length).to.be.greaterThan(0); \r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result is ordered by Name asc\", function () {\r", + " const results = pm.response.json();\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['asc']);\r", + " \r", + " pm.expect(results).to.eql(expectedSortedOrder);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&orderBy=name&direction=ASC", + "host": [ + "{{API_URL}}" + ], + "path": [ + "v2", + "odsInstances" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "orderBy", + "value": "name" + }, + { + "key": "direction", + "value": "ASC" + } + ] + } + }, + "response": [] + }, + { + "name": "Get ODS Instances order by Name Desc", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var _ = require('lodash');\r", + "\r", + "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results.length).to.be.greaterThan(0); \r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result is ordered by Name desc\", function () {\r", + " const results = pm.response.json();\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", + " \r", + " pm.expect(results).to.eql(expectedSortedOrder);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&orderBy=Name&direction=desc", + "host": [ + "{{API_URL}}" + ], + "path": [ + "v2", + "odsInstances" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "orderBy", + "value": "Name" + }, + { + "key": "direction", + "value": "desc" + } + ] + } + }, + "response": [] + }, + { + "name": "Get ODS Instances order by InstanceType Asc", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var _ = require('lodash');\r", + "\r", + "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results.length).to.be.greaterThan(0); \r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result is ordered by InstanceType asc\", function () {\r", + " const results = pm.response.json();\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType ? odsInstance.instanceType.toLowerCase() : null],['asc']);\r", + "\r", + " console.log(JSON.stringify(expectedSortedOrder));\r", + " console.log(JSON.stringify(results));\r", + " \r", + " pm.expect(results).to.eql(expectedSortedOrder);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&orderBy=instanceType&direction=ASC", + "host": [ + "{{API_URL}}" + ], + "path": [ + "v2", + "odsInstances" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "orderBy", + "value": "instanceType" + }, + { + "key": "direction", + "value": "ASC" + } + ] + } + }, + "response": [] + }, + { + "name": "Get ODS Instances order by InstanceType Desc", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "var _ = require('lodash');\r", + "\r", + "pm.test(\"GET ODS Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result includes ODS Instances\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results.length).to.be.greaterThan(0); \r", + "});\r", + "\r", + "pm.test(\"GET ODS Instances: Response result is ordered by InstanceType desc\", function () {\r", + " const results = pm.response.json();\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType ? odsInstance.instanceType.toLowerCase() : null],['desc']);\r", + " \r", + " pm.expect(results).to.eql(expectedSortedOrder);\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&orderBy=instanceType&direction=desc", + "host": [ + "{{API_URL}}" + ], + "path": [ + "v2", + "odsInstances" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "orderBy", + "value": "instanceType" + }, + { + "key": "direction", + "value": "desc" + } + ] + } + }, + "response": [] + }, + { + "name": "Get ODS Instances filter by Name", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"GET Ods Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET Ods Instances: Response result includes Ods instance\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results).to.have.lengthOf(1);\r", + "});\r", + "\r", + "pm.test(\"GET Ods Instances: Response result contains requested Ods instance\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results[0].name).to.eql(pm.collectionVariables.get(\"FILTERNAME\"));\r", + "});\r", + "" + ], + "type": "text/javascript", + "packages": {} + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript", + "packages": {} + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&name={{FILTERNAME}}", + "host": [ + "{{API_URL}}" + ], + "path": [ + "v2", + "odsInstances" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "name", + "value": "{{FILTERNAME}}" + } + ] + } + }, + "response": [] + }, + { + "name": "Get ODS Instances filter by InstanceType", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"GET Ods Instances: Status code is OK\", function () {\r", + " pm.response.to.have.status(200);\r", + "});\r", + "\r", + "pm.test(\"GET Ods Instances: Response result includes Ods Instance\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results).to.have.lengthOf(1);\r", + "});\r", + "\r", + "pm.test(\"GET Ods Instances: Response result contains requested Ods Instance\", function () {\r", + " const results = pm.response.json();\r", + " pm.expect(results[0].instanceType).to.eql(pm.collectionVariables.get(\"FILTERINSTANCETYPE\"));\r", + "});\r", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "protocolProfileBehavior": { + "disableBodyPruning": true + }, + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{API_URL}}/v2/odsInstances?offset={{offset}}&limit={{limit}}&instanceType={{FILTERINSTANCETYPE}}", + "host": [ + "{{API_URL}}" + ], + "path": [ + "v2", + "odsInstances" + ], + "query": [ + { + "key": "offset", + "value": "{{offset}}" + }, + { + "key": "limit", + "value": "{{limit}}" + }, + { + "key": "instanceType", + "value": "{{FILTERINSTANCETYPE}}" + } + ] + } + }, + "response": [] + } + ], + "auth": { + "type": "bearer", + "bearer": [ + { + "key": "token", + "value": "{{TOKEN}}", + "type": "string" + } + ] + }, + "event": [ + { + "listen": "prerequest", + "script": { + "type": "text/javascript", + "exec": [ + "/// -------", + "/// Authentication", + "/// -------", + "", + "var header = {};", + "", + "function generateClientSecret() {", + " const minLength = 32;", + " const maxLength = 128;", + " let result = '';", + " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';", + " const specialCharacters = '!@#$%^&*()_+{}:\"<>?|[];\\',./`~';", + " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;", + "", + " result += randomChar('abcdefghijklmnopqrstuvwxyz');", + " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');", + " result += randomChar('0123456789');", + " result += randomChar(specialCharacters);", + "", + " for (let i = result.length; i < length; i++) {", + " const charactersPlusSpecial = characters + specialCharacters;", + " result += charactersPlusSpecial.charAt(Math.floor(Math.random() * charactersPlusSpecial.length));", + " }", + "", + " return shuffleString(result);", + "}", + "", + "function randomChar(str) {", + " return str.charAt(Math.floor(Math.random() * str.length));", + "}", + "", + "function shuffleString(str) {", + " const array = str.split('');", + " for (let i = array.length - 1; i > 0; i--) {", + " const j = Math.floor(Math.random() * (i + 1));", + " [array[i], array[j]] = [array[j], array[i]];", + " }", + " return array.join('');", + "}", + "", + "const RegisterAndGetToken = () => new Promise((resolve) => {", + " let guid = pm.variables.replaceIn('{{$guid}}');", + " let client_secret = generateClientSecret();", + "", + " let header = {", + " 'Content-Type': 'application/x-www-form-urlencoded'", + " };", + "", + " if (pm.variables.get(\"isMultitenant\") == \"true\") {", + " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;", + " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });", + " }", + "", + " pm.sendRequest({", + " url: `${pm.variables.get(\"API_URL\")}/connect/register`,", + " method: 'POST',", + " header: header,", + " body: {", + " mode: 'urlencoded',", + " urlencoded: [", + " {key: 'ClientId', value: guid },", + " {key: 'ClientSecret', value: client_secret },", + " {key: 'DisplayName', value: guid }", + " ]", + " }", + " },", + " (err, res) => {", + " error = res.json().error", + " if(error) {", + " throw res.json().error_description", + " }", + "", + " pm.sendRequest({", + " url: `${pm.variables.get(\"API_URL\")}/connect/token`,", + " method: 'POST',", + " header: header,", + " body: {", + " mode: 'urlencoded',", + " urlencoded: [", + " {key: 'client_id', value: guid },", + " {key: 'client_secret', value: client_secret },", + " {key: 'grant_type', value: \"client_credentials\"},", + " {key: 'scope', value: \"edfi_admin_api/full_access\"}", + " ]", + " }", + " },", + " (err, res) => {", + " error = res.json().error", + " if(error) {", + " throw res.json().error_description", + " }", + " pm.collectionVariables.set(\"TOKEN\", res.json().access_token);", + " resolve();", + " });", + " });", + "});", + "", + "/// -------", + "/// ODS Instances", + "/// -------", + "", + "function generateAlphanumericString() {", + " const minLength = 8;", + " const maxLength = 24;", + " let result = '';", + " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';", + " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;", + "", + " result += randomChar('abcdefghijklmnopqrstuvwxyz');", + " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');", + " result += randomChar('0123456789');", + "", + " for (let i = result.length; i < length; i++) {", + " result += characters.charAt(Math.floor(Math.random() * characters.length));", + " }", + "", + " return shuffleString(result);", + "}", + "", + "const createODSInstance = (name, instanceType) => new Promise((resolve) => {", + " pm.sendRequest({", + " url: `${pm.variables.get(\"API_URL\")}/v2/odsInstances`,", + " method: 'POST',", + " header: header,", + " body: {", + " mode: 'raw',", + " raw: JSON.stringify({ \"name\": `${name}`, \"instanceType\": `${instanceType}`, \"connectionString\": pm.variables.get(\"connectionString\") })", + " }", + " }, (err, res) => {", + " let location = res.headers.get('Location');", + " let matches = location.match(/(\\d+)/);", + " odsInstanceId = parseInt(matches[0], 10);", + " resolve(odsInstanceId);", + " });", + "});", + "", + "(async function () {", + " await RegisterAndGetToken();", + "", + " header = {", + " 'Content-Type': 'application/json',", + " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`", + " };", + "", + " if (pm.variables.get(\"isMultitenant\") == \"true\") {", + " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;", + " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });", + " }", + "", + " odsInstancesToDelete = [];", + " for (let i = 0; i < parseInt(pm.collectionVariables.get(\"ODSINSTANCECOUNT\"), 10); i++) {", + " let name = `TestOdsInstance${generateAlphanumericString()}`;", + " let instanceType = generateAlphanumericString();", + "", + " pm.collectionVariables.set(\"FILTERNAME\", name);", + " pm.collectionVariables.set(\"FILTERINSTANCETYPE\", instanceType);", + "", + " odsInstancesToDelete.push(await createODSInstance(name, instanceType).then(odsInstanceId => odsInstanceId));", + " }", + "", + " pm.collectionVariables.set(\"ODSINSTANCESTODELETE\", JSON.stringify(odsInstancesToDelete));", + "})();", + "" + ] + } + }, + { + "listen": "test", + "script": { + "type": "text/javascript", + "exec": [ + "HEADER = {", + " 'CONTENT-TYPE': 'APPLICATION/JSON',", + " 'ACCEPT': '*/*',", + " 'AUTHORIZATION': `BEARER ${PM.COLLECTIONVARIABLES.GET(\"TOKEN\")}`", + "};", + "", + "IF (PM.VARIABLES.GET(\"ISMULTITENANT\") == \"TRUE\") {", + " HEADER['TENANT'] = `${PM.VARIABLES.GET(\"TENANT1\")}`;", + " PM.REQUEST.HEADERS.UPSERT({KEY: 'TENANT', VALUE: `${PM.VARIABLES.GET(\"TENANT1\")}` });", + "}", + "", + "FUNCTION DELETEODSINSTANCEBYID(ID) {", + " PM.SENDREQUEST({", + " URL: `${PM.VARIABLES.GET(\"API_URL\")}/V2/ODSINSTANCES/${ID}`,", + " METHOD: 'DELETE',", + " HEADER: HEADER", + " }, FUNCTION (ERR, RES) {", + " IF (ERR) {", + " CONSOLE.LOG(\"ERROR DELETING: \" + ERR);", + " }", + " });", + "}", + "", + "FUNCTION DELETEODSINSTANCES() {", + " LET ODSINSTANCESTODELETE = JSON.PARSE(PM.VARIABLES.GET(\"ODSINSTANCESTODELETE\"));", + " FOR (LET I = 0; I < ODSINSTANCESTODELETE.LENGTH; I++) {", + " DELETEODSINSTANCEBYID(ODSINSTANCESTODELETE[I]);", + " }", + "}", + "", + "DELETEODSINSTANCES();" + ] + } + } + ], + "variable": [ + { + "key": "TOKEN", + "value": "", + "type": "string" + }, + { + "key": "FILTERNAME", + "value": "", + "type": "string" + }, + { + "key": "FILTERINSTANCETYPE", + "value": "", + "type": "string" + }, + { + "key": "ODSINSTANCECOUNT", + "value": "4", + "type": "string" + }, + { + "key": "ODSINSTANCESTODELETE", + "value": "", + "type": "string" + } + ] } \ No newline at end of file From a77f35318fbade9d775fbeeeb9bc198bab2f24e1 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Wed, 21 Aug 2024 17:55:07 -0500 Subject: [PATCH 10/35] Fix syntax in js for odsintance e2e --- ...ng - ODS Instances.postman_collection.json | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json index 8a7d1f0d5..c9f6bd0b9 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json @@ -1024,37 +1024,37 @@ "script": { "type": "text/javascript", "exec": [ - "HEADER = {", - " 'CONTENT-TYPE': 'APPLICATION/JSON',", - " 'ACCEPT': '*/*',", - " 'AUTHORIZATION': `BEARER ${PM.COLLECTIONVARIABLES.GET(\"TOKEN\")}`", + "header = {", + " 'Content-Type': 'application/json',", + " 'Accept': '*/*',", + " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`", "};", "", - "IF (PM.VARIABLES.GET(\"ISMULTITENANT\") == \"TRUE\") {", - " HEADER['TENANT'] = `${PM.VARIABLES.GET(\"TENANT1\")}`;", - " PM.REQUEST.HEADERS.UPSERT({KEY: 'TENANT', VALUE: `${PM.VARIABLES.GET(\"TENANT1\")}` });", + "if (pm.variables.get(\"isMultitenant\") == \"true\") {", + " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;", + " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });", "}", "", - "FUNCTION DELETEODSINSTANCEBYID(ID) {", - " PM.SENDREQUEST({", - " URL: `${PM.VARIABLES.GET(\"API_URL\")}/V2/ODSINSTANCES/${ID}`,", - " METHOD: 'DELETE',", - " HEADER: HEADER", - " }, FUNCTION (ERR, RES) {", - " IF (ERR) {", - " CONSOLE.LOG(\"ERROR DELETING: \" + ERR);", + "function deleteODSInstanceById(id) {", + " pm.sendRequest({", + " url: `${pm.variables.get(\"API_URL\")}/v2/odsInstances/${id}`,", + " method: 'DELETE',", + " header: header", + " }, function (err, res) {", + " if (err) {", + " console.log(\"Error deleting: \" + err);", " }", " });", "}", "", - "FUNCTION DELETEODSINSTANCES() {", - " LET ODSINSTANCESTODELETE = JSON.PARSE(PM.VARIABLES.GET(\"ODSINSTANCESTODELETE\"));", - " FOR (LET I = 0; I < ODSINSTANCESTODELETE.LENGTH; I++) {", - " DELETEODSINSTANCEBYID(ODSINSTANCESTODELETE[I]);", + "function deleteODSInstances() {", + " let odsInstancesToDelete = JSON.parse(pm.variables.get(\"ODSINSTANCESTODELETE\"));", + " for (let i = 0; i < odsInstancesToDelete.length; i++) {", + " deleteODSInstanceById(odsInstancesToDelete[i]);", " }", "}", "", - "DELETEODSINSTANCES();" + "deleteODSInstances();" ] } } From a8a691382fe1e0088d3bcb8456ba576f25c8d437 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Wed, 21 Aug 2024 18:22:39 -0500 Subject: [PATCH 11/35] Add console.log to trace js errors --- ...tering - ODS Instances.postman_collection.json | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json index c9f6bd0b9..0fad1dad5 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json @@ -108,6 +108,11 @@ " const results = pm.response.json();\r", " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", " \r", + " console.log(\"JSON.stringify(results)\")\r", + " console.log(JSON.stringify(results))\r", + " console.log(\"JSON.stringify(expectedSortedOrder)\")\r", + " console.log(JSON.stringify(expectedSortedOrder))\r", + "\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -359,6 +364,11 @@ " const results = pm.response.json();\r", " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['asc']);\r", " \r", + " console.log(\"JSON.stringify(results)\")\r", + " console.log(JSON.stringify(results))\r", + " console.log(\"JSON.stringify(expectedSortedOrder)\")\r", + " console.log(JSON.stringify(expectedSortedOrder))\r", + "\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -444,6 +454,11 @@ " const results = pm.response.json();\r", " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", " \r", + " console.log(\"JSON.stringify(results)\")\r", + " console.log(JSON.stringify(results))\r", + " console.log(\"JSON.stringify(expectedSortedOrder)\")\r", + " console.log(JSON.stringify(expectedSortedOrder))\r", + "\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" From c9cc98b9dce2a0ebbb283417e4839b8f1499fa15 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Wed, 21 Aug 2024 22:21:51 -0500 Subject: [PATCH 12/35] Fix ODS Instance e2e --- ...ng - ODS Instances.postman_collection.json | 188 ++++++++++-------- 1 file changed, 101 insertions(+), 87 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json index 0fad1dad5..2e44120e2 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json @@ -872,8 +872,6 @@ "/// Authentication", "/// -------", "", - "var header = {};", - "", "function generateClientSecret() {", " const minLength = 32;", " const maxLength = 128;", @@ -908,67 +906,6 @@ " return array.join('');", "}", "", - "const RegisterAndGetToken = () => new Promise((resolve) => {", - " let guid = pm.variables.replaceIn('{{$guid}}');", - " let client_secret = generateClientSecret();", - "", - " let header = {", - " 'Content-Type': 'application/x-www-form-urlencoded'", - " };", - "", - " if (pm.variables.get(\"isMultitenant\") == \"true\") {", - " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;", - " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });", - " }", - "", - " pm.sendRequest({", - " url: `${pm.variables.get(\"API_URL\")}/connect/register`,", - " method: 'POST',", - " header: header,", - " body: {", - " mode: 'urlencoded',", - " urlencoded: [", - " {key: 'ClientId', value: guid },", - " {key: 'ClientSecret', value: client_secret },", - " {key: 'DisplayName', value: guid }", - " ]", - " }", - " },", - " (err, res) => {", - " error = res.json().error", - " if(error) {", - " throw res.json().error_description", - " }", - "", - " pm.sendRequest({", - " url: `${pm.variables.get(\"API_URL\")}/connect/token`,", - " method: 'POST',", - " header: header,", - " body: {", - " mode: 'urlencoded',", - " urlencoded: [", - " {key: 'client_id', value: guid },", - " {key: 'client_secret', value: client_secret },", - " {key: 'grant_type', value: \"client_credentials\"},", - " {key: 'scope', value: \"edfi_admin_api/full_access\"}", - " ]", - " }", - " },", - " (err, res) => {", - " error = res.json().error", - " if(error) {", - " throw res.json().error_description", - " }", - " pm.collectionVariables.set(\"TOKEN\", res.json().access_token);", - " resolve();", - " });", - " });", - "});", - "", - "/// -------", - "/// ODS Instances", - "/// -------", - "", "function generateAlphanumericString() {", " const minLength = 8;", " const maxLength = 24;", @@ -987,6 +924,9 @@ " return shuffleString(result);", "}", "", + "/// -------", + "/// ODS Instances", + "/// -------", "const createODSInstance = (name, instanceType) => new Promise((resolve) => {", " pm.sendRequest({", " url: `${pm.variables.get(\"API_URL\")}/v2/odsInstances`,", @@ -999,37 +939,103 @@ " }, (err, res) => {", " let location = res.headers.get('Location');", " let matches = location.match(/(\\d+)/);", - " odsInstanceId = parseInt(matches[0], 10);", + " let odsInstanceId = parseInt(matches[0], 10);", " resolve(odsInstanceId);", " });", "});", "", - "(async function () {", - " await RegisterAndGetToken();", + "var guid = pm.variables.replaceIn('{{$guid}}');", + "var client_secret = generateClientSecret();", + "var header = {", + " 'Content-Type': 'application/x-www-form-urlencoded'", + "};", "", - " header = {", - " 'Content-Type': 'application/json',", - " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`", - " };", + "const registerRequest = {", + " url: `${pm.variables.get(\"API_URL\")}/connect/register`,", + " method: 'POST',", + " header: header,", + " body: {", + " mode: 'urlencoded',", + " urlencoded: [", + " {key: 'ClientId', value: guid },", + " {key: 'ClientSecret', value: client_secret },", + " {key: 'DisplayName', value: guid }", + " ]", + " }", + "}", "", - " if (pm.variables.get(\"isMultitenant\") == \"true\") {", - " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;", - " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });", + "const tokenRequest = {", + " url: `${pm.variables.get(\"API_URL\")}/connect/token`,", + " method: 'POST',", + " header: header,", + " body: {", + " mode: 'urlencoded',", + " urlencoded: [", + " {key: 'client_id', value: guid },", + " {key: 'client_secret', value: client_secret },", + " {key: 'grant_type', value: \"client_credentials\"},", + " {key: 'scope', value: \"edfi_admin_api/full_access\"}", + " ]", " }", + "}", "", - " odsInstancesToDelete = [];", - " for (let i = 0; i < parseInt(pm.collectionVariables.get(\"ODSINSTANCECOUNT\"), 10); i++) {", - " let name = `TestOdsInstance${generateAlphanumericString()}`;", - " let instanceType = generateAlphanumericString();", + "if (pm.variables.get(\"isMultitenant\") == \"true\") {", + " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;", + " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });", + "}", "", - " pm.collectionVariables.set(\"FILTERNAME\", name);", - " pm.collectionVariables.set(\"FILTERINSTANCETYPE\", instanceType);", + "pm.sendRequest(registerRequest,", + " (err, res) => {", + " let error = res.json().error", + " if(error) {", + " throw res.json().error_description", + " }", "", - " odsInstancesToDelete.push(await createODSInstance(name, instanceType).then(odsInstanceId => odsInstanceId));", - " }", + " pm.sendRequest(tokenRequest,", + " (err, res) => {", + " let error = res.json().error", + " if(error) {", + " throw res.json().error_description", + " }", + " pm.collectionVariables.set(\"TOKEN\", res.json().access_token)", + "", + " header = {", + " 'Content-Type': 'application/json',", + " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`", + " };", + " ", + " if (pm.variables.get(\"isMultitenant\") == \"true\") {", + " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;", + " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });", + " }", + " let totalToCreate = parseInt(pm.collectionVariables.get(\"ODSINSTANCECOUNT\"), 10);", + " let odsInstancesToDelete = [];", + " for (let i = 0; i < totalToCreate; i++) {", + " let name = `TestOdsInstance${generateAlphanumericString()}`;", + " let instanceType = generateAlphanumericString();", + " ", + " pm.collectionVariables.set(\"FILTERNAME\", name);", + " pm.collectionVariables.set(\"FILTERINSTANCETYPE\", instanceType);", + " ", + " pm.sendRequest({", + " url: `${pm.variables.get(\"API_URL\")}/v2/odsInstances`,", + " method: 'POST',", + " header: header,", + " body: {", + " mode: 'raw',", + " raw: JSON.stringify({ \"name\": `${name}`, \"instanceType\": `${instanceType}`, \"connectionString\": pm.variables.get(\"connectionString\") })", + " }", + " }, (err, res) => {", + " let location = res.headers.get('Location');", + " let matches = location.match(/(\\d+)/);", + " let odsInstanceId = parseInt(matches[0], 10);", + " odsInstancesToDelete.push(odsInstanceId);", + " });", + " }", + " pm.collectionVariables.set(\"ODSINSTANCESTODELETE\", JSON.stringify(odsInstancesToDelete));", + " });", + "});", "", - " pm.collectionVariables.set(\"ODSINSTANCESTODELETE\", JSON.stringify(odsInstancesToDelete));", - "})();", "" ] } @@ -1044,11 +1050,13 @@ " 'Accept': '*/*',", " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`", "};", + "console.log(\"Test deleting odss\");", "", "if (pm.variables.get(\"isMultitenant\") == \"true\") {", " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;", " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });", "}", + "console.log(\"Test deleting odss isMultitenant\");", "", "function deleteODSInstanceById(id) {", " pm.sendRequest({", @@ -1063,9 +1071,15 @@ "}", "", "function deleteODSInstances() {", - " let odsInstancesToDelete = JSON.parse(pm.variables.get(\"ODSINSTANCESTODELETE\"));", - " for (let i = 0; i < odsInstancesToDelete.length; i++) {", - " deleteODSInstanceById(odsInstancesToDelete[i]);", + " console.log(\"Test deleting odss trying parsing data variable\");", + " if (!pm.variables.get(\"ODSINSTANCESTODELETE\"))", + " {", + " let odsInstancesToDelete = JSON.parse(pm.variables.get(\"ODSINSTANCESTODELETE\"));", + " console.log(\"Test deleting odss parsed data variable\");", + "", + " for (let i = 0; i < odsInstancesToDelete.length; i++) {", + " deleteODSInstanceById(odsInstancesToDelete[i]);", + " }", " }", "}", "", @@ -1092,7 +1106,7 @@ }, { "key": "ODSINSTANCECOUNT", - "value": "4", + "value": "5", "type": "string" }, { From 5c27fbd9321421aca255f254afdd1df9284b9ba2 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Thu, 22 Aug 2024 22:34:07 -0500 Subject: [PATCH 13/35] Add the collate to the orderby in odsinstance --- .../Infrastructure/Database/Queries/GetOdsInstancesQuery.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs index f3e7244ce..c7e4fa5a7 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs @@ -9,6 +9,7 @@ using EdFi.Ods.AdminApi.Helpers; using EdFi.Ods.AdminApi.Infrastructure.Extensions; using EdFi.Ods.AdminApi.Infrastructure.Helpers; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; namespace EdFi.Ods.AdminApi.Infrastructure.Database.Queries; @@ -28,7 +29,7 @@ public class GetOdsInstancesQuery : IGetOdsInstancesQuery new Dictionary>> (StringComparer.OrdinalIgnoreCase) { - { SortingColumns.DefaultNameColumn, x => x.Name }, + { SortingColumns.DefaultNameColumn, x => EF.Functions.Collate(x.Name, "SQL_Latin1_General_CP1_CS_AS") }, { SortingColumns.OdsInstanceInstanceTypeColumn, x => x.InstanceType }, { SortingColumns.DefaultIdColumn, x => x.OdsInstanceId } }; From 3163d91685fe6ec88391eb01b2ccfa87cf3898a0 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Thu, 22 Aug 2024 23:41:43 -0500 Subject: [PATCH 14/35] Add a different mechanism to sort data in js --- ...ng - ODS Instances.postman_collection.json | 91 +++++++++++++------ .../Database/Queries/GetOdsInstancesQuery.cs | 2 +- 2 files changed, 66 insertions(+), 27 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json index 2e44120e2..58f09da9a 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json @@ -25,7 +25,22 @@ "\r", "pm.test(\"GET ODS Instances: Response result is ordered by Name asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['asc']);\r", + " var expectedSortedOrder = results.sort(function(a, b) {\r", + " var a1st = -1; // negative value means left item should appear first\r", + " var b1st = 1; // positive value means right item should appear first\r", + " var equal = 0; // zero means objects are equal\r", + "\r", + " // compare your object's property values and determine their order\r", + " if (b.name < a.name) {\r", + " return b1st;\r", + " }\r", + " else if (a.name < b.name) {\r", + " return a1st;\r", + " }\r", + " else {\r", + " return equal;\r", + " }\r", + " });\r", " \r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", @@ -106,12 +121,23 @@ "\r", "pm.test(\"GET ODS Instances: Response result is ordered by Namne desc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", - " \r", - " console.log(\"JSON.stringify(results)\")\r", - " console.log(JSON.stringify(results))\r", - " console.log(\"JSON.stringify(expectedSortedOrder)\")\r", - " console.log(JSON.stringify(expectedSortedOrder))\r", + " var expectedSortedOrder = results.sort(function(a, b) {\r", + " var a1st = -1; // negative value means left item should appear first\r", + " var b1st = 1; // positive value means right item should appear first\r", + " var equal = 0; // zero means objects are equal\r", + "\r", + " // compare your object's property values and determine their order\r", + " if (b.name < a.name) {\r", + " return b1st;\r", + " }\r", + " else if (a.name < b.name) {\r", + " return a1st;\r", + " }\r", + " else {\r", + " return equal;\r", + " }\r", + " }).reverse();\r", + " //_.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", "\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", @@ -362,12 +388,22 @@ "\r", "pm.test(\"GET ODS Instances: Response result is ordered by Name asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['asc']);\r", - " \r", - " console.log(\"JSON.stringify(results)\")\r", - " console.log(JSON.stringify(results))\r", - " console.log(\"JSON.stringify(expectedSortedOrder)\")\r", - " console.log(JSON.stringify(expectedSortedOrder))\r", + " var expectedSortedOrder = results.sort(function(a, b) {\r", + " var a1st = -1; // negative value means left item should appear first\r", + " var b1st = 1; // positive value means right item should appear first\r", + " var equal = 0; // zero means objects are equal\r", + "\r", + " // compare your object's property values and determine their order\r", + " if (b.name < a.name) {\r", + " return b1st;\r", + " }\r", + " else if (a.name < b.name) {\r", + " return a1st;\r", + " }\r", + " else {\r", + " return equal;\r", + " }\r", + " });\r", "\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", @@ -452,12 +488,22 @@ "\r", "pm.test(\"GET ODS Instances: Response result is ordered by Name desc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", - " \r", - " console.log(\"JSON.stringify(results)\")\r", - " console.log(JSON.stringify(results))\r", - " console.log(\"JSON.stringify(expectedSortedOrder)\")\r", - " console.log(JSON.stringify(expectedSortedOrder))\r", + " var expectedSortedOrder = results.sort(function(a, b) {\r", + " var a1st = -1; // negative value means left item should appear first\r", + " var b1st = 1; // positive value means right item should appear first\r", + " var equal = 0; // zero means objects are equal\r", + "\r", + " // compare your object's property values and determine their order\r", + " if (b.name < a.name) {\r", + " return b1st;\r", + " }\r", + " else if (a.name < b.name) {\r", + " return a1st;\r", + " }\r", + " else {\r", + " return equal;\r", + " }\r", + " }).reverse();\r", "\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", @@ -543,9 +589,6 @@ "pm.test(\"GET ODS Instances: Response result is ordered by InstanceType asc\", function () {\r", " const results = pm.response.json();\r", " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType ? odsInstance.instanceType.toLowerCase() : null],['asc']);\r", - "\r", - " console.log(JSON.stringify(expectedSortedOrder));\r", - " console.log(JSON.stringify(results));\r", " \r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", @@ -1050,13 +1093,11 @@ " 'Accept': '*/*',", " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`", "};", - "console.log(\"Test deleting odss\");", "", "if (pm.variables.get(\"isMultitenant\") == \"true\") {", " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;", " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });", "}", - "console.log(\"Test deleting odss isMultitenant\");", "", "function deleteODSInstanceById(id) {", " pm.sendRequest({", @@ -1071,11 +1112,9 @@ "}", "", "function deleteODSInstances() {", - " console.log(\"Test deleting odss trying parsing data variable\");", " if (!pm.variables.get(\"ODSINSTANCESTODELETE\"))", " {", " let odsInstancesToDelete = JSON.parse(pm.variables.get(\"ODSINSTANCESTODELETE\"));", - " console.log(\"Test deleting odss parsed data variable\");", "", " for (let i = 0; i < odsInstancesToDelete.length; i++) {", " deleteODSInstanceById(odsInstancesToDelete[i]);", diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs index c7e4fa5a7..ccf16dc0f 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs @@ -29,7 +29,7 @@ public class GetOdsInstancesQuery : IGetOdsInstancesQuery new Dictionary>> (StringComparer.OrdinalIgnoreCase) { - { SortingColumns.DefaultNameColumn, x => EF.Functions.Collate(x.Name, "SQL_Latin1_General_CP1_CS_AS") }, + { SortingColumns.DefaultNameColumn, x => x.Name }, { SortingColumns.OdsInstanceInstanceTypeColumn, x => x.InstanceType }, { SortingColumns.DefaultIdColumn, x => x.OdsInstanceId } }; From 37c6f5dbbc96f8fe54bc691e64a5faeb1f9973ec Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Thu, 22 Aug 2024 23:50:42 -0500 Subject: [PATCH 15/35] Add the new mechanism to sort data in js but for a different column --- ...ng - ODS Instances.postman_collection.json | 38 +++++++++++++++++-- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json index 58f09da9a..bdd6683b9 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json @@ -588,8 +588,23 @@ "\r", "pm.test(\"GET ODS Instances: Response result is ordered by InstanceType asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType ? odsInstance.instanceType.toLowerCase() : null],['asc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType ? odsInstance.instanceType.toLowerCase() : null],['asc']);\r", + " var expectedSortedOrder = results.sort(function(a, b) {\r", + " var a1st = -1; // negative value means left item should appear first\r", + " var b1st = 1; // positive value means right item should appear first\r", + " var equal = 0; // zero means objects are equal\r", + "\r", + " // compare your object's property values and determine their order\r", + " if (b.instanceType < a.instanceType) {\r", + " return b1st;\r", + " }\r", + " else if (a.instanceType < b.instanceType) {\r", + " return a1st;\r", + " }\r", + " else {\r", + " return equal;\r", + " }\r", + " });\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -673,8 +688,23 @@ "\r", "pm.test(\"GET ODS Instances: Response result is ordered by InstanceType desc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType ? odsInstance.instanceType.toLowerCase() : null],['desc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType ? odsInstance.instanceType.toLowerCase() : null],['desc']);\r", + " var expectedSortedOrder = results.sort(function(a, b) {\r", + " var a1st = -1; // negative value means left item should appear first\r", + " var b1st = 1; // positive value means right item should appear first\r", + " var equal = 0; // zero means objects are equal\r", + "\r", + " // compare your object's property values and determine their order\r", + " if (b.instanceType < a.instanceType) {\r", + " return b1st;\r", + " }\r", + " else if (a.instanceType < b.instanceType) {\r", + " return a1st;\r", + " }\r", + " else {\r", + " return equal;\r", + " }\r", + " }).revese();\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" From 94078ab0f2cf60180e6841855a93c14143b0b5d8 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Thu, 22 Aug 2024 23:59:18 -0500 Subject: [PATCH 16/35] Fix typo --- ...rting and Filtering - ODS Instances.postman_collection.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json index bdd6683b9..35c4b9680 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json @@ -704,7 +704,7 @@ " else {\r", " return equal;\r", " }\r", - " }).revese();\r", + " }).reverse();\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -1102,6 +1102,7 @@ " let location = res.headers.get('Location');", " let matches = location.match(/(\\d+)/);", " let odsInstanceId = parseInt(matches[0], 10);", + " // odsInstancesToDelete.push({id: odsInstanceId, name: name, instanceType: instanceType});", " odsInstancesToDelete.push(odsInstanceId);", " });", " }", From f50a275811d37701e390f720c014444ba4f5e2b4 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Fri, 23 Aug 2024 14:49:28 -0500 Subject: [PATCH 17/35] Revert changes on odsintance e2e --- ...ng - ODS Instances.postman_collection.json | 46 +++++++++++++------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json index 35c4b9680..86126ee85 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json @@ -121,26 +121,42 @@ "\r", "pm.test(\"GET ODS Instances: Response result is ordered by Namne desc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = results.sort(function(a, b) {\r", - " var a1st = -1; // negative value means left item should appear first\r", - " var b1st = 1; // positive value means right item should appear first\r", - " var equal = 0; // zero means objects are equal\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", + " var other = sortByProperty(results, 'name', -1);\r", "\r", - " // compare your object's property values and determine their order\r", - " if (b.name < a.name) {\r", - " return b1st;\r", - " }\r", - " else if (a.name < b.name) {\r", - " return a1st;\r", - " }\r", - " else {\r", - " return equal;\r", - " }\r", - " }).reverse();\r", + " console.log(\"results\");\r", + " console.log(JSON.stringify(expectedSortedOrder));\r", + " console.log(\"other\");\r", + " console.log(JSON.stringify(other));\r", + " console.log(\"expected\");\r", + " console.log(JSON.stringify(results));\r", + " // sortByProperty(results, 'name', -1);\r", " //_.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", "\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", + "\r", + "function sortByProperty(objArray, prop, direction){\r", + " if (arguments.length<2) throw new Error(\"ARRAY, AND OBJECT PROPERTY MINIMUM ARGUMENTS, OPTIONAL DIRECTION\");\r", + " if (!Array.isArray(objArray)) throw new Error(\"FIRST ARGUMENT NOT AN ARRAY\");\r", + " const clone = objArray.slice(0);\r", + " const direct = arguments.length>2 ? arguments[2] : 1; //Default to ascending\r", + " const propPath = (prop.constructor===Array) ? prop : prop.split(\".\");\r", + " clone.sort(function(a,b){\r", + " for (let p in propPath){\r", + " if (a[propPath[p]] && b[propPath[p]]){\r", + " a = a[propPath[p]];\r", + " b = b[propPath[p]];\r", + " }\r", + " }\r", + " // convert numeric strings to integers\r", + " a = a.match(/^\\d+$/) ? +a : a;\r", + " b = b.match(/^\\d+$/) ? +b : b;\r", + " return ( (a < b) ? -1*direct : ((a > b) ? 1*direct : 0) );\r", + " });\r", + " return clone;\r", + "}\r", + "\r", "" ], "type": "text/javascript" From aa7cfc4b09198ebb7e08e04816144cc2a98ed195 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Fri, 23 Aug 2024 16:20:34 -0500 Subject: [PATCH 18/35] Add the collate function to the EF core in order to match with the js sorting --- ...ng - ODS Instances.postman_collection.json | 186 +++++++++++++++++- .../Database/Queries/GetOdsInstancesQuery.cs | 2 +- 2 files changed, 185 insertions(+), 3 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json index 86126ee85..5209e64ca 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json @@ -136,6 +136,17 @@ " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "\r", + "pm.test(\"GET ODS Instances: Response result is ordered by Namne desc - ALT\", function () {\r", + " const results = pm.response.json();\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", + " var other = sortByProperty(results, 'name', -1);\r", + "\r", + " // sortByProperty(results, 'name', -1);\r", + " //_.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", + "\r", + " pm.expect(results).to.eql(other);\r", + "});\r", + "\r", "function sortByProperty(objArray, prop, direction){\r", " if (arguments.length<2) throw new Error(\"ARRAY, AND OBJECT PROPERTY MINIMUM ARGUMENTS, OPTIONAL DIRECTION\");\r", " if (!Array.isArray(objArray)) throw new Error(\"FIRST ARGUMENT NOT AN ARRAY\");\r", @@ -157,6 +168,176 @@ " return clone;\r", "}\r", "\r", + "\r", + "function bIgnoreForPrimarySort (iCharCode)\r", + "{\r", + " /*--- A bunch of characters get ignored for the primary sort weight.\r", + " The most important ones are the hyphen and apostrophe characters.\r", + " A bunch of control characters and a couple of odds and ends, make up\r", + " the rest.\r", + " */\r", + " if (iCharCode < 9) return true;\r", + "\r", + " if (iCharCode >= 14 && iCharCode <= 31) return true;\r", + "\r", + " if (iCharCode >= 127 && iCharCode <= 159) return true;\r", + "\r", + " if (iCharCode == 39 || iCharCode == 45 || iCharCode == 173) return true;\r", + "\r", + " return false;\r", + "}\r", + "\r", + "\r", + "function SortByRoughSQL_Latin1_General_CP1_CS_AS (sA, sB)\r", + "{\r", + " /*--- This Sorts Latin1 and extended Latin1 unicode with an approximation\r", + " of SQL's SQL_Latin1_General_CP1_CS_AS collation.\r", + " Certain modifying characters or contractions my be off (not tested), we trade-off\r", + " perfect accuracy for speed and relative simplicity.\r", + "\r", + " True unicode sorting is devilishly complex and we're not getting paid enough to\r", + " fully implement it in Javascript. ;-)\r", + "\r", + " It looks like a definative sort would require painstaking exegesis of documents\r", + " such as: http://unicode.org/reports/tr10/\r", + " */\r", + " //--- This is the master lookup table for Latin1 code-points. Here through the extended set \\u02AF\r", + " //--- Make this static?\r", + " var aSortOrder = [\r", + " -1, 151, 152, 153, 154, 155, 156, 157, 158, 2, 3, 4, 5, 6, 159, 160, 161, 162, 163, 164,\r", + " 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 0, 7, 8, 9, 10, 11, 12, 210,\r", + " 13, 14, 15, 41, 16, 211, 17, 18, 65, 69, 71, 74, 76, 77, 80, 81, 82, 83, 19, 20,\r", + " 42, 43, 44, 21, 22, 214, 257, 266, 284, 308, 347, 352, 376, 387, 419, 427, 438, 459, 466, 486,\r", + " 529, 534, 538, 559, 576, 595, 636, 641, 647, 650, 661, 23, 24, 25, 26, 27, 28, 213, 255, 265,\r", + " 283, 307, 346, 350, 374, 385, 418, 426, 436, 458, 464, 485, 528, 533, 536, 558, 575, 594, 635, 640,\r", + " 646, 648, 660, 29, 30, 31, 32, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,\r", + " 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,\r", + " 1, 33, 53, 54, 55, 56, 34, 57, 35, 58, 215, 46, 59, 212, 60, 36, 61, 45, 72, 75,\r", + " 37, 62, 63, 64, 38, 70, 487, 47, 66, 67, 68, 39, 219, 217, 221, 231, 223, 233, 250, 276,\r", + " 312, 310, 316, 318, 392, 390, 395, 397, 295, 472, 491, 489, 493, 503, 495, 48, 511, 599, 597, 601,\r", + " 603, 652, 590, 573, 218, 216, 220, 230, 222, 232, 249, 275, 311, 309, 315, 317, 391, 389, 394, 396,\r", + " 294, 471, 490, 488, 492, 502, 494, 49, 510, 598, 596, 600, 602, 651, 589, 655, 229, 228, 227, 226,\r", + " 235, 234, 268, 267, 272, 271, 270, 269, 274, 273, 286, 285, 290, 287, 324, 323, 322, 321, 314, 313,\r", + " 326, 325, 320, 319, 358, 357, 362, 361, 356, 355, 364, 363, 378, 377, 380, 379, 405, 404, 403, 402,\r", + " 401, 400, 407, 406, 393, 388, 417, 416, 421, 420, 432, 431, 428, 440, 439, 447, 446, 444, 443, 442,\r", + " 441, 450, 449, 468, 467, 474, 473, 470, 469, 477, 484, 483, 501, 500, 499, 498, 507, 506, 527, 526,\r", + " 540, 539, 544, 543, 542, 541, 561, 560, 563, 562, 567, 566, 565, 564, 580, 579, 578, 577, 593, 592,\r", + " 611, 610, 609, 608, 607, 606, 613, 612, 617, 616, 615, 614, 643, 642, 654, 653, 656, 663, 662, 665,\r", + " 664, 667, 666, 574, 258, 260, 262, 261, 264, 263, 281, 278, 277, 304, 292, 289, 288, 297, 335, 337,\r", + " 332, 348, 349, 369, 371, 382, 415, 409, 434, 433, 448, 451, 462, 476, 479, 509, 521, 520, 524, 523,\r", + " 531, 530, 552, 572, 571, 569, 570, 583, 582, 581, 585, 632, 631, 634, 638, 658, 657, 669, 668, 673,\r", + " 677, 676, 678, 73, 79, 78, 680, 644, 50, 51, 52, 40, 303, 302, 301, 457, 456, 455, 482, 481,\r", + " 480, 225, 224, 399, 398, 497, 496, 605, 604, 626, 625, 620, 619, 624, 623, 622, 621, 334, 241, 240,\r", + " 237, 236, 254, 253, 366, 365, 360, 359, 430, 429, 505, 504, 515, 514, 675, 674, 422, 300, 299, 298,\r", + " 354, 353, 84, 85, 86, 87, 239, 238, 252, 251, 513, 512, 243, 242, 245, 244, 328, 327, 330, 329,\r", + " 411, 410, 413, 412, 517, 516, 519, 518, 547, 546, 549, 548, 628, 627, 630, 629, 88, 89, 90, 91,\r", + " 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,\r", + " 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,\r", + " 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 246, 247, 248, 259, 279, 280, 293, 291,\r", + " 339, 336, 338, 331, 340, 341, 342, 423, 367, 373, 351, 370, 372, 383, 381, 384, 408, 414, 386, 445,\r", + " 453, 452, 454, 461, 463, 460, 475, 478, 465, 508, 522, 525, 532, 550, 553, 554, 555, 545, 556, 557,\r", + " 537, 551, 568, 333, 424, 343, 344, 586, 584, 618, 633, 637, 639, 645, 659, 649, 670, 671, 672, 679,\r", + " 681, 682, 683, 282, 686, 256, 345, 368, 375, 425, 435, 437, 535, 684, 685, 305, 296, 306, 591, 587,\r", + " 588, 144, 145, 146, 147, 148, 149, 150\r", + " ];\r", + "\r", + " var iLenA = sA.length, iLenB = sB.length;\r", + " var jA = 0, jB = 0;\r", + " var sIgnoreBuff_A = [], sIgnoreBuff_B = [];\r", + "\r", + "\r", + " function iSortIgnoreBuff ()\r", + " {\r", + " var iIgLenA = sIgnoreBuff_A.length, iIgLenB = sIgnoreBuff_B.length;\r", + " var kA = 0, kB = 0;\r", + "\r", + " while (kA < iIgLenA && kB < iIgLenB)\r", + " {\r", + " var igA = sIgnoreBuff_A [kA++], igB = sIgnoreBuff_B [kB++];\r", + "\r", + " if (aSortOrder[igA] > aSortOrder[igB] ) return 1;\r", + " if (aSortOrder[igA] < aSortOrder[igB] ) return -1;\r", + " }\r", + " //--- All else equal, longest string loses\r", + " if (iIgLenA > iIgLenB) return 1;\r", + " if (iIgLenA < iIgLenB) return -1;\r", + "\r", + " return 0;\r", + " }\r", + "\r", + "\r", + " while (jA < iLenA && jB < iLenB)\r", + " {\r", + " var cA = sA.charCodeAt (jA++);\r", + " var cB = sB.charCodeAt (jB++);\r", + "\r", + " if (cA == cB)\r", + " {\r", + " continue;\r", + " }\r", + "\r", + " while (bIgnoreForPrimarySort (cA) )\r", + " {\r", + " sIgnoreBuff_A.push (cA);\r", + " if (jA < iLenA)\r", + " cA = sA.charCodeAt (jA++);\r", + " else\r", + " break;\r", + " }\r", + " while (bIgnoreForPrimarySort (cB) )\r", + " {\r", + " sIgnoreBuff_B.push (cB);\r", + " if (jB < iLenB)\r", + " cB = sB.charCodeAt (jB++);\r", + " else\r", + " break;\r", + " }\r", + "\r", + " /*--- Have we reached the end of one or both strings, ending on an ignore char?\r", + " The strings were equal, up to that point.\r", + " If one of the strings is NOT an ignore char, while the other is, it wins.\r", + " */\r", + " if (bIgnoreForPrimarySort (cA) )\r", + " {\r", + " if (! bIgnoreForPrimarySort (cB)) return -1;\r", + " }\r", + " else if (bIgnoreForPrimarySort (cB) )\r", + " {\r", + " return 1;\r", + " }\r", + " else\r", + " {\r", + " if (aSortOrder[cA] > aSortOrder[cB] )\r", + " return 1;\r", + "\r", + " if (aSortOrder[cA] < aSortOrder[cB] )\r", + " return -1;\r", + "\r", + " //--- We are equal, so far, on the main chars. Where there ignore chars?\r", + " var iBuffSort = iSortIgnoreBuff ();\r", + " if (iBuffSort) return iBuffSort;\r", + "\r", + " //--- Still here? Reset the ignore arrays.\r", + " sIgnoreBuff_A = [];\r", + " sIgnoreBuff_B = [];\r", + " }\r", + "\r", + " } //-- while (jA < iLenA && jB < iLenB)\r", + "\r", + " /*--- We have gone through all of at least one string and they are still both\r", + " equal barring ignore chars or unequal lengths.\r", + " */\r", + " var iBuffSort = iSortIgnoreBuff ();\r", + " if (iBuffSort) return iBuffSort;\r", + "\r", + " //--- All else equal, longest string loses\r", + " if (iLenA > iLenB) return 1;\r", + " if (iLenA < iLenB) return -1;\r", + "\r", + " return 0;\r", + "\r", + "} //-- function SortByRoughSQL_Latin1_General_CP1_CS_AS\r", + "\r", "" ], "type": "text/javascript" @@ -999,11 +1180,12 @@ " const minLength = 8;", " const maxLength = 24;", " let result = '';", - " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';", + " const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';", + " // const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';", " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;", "", " result += randomChar('abcdefghijklmnopqrstuvwxyz');", - " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');", + " // result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');", " result += randomChar('0123456789');", "", " for (let i = result.length; i < length; i++) {", diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs index ccf16dc0f..804e16655 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs @@ -29,7 +29,7 @@ public class GetOdsInstancesQuery : IGetOdsInstancesQuery new Dictionary>> (StringComparer.OrdinalIgnoreCase) { - { SortingColumns.DefaultNameColumn, x => x.Name }, + { SortingColumns.DefaultNameColumn, x => EF.Functions.Collate(x.Name, "Latin1_General_bin") }, { SortingColumns.OdsInstanceInstanceTypeColumn, x => x.InstanceType }, { SortingColumns.DefaultIdColumn, x => x.OdsInstanceId } }; From 431f38fb3b15f60f14c567a0d16eedc34c5a15f6 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Sat, 24 Aug 2024 12:39:41 -0500 Subject: [PATCH 19/35] Add a different mechansim in the e2e to validate sorting odsinstances --- ...ng - ODS Instances.postman_collection.json | 310 +----------------- .../Admin API.postman_environment.json | 10 +- .../Database/Queries/GetOdsInstancesQuery.cs | 2 +- 3 files changed, 27 insertions(+), 295 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json index 5209e64ca..43c3e07a1 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json @@ -25,22 +25,9 @@ "\r", "pm.test(\"GET ODS Instances: Response result is ordered by Name asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = results.sort(function(a, b) {\r", - " var a1st = -1; // negative value means left item should appear first\r", - " var b1st = 1; // positive value means right item should appear first\r", - " var equal = 0; // zero means objects are equal\r", - "\r", - " // compare your object's property values and determine their order\r", - " if (b.name < a.name) {\r", - " return b1st;\r", - " }\r", - " else if (a.name < b.name) {\r", - " return a1st;\r", - " }\r", - " else {\r", - " return equal;\r", - " }\r", - " });\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'name');\r", " \r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", @@ -122,222 +109,13 @@ "pm.test(\"GET ODS Instances: Response result is ordered by Namne desc\", function () {\r", " const results = pm.response.json();\r", " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", - " var other = sortByProperty(results, 'name', -1);\r", - "\r", - " console.log(\"results\");\r", - " console.log(JSON.stringify(expectedSortedOrder));\r", - " console.log(\"other\");\r", - " console.log(JSON.stringify(other));\r", - " console.log(\"expected\");\r", - " console.log(JSON.stringify(results));\r", - " // sortByProperty(results, 'name', -1);\r", - " //_.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", + " // const strSortByProperty = pm.variables.get('sortByProperty');\r", + " // eval(strSortByProperty);\r", + " // let expectedSortedOrder = sortByProperty(results, 'name', -1);\r", "\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "\r", - "pm.test(\"GET ODS Instances: Response result is ordered by Namne desc - ALT\", function () {\r", - " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", - " var other = sortByProperty(results, 'name', -1);\r", - "\r", - " // sortByProperty(results, 'name', -1);\r", - " //_.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", - "\r", - " pm.expect(results).to.eql(other);\r", - "});\r", - "\r", - "function sortByProperty(objArray, prop, direction){\r", - " if (arguments.length<2) throw new Error(\"ARRAY, AND OBJECT PROPERTY MINIMUM ARGUMENTS, OPTIONAL DIRECTION\");\r", - " if (!Array.isArray(objArray)) throw new Error(\"FIRST ARGUMENT NOT AN ARRAY\");\r", - " const clone = objArray.slice(0);\r", - " const direct = arguments.length>2 ? arguments[2] : 1; //Default to ascending\r", - " const propPath = (prop.constructor===Array) ? prop : prop.split(\".\");\r", - " clone.sort(function(a,b){\r", - " for (let p in propPath){\r", - " if (a[propPath[p]] && b[propPath[p]]){\r", - " a = a[propPath[p]];\r", - " b = b[propPath[p]];\r", - " }\r", - " }\r", - " // convert numeric strings to integers\r", - " a = a.match(/^\\d+$/) ? +a : a;\r", - " b = b.match(/^\\d+$/) ? +b : b;\r", - " return ( (a < b) ? -1*direct : ((a > b) ? 1*direct : 0) );\r", - " });\r", - " return clone;\r", - "}\r", - "\r", - "\r", - "function bIgnoreForPrimarySort (iCharCode)\r", - "{\r", - " /*--- A bunch of characters get ignored for the primary sort weight.\r", - " The most important ones are the hyphen and apostrophe characters.\r", - " A bunch of control characters and a couple of odds and ends, make up\r", - " the rest.\r", - " */\r", - " if (iCharCode < 9) return true;\r", - "\r", - " if (iCharCode >= 14 && iCharCode <= 31) return true;\r", - "\r", - " if (iCharCode >= 127 && iCharCode <= 159) return true;\r", - "\r", - " if (iCharCode == 39 || iCharCode == 45 || iCharCode == 173) return true;\r", - "\r", - " return false;\r", - "}\r", - "\r", - "\r", - "function SortByRoughSQL_Latin1_General_CP1_CS_AS (sA, sB)\r", - "{\r", - " /*--- This Sorts Latin1 and extended Latin1 unicode with an approximation\r", - " of SQL's SQL_Latin1_General_CP1_CS_AS collation.\r", - " Certain modifying characters or contractions my be off (not tested), we trade-off\r", - " perfect accuracy for speed and relative simplicity.\r", - "\r", - " True unicode sorting is devilishly complex and we're not getting paid enough to\r", - " fully implement it in Javascript. ;-)\r", - "\r", - " It looks like a definative sort would require painstaking exegesis of documents\r", - " such as: http://unicode.org/reports/tr10/\r", - " */\r", - " //--- This is the master lookup table for Latin1 code-points. Here through the extended set \\u02AF\r", - " //--- Make this static?\r", - " var aSortOrder = [\r", - " -1, 151, 152, 153, 154, 155, 156, 157, 158, 2, 3, 4, 5, 6, 159, 160, 161, 162, 163, 164,\r", - " 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 0, 7, 8, 9, 10, 11, 12, 210,\r", - " 13, 14, 15, 41, 16, 211, 17, 18, 65, 69, 71, 74, 76, 77, 80, 81, 82, 83, 19, 20,\r", - " 42, 43, 44, 21, 22, 214, 257, 266, 284, 308, 347, 352, 376, 387, 419, 427, 438, 459, 466, 486,\r", - " 529, 534, 538, 559, 576, 595, 636, 641, 647, 650, 661, 23, 24, 25, 26, 27, 28, 213, 255, 265,\r", - " 283, 307, 346, 350, 374, 385, 418, 426, 436, 458, 464, 485, 528, 533, 536, 558, 575, 594, 635, 640,\r", - " 646, 648, 660, 29, 30, 31, 32, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189,\r", - " 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209,\r", - " 1, 33, 53, 54, 55, 56, 34, 57, 35, 58, 215, 46, 59, 212, 60, 36, 61, 45, 72, 75,\r", - " 37, 62, 63, 64, 38, 70, 487, 47, 66, 67, 68, 39, 219, 217, 221, 231, 223, 233, 250, 276,\r", - " 312, 310, 316, 318, 392, 390, 395, 397, 295, 472, 491, 489, 493, 503, 495, 48, 511, 599, 597, 601,\r", - " 603, 652, 590, 573, 218, 216, 220, 230, 222, 232, 249, 275, 311, 309, 315, 317, 391, 389, 394, 396,\r", - " 294, 471, 490, 488, 492, 502, 494, 49, 510, 598, 596, 600, 602, 651, 589, 655, 229, 228, 227, 226,\r", - " 235, 234, 268, 267, 272, 271, 270, 269, 274, 273, 286, 285, 290, 287, 324, 323, 322, 321, 314, 313,\r", - " 326, 325, 320, 319, 358, 357, 362, 361, 356, 355, 364, 363, 378, 377, 380, 379, 405, 404, 403, 402,\r", - " 401, 400, 407, 406, 393, 388, 417, 416, 421, 420, 432, 431, 428, 440, 439, 447, 446, 444, 443, 442,\r", - " 441, 450, 449, 468, 467, 474, 473, 470, 469, 477, 484, 483, 501, 500, 499, 498, 507, 506, 527, 526,\r", - " 540, 539, 544, 543, 542, 541, 561, 560, 563, 562, 567, 566, 565, 564, 580, 579, 578, 577, 593, 592,\r", - " 611, 610, 609, 608, 607, 606, 613, 612, 617, 616, 615, 614, 643, 642, 654, 653, 656, 663, 662, 665,\r", - " 664, 667, 666, 574, 258, 260, 262, 261, 264, 263, 281, 278, 277, 304, 292, 289, 288, 297, 335, 337,\r", - " 332, 348, 349, 369, 371, 382, 415, 409, 434, 433, 448, 451, 462, 476, 479, 509, 521, 520, 524, 523,\r", - " 531, 530, 552, 572, 571, 569, 570, 583, 582, 581, 585, 632, 631, 634, 638, 658, 657, 669, 668, 673,\r", - " 677, 676, 678, 73, 79, 78, 680, 644, 50, 51, 52, 40, 303, 302, 301, 457, 456, 455, 482, 481,\r", - " 480, 225, 224, 399, 398, 497, 496, 605, 604, 626, 625, 620, 619, 624, 623, 622, 621, 334, 241, 240,\r", - " 237, 236, 254, 253, 366, 365, 360, 359, 430, 429, 505, 504, 515, 514, 675, 674, 422, 300, 299, 298,\r", - " 354, 353, 84, 85, 86, 87, 239, 238, 252, 251, 513, 512, 243, 242, 245, 244, 328, 327, 330, 329,\r", - " 411, 410, 413, 412, 517, 516, 519, 518, 547, 546, 549, 548, 628, 627, 630, 629, 88, 89, 90, 91,\r", - " 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,\r", - " 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131,\r", - " 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 246, 247, 248, 259, 279, 280, 293, 291,\r", - " 339, 336, 338, 331, 340, 341, 342, 423, 367, 373, 351, 370, 372, 383, 381, 384, 408, 414, 386, 445,\r", - " 453, 452, 454, 461, 463, 460, 475, 478, 465, 508, 522, 525, 532, 550, 553, 554, 555, 545, 556, 557,\r", - " 537, 551, 568, 333, 424, 343, 344, 586, 584, 618, 633, 637, 639, 645, 659, 649, 670, 671, 672, 679,\r", - " 681, 682, 683, 282, 686, 256, 345, 368, 375, 425, 435, 437, 535, 684, 685, 305, 296, 306, 591, 587,\r", - " 588, 144, 145, 146, 147, 148, 149, 150\r", - " ];\r", - "\r", - " var iLenA = sA.length, iLenB = sB.length;\r", - " var jA = 0, jB = 0;\r", - " var sIgnoreBuff_A = [], sIgnoreBuff_B = [];\r", - "\r", - "\r", - " function iSortIgnoreBuff ()\r", - " {\r", - " var iIgLenA = sIgnoreBuff_A.length, iIgLenB = sIgnoreBuff_B.length;\r", - " var kA = 0, kB = 0;\r", - "\r", - " while (kA < iIgLenA && kB < iIgLenB)\r", - " {\r", - " var igA = sIgnoreBuff_A [kA++], igB = sIgnoreBuff_B [kB++];\r", - "\r", - " if (aSortOrder[igA] > aSortOrder[igB] ) return 1;\r", - " if (aSortOrder[igA] < aSortOrder[igB] ) return -1;\r", - " }\r", - " //--- All else equal, longest string loses\r", - " if (iIgLenA > iIgLenB) return 1;\r", - " if (iIgLenA < iIgLenB) return -1;\r", - "\r", - " return 0;\r", - " }\r", - "\r", - "\r", - " while (jA < iLenA && jB < iLenB)\r", - " {\r", - " var cA = sA.charCodeAt (jA++);\r", - " var cB = sB.charCodeAt (jB++);\r", - "\r", - " if (cA == cB)\r", - " {\r", - " continue;\r", - " }\r", - "\r", - " while (bIgnoreForPrimarySort (cA) )\r", - " {\r", - " sIgnoreBuff_A.push (cA);\r", - " if (jA < iLenA)\r", - " cA = sA.charCodeAt (jA++);\r", - " else\r", - " break;\r", - " }\r", - " while (bIgnoreForPrimarySort (cB) )\r", - " {\r", - " sIgnoreBuff_B.push (cB);\r", - " if (jB < iLenB)\r", - " cB = sB.charCodeAt (jB++);\r", - " else\r", - " break;\r", - " }\r", - "\r", - " /*--- Have we reached the end of one or both strings, ending on an ignore char?\r", - " The strings were equal, up to that point.\r", - " If one of the strings is NOT an ignore char, while the other is, it wins.\r", - " */\r", - " if (bIgnoreForPrimarySort (cA) )\r", - " {\r", - " if (! bIgnoreForPrimarySort (cB)) return -1;\r", - " }\r", - " else if (bIgnoreForPrimarySort (cB) )\r", - " {\r", - " return 1;\r", - " }\r", - " else\r", - " {\r", - " if (aSortOrder[cA] > aSortOrder[cB] )\r", - " return 1;\r", - "\r", - " if (aSortOrder[cA] < aSortOrder[cB] )\r", - " return -1;\r", - "\r", - " //--- We are equal, so far, on the main chars. Where there ignore chars?\r", - " var iBuffSort = iSortIgnoreBuff ();\r", - " if (iBuffSort) return iBuffSort;\r", - "\r", - " //--- Still here? Reset the ignore arrays.\r", - " sIgnoreBuff_A = [];\r", - " sIgnoreBuff_B = [];\r", - " }\r", - "\r", - " } //-- while (jA < iLenA && jB < iLenB)\r", - "\r", - " /*--- We have gone through all of at least one string and they are still both\r", - " equal barring ignore chars or unequal lengths.\r", - " */\r", - " var iBuffSort = iSortIgnoreBuff ();\r", - " if (iBuffSort) return iBuffSort;\r", - "\r", - " //--- All else equal, longest string loses\r", - " if (iLenA > iLenB) return 1;\r", - " if (iLenA < iLenB) return -1;\r", - "\r", - " return 0;\r", - "\r", - "} //-- function SortByRoughSQL_Latin1_General_CP1_CS_AS\r", - "\r", "" ], "type": "text/javascript" @@ -585,22 +363,9 @@ "\r", "pm.test(\"GET ODS Instances: Response result is ordered by Name asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = results.sort(function(a, b) {\r", - " var a1st = -1; // negative value means left item should appear first\r", - " var b1st = 1; // positive value means right item should appear first\r", - " var equal = 0; // zero means objects are equal\r", - "\r", - " // compare your object's property values and determine their order\r", - " if (b.name < a.name) {\r", - " return b1st;\r", - " }\r", - " else if (a.name < b.name) {\r", - " return a1st;\r", - " }\r", - " else {\r", - " return equal;\r", - " }\r", - " });\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'name');\r", "\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", @@ -685,22 +450,9 @@ "\r", "pm.test(\"GET ODS Instances: Response result is ordered by Name desc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = results.sort(function(a, b) {\r", - " var a1st = -1; // negative value means left item should appear first\r", - " var b1st = 1; // positive value means right item should appear first\r", - " var equal = 0; // zero means objects are equal\r", - "\r", - " // compare your object's property values and determine their order\r", - " if (b.name < a.name) {\r", - " return b1st;\r", - " }\r", - " else if (a.name < b.name) {\r", - " return a1st;\r", - " }\r", - " else {\r", - " return equal;\r", - " }\r", - " }).reverse();\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'name', -1);\r", "\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", @@ -786,22 +538,9 @@ "pm.test(\"GET ODS Instances: Response result is ordered by InstanceType asc\", function () {\r", " const results = pm.response.json();\r", " // var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType ? odsInstance.instanceType.toLowerCase() : null],['asc']);\r", - " var expectedSortedOrder = results.sort(function(a, b) {\r", - " var a1st = -1; // negative value means left item should appear first\r", - " var b1st = 1; // positive value means right item should appear first\r", - " var equal = 0; // zero means objects are equal\r", - "\r", - " // compare your object's property values and determine their order\r", - " if (b.instanceType < a.instanceType) {\r", - " return b1st;\r", - " }\r", - " else if (a.instanceType < b.instanceType) {\r", - " return a1st;\r", - " }\r", - " else {\r", - " return equal;\r", - " }\r", - " });\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'instanceType');\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -886,22 +625,9 @@ "pm.test(\"GET ODS Instances: Response result is ordered by InstanceType desc\", function () {\r", " const results = pm.response.json();\r", " // var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType ? odsInstance.instanceType.toLowerCase() : null],['desc']);\r", - " var expectedSortedOrder = results.sort(function(a, b) {\r", - " var a1st = -1; // negative value means left item should appear first\r", - " var b1st = 1; // positive value means right item should appear first\r", - " var equal = 0; // zero means objects are equal\r", - "\r", - " // compare your object's property values and determine their order\r", - " if (b.instanceType < a.instanceType) {\r", - " return b1st;\r", - " }\r", - " else if (a.instanceType < b.instanceType) {\r", - " return a1st;\r", - " }\r", - " else {\r", - " return equal;\r", - " }\r", - " }).reverse();\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'instanceType', -1);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API.postman_environment.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API.postman_environment.json index 511aff89f..900508bb6 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API.postman_environment.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API.postman_environment.json @@ -22,7 +22,7 @@ }, { "key": "connectionString", - "value": "Data Source=.;Initial Catalog=EdFi_Admin;Integrated Security=True;TrustServerCertificate=True", + "value": "host=localhost;port=5401;username=postgres;password=P@ssw0rd;database=EdFi_Admin;pooling=false", "type": "default", "enabled": true }, @@ -31,7 +31,13 @@ "value": "false", "type": "default", "enabled": true - } + }, + { + "key": "sortByProperty", + "value": "function sortByProperty(objArray, prop, direction){ if (arguments.length<2) throw new Error(\"ARRAY, AND OBJECT PROPERTY MINIMUM ARGUMENTS, OPTIONAL DIRECTION\"); if (!Array.isArray(objArray)) throw new Error(\"FIRST ARGUMENT NOT AN ARRAY\"); const clone = objArray.slice(0); const direct = arguments.length>2 ? arguments[2] : 1; const propPath = (prop.constructor===Array) ? prop : prop.split(\".\"); clone.sort(function(a,b){ for (let p in propPath){ if (a[propPath[p]] && b[propPath[p]]){ a = a[propPath[p]]; b = b[propPath[p]]; } } a = a.match(/^\\d+$/) ? +a : a; b = b.match(/^\\d+$/) ? +b : b; return ( (a < b) ? -1*direct : ((a > b) ? 1*direct : 0) ); }); return clone; }", + "type": "default", + "enabled": true + } ], "_postman_variable_scope": "environment", "_postman_exported_at": "2023-08-11T19:49:43.269Z", diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs index 804e16655..ccf16dc0f 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs @@ -29,7 +29,7 @@ public class GetOdsInstancesQuery : IGetOdsInstancesQuery new Dictionary>> (StringComparer.OrdinalIgnoreCase) { - { SortingColumns.DefaultNameColumn, x => EF.Functions.Collate(x.Name, "Latin1_General_bin") }, + { SortingColumns.DefaultNameColumn, x => x.Name }, { SortingColumns.OdsInstanceInstanceTypeColumn, x => x.InstanceType }, { SortingColumns.DefaultIdColumn, x => x.OdsInstanceId } }; From ff26363a16154b89e3a5012b973f41aa6534ea45 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Sat, 24 Aug 2024 12:44:37 -0500 Subject: [PATCH 20/35] Add a different mechansim in the e2e to validate sorting odsinstances --- ... and Filtering - ODS Instances.postman_collection.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json index 43c3e07a1..54c0fc11c 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json @@ -108,10 +108,10 @@ "\r", "pm.test(\"GET ODS Instances: Response result is ordered by Namne desc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", - " // const strSortByProperty = pm.variables.get('sortByProperty');\r", - " // eval(strSortByProperty);\r", - " // let expectedSortedOrder = sortByProperty(results, 'name', -1);\r", + " // var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'name', -1);\r", "\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", From 87c156747d218233f83469cd528b23cad5542744 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Sat, 24 Aug 2024 12:47:34 -0500 Subject: [PATCH 21/35] Add a different mechansim in the e2e to validate sorting odsinstances --- ...Admin API Docker-single-mssql.postman_environment.json | 8 +++++++- ...Admin API Docker-single-pgsql.postman_environment.json | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-single-mssql.postman_environment.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-single-mssql.postman_environment.json index cfe55f19b..d466bb089 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-single-mssql.postman_environment.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-single-mssql.postman_environment.json @@ -31,7 +31,13 @@ "value": "false", "type": "default", "enabled": true - } + }, + { + "key": "sortByProperty", + "value": "function sortByProperty(objArray, prop, direction){ if (arguments.length<2) throw new Error(\"ARRAY, AND OBJECT PROPERTY MINIMUM ARGUMENTS, OPTIONAL DIRECTION\"); if (!Array.isArray(objArray)) throw new Error(\"FIRST ARGUMENT NOT AN ARRAY\"); const clone = objArray.slice(0); const direct = arguments.length>2 ? arguments[2] : 1; const propPath = (prop.constructor===Array) ? prop : prop.split(\".\"); clone.sort(function(a,b){ for (let p in propPath){ if (a[propPath[p]] && b[propPath[p]]){ a = a[propPath[p]]; b = b[propPath[p]]; } } a = a.match(/^\\d+$/) ? +a : a; b = b.match(/^\\d+$/) ? +b : b; return ( (a < b) ? -1*direct : ((a > b) ? 1*direct : 0) ); }); return clone; }", + "type": "default", + "enabled": true + } ], "_postman_variable_scope": "environment", "_postman_exported_at": "2023-08-11T19:57:02.536Z", diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-single-pgsql.postman_environment.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-single-pgsql.postman_environment.json index dac5c0c88..db298fd25 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-single-pgsql.postman_environment.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-single-pgsql.postman_environment.json @@ -31,7 +31,13 @@ "value": "false", "type": "default", "enabled": true - } + }, + { + "key": "sortByProperty", + "value": "function sortByProperty(objArray, prop, direction){ if (arguments.length<2) throw new Error(\"ARRAY, AND OBJECT PROPERTY MINIMUM ARGUMENTS, OPTIONAL DIRECTION\"); if (!Array.isArray(objArray)) throw new Error(\"FIRST ARGUMENT NOT AN ARRAY\"); const clone = objArray.slice(0); const direct = arguments.length>2 ? arguments[2] : 1; const propPath = (prop.constructor===Array) ? prop : prop.split(\".\"); clone.sort(function(a,b){ for (let p in propPath){ if (a[propPath[p]] && b[propPath[p]]){ a = a[propPath[p]]; b = b[propPath[p]]; } } a = a.match(/^\\d+$/) ? +a : a; b = b.match(/^\\d+$/) ? +b : b; return ( (a < b) ? -1*direct : ((a > b) ? 1*direct : 0) ); }); return clone; }", + "type": "default", + "enabled": true + } ], "_postman_variable_scope": "environment", "_postman_exported_at": "2023-08-11T19:57:02.536Z", From cceae37b93954bee994e8ad68381396d680dd4df Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Sat, 24 Aug 2024 15:07:48 -0500 Subject: [PATCH 22/35] Add the command to force collate in SQL server engine --- .../Database/Queries/GetAllActionsQuery.cs | 18 +++++++----- .../Queries/GetAllApplicationsQuery.cs | 17 ++++++----- .../Database/Queries/GetAllClaimSetsQuery.cs | 22 +++++++------- .../Database/Queries/GetOdsInstancesQuery.cs | 19 ++++++------ .../Database/Queries/GetVendorsQuery.cs | 29 +++++++++---------- .../Infrastructure/DatabaseEngineEnum.cs | 3 +- 6 files changed, 57 insertions(+), 51 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllActionsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllActionsQuery.cs index 7ee4bb47e..191779ed7 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllActionsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllActionsQuery.cs @@ -8,6 +8,7 @@ using EdFi.Ods.AdminApi.Infrastructure.Extensions; using EdFi.Ods.AdminApi.Infrastructure.Helpers; using EdFi.Security.DataAccess.Contexts; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; using Action = EdFi.Security.DataAccess.Models.Action; @@ -23,19 +24,20 @@ public class GetAllActionsQuery : IGetAllActionsQuery { private readonly ISecurityContext _securityContext; private readonly IOptions _options; - private static readonly Dictionary>> _orderByColumnActions = - new Dictionary>> - (StringComparer.OrdinalIgnoreCase) - { - { SortingColumns.DefaultNameColumn, x => x.ActionName }, - { SortingColumns.ActionUriColumn, x => x.ActionUri }, - { SortingColumns.DefaultIdColumn, x => x.ActionId } - }; + private readonly Dictionary>> _orderByColumnActions; public GetAllActionsQuery(ISecurityContext securityContext, IOptions options) { _securityContext = securityContext; _options = options; + var isSQLServerEngine = _options.Value.DatabaseEngine?.ToLowerInvariant() == DatabaseEngineEnum.SqlServer.ToLowerInvariant(); + _orderByColumnActions = new Dictionary>> + (StringComparer.OrdinalIgnoreCase) + { + { SortingColumns.DefaultNameColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.ActionName, DatabaseEngineEnum.SqlServerCollation) : x.ActionName }, + { SortingColumns.ActionUriColumn, x => x.ActionUri }, + { SortingColumns.DefaultIdColumn, x => x.ActionId } + }; } public IReadOnlyList Execute() diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllApplicationsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllApplicationsQuery.cs index 39bf2dc1e..2be7e99fa 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllApplicationsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllApplicationsQuery.cs @@ -23,19 +23,20 @@ public class GetAllApplicationsQuery : IGetAllApplicationsQuery { private readonly IUsersContext _context; private readonly IOptions _options; - private static readonly Dictionary>> _orderByColumnApplications = - new Dictionary>> - (StringComparer.OrdinalIgnoreCase) - { - { SortingColumns.ApplicationNameColumn, x => x.ApplicationName }, - { SortingColumns.ApplicationClaimSetNameColumn, x => x.ClaimSetName }, - { SortingColumns.DefaultIdColumn, x => x.ApplicationId } - }; + private readonly Dictionary>> _orderByColumnApplications; public GetAllApplicationsQuery(IUsersContext context, IOptions options) { _context = context; _options = options; + var isSQLServerEngine = _options.Value.DatabaseEngine?.ToLowerInvariant() == DatabaseEngineEnum.SqlServer.ToLowerInvariant(); + _orderByColumnApplications = new Dictionary>> + (StringComparer.OrdinalIgnoreCase) + { + { SortingColumns.ApplicationNameColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.ApplicationName, DatabaseEngineEnum.SqlServerCollation) : x.ApplicationName }, + { SortingColumns.ApplicationClaimSetNameColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.ClaimSetName, DatabaseEngineEnum.SqlServerCollation) : x.ClaimSetName }, + { SortingColumns.DefaultIdColumn, x => x.ApplicationId } + }; } public IReadOnlyList Execute(CommonQueryParams commonQueryParams, int? id, string? applicationName, string? claimsetName) diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllClaimSetsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllClaimSetsQuery.cs index 918fbe17b..eb7f5b8f9 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllClaimSetsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAllClaimSetsQuery.cs @@ -8,6 +8,7 @@ using EdFi.Ods.AdminApi.Infrastructure.Extensions; using EdFi.Ods.AdminApi.Infrastructure.Helpers; using EdFi.Security.DataAccess.Contexts; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; using ClaimSet = EdFi.Ods.AdminApi.Infrastructure.ClaimSetEditor.ClaimSet; @@ -23,19 +24,20 @@ public class GetAllClaimSetsQuery : IGetAllClaimSetsQuery { private readonly ISecurityContext _securityContext; private readonly IOptions _options; - private static readonly Dictionary>> _orderByColumnClaimSet = - new Dictionary>> - (StringComparer.OrdinalIgnoreCase) - { -#pragma warning disable CS8603 // Possible null reference return. - { SortingColumns.DefaultNameColumn, x => x.Name }, -#pragma warning restore CS8603 // Possible null reference return. - { SortingColumns.DefaultIdColumn, x => x.Id } - }; + private readonly Dictionary>> _orderByColumnClaimSet; public GetAllClaimSetsQuery(ISecurityContext securityContext, IOptions options) { _securityContext = securityContext; - _options = options; + _options = options; + var isSQLServerEngine = _options.Value.DatabaseEngine?.ToLowerInvariant() == DatabaseEngineEnum.SqlServer.ToLowerInvariant(); + _orderByColumnClaimSet = new Dictionary>> + (StringComparer.OrdinalIgnoreCase) + { + #pragma warning disable CS8603 // Possible null reference return. + { SortingColumns.DefaultNameColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.Name, DatabaseEngineEnum.SqlServerCollation) : x.Name }, + #pragma warning restore CS8603 // Possible null reference return. + { SortingColumns.DefaultIdColumn, x => x.Id } + }; } public IReadOnlyList Execute() diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs index ccf16dc0f..06450590c 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs @@ -25,19 +25,20 @@ public class GetOdsInstancesQuery : IGetOdsInstancesQuery { private readonly IUsersContext _usersContext; private readonly IOptions _options; - private static readonly Dictionary>> _orderByColumnOds = - new Dictionary>> - (StringComparer.OrdinalIgnoreCase) - { - { SortingColumns.DefaultNameColumn, x => x.Name }, - { SortingColumns.OdsInstanceInstanceTypeColumn, x => x.InstanceType }, - { SortingColumns.DefaultIdColumn, x => x.OdsInstanceId } - }; + private readonly Dictionary>> _orderByColumnOds; public GetOdsInstancesQuery(IUsersContext userContext, IOptions options) { _usersContext = userContext; - _options = options; + _options = options; + var isSQLServerEngine = _options.Value.DatabaseEngine?.ToLowerInvariant() == DatabaseEngineEnum.SqlServer.ToLowerInvariant(); + _orderByColumnOds = new Dictionary>> + (StringComparer.OrdinalIgnoreCase) + { + { SortingColumns.DefaultNameColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.Name, "Latin1_General_BIN2") : x.Name }, + { SortingColumns.OdsInstanceInstanceTypeColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.InstanceType, "Latin1_General_BIN2") : x.InstanceType }, + { SortingColumns.DefaultIdColumn, x => x.OdsInstanceId } + }; } public List Execute() diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs index 4fadb5752..c3a9cb813 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs @@ -25,24 +25,23 @@ public class GetVendorsQuery : IGetVendorsQuery { private readonly IUsersContext _context; private readonly IOptions _options; - private static readonly Dictionary>> _orderByColumnVendors = - new Dictionary>> - (StringComparer.OrdinalIgnoreCase) - { - { SortingColumns.VendorCompanyColumn, x => x.VendorName }, -#pragma warning disable CS8602 // Dereference of a possibly null reference. - { SortingColumns.VendorContactNameColumn, x => x.Users.FirstOrDefault().FullName }, -#pragma warning restore CS8602 // Dereference of a possibly null reference. -#pragma warning disable CS8602 // Dereference of a possibly null reference. - { SortingColumns.VendorContactEmailColumn, x => x.Users.FirstOrDefault().Email }, -#pragma warning restore CS8602 // Dereference of a possibly null reference. - { SortingColumns.VendorNamespacePrefixesColumn, x => x.VendorNamespacePrefixes.OrderBy(p => p.NamespacePrefix).First().NamespacePrefix }, - { SortingColumns.DefaultIdColumn, x => x.VendorId } - }; + private readonly Dictionary>> _orderByColumnVendors; public GetVendorsQuery(IUsersContext context, IOptions options) { _context = context; - _options = options; + _options = options; + var isSQLServerEngine = _options.Value.DatabaseEngine?.ToLowerInvariant() == DatabaseEngineEnum.SqlServer.ToLowerInvariant(); + _orderByColumnVendors = new Dictionary>> + (StringComparer.OrdinalIgnoreCase) + { + { SortingColumns.VendorCompanyColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.VendorName, DatabaseEngineEnum.SqlServerCollation) : x.VendorName }, + #pragma warning disable CS8602 // Dereference of a possibly null reference. + { SortingColumns.VendorContactNameColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.Users.FirstOrDefault().FullName, DatabaseEngineEnum.SqlServerCollation) : x.Users.FirstOrDefault().FullName }, + { SortingColumns.VendorContactEmailColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.Users.FirstOrDefault().Email, DatabaseEngineEnum.SqlServerCollation) : x.Users.FirstOrDefault().Email }, + #pragma warning restore CS8602 // Dereference of a possibly null reference. + { SortingColumns.VendorNamespacePrefixesColumn, x => x.VendorNamespacePrefixes.OrderBy(p => p.NamespacePrefix).First().NamespacePrefix }, + { SortingColumns.DefaultIdColumn, x => x.VendorId } + }; } public List Execute() diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/DatabaseEngineEnum.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/DatabaseEngineEnum.cs index fd566682d..b17d9a7b0 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/DatabaseEngineEnum.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/DatabaseEngineEnum.cs @@ -3,7 +3,8 @@ namespace EdFi.Ods.AdminApi.Infrastructure; public static class DatabaseEngineEnum { public const string SqlServer = "SqlServer"; - public const string PostgreSql = "PostgreSql"; + public const string PostgreSql = "PostgreSql"; + public const string SqlServerCollation = "Latin1_General_BIN2"; public static string Parse(string value) { From f5bd27d4220d072b2cba30dd6133615c64e5cdfc Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Sat, 24 Aug 2024 15:27:43 -0500 Subject: [PATCH 23/35] Add the js sort function to the env. Modify the application's e2e to use the js sort --- ... API Docker-multitenant-mssql.postman_environment.json | 8 +++++++- ... API Docker-multitenant-pgsql.postman_environment.json | 8 +++++++- ... and Filtering - ODS Instances.postman_collection.json | 8 ++++---- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-multitenant-mssql.postman_environment.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-multitenant-mssql.postman_environment.json index 238e29dac..6a9538de5 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-multitenant-mssql.postman_environment.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-multitenant-mssql.postman_environment.json @@ -43,7 +43,13 @@ "value": "Tenant2", "type": "default", "enabled": true - } + }, + { + "key": "sortByProperty", + "value": "function sortByProperty(objArray, prop, direction){ if (arguments.length<2) throw new Error(\"ARRAY, AND OBJECT PROPERTY MINIMUM ARGUMENTS, OPTIONAL DIRECTION\"); if (!Array.isArray(objArray)) throw new Error(\"FIRST ARGUMENT NOT AN ARRAY\"); const clone = objArray.slice(0); const direct = arguments.length>2 ? arguments[2] : 1; const propPath = (prop.constructor===Array) ? prop : prop.split(\".\"); clone.sort(function(a,b){ for (let p in propPath){ if (a[propPath[p]] && b[propPath[p]]){ a = a[propPath[p]]; b = b[propPath[p]]; } } a = a.match(/^\\d+$/) ? +a : a; b = b.match(/^\\d+$/) ? +b : b; return ( (a < b) ? -1*direct : ((a > b) ? 1*direct : 0) ); }); return clone; }", + "type": "default", + "enabled": true + } ], "_postman_variable_scope": "environment", "_postman_exported_at": "2023-08-11T19:57:02.536Z", diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-multitenant-pgsql.postman_environment.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-multitenant-pgsql.postman_environment.json index eac8779a2..6a6a7cfa4 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-multitenant-pgsql.postman_environment.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-multitenant-pgsql.postman_environment.json @@ -43,7 +43,13 @@ "value": "Tenant2", "type": "default", "enabled": true - } + }, + { + "key": "sortByProperty", + "value": "function sortByProperty(objArray, prop, direction){ if (arguments.length<2) throw new Error(\"ARRAY, AND OBJECT PROPERTY MINIMUM ARGUMENTS, OPTIONAL DIRECTION\"); if (!Array.isArray(objArray)) throw new Error(\"FIRST ARGUMENT NOT AN ARRAY\"); const clone = objArray.slice(0); const direct = arguments.length>2 ? arguments[2] : 1; const propPath = (prop.constructor===Array) ? prop : prop.split(\".\"); clone.sort(function(a,b){ for (let p in propPath){ if (a[propPath[p]] && b[propPath[p]]){ a = a[propPath[p]]; b = b[propPath[p]]; } } a = a.match(/^\\d+$/) ? +a : a; b = b.match(/^\\d+$/) ? +b : b; return ( (a < b) ? -1*direct : ((a > b) ? 1*direct : 0) ); }); return clone; }", + "type": "default", + "enabled": true + } ], "_postman_variable_scope": "environment", "_postman_exported_at": "2023-08-11T19:57:02.536Z", diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json index 54c0fc11c..2a74a9fc7 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json @@ -906,12 +906,12 @@ " const minLength = 8;", " const maxLength = 24;", " let result = '';", - " const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';", - " // const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';", + " //const characters = 'abcdefghijklmnopqrstuvwxyz0123456789';", + " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';", " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;", "", " result += randomChar('abcdefghijklmnopqrstuvwxyz');", - " // result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');", + " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');", " result += randomChar('0123456789');", "", " for (let i = result.length; i < length; i++) {", @@ -1008,7 +1008,7 @@ " let totalToCreate = parseInt(pm.collectionVariables.get(\"ODSINSTANCECOUNT\"), 10);", " let odsInstancesToDelete = [];", " for (let i = 0; i < totalToCreate; i++) {", - " let name = `TestOdsInstance${generateAlphanumericString()}`;", + " let name = `TestOdsInstance-${generateAlphanumericString()}`;", " let instanceType = generateAlphanumericString();", " ", " pm.collectionVariables.set(\"FILTERNAME\", name);", From 8e5ce734700731d59eb8097023f108ca4afc3ced Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Sun, 25 Aug 2024 19:03:02 -0500 Subject: [PATCH 24/35] Fix the vendor's e2e --- ...Filtering - Vendor.postman_collection.json | 277 +++++++++--------- 1 file changed, 141 insertions(+), 136 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Vendor.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Vendor.postman_collection.json index 72ad095e8..dfd1ca1c0 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Vendor.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Vendor.postman_collection.json @@ -1,9 +1,9 @@ { "info": { - "_postman_id": "fdf70825-fa33-48e1-9f54-97c42903565c", + "_postman_id": "97521082-4124-44ad-ab08-aaf5c30ebd73", "name": "Admin API E2E 2.0 - Sorting and Filtering - Vendor", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "5260609" + "_exporter_id": "37902114" }, "item": [ { @@ -26,7 +26,10 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by Company asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.company.toLowerCase()],['asc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'company');\r", + " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.company.toLowerCase()],['asc']);\r", " \r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", @@ -109,8 +112,10 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by Company desc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.company.toLowerCase()],['desc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.company.toLowerCase()],['desc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'company', -1);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -366,8 +371,10 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by Company asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.company.toLowerCase()],['asc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.company.toLowerCase()],['asc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'company');\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -453,7 +460,10 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by Company desc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.company.toLowerCase()],['desc']);\r", + " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.company.toLowerCase()],['desc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'company', -1);\r", " \r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", @@ -540,8 +550,10 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by contactEmailAddress asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.contactEmailAddress.toLowerCase()],['asc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.contactEmailAddress.toLowerCase()],['asc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'contactEmailAddress');\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -627,8 +639,10 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by contactEmailAddress desc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.contactEmailAddress.toLowerCase()],['desc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.contactEmailAddress.toLowerCase()],['desc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'contactEmailAddress', -1);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -714,8 +728,10 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by ContactName asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.contactName.toLowerCase()],['asc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.contactName.toLowerCase()],['asc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'contactName');\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -801,8 +817,10 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by ContactName desc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.contactName.toLowerCase()],['desc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.contactName.toLowerCase()],['desc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'contactName', -1);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -888,8 +906,10 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by CamespacePrefixes asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.namespacePrefixes.toLowerCase()],['asc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.namespacePrefixes.toLowerCase()],['asc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'namespacePrefixes');\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -975,8 +995,10 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by NamespacePrefixes desc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.namespacePrefixes.toLowerCase()],['desc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.namespacePrefixes.toLowerCase()],['desc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'namespacePrefixes', -1);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -1380,8 +1402,6 @@ "/// Authentication\r", "/// -------\r", "\r", - "let header = {};\r", - "\r", "function generateClientSecret() {\r", " const minLength = 32;\r", " const maxLength = 128;\r", @@ -1416,62 +1436,45 @@ " return array.join('');\r", "}\r", "\r", - "const RegisterAndGetToken = () => new Promise((resolve) => {\r", - " let guid = pm.variables.replaceIn('{{$guid}}');\r", - " let client_secret = generateClientSecret();\r", - "\r", - " let header = {\r", - " 'Content-Type': 'application/x-www-form-urlencoded'\r", - " };\r", + "var guid = pm.variables.replaceIn('{{$guid}}');\r", + "var client_secret = generateClientSecret();\r", + "var header = {\r", + " 'Content-Type': 'application/x-www-form-urlencoded'\r", + "};\r", "\r", - " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", - " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", - " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", + "const registerRequest = {\r", + " url: `${pm.variables.get(\"API_URL\")}/connect/register`,\r", + " method: 'POST',\r", + " header: header,\r", + " body: {\r", + " mode: 'urlencoded',\r", + " urlencoded: [\r", + " {key: 'ClientId', value: guid },\r", + " {key: 'ClientSecret', value: client_secret },\r", + " {key: 'DisplayName', value: guid }\r", + " ]\r", " }\r", + "}\r", "\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/connect/register`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'urlencoded',\r", - " urlencoded: [\r", - " {key: 'ClientId', value: guid },\r", - " {key: 'ClientSecret', value: client_secret },\r", - " {key: 'DisplayName', value: guid }\r", - " ]\r", - " }\r", - " },\r", - " (err, res) => {\r", - " error = res.json().error\r", - " if(error) {\r", - " throw res.json().error_description\r", - " }\r", + "const tokenRequest = {\r", + " url: `${pm.variables.get(\"API_URL\")}/connect/token`,\r", + " method: 'POST',\r", + " header: header,\r", + " body: {\r", + " mode: 'urlencoded',\r", + " urlencoded: [\r", + " {key: 'client_id', value: guid },\r", + " {key: 'client_secret', value: client_secret },\r", + " {key: 'grant_type', value: \"client_credentials\"},\r", + " {key: 'scope', value: \"edfi_admin_api/full_access\"}\r", + " ]\r", + " }\r", + "}\r", "\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/connect/token`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'urlencoded',\r", - " urlencoded: [\r", - " {key: 'client_id', value: guid },\r", - " {key: 'client_secret', value: client_secret },\r", - " {key: 'grant_type', value: \"client_credentials\"},\r", - " {key: 'scope', value: \"edfi_admin_api/full_access\"}\r", - " ]\r", - " }\r", - " },\r", - " (err, res) => {\r", - " error = res.json().error\r", - " if(error) {\r", - " throw res.json().error_description\r", - " }\r", - " pm.collectionVariables.set(\"TOKEN\", res.json().access_token);\r", - " resolve();\r", - " });\r", - " });\r", - "});\r", + "if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", + " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", + " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", + "}\r", "\r", "/// -------\r", "/// Vendors\r", @@ -1495,53 +1498,62 @@ " return shuffleString(result);\r", "}\r", "\r", - "const createVendor = (company, namespacePrefixes, contactName, contactEmailAddress) => new Promise((resolve) => {\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/v2/vendors`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'raw',\r", - " raw: JSON.stringify({ \"company\": `${company}`, \"namespacePrefixes\": `${namespacePrefixes}`, \"contactName\": `${contactName}`, \"contactEmailAddress\": `${contactEmailAddress}` })\r", + "pm.sendRequest(registerRequest,\r", + " (err, res) => {\r", + " let error = res.json().error\r", + " if(error) {\r", + " throw res.json().error_description\r", " }\r", - " }, (err, res) => {\r", - " let location = res.headers.get('Location');\r", - " let matches = location.match(/(\\d+)/);\r", - " vendorId = parseInt(matches[0], 10);\r", - " resolve(vendorId);\r", - " });\r", - "});\r", - "\r", - "(async function () {\r", - " await RegisterAndGetToken();\r", - "\r", - " header = {\r", - " 'Content-Type': 'application/json',\r", - " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`\r", - " };\r", - "\r", - " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", - " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", - " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", - " }\r", "\r", - " let vendorsToDelete = [];\r", - " for (let i = 0; i < parseInt(pm.collectionVariables.get(\"VENDORSCOUNT\"), 10); i++) {\r", - " let company = generateAlphanumericString();\r", - " let namespacePrefixes = `uri://${generateAlphanumericString()}.org`;\r", - " let contactName = generateAlphanumericString();\r", - " let contactEmailAddress = `${generateAlphanumericString()}@test-ed-fi.org`;\r", + " pm.sendRequest(tokenRequest,\r", + " (err, res) => {\r", + " let error = res.json().error\r", + " if(error) {\r", + " throw res.json().error_description\r", + " }\r", + " pm.collectionVariables.set(\"TOKEN\", res.json().access_token)\r", "\r", - " pm.collectionVariables.set(\"FILTERCOMPANY\", company);\r", - " pm.collectionVariables.set(\"FILTERNAMESPACEPREFIXES\", namespacePrefixes);\r", - " pm.collectionVariables.set(\"FILTERCONTACTNAME\", contactName);\r", - " pm.collectionVariables.set(\"FILTERCONTACTEMAILADDRESS\", contactEmailAddress);\r", + " header = {\r", + " 'Content-Type': 'application/json',\r", + " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`\r", + " };\r", + " \r", + " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", + " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", + " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", + " }\r", + " let totalToCreate = parseInt(pm.collectionVariables.get(\"VENDORSCOUNT\"), 10);\r", + " let vendorsToDelete = [];\r", + " for (let i = 0; i < totalToCreate; i++) {\r", + " let company = generateAlphanumericString();\r", + " let namespacePrefixes = `uri://${generateAlphanumericString()}.org`;\r", + " let contactName = generateAlphanumericString();\r", + " let contactEmailAddress = `${generateAlphanumericString()}@test-ed-fi.org`;\r", "\r", - " vendorsToDelete.push(await createVendor(company, namespacePrefixes, contactName, contactEmailAddress).then(vendorId => vendorId));\r", - " }\r", - "\r", - " pm.collectionVariables.set(\"VENDORSTODELETE\", JSON.stringify(vendorsToDelete));\r", - "})();\r", + " pm.collectionVariables.set(\"FILTERCOMPANY\", company);\r", + " pm.collectionVariables.set(\"FILTERNAMESPACEPREFIXES\", namespacePrefixes);\r", + " pm.collectionVariables.set(\"FILTERCONTACTNAME\", contactName);\r", + " pm.collectionVariables.set(\"FILTERCONTACTEMAILADDRESS\", contactEmailAddress);\r", + " \r", + " pm.sendRequest({\r", + " url: `${pm.variables.get(\"API_URL\")}/v2/vendors`,\r", + " method: 'POST',\r", + " header: header,\r", + " body: {\r", + " mode: 'raw',\r", + " raw: JSON.stringify({ \"company\": `${company}`, \"namespacePrefixes\": `${namespacePrefixes}`, \"contactName\": `${contactName}`, \"contactEmailAddress\": `${contactEmailAddress}` })\r", + " }\r", + " }, (err, res) => {\r", + " let location = res.headers.get('Location');\r", + " let matches = location.match(/(\\d+)/);\r", + " vendorId = parseInt(matches[0], 10);\r", + " // odsInstancesToDelete.push({id: odsInstanceId, name: name, instanceType: instanceType});\r", + " vendorsToDelete.push(vendorId);\r", + " });\r", + " }\r", + " pm.collectionVariables.set(\"VENDORSTODELETE\", JSON.stringify(vendorsToDelete));\r", + " });\r", + "});\r", "" ] } @@ -1563,26 +1575,19 @@ " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", "}\r", "\r", - "function deleteVendorById(id) {\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/v2/vendors/${id}`,\r", - " method: 'DELETE',\r", - " header: header\r", - " }, function (err, res) {\r", - " if (err) {\r", - " console.log(err);\r", - " }\r", - " });\r", - "}\r", - "\r", - "function deleteVendors() {\r", - " let vendorsToDelete = JSON.parse(pm.variables.get(\"VENDORSTODELETE\"));\r", - " for (let i = 0; i < vendorsToDelete.length; i++) {\r", - " deleteVendorById(vendorsToDelete[i]);\r", - " }\r", + "let vendorsToDelete = JSON.parse(pm.variables.get(\"VENDORSTODELETE\"));\r", + "for (let i = 0; i < vendorsToDelete.length; i++) {\r", + " pm.sendRequest({ \r", + " url: `${pm.variables.get(\"API_URL\")}/v2/vendors/${id}`,\r", + " method: 'DELETE',\r", + " header: header\r", + " }, function (err, res) {\r", + " if (err) {\r", + " console.log(err);\r", + " }\r", + " });\r", "}\r", - "\r", - "deleteVendors();" + "" ] } } From 8cf4ffa38cb79f9ebc6e6250c97e9c37ca23753e Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Sun, 25 Aug 2024 22:40:50 -0500 Subject: [PATCH 25/35] Add jshelper as a variable. Modify profile's e2e --- ...multitenant-mssql.postman_environment.json | 8 +- ...multitenant-pgsql.postman_environment.json | 8 +- ...cker-single-mssql.postman_environment.json | 8 +- ...cker-single-pgsql.postman_environment.json | 8 +- ...iltering - Profile.postman_collection.json | 278 ++++++++---------- ...Filtering - Vendor.postman_collection.json | 58 +--- .../Admin API.postman_environment.json | 24 +- 7 files changed, 174 insertions(+), 218 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-multitenant-mssql.postman_environment.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-multitenant-mssql.postman_environment.json index 6a9538de5..f4d0500f3 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-multitenant-mssql.postman_environment.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-multitenant-mssql.postman_environment.json @@ -49,7 +49,13 @@ "value": "function sortByProperty(objArray, prop, direction){ if (arguments.length<2) throw new Error(\"ARRAY, AND OBJECT PROPERTY MINIMUM ARGUMENTS, OPTIONAL DIRECTION\"); if (!Array.isArray(objArray)) throw new Error(\"FIRST ARGUMENT NOT AN ARRAY\"); const clone = objArray.slice(0); const direct = arguments.length>2 ? arguments[2] : 1; const propPath = (prop.constructor===Array) ? prop : prop.split(\".\"); clone.sort(function(a,b){ for (let p in propPath){ if (a[propPath[p]] && b[propPath[p]]){ a = a[propPath[p]]; b = b[propPath[p]]; } } a = a.match(/^\\d+$/) ? +a : a; b = b.match(/^\\d+$/) ? +b : b; return ( (a < b) ? -1*direct : ((a > b) ? 1*direct : 0) ); }); return clone; }", "type": "default", "enabled": true - } + }, + { + "key": "jsHelper", + "value": "(function () { const rndChar = function (str) { return str.charAt(Math.floor(Math.random() * str.length)); }; const shfChar = function (str) { const array = str.split(''); for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array.join(''); }; return { generateClientSecret: function(){ const minLength = 32; const maxLength = 128; let result = ''; const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const specialCharacters = '!@#$%^&*()_+{}:\"<>?|[];\\',./`~'; const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength; result += rndChar('abcdefghijklmnopqrstuvwxyz'); result += rndChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ'); result += rndChar('0123456789'); result += rndChar(specialCharacters); for (let i = result.length; i < length; i++) { const charactersPlusSpecial = characters + specialCharacters; result += charactersPlusSpecial.charAt(Math.floor(Math.random() * charactersPlusSpecial.length)); } return shfChar(result); }, randomChar : rndChar, shuffleString: shfChar } })", + "type": "default", + "enabled": true + } ], "_postman_variable_scope": "environment", "_postman_exported_at": "2023-08-11T19:57:02.536Z", diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-multitenant-pgsql.postman_environment.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-multitenant-pgsql.postman_environment.json index 6a6a7cfa4..3db46273a 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-multitenant-pgsql.postman_environment.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-multitenant-pgsql.postman_environment.json @@ -49,7 +49,13 @@ "value": "function sortByProperty(objArray, prop, direction){ if (arguments.length<2) throw new Error(\"ARRAY, AND OBJECT PROPERTY MINIMUM ARGUMENTS, OPTIONAL DIRECTION\"); if (!Array.isArray(objArray)) throw new Error(\"FIRST ARGUMENT NOT AN ARRAY\"); const clone = objArray.slice(0); const direct = arguments.length>2 ? arguments[2] : 1; const propPath = (prop.constructor===Array) ? prop : prop.split(\".\"); clone.sort(function(a,b){ for (let p in propPath){ if (a[propPath[p]] && b[propPath[p]]){ a = a[propPath[p]]; b = b[propPath[p]]; } } a = a.match(/^\\d+$/) ? +a : a; b = b.match(/^\\d+$/) ? +b : b; return ( (a < b) ? -1*direct : ((a > b) ? 1*direct : 0) ); }); return clone; }", "type": "default", "enabled": true - } + }, + { + "key": "jsHelper", + "value": "(function () { const rndChar = function (str) { return str.charAt(Math.floor(Math.random() * str.length)); }; const shfChar = function (str) { const array = str.split(''); for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array.join(''); }; return { generateClientSecret: function(){ const minLength = 32; const maxLength = 128; let result = ''; const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const specialCharacters = '!@#$%^&*()_+{}:\"<>?|[];\\',./`~'; const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength; result += rndChar('abcdefghijklmnopqrstuvwxyz'); result += rndChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ'); result += rndChar('0123456789'); result += rndChar(specialCharacters); for (let i = result.length; i < length; i++) { const charactersPlusSpecial = characters + specialCharacters; result += charactersPlusSpecial.charAt(Math.floor(Math.random() * charactersPlusSpecial.length)); } return shfChar(result); }, randomChar : rndChar, shuffleString: shfChar } })", + "type": "default", + "enabled": true + } ], "_postman_variable_scope": "environment", "_postman_exported_at": "2023-08-11T19:57:02.536Z", diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-single-mssql.postman_environment.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-single-mssql.postman_environment.json index d466bb089..ea3e9244e 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-single-mssql.postman_environment.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-single-mssql.postman_environment.json @@ -37,7 +37,13 @@ "value": "function sortByProperty(objArray, prop, direction){ if (arguments.length<2) throw new Error(\"ARRAY, AND OBJECT PROPERTY MINIMUM ARGUMENTS, OPTIONAL DIRECTION\"); if (!Array.isArray(objArray)) throw new Error(\"FIRST ARGUMENT NOT AN ARRAY\"); const clone = objArray.slice(0); const direct = arguments.length>2 ? arguments[2] : 1; const propPath = (prop.constructor===Array) ? prop : prop.split(\".\"); clone.sort(function(a,b){ for (let p in propPath){ if (a[propPath[p]] && b[propPath[p]]){ a = a[propPath[p]]; b = b[propPath[p]]; } } a = a.match(/^\\d+$/) ? +a : a; b = b.match(/^\\d+$/) ? +b : b; return ( (a < b) ? -1*direct : ((a > b) ? 1*direct : 0) ); }); return clone; }", "type": "default", "enabled": true - } + }, + { + "key": "jsHelper", + "value": "(function () { const rndChar = function (str) { return str.charAt(Math.floor(Math.random() * str.length)); }; const shfChar = function (str) { const array = str.split(''); for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array.join(''); }; return { generateClientSecret: function(){ const minLength = 32; const maxLength = 128; let result = ''; const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const specialCharacters = '!@#$%^&*()_+{}:\"<>?|[];\\',./`~'; const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength; result += rndChar('abcdefghijklmnopqrstuvwxyz'); result += rndChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ'); result += rndChar('0123456789'); result += rndChar(specialCharacters); for (let i = result.length; i < length; i++) { const charactersPlusSpecial = characters + specialCharacters; result += charactersPlusSpecial.charAt(Math.floor(Math.random() * charactersPlusSpecial.length)); } return shfChar(result); }, randomChar : rndChar, shuffleString: shfChar } })", + "type": "default", + "enabled": true + } ], "_postman_variable_scope": "environment", "_postman_exported_at": "2023-08-11T19:57:02.536Z", diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-single-pgsql.postman_environment.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-single-pgsql.postman_environment.json index db298fd25..90bb4af13 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-single-pgsql.postman_environment.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API Docker-single-pgsql.postman_environment.json @@ -37,7 +37,13 @@ "value": "function sortByProperty(objArray, prop, direction){ if (arguments.length<2) throw new Error(\"ARRAY, AND OBJECT PROPERTY MINIMUM ARGUMENTS, OPTIONAL DIRECTION\"); if (!Array.isArray(objArray)) throw new Error(\"FIRST ARGUMENT NOT AN ARRAY\"); const clone = objArray.slice(0); const direct = arguments.length>2 ? arguments[2] : 1; const propPath = (prop.constructor===Array) ? prop : prop.split(\".\"); clone.sort(function(a,b){ for (let p in propPath){ if (a[propPath[p]] && b[propPath[p]]){ a = a[propPath[p]]; b = b[propPath[p]]; } } a = a.match(/^\\d+$/) ? +a : a; b = b.match(/^\\d+$/) ? +b : b; return ( (a < b) ? -1*direct : ((a > b) ? 1*direct : 0) ); }); return clone; }", "type": "default", "enabled": true - } + }, + { + "key": "jsHelper", + "value": "(function () { const rndChar = function (str) { return str.charAt(Math.floor(Math.random() * str.length)); }; const shfChar = function (str) { const array = str.split(''); for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array.join(''); }; return { generateClientSecret: function(){ const minLength = 32; const maxLength = 128; let result = ''; const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const specialCharacters = '!@#$%^&*()_+{}:\"<>?|[];\\',./`~'; const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength; result += rndChar('abcdefghijklmnopqrstuvwxyz'); result += rndChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ'); result += rndChar('0123456789'); result += rndChar(specialCharacters); for (let i = result.length; i < length; i++) { const charactersPlusSpecial = characters + specialCharacters; result += charactersPlusSpecial.charAt(Math.floor(Math.random() * charactersPlusSpecial.length)); } return shfChar(result); }, randomChar : rndChar, shuffleString: shfChar } })", + "type": "default", + "enabled": true + } ], "_postman_variable_scope": "environment", "_postman_exported_at": "2023-08-11T19:57:02.536Z", diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Profile.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Profile.postman_collection.json index c686cd714..af022fff9 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Profile.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Profile.postman_collection.json @@ -1,9 +1,9 @@ { "info": { - "_postman_id": "a1009842-eb76-4bc6-b8d7-0d40ca7d500b", + "_postman_id": "25fa645a-e896-41fb-842b-5a7865a60323", "name": "Admin API E2E 2.0 - Sorting and Filtering - Profile", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "5260609" + "_exporter_id": "37902114" }, "item": [ { @@ -26,8 +26,10 @@ "\r", "pm.test(\"GET Profiles: Response result is ordered by Name asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [profile => profile.name.toLowerCase()],['asc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [profile => profile.name.toLowerCase()],['asc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'name');\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -109,8 +111,10 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by Name desc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [profile => profile.name.toLowerCase()],['desc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [profile => profile.name.toLowerCase()],['desc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'name', -1);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -366,8 +370,10 @@ "\r", "pm.test(\"GET Profiles: Response result is ordered by Name asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [profile => profile.name.toLowerCase()],['asc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [profile => profile.name.toLowerCase()],['asc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'name');\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -442,19 +448,21 @@ "exec": [ "var _ = require('lodash');\r", "\r", - "pm.test(\"GET Vendors: Status code is OK\", function () {\r", + "pm.test(\"GET Profiles: Status code is OK\", function () {\r", " pm.response.to.have.status(200);\r", "});\r", "\r", - "pm.test(\"GET Vendors: Response result includes vendors\", function () {\r", + "pm.test(\"GET Profiles: Response result includes profiles\", function () {\r", " const results = pm.response.json();\r", " pm.expect(results.length).to.be.greaterThan(0); \r", "});\r", "\r", - "pm.test(\"GET Vendors: Response result is ordered by Name desc\", function () {\r", + "pm.test(\"GET Profiles: Response result is ordered by Name desc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [profile => profile.name.toLowerCase()],['desc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [profile => profile.name.toLowerCase()],['desc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'name', -1);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -621,98 +629,47 @@ "/// Authentication\r", "/// -------\r", "\r", - "let header = {};\r", - "\r", - "function generateClientSecret() {\r", - " const minLength = 32;\r", - " const maxLength = 128;\r", - " let result = '';\r", - " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r", - " const specialCharacters = '!@#$%^&*()_+{}:\"<>?|[];\\',./`~';\r", - " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;\r", - "\r", - " result += randomChar('abcdefghijklmnopqrstuvwxyz');\r", - " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');\r", - " result += randomChar('0123456789');\r", - " result += randomChar(specialCharacters);\r", + "const jsHelperVar = pm.variables.get('jsHelper');\r", + "const jsHelper = eval(jsHelperVar);\r", + "var guid = pm.variables.replaceIn('{{$guid}}');\r", + "var client_secret = jsHelper().generateClientSecret();\r", + "var header = {\r", + " 'Content-Type': 'application/x-www-form-urlencoded'\r", + "};\r", "\r", - " for (let i = result.length; i < length; i++) {\r", - " const charactersPlusSpecial = characters + specialCharacters;\r", - " result += charactersPlusSpecial.charAt(Math.floor(Math.random() * charactersPlusSpecial.length));\r", + "const registerRequest = {\r", + " url: `${pm.variables.get(\"API_URL\")}/connect/register`,\r", + " method: 'POST',\r", + " header: header,\r", + " body: {\r", + " mode: 'urlencoded',\r", + " urlencoded: [\r", + " {key: 'ClientId', value: guid },\r", + " {key: 'ClientSecret', value: client_secret },\r", + " {key: 'DisplayName', value: guid }\r", + " ]\r", " }\r", - "\r", - " return shuffleString(result);\r", - "}\r", - "\r", - "function randomChar(str) {\r", - " return str.charAt(Math.floor(Math.random() * str.length));\r", "}\r", "\r", - "function shuffleString(str) {\r", - " const array = str.split('');\r", - " for (let i = array.length - 1; i > 0; i--) {\r", - " const j = Math.floor(Math.random() * (i + 1));\r", - " [array[i], array[j]] = [array[j], array[i]];\r", + "const tokenRequest = {\r", + " url: `${pm.variables.get(\"API_URL\")}/connect/token`,\r", + " method: 'POST',\r", + " header: header,\r", + " body: {\r", + " mode: 'urlencoded',\r", + " urlencoded: [\r", + " {key: 'client_id', value: guid },\r", + " {key: 'client_secret', value: client_secret },\r", + " {key: 'grant_type', value: \"client_credentials\"},\r", + " {key: 'scope', value: \"edfi_admin_api/full_access\"}\r", + " ]\r", " }\r", - " return array.join('');\r", "}\r", "\r", - "const RegisterAndGetToken = () => new Promise((resolve) => {\r", - " let guid = pm.variables.replaceIn('{{$guid}}');\r", - " let client_secret = generateClientSecret();\r", - "\r", - " let header = {\r", - " 'Content-Type': 'application/x-www-form-urlencoded'\r", - " };\r", - "\r", - " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", - " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", - " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", - " }\r", - "\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/connect/register`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'urlencoded',\r", - " urlencoded: [\r", - " {key: 'ClientId', value: guid },\r", - " {key: 'ClientSecret', value: client_secret },\r", - " {key: 'DisplayName', value: guid }\r", - " ]\r", - " }\r", - " },\r", - " (err, res) => {\r", - " error = res.json().error\r", - " if(error) {\r", - " throw res.json().error_description\r", - " }\r", - "\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/connect/token`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'urlencoded',\r", - " urlencoded: [\r", - " {key: 'client_id', value: guid },\r", - " {key: 'client_secret', value: client_secret },\r", - " {key: 'grant_type', value: \"client_credentials\"},\r", - " {key: 'scope', value: \"edfi_admin_api/full_access\"}\r", - " ]\r", - " }\r", - " },\r", - " (err, res) => {\r", - " error = res.json().error\r", - " if(error) {\r", - " throw res.json().error_description\r", - " }\r", - " pm.collectionVariables.set(\"TOKEN\", res.json().access_token);\r", - " resolve();\r", - " });\r", - " });\r", - "});\r", + "if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", + " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", + " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", + "}\r", "\r", "/// -------\r", "/// Profiles\r", @@ -725,58 +682,67 @@ " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r", " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;\r", "\r", - " result += randomChar('abcdefghijklmnopqrstuvwxyz');\r", - " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');\r", - " result += randomChar('0123456789');\r", + " result += jsHelper().randomChar('abcdefghijklmnopqrstuvwxyz');\r", + " result += jsHelper().randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');\r", + " result += jsHelper().randomChar('0123456789');\r", "\r", " for (let i = result.length; i < length; i++) {\r", " result += characters.charAt(Math.floor(Math.random() * characters.length));\r", " }\r", "\r", - " return shuffleString(result);\r", + " return jsHelper().shuffleString(result);\r", "}\r", "\r", - "const createProfile = (name) => new Promise((resolve) => {\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/v2/profiles`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'raw',\r", - " raw: JSON.stringify({ \"name\": `${name}`, \"definition\": `` })\r", + "pm.sendRequest(registerRequest,\r", + " (err, res) => {\r", + " let error = res.json().error\r", + " if(error) {\r", + " throw res.json().error_description\r", " }\r", - " }, (err, res) => {\r", - " let location = res.headers.get('Location');\r", - " let matches = location.match(/(\\d+)/);\r", - " profileId = parseInt(matches[0], 10);\r", - " resolve(profileId);\r", - " });\r", - "});\r", "\r", - "(async function () {\r", - " await RegisterAndGetToken();\r", + " pm.sendRequest(tokenRequest,\r", + " (err, res) => {\r", + " let error = res.json().error\r", + " if(error) {\r", + " throw res.json().error_description\r", + " }\r", + " pm.collectionVariables.set(\"TOKEN\", res.json().access_token)\r", "\r", - " header = {\r", - " 'Content-Type': 'application/json',\r", - " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`\r", - " };\r", - "\r", - " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", - " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", - " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", - " }\r", + " header = {\r", + " 'Content-Type': 'application/json',\r", + " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`\r", + " };\r", + " \r", + " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", + " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", + " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", + " }\r", + " let totalToCreate = parseInt(pm.collectionVariables.get(\"PROFILECOUNT\"), 10);\r", + " var profilesToDelete = [];\r", + " for (let i = 0; i < totalToCreate; i++) {\r", + " let name = generateAlphanumericString();\r", + " pm.collectionVariables.set(\"FILTERNAME\", name);\r", + " \r", "\r", - " let profilesToDelete = [];\r", - " for (let i = 0; i < parseInt(pm.collectionVariables.get(\"PROFILECOUNT\"), 10); i++) {\r", - " let name = generateAlphanumericString();\r", - "\r", - " pm.collectionVariables.set(\"FILTERNAME\", name);\r", - "\r", - " profilesToDelete.push(await createProfile(name).then(profileId => profileId));\r", - " }\r", - "\r", - " pm.collectionVariables.set(\"PROFILESTODELETE\", JSON.stringify(profilesToDelete));\r", - "})();" + " pm.sendRequest({\r", + " url: `${pm.variables.get(\"API_URL\")}/v2/profiles`,\r", + " method: 'POST',\r", + " header: header,\r", + " body: {\r", + " mode: 'raw',\r", + " raw: JSON.stringify({ \"name\": `${name}`, \"definition\": `` })\r", + " }\r", + " }, (err, res) => {\r", + " let location = res.headers.get('Location');\r", + " let matches = location.match(/(\\d+)/);\r", + " profileId = parseInt(matches[0], 10);\r", + " profilesToDelete.push(profileId)\r", + " });\r", + " }\r", + " pm.collectionVariables.set(\"PROFILESTODELETE\", profilesToDelete);\r", + " });\r", + "});\r", + "" ] } }, @@ -796,27 +762,19 @@ " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", "}\r", - "\r", - "function deleteProfileById(id) {\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/v2/profiles/${id}`,\r", - " method: 'DELETE',\r", - " header: header\r", - " }, function (err, res) {\r", - " if (err) {\r", - " console.log(err);\r", - " }\r", - " });\r", - "}\r", - "\r", - "function deleteProfiles() {\r", - " let profilesToDelete = JSON.parse(pm.variables.get(\"PROFILESTODELETE\"));\r", - " for (let i = 0; i < profilesToDelete.length; i++) {\r", - " deleteProfileById(profilesToDelete[i]);\r", - " }\r", - "}\r", - "\r", - "deleteProfiles();" + "let idsToDelete = pm.collectionVariables.get(\"PROFILESTODELETE\");\r", + "for (let i = 0; i < idsToDelete.length; i++) {\r", + " let id = idsToDelete[i];\r", + " pm.sendRequest({ \r", + " url: `${pm.variables.get(\"API_URL\")}/v2/profiles/${id}`,\r", + " method: 'DELETE',\r", + " header: header\r", + " }, function (err, res) {\r", + " if (err) {\r", + " console.log(err);\r", + " }\r", + " });\r", + "}" ] } } diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Vendor.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Vendor.postman_collection.json index dfd1ca1c0..06a597c40 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Vendor.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Vendor.postman_collection.json @@ -1402,42 +1402,10 @@ "/// Authentication\r", "/// -------\r", "\r", - "function generateClientSecret() {\r", - " const minLength = 32;\r", - " const maxLength = 128;\r", - " let result = '';\r", - " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r", - " const specialCharacters = '!@#$%^&*()_+{}:\"<>?|[];\\',./`~';\r", - " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;\r", - "\r", - " result += randomChar('abcdefghijklmnopqrstuvwxyz');\r", - " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');\r", - " result += randomChar('0123456789');\r", - " result += randomChar(specialCharacters);\r", - "\r", - " for (let i = result.length; i < length; i++) {\r", - " const charactersPlusSpecial = characters + specialCharacters;\r", - " result += charactersPlusSpecial.charAt(Math.floor(Math.random() * charactersPlusSpecial.length));\r", - " }\r", - "\r", - " return shuffleString(result);\r", - "}\r", - "\r", - "function randomChar(str) {\r", - " return str.charAt(Math.floor(Math.random() * str.length));\r", - "}\r", - "\r", - "function shuffleString(str) {\r", - " const array = str.split('');\r", - " for (let i = array.length - 1; i > 0; i--) {\r", - " const j = Math.floor(Math.random() * (i + 1));\r", - " [array[i], array[j]] = [array[j], array[i]];\r", - " }\r", - " return array.join('');\r", - "}\r", - "\r", + "const jsHelperVar = pm.variables.get('jsHelper');\r", + "const jsHelper = eval(jsHelperVar);\r", "var guid = pm.variables.replaceIn('{{$guid}}');\r", - "var client_secret = generateClientSecret();\r", + "var client_secret = jsHelper().generateClientSecret();\r", "var header = {\r", " 'Content-Type': 'application/x-www-form-urlencoded'\r", "};\r", @@ -1487,15 +1455,15 @@ " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r", " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;\r", "\r", - " result += randomChar('abcdefghijklmnopqrstuvwxyz');\r", - " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');\r", - " result += randomChar('0123456789');\r", + " result += jsHelper().randomChar('abcdefghijklmnopqrstuvwxyz');\r", + " result += jsHelper().randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');\r", + " result += jsHelper().randomChar('0123456789');\r", "\r", " for (let i = result.length; i < length; i++) {\r", " result += characters.charAt(Math.floor(Math.random() * characters.length));\r", " }\r", "\r", - " return shuffleString(result);\r", + " return jsHelper().shuffleString(result);\r", "}\r", "\r", "pm.sendRequest(registerRequest,\r", @@ -1523,7 +1491,7 @@ " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", " }\r", " let totalToCreate = parseInt(pm.collectionVariables.get(\"VENDORSCOUNT\"), 10);\r", - " let vendorsToDelete = [];\r", + " var vendorsToDelete = [];\r", " for (let i = 0; i < totalToCreate; i++) {\r", " let company = generateAlphanumericString();\r", " let namespacePrefixes = `uri://${generateAlphanumericString()}.org`;\r", @@ -1551,7 +1519,7 @@ " vendorsToDelete.push(vendorId);\r", " });\r", " }\r", - " pm.collectionVariables.set(\"VENDORSTODELETE\", JSON.stringify(vendorsToDelete));\r", + " pm.collectionVariables.set(\"VENDORSTODELETE\", vendorsToDelete);\r", " });\r", "});\r", "" @@ -1574,9 +1542,10 @@ " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", "}\r", - "\r", - "let vendorsToDelete = JSON.parse(pm.variables.get(\"VENDORSTODELETE\"));\r", + "let vendorsToDelete = pm.collectionVariables.get(\"VENDORSTODELETE\");\r", "for (let i = 0; i < vendorsToDelete.length; i++) {\r", + " console.log(vendorsToDelete)\r", + " let id = vendorsToDelete[i];\r", " pm.sendRequest({ \r", " url: `${pm.variables.get(\"API_URL\")}/v2/vendors/${id}`,\r", " method: 'DELETE',\r", @@ -1586,8 +1555,7 @@ " console.log(err);\r", " }\r", " });\r", - "}\r", - "" + "}" ] } } diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API.postman_environment.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API.postman_environment.json index 900508bb6..5ccdf4851 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API.postman_environment.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API.postman_environment.json @@ -1,5 +1,5 @@ { - "id": "3fe4fa23-95ab-4005-a97c-d519911a9a29", + "id": "dde8ae58-e386-4794-a055-ac62bc2e2eaa", "name": "Admin API", "values": [ { @@ -33,13 +33,19 @@ "enabled": true }, { - "key": "sortByProperty", - "value": "function sortByProperty(objArray, prop, direction){ if (arguments.length<2) throw new Error(\"ARRAY, AND OBJECT PROPERTY MINIMUM ARGUMENTS, OPTIONAL DIRECTION\"); if (!Array.isArray(objArray)) throw new Error(\"FIRST ARGUMENT NOT AN ARRAY\"); const clone = objArray.slice(0); const direct = arguments.length>2 ? arguments[2] : 1; const propPath = (prop.constructor===Array) ? prop : prop.split(\".\"); clone.sort(function(a,b){ for (let p in propPath){ if (a[propPath[p]] && b[propPath[p]]){ a = a[propPath[p]]; b = b[propPath[p]]; } } a = a.match(/^\\d+$/) ? +a : a; b = b.match(/^\\d+$/) ? +b : b; return ( (a < b) ? -1*direct : ((a > b) ? 1*direct : 0) ); }); return clone; }", - "type": "default", - "enabled": true - } + "key": "sortByProperty", + "value": "function sortByProperty(objArray, prop, direction){ if (arguments.length<2) throw new Error(\"ARRAY, AND OBJECT PROPERTY MINIMUM ARGUMENTS, OPTIONAL DIRECTION\"); if (!Array.isArray(objArray)) throw new Error(\"FIRST ARGUMENT NOT AN ARRAY\"); const clone = objArray.slice(0); const direct = arguments.length>2 ? arguments[2] : 1; const propPath = (prop.constructor===Array) ? prop : prop.split(\".\"); clone.sort(function(a,b){ for (let p in propPath){ if (a[propPath[p]] && b[propPath[p]]){ a = a[propPath[p]]; b = b[propPath[p]]; } } a = a.match(/^\\d+$/) ? +a : a; b = b.match(/^\\d+$/) ? +b : b; return ( (a < b) ? -1*direct : ((a > b) ? 1*direct : 0) ); }); return clone; }", + "type": "default", + "enabled": true + }, + { + "key": "jsHelper", + "value": "(function () { const rndChar = function (str) { return str.charAt(Math.floor(Math.random() * str.length)); }; const shfChar = function (str) { const array = str.split(''); for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array.join(''); }; return { generateClientSecret: function(){ const minLength = 32; const maxLength = 128; let result = ''; const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const specialCharacters = '!@#$%^&*()_+{}:\"<>?|[];\\',./`~'; const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength; result += rndChar('abcdefghijklmnopqrstuvwxyz'); result += rndChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ'); result += rndChar('0123456789'); result += rndChar(specialCharacters); for (let i = result.length; i < length; i++) { const charactersPlusSpecial = characters + specialCharacters; result += charactersPlusSpecial.charAt(Math.floor(Math.random() * charactersPlusSpecial.length)); } return shfChar(result); }, randomChar : rndChar, shuffleString: shfChar } })", + "type": "default", + "enabled": true + } ], "_postman_variable_scope": "environment", - "_postman_exported_at": "2023-08-11T19:49:43.269Z", - "_postman_exported_using": "Postman/10.17.0" -} + "_postman_exported_at": "2024-08-26T03:23:09.412Z", + "_postman_exported_using": "Postman/11.9.2" +} \ No newline at end of file From 49182871a2bcf7a232acb1922fa2475ddfc143eb Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Mon, 26 Aug 2024 09:01:11 -0500 Subject: [PATCH 26/35] Fix the ifs statements in connectionstringhelper --- .../Infrastructure/Helpers/ConnectionStringHelper.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Helpers/ConnectionStringHelper.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Helpers/ConnectionStringHelper.cs index 1328b8854..0c95c685a 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Helpers/ConnectionStringHelper.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Helpers/ConnectionStringHelper.cs @@ -15,7 +15,7 @@ public static class ConnectionStringHelper public static bool ValidateConnectionString(string databaseEngine, string? connectionString) { bool result = true; - if (databaseEngine == "SqlServer") + if (databaseEngine.ToLowerInvariant() == DatabaseEngineEnum.SqlServer.ToLowerInvariant()) { try { @@ -32,7 +32,7 @@ ex is FormatException || } } } - else if (databaseEngine == "PostgreSQL") + else if (databaseEngine.ToLowerInvariant() == DatabaseEngineEnum.PostgreSql.ToLowerInvariant()) { try { From c042ceaed3a0c3c7fcb781a628b3e763d803cee2 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Mon, 26 Aug 2024 09:48:10 -0500 Subject: [PATCH 27/35] Fix the Claimsets e2e --- ...ltering - Claimset.postman_collection.json | 308 ++++++++---------- 1 file changed, 135 insertions(+), 173 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Claimset.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Claimset.postman_collection.json index 6ba82222f..c82c51872 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Claimset.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Claimset.postman_collection.json @@ -1,9 +1,9 @@ { "info": { - "_postman_id": "83fc509c-664a-46d3-9739-b8788b039c97", + "_postman_id": "e2786e24-07c1-457f-8a18-718ab118ccf4", "name": "Admin API E2E 2.0 - Sorting and Filtering - Claimset", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "5260609" + "_exporter_id": "37902114" }, "item": [ { @@ -26,8 +26,10 @@ "\r", "pm.test(\"GET Claimsets: Response result is ordered by Name asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [claimset => claimset.name.toLowerCase()],['asc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [claimset => claimset.name.toLowerCase()],['asc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'name');\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -109,8 +111,10 @@ "\r", "pm.test(\"GET Claimsets: Response result is ordered by Name asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [claimset => claimset.name.toLowerCase()],['desc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [claimset => claimset.name.toLowerCase()],['desc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'name', -1);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -366,8 +370,10 @@ "\r", "pm.test(\"GET Claimsets: Response result is ordered by Name asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [claimset => claimset.name.toLowerCase()],['asc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [claimset => claimset.name.toLowerCase()],['asc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'name');\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -453,8 +459,10 @@ "\r", "pm.test(\"GET Claimsets: Response result is ordered by Name asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [claimset => claimset.name.toLowerCase()],['desc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [claimset => claimset.name.toLowerCase()],['desc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'name', -1);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -539,8 +547,7 @@ "pm.test(\"GET Claimsets: Response result contains requested claimset\", function () {\r", " const results = pm.response.json();\r", " pm.expect(results[0].name).to.eql(pm.collectionVariables.get(\"FILTERNAME\"));\r", - "});\r", - "" + "});" ], "type": "text/javascript", "packages": {} @@ -620,99 +627,49 @@ "/// -------\r", "/// Authentication\r", "/// -------\r", + "const jsHelperVar = pm.variables.get('jsHelper');\r", + "const jsHelper = eval(jsHelperVar);\r", "\r", - "let header = {};\r", - "\r", - "function generateClientSecret() {\r", - " const minLength = 32;\r", - " const maxLength = 128;\r", - " let result = '';\r", - " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r", - " const specialCharacters = '!@#$%^&*()_+{}:\"<>?|[];\\',./`~';\r", - " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;\r", - "\r", - " result += randomChar('abcdefghijklmnopqrstuvwxyz');\r", - " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');\r", - " result += randomChar('0123456789');\r", - " result += randomChar(specialCharacters);\r", - "\r", - " for (let i = result.length; i < length; i++) {\r", - " const charactersPlusSpecial = characters + specialCharacters;\r", - " result += charactersPlusSpecial.charAt(Math.floor(Math.random() * charactersPlusSpecial.length));\r", - " }\r", - "\r", - " return shuffleString(result);\r", - "}\r", - "\r", - "function randomChar(str) {\r", - " return str.charAt(Math.floor(Math.random() * str.length));\r", - "}\r", - "\r", - "function shuffleString(str) {\r", - " const array = str.split('');\r", - " for (let i = array.length - 1; i > 0; i--) {\r", - " const j = Math.floor(Math.random() * (i + 1));\r", - " [array[i], array[j]] = [array[j], array[i]];\r", - " }\r", - " return array.join('');\r", - "}\r", + "var header = {\r", + " 'Content-Type': 'application/x-www-form-urlencoded'\r", + "};\r", "\r", - "const RegisterAndGetToken = () => new Promise((resolve) => {\r", - " let guid = pm.variables.replaceIn('{{$guid}}');\r", - " let client_secret = generateClientSecret();\r", + "var guid = pm.variables.replaceIn('{{$guid}}');\r", + "var client_secret = jsHelper().generateClientSecret();\r", "\r", - " let header = {\r", - " 'Content-Type': 'application/x-www-form-urlencoded'\r", - " };\r", + " const registerRequest = {\r", + " url: `${pm.variables.get(\"API_URL\")}/connect/register`,\r", + " method: 'POST',\r", + " header: header,\r", + " body: {\r", + " mode: 'urlencoded',\r", + " urlencoded: [\r", + " {key: 'ClientId', value: guid },\r", + " {key: 'ClientSecret', value: client_secret },\r", + " {key: 'DisplayName', value: guid }\r", + " ]\r", + " }\r", + " }\r", "\r", - " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", - " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", - " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", - " }\r", + " const tokenRequest = {\r", + " url: `${pm.variables.get(\"API_URL\")}/connect/token`,\r", + " method: 'POST',\r", + " header: header,\r", + " body: {\r", + " mode: 'urlencoded',\r", + " urlencoded: [\r", + " {key: 'client_id', value: guid },\r", + " {key: 'client_secret', value: client_secret },\r", + " {key: 'grant_type', value: \"client_credentials\"},\r", + " {key: 'scope', value: \"edfi_admin_api/full_access\"}\r", + " ]\r", + " }\r", + " }\r", "\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/connect/register`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'urlencoded',\r", - " urlencoded: [\r", - " {key: 'ClientId', value: guid },\r", - " {key: 'ClientSecret', value: client_secret },\r", - " {key: 'DisplayName', value: guid }\r", - " ]\r", - " }\r", - " },\r", - " (err, res) => {\r", - " error = res.json().error\r", - " if(error) {\r", - " throw res.json().error_description\r", - " }\r", - "\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/connect/token`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'urlencoded',\r", - " urlencoded: [\r", - " {key: 'client_id', value: guid },\r", - " {key: 'client_secret', value: client_secret },\r", - " {key: 'grant_type', value: \"client_credentials\"},\r", - " {key: 'scope', value: \"edfi_admin_api/full_access\"}\r", - " ]\r", - " }\r", - " },\r", - " (err, res) => {\r", - " error = res.json().error\r", - " if(error) {\r", - " throw res.json().error_description\r", - " }\r", - " pm.collectionVariables.set(\"TOKEN\", res.json().access_token);\r", - " resolve();\r", - " });\r", - " });\r", - "});\r", + " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", + " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", + " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", + " }\r", "\r", "/// -------\r", "/// Claimsets\r", @@ -725,59 +682,67 @@ " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r", " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;\r", "\r", - " result += randomChar('abcdefghijklmnopqrstuvwxyz');\r", - " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');\r", - " result += randomChar('0123456789');\r", + " result += jsHelper().randomChar('abcdefghijklmnopqrstuvwxyz');\r", + " result += jsHelper().randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');\r", + " result += jsHelper().randomChar('0123456789');\r", "\r", " for (let i = result.length; i < length; i++) {\r", " result += characters.charAt(Math.floor(Math.random() * characters.length));\r", " }\r", "\r", - " return shuffleString(result);\r", + " return jsHelper().shuffleString(result);\r", "}\r", "\r", - "const createClaimset = (name) => new Promise((resolve) => {\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/v2/claimSets`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'raw',\r", - " raw: JSON.stringify({ \"name\": `${name}` })\r", - "\r", - " }\r", - " }, (err, res) => {\r", - " let location = res.headers.get('Location');\r", - " let matches = location.match(/(\\d+)/);\r", - " claimsetId = parseInt(matches[0], 10);\r", - " resolve(claimsetId);\r", - " });\r", - "});\r", + "pm.sendRequest(registerRequest,\r", + " (err, res) => {\r", + " let error = res.json().error\r", + " if(error) {\r", + " throw res.json().error_description\r", + " }\r", "\r", - "(async function () {\r", - " await RegisterAndGetToken();\r", + " pm.sendRequest(tokenRequest,\r", + " (err, res) => {\r", + " let error = res.json().error\r", + " if(error) {\r", + " throw res.json().error_description\r", + " }\r", + " pm.collectionVariables.set(\"TOKEN\", res.json().access_token)\r", "\r", - " header = {\r", - " 'Content-Type': 'application/json',\r", - " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`\r", - " };\r", + " header = {\r", + " 'Content-Type': 'application/json',\r", + " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`\r", + " };\r", + " \r", + " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", + " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", + " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", + " }\r", + " let totalToCreate = parseInt(pm.collectionVariables.get(\"CLAIMSETCOUNT\"), 10);\r", + " var claimsetsToDelete = [];\r", + " for (let i = 0; i < totalToCreate; i++) {\r", + " let name = generateAlphanumericString();\r", + " pm.collectionVariables.set(\"FILTERNAME\", name);\r", + " pm.sendRequest({\r", + " url: `${pm.variables.get(\"API_URL\")}/v2/claimSets`,\r", + " method: 'POST',\r", + " header: header,\r", + " body: {\r", + " mode: 'raw',\r", + " raw: JSON.stringify({ \"name\": `${name}` })\r", "\r", - " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", - " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", - " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", - " }\r", - "\r", - " let claimsetsToDelete = [];\r", - " for (let i = 0; i < parseInt(pm.collectionVariables.get(\"CLAIMSETCOUNT\"), 10); i++) {\r", - " let name = generateAlphanumericString();\r", - "\r", - " pm.collectionVariables.set(\"FILTERNAME\", name);\r", - "\r", - " claimsetsToDelete.push(await createClaimset(name).then(claimsetId => claimsetId));\r", - " }\r", + " }\r", + " }, (err, res) => {\r", + " let location = res.headers.get('Location');\r", + " let matches = location.match(/(\\d+)/);\r", + " id = parseInt(matches[0], 10);\r", + " claimsetsToDelete.push(id)\r", + " });\r", + " }\r", + " pm.collectionVariables.set(\"CLAIMSETSTODELETE\", claimsetsToDelete);\r", + " });\r", + " });\r", "\r", - " pm.collectionVariables.set(\"CLAIMSETSTODELETE\", JSON.stringify(claimsetsToDelete));\r", - "})();" + "" ] } }, @@ -787,37 +752,34 @@ "type": "text/javascript", "packages": {}, "exec": [ - "header = {\r", - " 'Content-Type': 'application/json',\r", - " 'Accept': '*/*',\r", - " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`\r", - "};\r", - "\r", - "if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", - " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", - " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", - "}\r", - "\r", - "function deleteClaimsetById(id) {\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/v2/claimSets/${id}`,\r", - " method: 'DELETE',\r", - " header: header\r", - " }, function (err, res) {\r", - " if (err) {\r", - " console.log(err);\r", - " }\r", - " });\r", - "}\r", - "\r", - "function deleteClaimsets() {\r", - " let claimsetsToDelete = JSON.parse(pm.variables.get(\"CLAIMSETSTODELETE\"));\r", - " for (let i = 0; i < claimsetsToDelete.length; i++) {\r", - " deleteClaimsetById(claimsetsToDelete[i]);\r", - " }\r", - "}\r", - "\r", - "deleteClaimsets();" + "var header = {\r", + " 'Content-Type': 'application/json',\r", + " 'Accept': '*/*',\r", + " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`\r", + " };\r", + " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", + " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", + " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", + " }\r", + " function deleteClaimsetById(id) {\r", + " pm.sendRequest({\r", + " url: `${pm.variables.get(\"API_URL\")}/v2/claimSets/${id}`,\r", + " method: 'DELETE',\r", + " header: header\r", + " }, function (err, res) {\r", + " if (err) {\r", + " console.log(err);\r", + " }\r", + " });\r", + " }\r", + " function deleteClaimsets() {\r", + " let claimsetsToDelete = pm.collectionVariables.get(\"CLAIMSETSTODELETE\").split(\",\");\r", + " for (let i = 0; i < claimsetsToDelete.length; i++) {\r", + " deleteClaimsetById(claimsetsToDelete[i]);\r", + " }\r", + " }\r", + " deleteClaimsets();\r", + "" ] } } From 7411e0a7b1a96fcf67bd339c566ab37b4e757206 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Mon, 26 Aug 2024 11:46:46 -0500 Subject: [PATCH 28/35] Fix applications e2e --- ...ring - Application.postman_collection.json | 381 ++++++++---------- 1 file changed, 169 insertions(+), 212 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Application.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Application.postman_collection.json index 34f17177a..253cd1cb8 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Application.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Application.postman_collection.json @@ -1,9 +1,9 @@ { "info": { - "_postman_id": "3fdaec22-4d80-432a-bc87-a81b6bdcf485", + "_postman_id": "466e196e-c944-44cc-9ebe-f9d42517a87b", "name": "Admin API E2E 2.0 - Sorting and Filtering - Application", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "5260609" + "_exporter_id": "37902114" }, "item": [ { @@ -26,8 +26,10 @@ "\r", "pm.test(\"GET Applications: Response result is ordered by ApplicationName asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [application => application.applicationName.toLowerCase()],['asc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [application => application.applicationName.toLowerCase()],['asc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'applicationName');\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -109,8 +111,10 @@ "\r", "pm.test(\"GET Applications: Response result is ordered by ApplicationName desc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [application => application.applicationName.toLowerCase()],['desc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [application => application.applicationName.toLowerCase()],['desc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'applicationName', -1);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -366,8 +370,10 @@ "\r", "pm.test(\"GET Applications: Response result is ordered by ApplicationName asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [application => application.applicationName.toLowerCase()],['asc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [application => application.applicationName.toLowerCase()],['asc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'applicationName');\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -453,8 +459,10 @@ "\r", "pm.test(\"GET Applications: Response result is ordered by ApplicationName desc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [application => application.applicationName.toLowerCase()],['desc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [application => application.applicationName.toLowerCase()],['desc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'applicationName', -1);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -540,8 +548,10 @@ "\r", "pm.test(\"GET Applications: Response result is ordered by ClaimsetName asc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [application => application.claimSetName.toLowerCase()],['asc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [application => application.claimSetName.toLowerCase()],['asc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'claimSetName');\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -627,8 +637,10 @@ "\r", "pm.test(\"GET Applications: Response result is ordered by ClaimSetName Name desc\", function () {\r", " const results = pm.response.json();\r", - " var expectedSortedOrder = _.orderBy(results, [application => application.claimSetName.toLowerCase()],['desc']);\r", - " \r", + " // var expectedSortedOrder = _.orderBy(results, [application => application.claimSetName.toLowerCase()],['desc']);\r", + " const strSortByProperty = pm.variables.get('sortByProperty');\r", + " eval(strSortByProperty);\r", + " let expectedSortedOrder = sortByProperty(results, 'claimSetName', -1);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -875,98 +887,49 @@ "/// Authentication\r", "/// -------\r", "\r", - "let header = {};\r", + "const jsHelperVar = pm.variables.get('jsHelper');\r", + "const jsHelper = eval(jsHelperVar);\r", "\r", - "function generateClientSecret() {\r", - " const minLength = 32;\r", - " const maxLength = 128;\r", - " let result = '';\r", - " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r", - " const specialCharacters = '!@#$%^&*()_+{}:\"<>?|[];\\',./`~';\r", - " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;\r", - "\r", - " result += randomChar('abcdefghijklmnopqrstuvwxyz');\r", - " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');\r", - " result += randomChar('0123456789');\r", - " result += randomChar(specialCharacters);\r", - "\r", - " for (let i = result.length; i < length; i++) {\r", - " const charactersPlusSpecial = characters + specialCharacters;\r", - " result += charactersPlusSpecial.charAt(Math.floor(Math.random() * charactersPlusSpecial.length));\r", - " }\r", - "\r", - " return shuffleString(result);\r", - "}\r", - "\r", - "function randomChar(str) {\r", - " return str.charAt(Math.floor(Math.random() * str.length));\r", - "}\r", - "\r", - "function shuffleString(str) {\r", - " const array = str.split('');\r", - " for (let i = array.length - 1; i > 0; i--) {\r", - " const j = Math.floor(Math.random() * (i + 1));\r", - " [array[i], array[j]] = [array[j], array[i]];\r", - " }\r", - " return array.join('');\r", - "}\r", - "\r", - "const RegisterAndGetToken = () => new Promise((resolve) => {\r", - " let guid = pm.variables.replaceIn('{{$guid}}');\r", - " let client_secret = generateClientSecret();\r", + "var header = {\r", + " 'Content-Type': 'application/x-www-form-urlencoded'\r", + "};\r", "\r", - " let header = {\r", - " 'Content-Type': 'application/x-www-form-urlencoded'\r", - " };\r", + "var guid = pm.variables.replaceIn('{{$guid}}');\r", + "var client_secret = jsHelper().generateClientSecret();\r", "\r", - " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", - " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", - " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", - " }\r", + " const registerRequest = {\r", + " url: `${pm.variables.get(\"API_URL\")}/connect/register`,\r", + " method: 'POST',\r", + " header: header,\r", + " body: {\r", + " mode: 'urlencoded',\r", + " urlencoded: [\r", + " {key: 'ClientId', value: guid },\r", + " {key: 'ClientSecret', value: client_secret },\r", + " {key: 'DisplayName', value: guid }\r", + " ]\r", + " }\r", + " }\r", "\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/connect/register`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'urlencoded',\r", - " urlencoded: [\r", - " {key: 'ClientId', value: guid },\r", - " {key: 'ClientSecret', value: client_secret },\r", - " {key: 'DisplayName', value: guid }\r", - " ]\r", - " }\r", - " },\r", - " (err, res) => {\r", - " error = res.json().error\r", - " if(error) {\r", - " throw res.json().error_description\r", - " }\r", + " const tokenRequest = {\r", + " url: `${pm.variables.get(\"API_URL\")}/connect/token`,\r", + " method: 'POST',\r", + " header: header,\r", + " body: {\r", + " mode: 'urlencoded',\r", + " urlencoded: [\r", + " {key: 'client_id', value: guid },\r", + " {key: 'client_secret', value: client_secret },\r", + " {key: 'grant_type', value: \"client_credentials\"},\r", + " {key: 'scope', value: \"edfi_admin_api/full_access\"}\r", + " ]\r", + " }\r", + " }\r", "\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/connect/token`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'urlencoded',\r", - " urlencoded: [\r", - " {key: 'client_id', value: guid },\r", - " {key: 'client_secret', value: client_secret },\r", - " {key: 'grant_type', value: \"client_credentials\"},\r", - " {key: 'scope', value: \"edfi_admin_api/full_access\"}\r", - " ]\r", - " }\r", - " },\r", - " (err, res) => {\r", - " error = res.json().error\r", - " if(error) {\r", - " throw res.json().error_description\r", - " }\r", - " pm.collectionVariables.set(\"TOKEN\", res.json().access_token);\r", - " resolve();\r", - " });\r", - " });\r", - "});\r", + " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", + " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", + " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", + " }\r", "\r", "/// -------\r", "/// Vendors\r", @@ -979,128 +942,122 @@ " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\r", " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;\r", "\r", - " result += randomChar('abcdefghijklmnopqrstuvwxyz');\r", - " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');\r", - " result += randomChar('0123456789');\r", + " result += jsHelper().randomChar('abcdefghijklmnopqrstuvwxyz');\r", + " result += jsHelper().randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');\r", + " result += jsHelper().randomChar('0123456789');\r", "\r", " for (let i = result.length; i < length; i++) {\r", " result += characters.charAt(Math.floor(Math.random() * characters.length));\r", " }\r", "\r", - " return shuffleString(result);\r", + " return jsHelper().shuffleString(result);\r", "}\r", "\r", - "let createOdsInstance = function() {\r", - " return new Promise((resolve, reject) => {\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/v2/odsInstances`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'raw',\r", - " raw: JSON.stringify({ \"name\": generateAlphanumericString(), \"instanceType\": 'postgresql', \"connectionString\": pm.variables.get(\"connectionString\") })\r", - " }\r", - " }, (err, res) => {\r", - " let location = res.headers.get('location');\r", - " let matches = location.match(/(\\d+)/);\r", - " odsInstanceId = parseInt(matches[0], 10); \r", - " resolve(odsInstanceId);\r", - " });\r", - " });\r", - "}\r", - "\r", - "const createVendor = () => new Promise((resolve) => {\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/v2/vendors`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'raw',\r", - " raw: JSON.stringify({ \"company\": generateAlphanumericString(), \"namespacePrefixes\": `uri://${generateAlphanumericString()}.org`, \"contactName\": generateAlphanumericString(), \"contactEmailAddress\": `${generateAlphanumericString()}@test-ed-fi.org` })\r", + "pm.sendRequest(registerRequest,\r", + " (err, res) => {\r", + " let error = res.json().error\r", + " if(error) {\r", + " throw res.json().error_description\r", " }\r", - " }, (err, res) => {\r", - " let location = res.headers.get('location');\r", - " let matches = location.match(/(\\d+)/);\r", - " vendorId = parseInt(matches[0], 10);\r", - " resolve(vendorId);\r", - " });\r", - "});\r", "\r", - "const createClaimset = (claimsetName) => new Promise((resolve) => {\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/v2/claimSets`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'raw',\r", - " raw: JSON.stringify({ \"name\": claimsetName })\r", - " }\r", - " }, (err, res) => {\r", - " let location = res.headers.get('location');\r", - " let matches = location.match(/(\\d+)/);\r", - " claimsetId = parseInt(matches[0], 10);\r", - " resolve(claimsetId);\r", - " });\r", - "});\r", + " pm.sendRequest(tokenRequest,\r", + " (err, res) => {\r", + " let error = res.json().error\r", + " if(error) {\r", + " throw res.json().error_description\r", + " }\r", + " pm.collectionVariables.set(\"TOKEN\", res.json().access_token)\r", "\r", - "const createApplication = (applicationName, vendorId, claimsetName, odsInstanceId) => new Promise((resolve) => {\r", - " pm.sendRequest({\r", - " url: `${pm.variables.get(\"API_URL\")}/v2/applications`,\r", - " method: 'POST',\r", - " header: header,\r", - " body: {\r", - " mode: 'raw',\r", - " raw: JSON.stringify({ \"applicationName\": applicationName, \"vendorId\": vendorId, \"claimSetName\": claimsetName, 'educationOrganizationIds': [ 0 ], \"odsInstanceIds\": [ odsInstanceId ]})\r", - " }\r", - " }, (err, res) => {\r", - " let location = res.headers.get('location');\r", - " let matches = location.match(/(\\d+)/);\r", - " applicationId = parseInt(matches[0], 10);\r", - " resolve(applicationId);\r", - " });\r", - "});\r", - "\r", - "(async function () {\r", - " await RegisterAndGetToken();\r", - "\r", - " header = {\r", - " 'Content-Type': 'application/json',\r", - " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`\r", - " };\r", + " header = {\r", + " 'Content-Type': 'application/json',\r", + " 'Authorization': `Bearer ${pm.collectionVariables.get(\"TOKEN\")}`\r", + " };\r", + " \r", + " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", + " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", + " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", + " }\r", + " let totalToCreate = parseInt(pm.collectionVariables.get(\"APPLICATIONCOUNT\"), 10);\r", + " var claimsetsToDelete = [];\r", + " var vendorsToDelete = [];\r", + " var odsintancesToDelete = [];\r", + " var applicationsToDelete = [];\r", "\r", - " if (pm.variables.get(\"isMultitenant\") == \"true\") {\r", - " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", - " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", - " }\r", - "\r", - " let odsInstanceIdCreated = await createOdsInstance().then(odsInstanceId => odsInstanceId);\r", - " let vendorIdCreated = await createVendor().then(vendorId => vendorId);\r", - " let applicationcount = parseInt(pm.collectionVariables.get(\"APPLICATIONCOUNT\"), 10);\r", - "\r", - " let claimsetNamesCreated = [];\r", - " for (let i = 0; i < applicationcount; i++) {\r", - " claimsetNamesCreated.push(generateAlphanumericString());\r", - " }\r", - " \r", - " let claimsetIdsCreated = [];\r", - " for (let i = 0; i < applicationcount; i++) {\r", - " claimsetIdsCreated.push(await createClaimset(claimsetNamesCreated[i]).then(claimsetId => claimsetId));\r", - " }\r", - " \r", - " for (let i = 0; i < applicationcount; i++) {\r", - " let claimsetName = claimsetNamesCreated[i];\r", - " let applicationName = generateAlphanumericString();\r", + " for (let i = 0; i < totalToCreate; i++) {\r", + " let applicationName = generateAlphanumericString();\r", + " let claimsetName = generateAlphanumericString();\r", + " var vendorId = 0;\r", + " var odsInstanceId = 0;\r", + " pm.collectionVariables.set(\"FILTERAPPLICATIONNAME\", applicationName);\r", + " pm.collectionVariables.set(\"FILTERCLAIMSETNAME\", claimsetName);\r", + " pm.sendRequest({\r", + " url: `${pm.variables.get(\"API_URL\")}/v2/claimSets`,\r", + " method: 'POST',\r", + " header: header,\r", + " body: {\r", + " mode: 'raw',\r", + " raw: JSON.stringify({ \"name\": `${claimsetName}` })\r", "\r", - " pm.collectionVariables.set(\"FILTERAPPLICATIONNAME\", applicationName);\r", - " pm.collectionVariables.set(\"FILTERCLAIMSETNAME\", claimsetName);\r", + " }\r", + " }, (err, res) => {\r", + " let location = res.headers.get('Location');\r", + " let matches = location.match(/(\\d+)/);\r", + " id = parseInt(matches[0], 10);\r", + " claimsetsToDelete.push(id)\r", + " pm.sendRequest({\r", + " url: `${pm.variables.get(\"API_URL\")}/v2/vendors`,\r", + " method: 'POST',\r", + " header: header,\r", + " body: {\r", + " mode: 'raw',\r", + " raw: JSON.stringify({ \"company\": generateAlphanumericString(), \"namespacePrefixes\": `uri://${generateAlphanumericString()}.org`, \"contactName\": generateAlphanumericString(), \"contactEmailAddress\": `${generateAlphanumericString()}@test-ed-fi.org` })\r", + " }\r", + " }, (err, res) => {\r", + " let location = res.headers.get('Location');\r", + " let matches = location.match(/(\\d+)/);\r", + " id = parseInt(matches[0], 10);\r", + " vendorId = id;\r", + " vendorsToDelete.push(id)\r", + " pm.sendRequest({\r", + " url: `${pm.variables.get(\"API_URL\")}/v2/odsInstances`,\r", + " method: 'POST',\r", + " header: header,\r", + " body: {\r", + " mode: 'raw',\r", + " raw: JSON.stringify({ \"name\": generateAlphanumericString(), \"instanceType\": 'postgresql', \"connectionString\": pm.variables.get(\"connectionString\") })\r", + " }\r", + " }, (err, res) => {\r", + " let location = res.headers.get('Location');\r", + " let matches = location.match(/(\\d+)/);\r", + " id = parseInt(matches[0], 10);\r", + " odsInstanceId = id;\r", + " odsintancesToDelete.push(id)\r", + " pm.sendRequest({\r", + " url: `${pm.variables.get(\"API_URL\")}/v2/applications`,\r", + " method: 'POST',\r", + " header: header,\r", + " body: {\r", + " mode: 'raw',\r", + " raw: JSON.stringify({ \"applicationName\": applicationName, \"vendorId\": vendorId, \"claimSetName\": claimsetName, 'educationOrganizationIds': [ 0 ], \"odsInstanceIds\": [ odsInstanceId ]})\r", + " }\r", + " }, (err, res) => {\r", + " let location = res.headers.get('location');\r", + " let matches = location.match(/(\\d+)/);\r", + " let id = parseInt(matches[0], 10);\r", + " applicationsToDelete.push(id)\r", + " });\r", + " });\r", + " });\r", + " });\r", + " }\r", + " pm.collectionVariables.set(\"VENDORTODELETE\", vendorsToDelete);\r", + " pm.collectionVariables.set(\"CLAIMSETSTODELETE\", claimsetsToDelete);\r", + " pm.collectionVariables.set(\"ODSINSTANCETODELETE\", odsintancesToDelete);\r", + " pm.collectionVariables.set(\"APPLICATIONSTODELETE\", applicationsToDelete);\r", + " });\r", + " });\r", "\r", - " await createApplication(applicationName, vendorIdCreated, claimsetName, odsInstanceIdCreated);\r", - " }\r", "\r", - " pm.collectionVariables.set(\"VENDORTODELETE\", vendorIdCreated);\r", - " pm.collectionVariables.set(\"CLAIMSETSTODELETE\", JSON.stringify(claimsetIdsCreated));\r", - " pm.collectionVariables.set(\"ODSINSTANCETODELETE\", odsInstanceIdCreated);\r", - "})();\r", "" ] } @@ -1157,19 +1114,19 @@ "}\r", "\r", "function deleteClaimsets() {\r", - " let claimsetsToDelete = JSON.parse(pm.variables.get(\"CLAIMSETSTODELETE\"));\r", + " let claimsetsToDelete = pm.collectionVariables.get(\"CLAIMSETSTODELETE\").split(\",\");\r", " for (let i = 0; i < claimsetsToDelete.length; i++) {\r", " deleteClaimsetById(claimsetsToDelete[i]);\r", " }\r", "}\r", "\r", "function deleteOdsInstance() {\r", - " let odsInstanceToDelete = pm.variables.get(\"ODSINSTANCETODELETE\");\r", + " let odsInstanceToDelete = pm.collectionVariables.get(\"ODSINSTANCETODELETE\").split(\",\");\r", " deleteODSInstanceById(odsInstanceToDelete);\r", "}\r", "\r", "(async function () {\r", - " let vendorToDelete = pm.variables.get(\"VENDORTODELETE\");\r", + " let vendorToDelete = pm.collectionVariables.get(\"VENDORTODELETE\").split(\",\");\r", " await deleteVendorById(vendorToDelete);\r", "\r", " deleteClaimsets();\r", From e27c2507bf97732b74b10b84e21507f951de915b Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Mon, 26 Aug 2024 15:07:05 -0500 Subject: [PATCH 29/35] Fix the profile's e2e --- ...Filtering - Profile.postman_collection.json | 3 +-- .../Database/Queries/GetProfilesQuery.cs | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Profile.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Profile.postman_collection.json index af022fff9..44045df9e 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Profile.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Profile.postman_collection.json @@ -722,7 +722,6 @@ " for (let i = 0; i < totalToCreate; i++) {\r", " let name = generateAlphanumericString();\r", " pm.collectionVariables.set(\"FILTERNAME\", name);\r", - " \r", "\r", " pm.sendRequest({\r", " url: `${pm.variables.get(\"API_URL\")}/v2/profiles`,\r", @@ -762,7 +761,7 @@ " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", "}\r", - "let idsToDelete = pm.collectionVariables.get(\"PROFILESTODELETE\");\r", + "let idsToDelete = pm.collectionVariables.get(\"PROFILESTODELETE\").split(\",\");\r", "for (let i = 0; i < idsToDelete.length; i++) {\r", " let id = idsToDelete[i];\r", " pm.sendRequest({ \r", diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetProfilesQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetProfilesQuery.cs index eb7358cd2..eec5e1668 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetProfilesQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetProfilesQuery.cs @@ -9,6 +9,7 @@ using EdFi.Ods.AdminApi.Helpers; using EdFi.Ods.AdminApi.Infrastructure.Extensions; using EdFi.Ods.AdminApi.Infrastructure.Helpers; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; namespace EdFi.Ods.AdminApi.Infrastructure.Database.Queries; @@ -23,17 +24,18 @@ public class GetProfilesQuery : IGetProfilesQuery { private readonly IUsersContext _usersContext; private readonly IOptions _options; - private static readonly Dictionary>> _orderByColumnProfiles = - new Dictionary>> - (StringComparer.OrdinalIgnoreCase) - { - { SortingColumns.DefaultNameColumn, x => x.ProfileName }, - { SortingColumns.DefaultIdColumn, x => x.ProfileId } - }; + private readonly Dictionary>> _orderByColumnProfiles; public GetProfilesQuery(IUsersContext usersContext, IOptions options) { _usersContext = usersContext; - _options = options; + _options = options; + var isSQLServerEngine = _options.Value.DatabaseEngine?.ToLowerInvariant() == DatabaseEngineEnum.SqlServer.ToLowerInvariant(); + _orderByColumnProfiles = new Dictionary>> + (StringComparer.OrdinalIgnoreCase) + { + { SortingColumns.DefaultNameColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.ProfileName, DatabaseEngineEnum.SqlServerCollation) : x.ProfileName }, + { SortingColumns.DefaultIdColumn, x => x.ProfileId } + }; } public List Execute() From acb2652b40aeb69f1f148f1a6c87d506315ca510 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Mon, 26 Aug 2024 15:08:06 -0500 Subject: [PATCH 30/35] Set a different collation to sql server order Latin1_General_100_BIN2_UTF8 --- .../EdFi.Ods.AdminApi/Infrastructure/DatabaseEngineEnum.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/DatabaseEngineEnum.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/DatabaseEngineEnum.cs index b17d9a7b0..a832692a6 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/DatabaseEngineEnum.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/DatabaseEngineEnum.cs @@ -4,7 +4,7 @@ public static class DatabaseEngineEnum { public const string SqlServer = "SqlServer"; public const string PostgreSql = "PostgreSql"; - public const string SqlServerCollation = "Latin1_General_BIN2"; + public const string SqlServerCollation = "Latin1_General_100_BIN2_UTF8"; public static string Parse(string value) { From 48648b5869a4ccfcaa9b308c57ee6cd438ea66db Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Mon, 26 Aug 2024 15:08:50 -0500 Subject: [PATCH 31/35] Fix the vendor's e2e sqlserver --- ... - Sorting and Filtering - Vendor.postman_collection.json | 5 ++--- .../Infrastructure/Database/Queries/GetVendorsQuery.cs | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Vendor.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Vendor.postman_collection.json index 06a597c40..af4258781 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Vendor.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Vendor.postman_collection.json @@ -904,7 +904,7 @@ " pm.expect(results.length).to.be.greaterThan(0); \r", "});\r", "\r", - "pm.test(\"GET Vendors: Response result is ordered by CamespacePrefixes asc\", function () {\r", + "pm.test(\"GET Vendors: Response result is ordered by NamespacePrefixes asc\", function () {\r", " const results = pm.response.json();\r", " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.namespacePrefixes.toLowerCase()],['asc']);\r", " const strSortByProperty = pm.variables.get('sortByProperty');\r", @@ -1542,9 +1542,8 @@ " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;\r", " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });\r", "}\r", - "let vendorsToDelete = pm.collectionVariables.get(\"VENDORSTODELETE\");\r", + "let vendorsToDelete = pm.collectionVariables.get(\"VENDORSTODELETE\").split(\",\");\r", "for (let i = 0; i < vendorsToDelete.length; i++) {\r", - " console.log(vendorsToDelete)\r", " let id = vendorsToDelete[i];\r", " pm.sendRequest({ \r", " url: `${pm.variables.get(\"API_URL\")}/v2/vendors/${id}`,\r", diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs index c3a9cb813..4bf5ca18d 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetVendorsQuery.cs @@ -39,7 +39,7 @@ public GetVendorsQuery(IUsersContext context, IOptions options) { SortingColumns.VendorContactNameColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.Users.FirstOrDefault().FullName, DatabaseEngineEnum.SqlServerCollation) : x.Users.FirstOrDefault().FullName }, { SortingColumns.VendorContactEmailColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.Users.FirstOrDefault().Email, DatabaseEngineEnum.SqlServerCollation) : x.Users.FirstOrDefault().Email }, #pragma warning restore CS8602 // Dereference of a possibly null reference. - { SortingColumns.VendorNamespacePrefixesColumn, x => x.VendorNamespacePrefixes.OrderBy(p => p.NamespacePrefix).First().NamespacePrefix }, + { SortingColumns.VendorNamespacePrefixesColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.VendorNamespacePrefixes.OrderBy(p => p.NamespacePrefix).First().NamespacePrefix, DatabaseEngineEnum.SqlServerCollation) : x.VendorNamespacePrefixes.OrderBy(p => p.NamespacePrefix).First().NamespacePrefix }, { SortingColumns.DefaultIdColumn, x => x.VendorId } }; } From 0f967d414bad66596bb394c21d8b94466f939f0d Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Mon, 26 Aug 2024 15:09:39 -0500 Subject: [PATCH 32/35] Add the collation function to the column sorting --- .../Queries/GetAuthStrategiesQuery.cs | 21 +++++++++++-------- .../Queries/GetOdsInstanceContextsQuery.cs | 19 +++++++++-------- .../Queries/GetOdsInstanceDerivativesQuery.cs | 21 ++++++++++--------- .../Database/Queries/GetOdsInstancesQuery.cs | 4 ++-- 4 files changed, 35 insertions(+), 30 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAuthStrategiesQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAuthStrategiesQuery.cs index 4d634a942..46373a2fd 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAuthStrategiesQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetAuthStrategiesQuery.cs @@ -9,6 +9,7 @@ using EdFi.Ods.AdminApi.Infrastructure.Helpers; using EdFi.Security.DataAccess.Contexts; using EdFi.Security.DataAccess.Models; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Options; namespace EdFi.Ods.AdminApi.Infrastructure.Database.Queries; @@ -23,18 +24,20 @@ public class GetAuthStrategiesQuery : IGetAuthStrategiesQuery { private readonly ISecurityContext _context; private readonly IOptions _options; - private static readonly Dictionary>> _orderByColumnAuthorizationStrategies = - new Dictionary>>(StringComparer.OrdinalIgnoreCase) - { - { SortingColumns.DefaultNameColumn, x => x.AuthorizationStrategyName }, - { SortingColumns.AuthorizationStrategyDisplayNameColumn, x => x.DisplayName }, - { SortingColumns.DefaultIdColumn, x => x.AuthorizationStrategyId } - }; - + private readonly Dictionary>> _orderByColumnAuthorizationStrategies; public GetAuthStrategiesQuery(ISecurityContext context, IOptions options) { _context = context; - _options = options; + _options = options; + var isSQLServerEngine = _options.Value.DatabaseEngine?.ToLowerInvariant() == DatabaseEngineEnum.SqlServer.ToLowerInvariant(); + + _orderByColumnAuthorizationStrategies = new Dictionary>> + (StringComparer.OrdinalIgnoreCase) + { + { SortingColumns.DefaultNameColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.AuthorizationStrategyName, DatabaseEngineEnum.SqlServerCollation) : x.AuthorizationStrategyName }, + { SortingColumns.AuthorizationStrategyDisplayNameColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.DisplayName, DatabaseEngineEnum.SqlServerCollation) : x.DisplayName }, + { SortingColumns.DefaultIdColumn, x => x.AuthorizationStrategyId } + }; } public List Execute() diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceContextsQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceContextsQuery.cs index bae55f923..0e41fb756 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceContextsQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceContextsQuery.cs @@ -25,18 +25,19 @@ public class GetOdsInstanceContextsQuery : IGetOdsInstanceContextsQuery { private readonly IUsersContext _usersContext; private readonly IOptions _options; - private static readonly Dictionary>> _orderByColumnOds = - new Dictionary>> - (StringComparer.OrdinalIgnoreCase) - { - { SortingColumns.OdsInstanceContextKeyColumn, x => x.ContextKey }, - { SortingColumns.OdsInstanceContextValueColumn, x => x.ContextValue }, - { SortingColumns.DefaultIdColumn, x => x.OdsInstanceContextId } - }; + private readonly Dictionary>> _orderByColumnOds; public GetOdsInstanceContextsQuery(IUsersContext usersContext, IOptions options) { _usersContext = usersContext; - _options = options; + _options = options; + var isSQLServerEngine = _options.Value.DatabaseEngine?.ToLowerInvariant() == DatabaseEngineEnum.SqlServer.ToLowerInvariant(); + _orderByColumnOds = new Dictionary>> + (StringComparer.OrdinalIgnoreCase) + { + { SortingColumns.OdsInstanceContextKeyColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.ContextKey, DatabaseEngineEnum.SqlServerCollation) : x.ContextKey }, + { SortingColumns.OdsInstanceContextValueColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.ContextValue, DatabaseEngineEnum.SqlServerCollation) : x.ContextValue }, + { SortingColumns.DefaultIdColumn, x => x.OdsInstanceContextId } + }; } public List Execute() diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceDerivativesQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceDerivativesQuery.cs index 3d2b286db..2facd35e8 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceDerivativesQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstanceDerivativesQuery.cs @@ -24,19 +24,20 @@ public class GetOdsInstanceDerivativesQuery : IGetOdsInstanceDerivativesQuery { private readonly IUsersContext _usersContext; private readonly IOptions _options; - private static readonly Dictionary>> _orderByColumnOds = - new Dictionary>> - (StringComparer.OrdinalIgnoreCase) - { - { SortingColumns.OdsInstanceDerivativeTypeColumn, x => x.DerivativeType }, - { SortingColumns.OdsInstanceDerivativeOdsInstanceIdColumn, x => x.OdsInstance.OdsInstanceId }, - { SortingColumns.DefaultIdColumn, x => x.OdsInstanceDerivativeId } - }; - + private readonly Dictionary>> _orderByColumnOds; public GetOdsInstanceDerivativesQuery(IUsersContext usersContext, IOptions options) { _usersContext = usersContext; - _options = options; + _options = options; + var isSQLServerEngine = _options.Value.DatabaseEngine?.ToLowerInvariant() == DatabaseEngineEnum.SqlServer.ToLowerInvariant(); + _orderByColumnOds = new Dictionary>> + (StringComparer.OrdinalIgnoreCase) + { + { SortingColumns.OdsInstanceDerivativeTypeColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.DerivativeType, DatabaseEngineEnum.SqlServerCollation) : x.DerivativeType }, + { SortingColumns.OdsInstanceDerivativeOdsInstanceIdColumn, x => x.OdsInstance.OdsInstanceId }, + { SortingColumns.DefaultIdColumn, x => x.OdsInstanceDerivativeId } + }; + } public List Execute() diff --git a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs index 06450590c..0f8586b5f 100644 --- a/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs +++ b/Application/EdFi.Ods.AdminApi/Infrastructure/Database/Queries/GetOdsInstancesQuery.cs @@ -35,8 +35,8 @@ public GetOdsInstancesQuery(IUsersContext userContext, IOptions opt _orderByColumnOds = new Dictionary>> (StringComparer.OrdinalIgnoreCase) { - { SortingColumns.DefaultNameColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.Name, "Latin1_General_BIN2") : x.Name }, - { SortingColumns.OdsInstanceInstanceTypeColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.InstanceType, "Latin1_General_BIN2") : x.InstanceType }, + { SortingColumns.DefaultNameColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.Name, DatabaseEngineEnum.SqlServerCollation) : x.Name }, + { SortingColumns.OdsInstanceInstanceTypeColumn, x => isSQLServerEngine ? EF.Functions.Collate(x.InstanceType, DatabaseEngineEnum.SqlServerCollation) : x.InstanceType }, { SortingColumns.DefaultIdColumn, x => x.OdsInstanceId } }; } From 209c8b67abbfc7acdd882a15413dd60f827d7e0b Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Mon, 26 Aug 2024 16:04:32 -0500 Subject: [PATCH 33/35] Fix to delete data after e2e passed --- ...ring - Application.postman_collection.json | 9 +- ...ng - ODS Instances.postman_collection.json | 150 ++++++------------ 2 files changed, 58 insertions(+), 101 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Application.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Application.postman_collection.json index 253cd1cb8..e6592075e 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Application.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Application.postman_collection.json @@ -1122,13 +1122,16 @@ "\r", "function deleteOdsInstance() {\r", " let odsInstanceToDelete = pm.collectionVariables.get(\"ODSINSTANCETODELETE\").split(\",\");\r", - " deleteODSInstanceById(odsInstanceToDelete);\r", + " for (let i = 0; i < claimsetsToDelete.length; i++) {\r", + " deleteODSInstanceById(odsInstanceToDelete);\r", + " }\r", "}\r", "\r", "(async function () {\r", " let vendorToDelete = pm.collectionVariables.get(\"VENDORTODELETE\").split(\",\");\r", - " await deleteVendorById(vendorToDelete);\r", - "\r", + " for (let i = 0; i < vendorToDelete.length; i++) {\r", + " await deleteVendorById(vendorToDelete[i]);\r", + " }\r", " deleteClaimsets();\r", " deleteOdsInstance();\r", "})();" diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json index 2a74a9fc7..07f3889ba 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json @@ -1,8 +1,9 @@ { "info": { - "_postman_id": "ee933872-22de-440c-ac3b-b79a8a7fc422", + "_postman_id": "be57956c-6278-4137-8514-55c0d27a5f3e", "name": "Admin API E2E 2.0 - Sorting and Filtering - ODS Instances", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "37902114" }, "item": [ { @@ -868,39 +869,49 @@ "/// Authentication", "/// -------", "", - "function generateClientSecret() {", - " const minLength = 32;", - " const maxLength = 128;", - " let result = '';", - " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';", - " const specialCharacters = '!@#$%^&*()_+{}:\"<>?|[];\\',./`~';", - " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;", + "const jsHelperVar = pm.variables.get('jsHelper');", + "const jsHelper = eval(jsHelperVar);", "", - " result += randomChar('abcdefghijklmnopqrstuvwxyz');", - " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');", - " result += randomChar('0123456789');", - " result += randomChar(specialCharacters);", + "var header = {", + " 'Content-Type': 'application/x-www-form-urlencoded'", + "};", "", - " for (let i = result.length; i < length; i++) {", - " const charactersPlusSpecial = characters + specialCharacters;", - " result += charactersPlusSpecial.charAt(Math.floor(Math.random() * charactersPlusSpecial.length));", - " }", + "var guid = pm.variables.replaceIn('{{$guid}}');", + "var client_secret = jsHelper().generateClientSecret();", "", - " return shuffleString(result);", - "}", + " const registerRequest = {", + " url: `${pm.variables.get(\"API_URL\")}/connect/register`,", + " method: 'POST',", + " header: header,", + " body: {", + " mode: 'urlencoded',", + " urlencoded: [", + " {key: 'ClientId', value: guid },", + " {key: 'ClientSecret', value: client_secret },", + " {key: 'DisplayName', value: guid }", + " ]", + " }", + " }", "", - "function randomChar(str) {", - " return str.charAt(Math.floor(Math.random() * str.length));", - "}", + " const tokenRequest = {", + " url: `${pm.variables.get(\"API_URL\")}/connect/token`,", + " method: 'POST',", + " header: header,", + " body: {", + " mode: 'urlencoded',", + " urlencoded: [", + " {key: 'client_id', value: guid },", + " {key: 'client_secret', value: client_secret },", + " {key: 'grant_type', value: \"client_credentials\"},", + " {key: 'scope', value: \"edfi_admin_api/full_access\"}", + " ]", + " }", + " }", "", - "function shuffleString(str) {", - " const array = str.split('');", - " for (let i = array.length - 1; i > 0; i--) {", - " const j = Math.floor(Math.random() * (i + 1));", - " [array[i], array[j]] = [array[j], array[i]];", - " }", - " return array.join('');", - "}", + " if (pm.variables.get(\"isMultitenant\") == \"true\") {", + " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;", + " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });", + " }", "", "function generateAlphanumericString() {", " const minLength = 8;", @@ -910,76 +921,20 @@ " const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';", " const length = Math.floor(Math.random() * (maxLength - minLength + 1)) + minLength;", "", - " result += randomChar('abcdefghijklmnopqrstuvwxyz');", - " result += randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');", - " result += randomChar('0123456789');", + " result += jsHelper().randomChar('abcdefghijklmnopqrstuvwxyz');", + " result += jsHelper().randomChar('ABCDEFGHIJKLMNOPQRSTUVWXYZ');", + " result += jsHelper().randomChar('0123456789');", "", " for (let i = result.length; i < length; i++) {", " result += characters.charAt(Math.floor(Math.random() * characters.length));", " }", "", - " return shuffleString(result);", + " return jsHelper().shuffleString(result);", "}", "", "/// -------", "/// ODS Instances", "/// -------", - "const createODSInstance = (name, instanceType) => new Promise((resolve) => {", - " pm.sendRequest({", - " url: `${pm.variables.get(\"API_URL\")}/v2/odsInstances`,", - " method: 'POST',", - " header: header,", - " body: {", - " mode: 'raw',", - " raw: JSON.stringify({ \"name\": `${name}`, \"instanceType\": `${instanceType}`, \"connectionString\": pm.variables.get(\"connectionString\") })", - " }", - " }, (err, res) => {", - " let location = res.headers.get('Location');", - " let matches = location.match(/(\\d+)/);", - " let odsInstanceId = parseInt(matches[0], 10);", - " resolve(odsInstanceId);", - " });", - "});", - "", - "var guid = pm.variables.replaceIn('{{$guid}}');", - "var client_secret = generateClientSecret();", - "var header = {", - " 'Content-Type': 'application/x-www-form-urlencoded'", - "};", - "", - "const registerRequest = {", - " url: `${pm.variables.get(\"API_URL\")}/connect/register`,", - " method: 'POST',", - " header: header,", - " body: {", - " mode: 'urlencoded',", - " urlencoded: [", - " {key: 'ClientId', value: guid },", - " {key: 'ClientSecret', value: client_secret },", - " {key: 'DisplayName', value: guid }", - " ]", - " }", - "}", - "", - "const tokenRequest = {", - " url: `${pm.variables.get(\"API_URL\")}/connect/token`,", - " method: 'POST',", - " header: header,", - " body: {", - " mode: 'urlencoded',", - " urlencoded: [", - " {key: 'client_id', value: guid },", - " {key: 'client_secret', value: client_secret },", - " {key: 'grant_type', value: \"client_credentials\"},", - " {key: 'scope', value: \"edfi_admin_api/full_access\"}", - " ]", - " }", - "}", - "", - "if (pm.variables.get(\"isMultitenant\") == \"true\") {", - " header['Tenant'] = `${pm.variables.get(\"tenant1\")}`;", - " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });", - "}", "", "pm.sendRequest(registerRequest,", " (err, res) => {", @@ -1006,7 +961,7 @@ " pm.request.headers.upsert({key: 'Tenant', value: `${pm.variables.get(\"tenant1\")}` });", " }", " let totalToCreate = parseInt(pm.collectionVariables.get(\"ODSINSTANCECOUNT\"), 10);", - " let odsInstancesToDelete = [];", + " var odsInstancesToDelete = [];", " for (let i = 0; i < totalToCreate; i++) {", " let name = `TestOdsInstance-${generateAlphanumericString()}`;", " let instanceType = generateAlphanumericString();", @@ -1030,7 +985,7 @@ " odsInstancesToDelete.push(odsInstanceId);", " });", " }", - " pm.collectionVariables.set(\"ODSINSTANCESTODELETE\", JSON.stringify(odsInstancesToDelete));", + " pm.collectionVariables.set(\"ODSINSTANCESTODELETE\", odsInstancesToDelete);", " });", "});", "", @@ -1067,14 +1022,13 @@ "}", "", "function deleteODSInstances() {", - " if (!pm.variables.get(\"ODSINSTANCESTODELETE\"))", - " {", - " let odsInstancesToDelete = JSON.parse(pm.variables.get(\"ODSINSTANCESTODELETE\"));", + " ", + " let odsInstancesToDelete = pm.collectionVariables.get(\"ODSINSTANCESTODELETE\").split(\",\");", "", - " for (let i = 0; i < odsInstancesToDelete.length; i++) {", - " deleteODSInstanceById(odsInstancesToDelete[i]);", - " }", + " for (let i = 0; i < odsInstancesToDelete.length; i++) {", + " deleteODSInstanceById(odsInstancesToDelete[i]);", " }", + " ", "}", "", "deleteODSInstances();" From f26dcce4d230201591ff317dd7ac53f74a6f27ce Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Mon, 26 Aug 2024 16:10:52 -0500 Subject: [PATCH 34/35] Fix a typo --- ... Sorting and Filtering - Application.postman_collection.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Application.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Application.postman_collection.json index e6592075e..1fb92c562 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Application.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Application.postman_collection.json @@ -1122,7 +1122,7 @@ "\r", "function deleteOdsInstance() {\r", " let odsInstanceToDelete = pm.collectionVariables.get(\"ODSINSTANCETODELETE\").split(\",\");\r", - " for (let i = 0; i < claimsetsToDelete.length; i++) {\r", + " for (let i = 0; i < odsInstanceToDelete.length; i++) {\r", " deleteODSInstanceById(odsInstanceToDelete);\r", " }\r", "}\r", From b09543f12d918607a7ed2a3304774f52ae3a61e0 Mon Sep 17 00:00:00 2001 From: Juan Agudelo Date: Tue, 27 Aug 2024 10:37:17 -0500 Subject: [PATCH 35/35] Revert to use loadash in the e2e --- ...ring - Application.postman_collection.json | 30 ++------ ...ltering - Claimset.postman_collection.json | 15 +--- ...ng - ODS Instances.postman_collection.json | 68 +++++++++---------- ...iltering - Profile.postman_collection.json | 20 ++---- ...Filtering - Vendor.postman_collection.json | 50 +++----------- 5 files changed, 54 insertions(+), 129 deletions(-) diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Application.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Application.postman_collection.json index 1fb92c562..6ac38cf3c 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Application.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Application.postman_collection.json @@ -26,10 +26,7 @@ "\r", "pm.test(\"GET Applications: Response result is ordered by ApplicationName asc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [application => application.applicationName.toLowerCase()],['asc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'applicationName');\r", + " var expectedSortedOrder = _.orderBy(results, [application => application.applicationName],['asc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -111,10 +108,7 @@ "\r", "pm.test(\"GET Applications: Response result is ordered by ApplicationName desc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [application => application.applicationName.toLowerCase()],['desc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'applicationName', -1);\r", + " var expectedSortedOrder = _.orderBy(results, [application => application.applicationName],['desc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -370,10 +364,7 @@ "\r", "pm.test(\"GET Applications: Response result is ordered by ApplicationName asc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [application => application.applicationName.toLowerCase()],['asc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'applicationName');\r", + " var expectedSortedOrder = _.orderBy(results, [application => application.applicationName],['asc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -459,10 +450,7 @@ "\r", "pm.test(\"GET Applications: Response result is ordered by ApplicationName desc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [application => application.applicationName.toLowerCase()],['desc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'applicationName', -1);\r", + " var expectedSortedOrder = _.orderBy(results, [application => application.applicationName],['desc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -548,10 +536,7 @@ "\r", "pm.test(\"GET Applications: Response result is ordered by ClaimsetName asc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [application => application.claimSetName.toLowerCase()],['asc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'claimSetName');\r", + " var expectedSortedOrder = _.orderBy(results, [application => application.claimSetName],['asc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -637,10 +622,7 @@ "\r", "pm.test(\"GET Applications: Response result is ordered by ClaimSetName Name desc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [application => application.claimSetName.toLowerCase()],['desc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'claimSetName', -1);\r", + " var expectedSortedOrder = _.orderBy(results, [application => application.claimSetName],['desc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Claimset.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Claimset.postman_collection.json index c82c51872..bd3ca90fe 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Claimset.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Claimset.postman_collection.json @@ -26,10 +26,7 @@ "\r", "pm.test(\"GET Claimsets: Response result is ordered by Name asc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [claimset => claimset.name.toLowerCase()],['asc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'name');\r", + " var expectedSortedOrder = _.orderBy(results, [claimset => claimset.name],['asc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -111,10 +108,7 @@ "\r", "pm.test(\"GET Claimsets: Response result is ordered by Name asc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [claimset => claimset.name.toLowerCase()],['desc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'name', -1);\r", + " var expectedSortedOrder = _.orderBy(results, [claimset => claimset.name],['desc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -370,10 +364,7 @@ "\r", "pm.test(\"GET Claimsets: Response result is ordered by Name asc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [claimset => claimset.name.toLowerCase()],['asc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'name');\r", + " var expectedSortedOrder = _.orderBy(results, [claimset => claimset.name],['asc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json index 07f3889ba..7b6f28f78 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - ODS Instances.postman_collection.json @@ -26,15 +26,13 @@ "\r", "pm.test(\"GET ODS Instances: Response result is ordered by Name asc\", function () {\r", " const results = pm.response.json();\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'name');\r", - " \r", + " var expectedSortedOrder = _.orderBy(results, [dt => dt.name],['asc']) \r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" ], - "type": "text/javascript" + "type": "text/javascript", + "packages": {} } }, { @@ -43,7 +41,8 @@ "exec": [ "" ], - "type": "text/javascript" + "type": "text/javascript", + "packages": {} } } ], @@ -109,17 +108,15 @@ "\r", "pm.test(\"GET ODS Instances: Response result is ordered by Namne desc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name.toLowerCase()],['desc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'name', -1);\r", - "\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name],['desc']);\r", + " \r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "\r", "" ], - "type": "text/javascript" + "type": "text/javascript", + "packages": {} } }, { @@ -128,7 +125,8 @@ "exec": [ "" ], - "type": "text/javascript" + "type": "text/javascript", + "packages": {} } } ], @@ -364,15 +362,13 @@ "\r", "pm.test(\"GET ODS Instances: Response result is ordered by Name asc\", function () {\r", " const results = pm.response.json();\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'name');\r", - "\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name],['asc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" ], - "type": "text/javascript" + "type": "text/javascript", + "packages": {} } }, { @@ -381,7 +377,8 @@ "exec": [ "" ], - "type": "text/javascript" + "type": "text/javascript", + "packages": {} } } ], @@ -451,15 +448,13 @@ "\r", "pm.test(\"GET ODS Instances: Response result is ordered by Name desc\", function () {\r", " const results = pm.response.json();\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'name', -1);\r", - "\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.name],['desc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" ], - "type": "text/javascript" + "type": "text/javascript", + "packages": {} } }, { @@ -468,7 +463,8 @@ "exec": [ "" ], - "type": "text/javascript" + "type": "text/javascript", + "packages": {} } } ], @@ -538,15 +534,13 @@ "\r", "pm.test(\"GET ODS Instances: Response result is ordered by InstanceType asc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType ? odsInstance.instanceType.toLowerCase() : null],['asc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'instanceType');\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType ? odsInstance.instanceType : null],['asc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" ], - "type": "text/javascript" + "type": "text/javascript", + "packages": {} } }, { @@ -555,7 +549,8 @@ "exec": [ "" ], - "type": "text/javascript" + "type": "text/javascript", + "packages": {} } } ], @@ -625,15 +620,13 @@ "\r", "pm.test(\"GET ODS Instances: Response result is ordered by InstanceType desc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType ? odsInstance.instanceType.toLowerCase() : null],['desc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'instanceType', -1);\r", + " var expectedSortedOrder = _.orderBy(results, [odsInstance => odsInstance.instanceType ? odsInstance.instanceType : null],['desc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" ], - "type": "text/javascript" + "type": "text/javascript", + "packages": {} } }, { @@ -642,7 +635,8 @@ "exec": [ "" ], - "type": "text/javascript" + "type": "text/javascript", + "packages": {} } } ], diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Profile.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Profile.postman_collection.json index 44045df9e..5ca6347cd 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Profile.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Profile.postman_collection.json @@ -26,10 +26,7 @@ "\r", "pm.test(\"GET Profiles: Response result is ordered by Name asc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [profile => profile.name.toLowerCase()],['asc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'name');\r", + " var expectedSortedOrder = _.orderBy(results, [profile => profile.name],['asc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -111,10 +108,7 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by Name desc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [profile => profile.name.toLowerCase()],['desc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'name', -1);\r", + " var expectedSortedOrder = _.orderBy(results, [profile => profile.name],['desc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -370,10 +364,7 @@ "\r", "pm.test(\"GET Profiles: Response result is ordered by Name asc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [profile => profile.name.toLowerCase()],['asc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'name');\r", + " var expectedSortedOrder = _.orderBy(results, [profile => profile.name],['asc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -459,10 +450,7 @@ "\r", "pm.test(\"GET Profiles: Response result is ordered by Name desc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [profile => profile.name.toLowerCase()],['desc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'name', -1);\r", + " var expectedSortedOrder = _.orderBy(results, [profile => profile.name],['desc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" diff --git a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Vendor.postman_collection.json b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Vendor.postman_collection.json index af4258781..9467944d3 100644 --- a/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Vendor.postman_collection.json +++ b/Application/EdFi.Ods.AdminApi/E2E Tests/Admin API E2E 2.0 - Sorting and Filtering - Vendor.postman_collection.json @@ -26,10 +26,7 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by Company asc\", function () {\r", " const results = pm.response.json();\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'company');\r", - " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.company.toLowerCase()],['asc']);\r", + " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.company],['asc']);\r", " \r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", @@ -112,10 +109,7 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by Company desc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.company.toLowerCase()],['desc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'company', -1);\r", + " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.company],['desc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -371,10 +365,7 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by Company asc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.company.toLowerCase()],['asc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'company');\r", + " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.company],['asc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -460,10 +451,7 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by Company desc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.company.toLowerCase()],['desc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'company', -1);\r", + " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.company],['desc']);\r", " \r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", @@ -550,10 +538,7 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by contactEmailAddress asc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.contactEmailAddress.toLowerCase()],['asc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'contactEmailAddress');\r", + " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.contactEmailAddress],['asc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -639,10 +624,7 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by contactEmailAddress desc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.contactEmailAddress.toLowerCase()],['desc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'contactEmailAddress', -1);\r", + " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.contactEmailAddress],['desc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -728,10 +710,7 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by ContactName asc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.contactName.toLowerCase()],['asc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'contactName');\r", + " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.contactName],['asc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -817,10 +796,7 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by ContactName desc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.contactName.toLowerCase()],['desc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'contactName', -1);\r", + " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.contactName],['desc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -906,10 +882,7 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by NamespacePrefixes asc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.namespacePrefixes.toLowerCase()],['asc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'namespacePrefixes');\r", + " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.namespacePrefixes],['asc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", "" @@ -995,10 +968,7 @@ "\r", "pm.test(\"GET Vendors: Response result is ordered by NamespacePrefixes desc\", function () {\r", " const results = pm.response.json();\r", - " // var expectedSortedOrder = _.orderBy(results, [vendor => vendor.namespacePrefixes.toLowerCase()],['desc']);\r", - " const strSortByProperty = pm.variables.get('sortByProperty');\r", - " eval(strSortByProperty);\r", - " let expectedSortedOrder = sortByProperty(results, 'namespacePrefixes', -1);\r", + " var expectedSortedOrder = _.orderBy(results, [vendor => vendor.namespacePrefixes],['desc']);\r", " pm.expect(results).to.eql(expectedSortedOrder);\r", "});\r", ""