Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
7a0b32d
Separate API test workflow infrastructure from AL uptake
t-prda Sep 25, 2026
564bc06
Remove relocated auth source-pattern checks from workflow tests
t-prda Sep 25, 2026
6e1d8bb
Keep clean-codeunit lanes opt-in until authentication uptake
t-prda Sep 25, 2026
1d81466
Merge current main baseline while preserving scoped API test exclusions
t-prda Sep 30, 2026
156bca0
Do not classify ordinary API HTTP500 failures as platform races
t-prda Oct 2, 2026
decc121
Do not classify ordinary API HTTP500 failures as platform races
t-prda Oct 2, 2026
a439380
Move API test credential cleanup to supported PipelineFinalize hook
t-prda Oct 2, 2026
dd6207b
Simplify finalizer maintenance by retaining committed wrappers
t-prda Oct 2, 2026
331ae4b
Merge current main with simplified supported API credential finalizer
t-prda Oct 2, 2026
dcc0733
Merge main baseline containing upstream CLEAN27 warning cleanup
t-prda Oct 2, 2026
7003849
Document tenant info object return contract
t-prda Oct 4, 2026
69df417
Merge captured main to unblock stacked API validation
t-prda Oct 4, 2026
304e5b1
Enable reviewed Expense APIs and consolidate unique Expense regressions
t-prda Oct 5, 2026
4316269
Enable remaining Expense HTTP API tests with existing clean isolation
t-prda Oct 5, 2026
88881be
Merge captured main after workflow squash to restore Expense-only review
t-prda Oct 5, 2026
3070e7a
Defer general API clean-isolation tests until authenticated uptake
t-prda Oct 5, 2026
bd3bbc0
Reuse existing API exclusion manifests for Expense-first sequencing
t-prda Oct 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/AL-Go-Settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"repoVersion": "30.0",
"memoryLimit": "16G",
"numberOfTenantsForTesting": 4,
"enableCleanTestCodeunitExecution": true,
"maxTestAppReruns": 2,
"failOn": "newWarning",
"workspaceCompilation": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ namespace Microsoft.ExpenseAgent;

using Microsoft.Finance.SpendRequest;
using System.Telemetry;
using System.Text;

