0

I am testing a TFrame with CEF4Delphi component in it but I have issues when it comes to freeing up the TForm containing the TFrame and the relevant CEF4Delphi components.

The following is a Minimal Example

program MyTFrameExample;
{

  Delphi DUnit Test Project
  -------------------------
  This project contains the DUnit test framework and the GUI/Console test runners.
  Add "CONSOLE_TESTRUNNER" to the conditional defines entry in the project options
  to use the console test runner.  Otherwise the GUI test runner will be used by
  default.

}

{$IFDEF CONSOLE_TESTRUNNER}
{$APPTYPE CONSOLE}
{$ENDIF}

uses
  madExcept,
  madLinkDisAsm,
  madListHardware,
  madListProcesses,
  madListModules,
  DUnitTestRunner,
  Vcl.Forms,
  WinApi.Windows,
  uCEFApplication,
  SSFrame in '..\..\SS\SSFrame.pas' {SSFrm: TFrame},
  TestSSFrame in '..\..\Test\TestSSFrame.pas';

{*.RES}

{$I cef.inc}

{$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE}

begin

  GlobalCEFApp := TCefApplication.Create;
  GlobalCEFApp.SingleProcess := True;

  if GlobalCEFApp.StartMainProcess then
  begin
    Application.Initialize;
    Application.MainFormOnTaskbar := True;
    DUnitTestRunner.RunRegisteredTests;
    Application.Run;
  end;

  GlobalCEFApp.Free;
end.

unit TestSSFrame;
{

  Delphi DUnit Test Case
  ----------------------
  This unit contains a skeleton test case class generated by the Test Case Wizard.
  Modify the generated code to correctly setup and call the methods from the unit
  being tested.

}

interface

uses
  TestFramework,
  System.SysUtils,
  Vcl.Graphics,
  uCEFChromium,
  Winapi.Windows,
  System.Variants,
  uCEFInterfaces,
  uCEFChromiumWindow,
  Vcl.Dialogs,
  Vcl.Controls,
  uCEFWindowParent,
  Vcl.Forms,
  Winapi.Messages,
  SSFrame,
  System.Classes;

type
  // Test methods for class TSSFrm

  TestTSSFrm = class(TTestCase)
  strict private
    FSSFrm: TSSFrm;
    FMainForm: TForm;
  public
    procedure SetUp; override;
    procedure TearDown; override;
  published
    procedure TestChromium1AfterCreated;
  end;

implementation

procedure TestTSSFrm.SetUp;
begin
  Application.CreateForm(TForm, FMainForm);
  FSSFrm := TSSFrm.Create(FMainForm);
  FSSFrm.Parent := FMainForm;
  FSSFrm.Visible := True;
  FSSFrm.Align := alClient;

  FSSFrm.Chromium1.CreateBrowser(FSSFrm.ChromiumWindow1);
  if not (FSSFrm.ChromiumWindow1.CreateBrowser) then
    FSSFrm.Timer1.Enabled := True;

  while FSSFrm.Chromium1.Initialized = False do
  begin
    Application.ProcessMessages;
  end;

  FMainForm.Show;
end;

procedure TestTSSFrm.TearDown;
begin
  FMainForm.Free;
[enter link description here][1]  FMainForm := nil;
end;

procedure TestTSSFrm.TestChromium1AfterCreated;
var
  a: Boolean;
begin
  if (FMainForm.Components[0] is TSSFrm) then
  begin
    a := (FMainForm.Components[0] as TSSFrm).IsGoogleSearchPageCreated;
    CheckTrue(a);
  end;
end;


initialization
  // Register any test cases with the test runner
  RegisterTest(TestTSSFrm.Suite);

end.

unit SSFrame;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  uCEFWindowParent,
  uCEFChromiumWindow,
  uCEFInterfaces,
  uCEFChromium,
  Vcl.StdCtrls,
  Vcl.ExtCtrls;

type
  TSSFrm = class(TFrame)
    Chromium1: TChromium;
    ChromiumWindow1: TChromiumWindow;
    Timer1: TTimer;
    procedure Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
    FIsGoogleSearchPageLoaded: Boolean;
    FIsGoogleSearchPageCreated: Boolean;
  public
    { Public declarations }
    function IsGoogleSearchPageCreated: Boolean;
  end;

implementation

{$R *.dfm}

procedure TSSFrm.Chromium1AfterCreated(Sender: TObject; const browser: ICefBrowser);
begin
  FIsGoogleSearchPageLoaded := False;
  FIsGoogleSearchPageCreated := True;
end;

function TSSFrm.IsGoogleSearchPageCreated: Boolean;
begin
  Result := FIsGoogleSearchPageCreated;
end;

procedure TSSFrm.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled := False;
  if not (ChromiumWindow1.CreateBrowser) and not (ChromiumWindow1.Initialized) then
    Timer1.Enabled := True;
end;

end.

When I run TestTSSFrm.TestChromium1AfterCreated; the test pass but when it comes to close the test application then the application itself does not close completely and I have to reset it from the IDE manually. If I comment out the lines

  FMainForm.Free;
  FMainForm := nil;

then I have no issues with closing the test application but I have to close the form manually.

Where am I doing wrong?

Jan Doggen
  • 8,799
  • 13
  • 70
  • 144
pio pio
  • 732
  • 1
  • 7
  • 29
  • 1
    You shouldn't need to explicitly free FMainForm, since it was created with Application.CreateForm, which sets Application as the owner, because Application will free it. TearDown should probably just call FMainForm.Close. The whole arrangement looks very odd – Dave Nottage Jun 09 '18 at 23:10
  • Thank you for your suggestion. I have replaced Application.CreateForm(TForm, FMainForm); with FMainForm := TForm.Create(nil); and the application closes completely now. – pio pio Jun 10 '18 at 14:21

0 Answers0