mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-08-08 02:16:52 +01:00
Add new action skills for AL testing and documentation
- Introduced `al-test-writer` to generate AL test codeunits for production objects based on TDD principles. - Added `al-userguide-test-writer` to create test codeunits from user guide steps, mapping actions and assertions. - Implemented `bc-extension-test-guide` to generate a comprehensive TEST_GUIDE.md for Business Central extensions, covering various categories. - Created `bc-webclient-runner` to automate UI testing of the Business Central web client, capturing screenshots and asserting UI states. - Developed `page-scripting-e2e` to produce a recording plan for Page Scripting, ensuring a structured approach to browser-level testing.
This commit is contained in:
parent
822cae1b27
commit
07140e2223
76 changed files with 4353 additions and 6 deletions
|
|
@ -0,0 +1,73 @@
|
|||
// Best practice: the posting subscriber only STAGES an outbound message and returns.
|
||||
// The HttpClient.Send happens later, in a Job Queue codeunit, outside the posting lock.
|
||||
// The row is inserted inside the posting transaction, so it exists only if the post
|
||||
// committed; the callout runs in a separate transaction where a remote outage can only
|
||||
// delay delivery, never roll back a posted shipment.
|
||||
|
||||
codeunit 50110 "Post Shipment Notifier"
|
||||
{
|
||||
// Subscriber on the real posting publisher. It runs while posting locks are held,
|
||||
// so it must do nothing that can block: no HTTP, no second remote call, just an Insert.
|
||||
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Sales-Post", 'OnAfterPostSalesDoc', '', false, false)]
|
||||
local procedure StageShipmentNotification(var SalesHeader: Record "Sales Header")
|
||||
var
|
||||
IntegrationMessage: Record "Integration Message";
|
||||
begin
|
||||
// Only notify on an actual posted shipment, not on every posted document kind.
|
||||
if not SalesHeader.Ship then
|
||||
exit;
|
||||
|
||||
IntegrationMessage.Init();
|
||||
IntegrationMessage."Message ID" := CreateGuid();
|
||||
// Direction Outbound + Status New is exactly what the Job Queue processor queries for.
|
||||
IntegrationMessage.Direction := IntegrationMessage.Direction::Outbound;
|
||||
IntegrationMessage.Status := IntegrationMessage.Status::New;
|
||||
IntegrationMessage.Type := 'SHIPMENT-NOTIFY';
|
||||
// Carry the document ANCHOR, not a live handle. The processor re-reads detail later.
|
||||
IntegrationMessage."Document No." := SalesHeader."No.";
|
||||
IntegrationMessage."External Reference" := SalesHeader."External Document No.";
|
||||
// Correlation id threads this notification to the rest of the flow's log lines.
|
||||
IntegrationMessage."Correlation ID" := CopyStr(DelChr(LowerCase(Format(CreateGuid())), '=', '{}'), 1, 40);
|
||||
// Insert participates in the posting transaction: the row lives only if the post commits,
|
||||
// and rolls back cleanly with the post if posting fails. No remote system is touched here.
|
||||
IntegrationMessage.Insert(true);
|
||||
end;
|
||||
}
|
||||
|
||||
codeunit 50111 "Outbound Sender"
|
||||
{
|
||||
// Runs as a Job Queue entry, well after posting has committed and released its locks.
|
||||
// Nothing it does can lengthen a posting lock window, because there is no longer a post in flight.
|
||||
procedure SendNew()
|
||||
var
|
||||
IntegrationMessage: Record "Integration Message";
|
||||
begin
|
||||
IntegrationMessage.SetRange(Direction, IntegrationMessage.Direction::Outbound);
|
||||
IntegrationMessage.SetRange(Status, IntegrationMessage.Status::New);
|
||||
if IntegrationMessage.FindSet() then
|
||||
repeat
|
||||
// Each row is its own short unit of work. A slow endpoint stalls delivery
|
||||
// of THIS message only; it cannot stall anyone's posting.
|
||||
SendOne(IntegrationMessage);
|
||||
until IntegrationMessage.Next() = 0;
|
||||
end;
|
||||
|
||||
local procedure SendOne(var IntegrationMessage: Record "Integration Message")
|
||||
var
|
||||
Client: HttpClient;
|
||||
Content: HttpContent;
|
||||
Response: HttpResponseMessage;
|
||||
begin
|
||||
Content.WriteFrom(BuildShipmentJson(IntegrationMessage));
|
||||
if Client.Post(GetEndpoint(IntegrationMessage), Content, Response) and Response.IsSuccessStatusCode() then begin
|
||||
IntegrationMessage.Status := IntegrationMessage.Status::Resolved;
|
||||
IntegrationMessage.Modify(true);
|
||||
end else begin
|
||||
// A failure here is recorded on the row and retried later. The posted shipment
|
||||
// is already durable, so a WMS outage never costs us the posting.
|
||||
IntegrationMessage."Retry Count" += 1;
|
||||
IntegrationMessage."Error Message" := CopyStr(GetLastErrorText(), 1, 2048);
|
||||
IntegrationMessage.Modify(true);
|
||||
end;
|
||||
end;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue