-
Notifications
You must be signed in to change notification settings - Fork 24
/
Grijjy.Mvvm.Mock.pas
109 lines (89 loc) · 2.95 KB
/
Grijjy.Mvvm.Mock.pas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
unit Grijjy.Mvvm.Mock;
{ Some mock classes for unit testing MVVM functionality. }
{$INCLUDE 'Grijjy.inc'}
interface
uses
System.UITypes,
System.Classes,
System.SysUtils,
System.Generics.Collections,
Grijjy.Mvvm.Types;
type
{ A mock view that implements the IgoView interface.
The type parameter TVM is the type of the view model used by the view. }
TgoMockView<TVM: class> = class(TComponent, IgoView, IgoView<TVM>)
{$REGION 'Internal Declarations'}
private class var
FRegisteredMockViews: TDictionary<TComponentClass, TFunc<TVM, TModalResult>>;
private
FViewModel: TVM;
FOwnsViewModel: Boolean;
protected
{ IgoView }
procedure InitView(const AViewModel: TVM; const AOwnsViewModel: Boolean);
procedure ExecuteModal(const AResultProc: TProc<TModalResult>);
public
class destructor Destroy;
{$ENDREGION 'Internal Declarations'}
public
destructor Destroy; override;
{ Registers a mock view with the view factory.
Parameters:
AName: the name of the view. The view factory uses this name to look up
the type of view to create.
AExecuteModal: an anonymous function that is executed to simulate the
modal execution of the view. This function has a single parameter with
the type of the view modal associated with the view. It must return a
TModalResult value to indicate how the view was closed. Cannot be nil. }
class procedure Register(const AName: String;
const AExecuteModal: TFunc<TVM, TModalResult>);
{ The view model for the view. }
property ViewModel: TVM read FViewModel;
end;
implementation
uses
Grijjy.Mvvm.ViewFactory;
{ TgoMockView<TVM> }
destructor TgoMockView<TVM>.Destroy;
begin
if (FOwnsViewModel) then
FViewModel.Free;
inherited;
end;
class destructor TgoMockView<TVM>.Destroy;
begin
FRegisteredMockViews.Free;
end;
procedure TgoMockView<TVM>.ExecuteModal(const AResultProc: TProc<TModalResult>);
var
ExecuteModal: TFunc<TVM, TModalResult>;
ModalResult: TModalResult;
begin
ModalResult := mrNone;
if Assigned(FRegisteredMockViews)
and (FRegisteredMockViews.TryGetValue(TComponentClass(ClassType), ExecuteModal))
then
ModalResult := ExecuteModal(FViewModel);
if Assigned(AResultProc) then
AResultProc(ModalResult);
{ Mimic the free-on-close behavior of a form }
DisposeOf;
end;
procedure TgoMockView<TVM>.InitView(const AViewModel: TVM;
const AOwnsViewModel: Boolean);
begin
Assert(AViewModel <> nil);
Assert(FViewModel = nil);
FViewModel := AViewModel;
FOwnsViewModel := AOwnsViewModel;
end;
class procedure TgoMockView<TVM>.Register(const AName: String;
const AExecuteModal: TFunc<TVM, TModalResult>);
begin
Assert(Assigned(AExecuteModal));
TgoViewFactory.Register(Self, AName);
if (FRegisteredMockViews = nil) then
FRegisteredMockViews := TDictionary<TComponentClass, TFunc<TVM, TModalResult>>.Create;
FRegisteredMockViews.AddOrSetValue(Self, AExecuteModal);
end;
end.