codeunit 7133 "Travel Request Approval"
{
Expand Down Expand Up @@ -318,13 +317,17 @@ codeunit 7133 "Travel Request Approval"
var
ExpenseApprovalSetup: Record "Expense Approval Setup";
ExpenseAgentSetup: Record "Expense Agent Setup";
SelectionFilterManagement: Codeunit SelectionFilterManagement;
RecRef: RecordRef;
AssignedFilter: TextBuilder;
begin
ExpenseApprovalSetup.SetCurrentKey("Approver No.");
ExpenseApprovalSetup.SetRange("Approver No.", ApproverExpenseUserNo);
RecRef.GetTable(ExpenseApprovalSetup);
RequestedForFilter := SelectionFilterManagement.GetSelectionFilter(RecRef, ExpenseApprovalSetup.FieldNo("Expense User No."));
ExpenseApprovalSetup.SetLoadFields("Expense User No.");
// Ranges between setup rows could include expense users without any approval setup.
if ExpenseApprovalSetup.FindSet() then
repeat
AppendSubmitterFilter(AssignedFilter, ExpenseApprovalSetup."Expense User No.");
until ExpenseApprovalSetup.Next() = 0;
RequestedForFilter := AssignedFilter.ToText();

ExpenseAgentSetup.GetRecordOnce();
if ExpenseAgentSetup."Default Approver No." = ApproverExpenseUserNo then
Expand All @@ -337,7 +340,6 @@ codeunit 7133 "Travel Request Approval"
local procedure AppendDefaultSubmitters(var RequestedForFilter: Text)
var
ExpenseUser: Record "Expense User";
SelectionFilterManagement: Codeunit SelectionFilterManagement;
DefaultFilter: TextBuilder;
begin
if RequestedForFilter <> '' then
Expand All @@ -348,14 +350,23 @@ codeunit 7133 "Travel Request Approval"
ExpenseUser.SetLoadFields("No.");
if ExpenseUser.FindSet() then
repeat
if DefaultFilter.Length > 0 then
DefaultFilter.Append('|');
DefaultFilter.Append(SelectionFilterManagement.AddQuotes(ExpenseUser."No."));
AppendSubmitterFilter(DefaultFilter, ExpenseUser."No.");
until ExpenseUser.Next() = 0;

RequestedForFilter := DefaultFilter.ToText();
end;

local procedure AppendSubmitterFilter(var SubmitterFilter: TextBuilder; ExpenseUserNo: Code[20])
var
ExpenseUserFilter: Record "Expense User";
begin
// Serialize an exact value so filter operators in user numbers remain literal.
ExpenseUserFilter.SetRange("No.", ExpenseUserNo);
if SubmitterFilter.Length > 0 then
SubmitterFilter.Append('|');
SubmitterFilter.Append(ExpenseUserFilter.GetFilter("No."));
end;

var
FeatureTelemetry: Codeunit "Feature Telemetry";
ExpenseActivityLogMgt: Codeunit "Expense Activity Log Mgt.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ codeunit 148343 "Expense Activity Log API Test"
LibraryGraphMgt: Codeunit "Library - Graph Mgt";
LibraryTestInitialize: Codeunit "Library - Test Initialize";
LibrarySetupStorage: Codeunit "Library - Setup Storage";
APITestAuthHelper: Codeunit "Expense API Test Auth Helper";
IsInitialized: Boolean;
ServiceNameTok: Label 'expenseActivityLogEntries', Locked = true;
ExpenseReportsServiceNameTok: Label 'expenseReports', Locked = true;
Expand Down Expand Up @@ -476,19 +475,23 @@ codeunit 148343 "Expense Activity Log API Test"
RequestBody.WriteTo(RequestText);
ReportURL := LibraryGraphMgt.CreateTargetURLWithSubpage(
Format(SubmitterExpenseUser.SystemId), Page::"Expense Users API", ExpenseUsersServiceNameTok, ExpenseReportsServiceNameTok);
ReportURL += '(' + LibraryGraphMgt.StripBrackets(Format(ExpenseReportHeader.SystemId)) + ')';
ReportURL := LibraryGraphMgt.AppendPathToTargetURL(
ReportURL, '(' + LibraryGraphMgt.StripBrackets(Format(ExpenseReportHeader.SystemId)) + ')');
Commit();

// [WHEN] The standard submission action is requested through the submitting user.
LibraryGraphMgt.PostToWebServiceAndCheckResponseCode(ReportURL + '/' + SubmitWithCommentActionTok, RequestText, ResponseText, 200);
Clear(ResponseText);
LibraryGraphMgt.PostToWebServiceAndCheckResponseCode(
LibraryGraphMgt.AppendPathToTargetURL(ReportURL, '/' + SubmitWithCommentActionTok), RequestText, ResponseText, 200);

// [THEN] Exactly one structured snapshot is visible without a new callback or capability.
ExpenseActivityLogEntry.SetRange("Subject System ID", ExpenseReportHeader.SystemId);
ExpenseActivityLogEntry.SetRange("Event Type", ExpenseActivityLogEntry."Event Type"::PolicyEvaluated);
Assert.RecordCount(ExpenseActivityLogEntry, 1);
ExpenseActivityLogEntry.FindFirst();
Clear(ResponseText);
LibraryGraphMgt.GetFromWebServiceAndCheckResponseCode(ResponseText, ReportURL + '/' + ServiceNameTok, 200);
LibraryGraphMgt.GetFromWebServiceAndCheckResponseCode(
ResponseText, LibraryGraphMgt.AppendPathToTargetURL(ReportURL, '/' + ServiceNameTok), 200);
VerifyPolicyCategoryCode(ResponseText, ExpenseCategory.Code);
ResponseText := LowerCase(ResponseText);
Assert.AreNotEqual(0, StrPos(ResponseText, '"eventtype":"policyevaluated"'), 'The event type must identify the policy snapshot.');
Expand All @@ -502,7 +505,8 @@ codeunit 148343 "Expense Activity Log API Test"
HistoryURL := LibraryGraphMgt.CreateTargetURLWithSubpage(
Format(SubmitterExpenseUser.SystemId), Page::"Expense Users API", ExpenseUsersServiceNameTok, ServiceNameTok);
Clear(ResponseText);
LibraryGraphMgt.GetFromWebServiceAndCheckResponseCode(ResponseText, HistoryURL + '?$filter=historyActorRole eq ''Submitter''', 200);
LibraryGraphMgt.GetFromWebServiceAndCheckResponseCode(
ResponseText, LibraryGraphMgt.AppendQueryParameterToTargetURL(HistoryURL, '$filter=historyActorRole eq ''Submitter'''), 200);

// [THEN] The real submitter sees the agent snapshot in the complete timeline.
Assert.AreNotEqual(0, StrPos(LowerCase(ResponseText), LowerCase(LibraryGraphMgt.StripBrackets(Format(ExpenseActivityLogEntry.SystemId)))), 'The submitter timeline must contain the snapshot.');
Expand All @@ -511,7 +515,8 @@ codeunit 148343 "Expense Activity Log API Test"
HistoryURL := LibraryGraphMgt.CreateTargetURLWithSubpage(
Format(ApproverExpenseUser.SystemId), Page::"Expense Users API", ExpenseUsersServiceNameTok, ServiceNameTok);
Clear(ResponseText);
LibraryGraphMgt.GetFromWebServiceAndCheckResponseCode(ResponseText, HistoryURL + '?$filter=historyActorRole eq ''Approver''', 200);
LibraryGraphMgt.GetFromWebServiceAndCheckResponseCode(
ResponseText, LibraryGraphMgt.AppendQueryParameterToTargetURL(HistoryURL, '$filter=historyActorRole eq ''Approver'''), 200);

// [THEN] The agent event must not grant approver participation.
Assert.AreEqual(0, StrPos(LowerCase(ResponseText), LowerCase(LibraryGraphMgt.StripBrackets(Format(ExpenseReportHeader.SystemId)))), 'The agent snapshot must not grant approver history access.');
Expand Down Expand Up @@ -803,7 +808,9 @@ codeunit 148343 "Expense Activity Log API Test"
if IsInitialized then
exit;

BindSubscription(APITestAuthHelper);
LibraryGraphMgt.SetAuthenticationProvider(
Enum::"API Test Authentication"::"Microsoft Test Environment");

LibraryTestInitialize.OnBeforeTestSuiteInitialize(Codeunit::"Expense Activity Log API Test");
LibraryERMCountryData.UpdateGeneralLedgerSetup();
if not ExpenseAgentSetup.Get() then begin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ codeunit 148333 "Expense Agent Setup API Test"
if IsInitialized then
exit;

LibraryGraphMgt.SetAuthenticationProvider(
Enum::"API Test Authentication"::"Microsoft Test Environment");

LibraryTestInitialize.OnBeforeTestSuiteInitialize(Codeunit::"Expense Agent Setup API Test");
LibraryExpense.SetupNumberSeriesInExpenseMgmt();
IsInitialized := true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ codeunit 148318 "Expense Capabilities API Test"
LibraryExpenseAgent: Codeunit "Library - Expense Agent";
LibraryGraphMgt: Codeunit "Library - Graph Mgt";
LibraryTestInitialize: Codeunit "Library - Test Initialize";
APITestAuthHelper: Codeunit "Expense API Test Auth Helper";
IsInitialized: Boolean;
ServiceNameTok: Label 'expenseCapabilities', Locked = true;
ActivityLogCapabilityNameTok: Label 'activityLog', Locked = true;
Expand Down Expand Up @@ -104,8 +103,6 @@ codeunit 148318 "Expense Capabilities API Test"
TargetURL: Text;
ResponseText: Text;
begin
// Excluded in BCApps CI until authenticated OData execution in a dedicated test company
// with disabled isolation is available; then remove this method's DisabledTest.json entry.
// [SCENARIO] Travel requests are advertised when the supporting APIs are installed.
Initialize();

Expand Down Expand Up @@ -248,7 +245,9 @@ codeunit 148318 "Expense Capabilities API Test"
if IsInitialized then
exit;

BindSubscription(APITestAuthHelper);
LibraryGraphMgt.SetAuthenticationProvider(
Enum::"API Test Authentication"::"Microsoft Test Environment");

LibraryTestInitialize.OnBeforeTestSuiteInitialize(Codeunit::"Expense Capabilities API Test");
IsInitialized := true;
Commit();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ codeunit 148349 "Expense PerDiem Locations Test"
LibraryUtility: Codeunit "Library - Utility";
LibraryGraphMgt: Codeunit "Library - Graph Mgt";
LibraryTestInitialize: Codeunit "Library - Test Initialize";
APITestAuthHelper: Codeunit "Expense API Test Auth Helper";
IsInitialized: Boolean;

[Test]
Expand Down Expand Up @@ -82,11 +81,14 @@ codeunit 148349 "Expense PerDiem Locations Test"

local procedure Initialize()
begin
LibraryGraphMgt.SetLicenseSafeWorkDate();
LibraryTestInitialize.OnTestInitialize(Codeunit::"Expense PerDiem Locations Test");
if IsInitialized then
exit;

BindSubscription(APITestAuthHelper);
LibraryGraphMgt.SetAuthenticationProvider(
Enum::"API Test Authentication"::"Microsoft Test Environment");

LibraryTestInitialize.OnBeforeTestSuiteInitialize(Codeunit::"Expense PerDiem Locations Test");
IsInitialized := true;
Commit();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ codeunit 148331 "Expense Projects API Test"
LibraryHumanResource: Codeunit "Library - Human Resource";
LibraryGraphMgt: Codeunit "Library - Graph Mgt";
LibraryTestInitialize: Codeunit "Library - Test Initialize";
APITestAuthHelper: Codeunit "Expense API Test Auth Helper";
IsInitialized: Boolean;
ExpenseUsersServiceNameTok: Label 'expenseUsers', Locked = true;
ProjectsServiceNameTok: Label 'expenseProjects', Locked = true;
Expand Down Expand Up @@ -723,7 +722,9 @@ codeunit 148331 "Expense Projects API Test"
if IsInitialized then
exit;

BindSubscription(APITestAuthHelper);
LibraryGraphMgt.SetAuthenticationProvider(
Enum::"API Test Authentication"::"Microsoft Test Environment");

LibraryTestInitialize.OnBeforeTestSuiteInitialize(Codeunit::"Expense Projects API Test");
if not ExpenseAgentSetup.Get() then begin
ExpenseAgentSetup.Init();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ codeunit 148315 "Expense Users API Test"
LibraryUtility: Codeunit "Library - Utility";
LibraryGraphMgt: Codeunit "Library - Graph Mgt";
LibraryTestInitialize: Codeunit "Library - Test Initialize";
APITestAuthHelper: Codeunit "Expense API Test Auth Helper";
IsInitialized: Boolean;
ServiceNameTok: Label 'expenseUsers', Locked = true;
EmployeesServiceNameTok: Label 'employees', Locked = true;
Expand Down Expand Up @@ -125,7 +124,9 @@ codeunit 148315 "Expense Users API Test"
if IsInitialized then
exit;

BindSubscription(APITestAuthHelper);
LibraryGraphMgt.SetAuthenticationProvider(
Enum::"API Test Authentication"::"Microsoft Test Environment");

LibraryTestInitialize.OnBeforeTestSuiteInitialize(Codeunit::"Expense Users API Test");
if not ExpenseAgentSetup.Get() then begin
ExpenseAgentSetup.Init();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ codeunit 148348 "Expense VAT Spec. API Test"
{
Subtype = Test;
TestType = IntegrationTest;
RequiredTestIsolation = Disabled;
TestPermissions = Disabled;

var
Expand All @@ -19,7 +20,6 @@ codeunit 148348 "Expense VAT Spec. API Test"
LibraryERM: Codeunit "Library - ERM";
LibraryGraphMgt: Codeunit "Library - Graph Mgt";
LibraryTestInitialize: Codeunit "Library - Test Initialize";
APITestAuthHelper: Codeunit "Expense API Test Auth Helper";
IsInitialized: Boolean;
ServiceNameTok: Label 'expenseVATSpecifications', Locked = true;

Expand Down Expand Up @@ -89,7 +89,9 @@ codeunit 148348 "Expense VAT Spec. API Test"
if IsInitialized then
exit;

BindSubscription(APITestAuthHelper);
LibraryGraphMgt.SetAuthenticationProvider(
Enum::"API Test Authentication"::"Microsoft Test Environment");

LibraryTestInitialize.OnBeforeTestSuiteInitialize(Codeunit::"Expense VAT Spec. API Test");
LibraryExpense.SetupNumberSeriesInExpenseMgmt();
LibraryERM.CreateVATBusinessPostingGroup(VATBusinessPostingGroup);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ codeunit 148345 "Policies To Evaluate API Test"
LibraryExpense: Codeunit "Library - Expense";
LibraryGraphMgt: Codeunit "Library - Graph Mgt";
LibraryTestInitialize: Codeunit "Library - Test Initialize";
APITestAuthHelper: Codeunit "Expense API Test Auth Helper";
IsInitialized: Boolean;
ExpenseReportLinesServiceNameTok: Label 'expenseReportLines', Locked = true;

Expand Down Expand Up @@ -117,7 +116,9 @@ codeunit 148345 "Policies To Evaluate API Test"
if IsInitialized then
exit;

BindSubscription(APITestAuthHelper);
LibraryGraphMgt.SetAuthenticationProvider(
Enum::"API Test Authentication"::"Microsoft Test Environment");

LibraryTestInitialize.OnBeforeTestSuiteInitialize(Codeunit::"Policies To Evaluate API Test");
LibraryERMCountryData.CreateVATData();
LibraryERMCountryData.UpdateGeneralPostingSetup();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ codeunit 148344 "Policy Evaluations API Test"
LibraryExpense: Codeunit "Library - Expense";
LibraryGraphMgt: Codeunit "Library - Graph Mgt";
LibraryTestInitialize: Codeunit "Library - Test Initialize";
APITestAuthHelper: Codeunit "Expense API Test Auth Helper";
IsInitialized: Boolean;
ServiceNameTok: Label 'expensePolicyEvaluations', Locked = true;
BadRequestResponseErr: Label 'Response code is 400', Locked = true;
Expand Down Expand Up @@ -121,7 +120,9 @@ codeunit 148344 "Policy Evaluations API Test"
if IsInitialized then
exit;

BindSubscription(APITestAuthHelper);
LibraryGraphMgt.SetAuthenticationProvider(
Enum::"API Test Authentication"::"Microsoft Test Environment");

LibraryTestInitialize.OnBeforeTestSuiteInitialize(Codeunit::"Policy Evaluations API Test");
LibraryERMCountryData.CreateVATData();
LibraryERMCountryData.UpdateGeneralPostingSetup();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,6 @@ using Microsoft.Finance.GeneralLedger.Setup;
using Microsoft.Finance.SpendRequest;
using Microsoft.HumanResources.Employee;

// These HTTP tests remain excluded in Expense_Agent_Tests.DisabledTest.json until the
// authentication prerequisite provides an authenticated OData endpoint and a dedicated
// test company with committed fixtures and disabled test isolation.
// In-process employee filtering, traveler mapping/navigation, lifecycle, date, and scope coverage
// in "Spend Request Test", and restrictive role coverage in "Expense Permissions Test", remain enabled.
// Only the HTTP scenarios are excluded.
codeunit 148347 "Travel Requests API Test"
{
Subtype = Test;
Expand All @@ -31,7 +25,6 @@ codeunit 148347 "Travel Requests API Test"
LibraryHumanResource: Codeunit "Library - Human Resource";
LibraryRandom: Codeunit "Library - Random";
LibraryTestInitialize: Codeunit "Library - Test Initialize";
APITestAuthHelper: Codeunit "Expense API Test Auth Helper";
IsInitialized: Boolean;
ExpenseUsersServiceNameTok: Label 'expenseUsers', Locked = true;
#if not CLEAN30
Expand Down Expand Up @@ -1291,7 +1284,9 @@ codeunit 148347 "Travel Requests API Test"
if IsInitialized then
exit;

BindSubscription(APITestAuthHelper);
LibraryGraphMgt.SetAuthenticationProvider(
Enum::"API Test Authentication"::"Microsoft Test Environment");

LibraryTestInitialize.OnBeforeTestSuiteInitialize(Codeunit::"Travel Requests API Test");
if not ExpenseAgentSetup.Get() then begin
ExpenseAgentSetup.Init();
Expand Down
Loading
Loading