tcbasemustache.pas 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. {
  2. This file is part of the Free Pascal Run time library.
  3. Copyright (c) 2021 by Michael Van Canneyt ([email protected])
  4. Helper classes for Mustache test cases
  5. See the File COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. unit tcbasemustache;
  12. {$mode ObjFPC}{$H+}
  13. interface
  14. uses
  15. Classes, SysUtils, fpcunit, fpmustache;
  16. type
  17. { TTestContext }
  18. (* StringList with following encoding
  19. // Null value
  20. aName=<null>
  21. // false value
  22. aName=<null>
  23. // plain value
  24. aName=AValue
  25. // Object value & member. Object value must be present
  26. SubObj={}
  27. SubObj.aName=aValue
  28. // Array and members. Array value must be present
  29. SubObj.SubArr=[]
  30. SubObj.SubArr[0]={}
  31. SubObj.SubArr[0].aName=aValue
  32. SubObj.SubArr[1]={}
  33. Subobj.SubArr[1].aName=aValue
  34. *)
  35. TTestContext = class (TMustacheContext)
  36. Private
  37. FValues : TStringList;
  38. FPath : String;
  39. public
  40. Constructor Create(aCallback: TGetTextValueEvent); override;
  41. Destructor destroy; override;
  42. Function GetTextValue(Const aName : TMustacheString) : TMustacheString; override;
  43. Function MoveNextSectionItem(Const aName : TMustacheString) : Boolean; override;
  44. Function PushSection(Const aName : TMustacheString) : TMustacheSectionType; override;
  45. Procedure PopSection(Const aName : TMustacheString); override;
  46. Procedure SetValue(const aPath,aValue : string);
  47. Property Values : TStringList read FValues;
  48. end;
  49. TBaseMustacheTest = class(TTestCase)
  50. Private
  51. FPartials: TStrings;
  52. FTemplate: String;
  53. FResult: TMustacheElement;
  54. FParser: TMustacheParser;
  55. Protected
  56. Function CreateParser : TMustacheParser; virtual; abstract;
  57. Procedure DoGetPartial(const aName: TMustacheString; var aHandled: Boolean; var aValue: TMustacheString);
  58. Public
  59. Class Procedure AssertEquals(Msg : String; aExpected,aActual : TMustacheElementType); overload;
  60. Class Function AssertElement(aParent : TMustacheElement; aIndex: Integer; aType: TMustacheElementType; aData: String; aClass : TMustacheElementClass = Nil) : TMustacheElement; overload;
  61. Function AssertElement(aIndex: Integer; aType: TMustacheElementType; aData: String; aClass : TMustacheElementClass = Nil) : TMustacheElement; overload;
  62. Procedure AssertResultCount(aCount : Integer);
  63. procedure SetUp; override;
  64. procedure TearDown; override;
  65. Procedure CallParser;
  66. Procedure AddPartial(Const aName,aText: TMustacheString);
  67. Property Partials : TStrings Read FPartials;
  68. Property Template : String Read FTemplate Write FTemplate;
  69. property ParseResult : TMustacheElement Read FResult;
  70. property Parser : TMustacheParser Read FParser;
  71. end;
  72. implementation
  73. uses strutils, typinfo;
  74. { TTestContext }
  75. constructor TTestContext.Create(aCallback: TGetTextValueEvent);
  76. begin
  77. inherited Create(aCallback);
  78. FValues:=TStringList.Create;
  79. FValues.OwnsObjects:=True;
  80. end;
  81. destructor TTestContext.destroy;
  82. begin
  83. FreeAndNil(FValues);
  84. inherited destroy;
  85. end;
  86. function TTestContext.GetTextValue(const aName: TMustacheString
  87. ): TMustacheString;
  88. Var
  89. aPath,N : String;
  90. Done : Boolean;
  91. begin
  92. Result:='';
  93. aPath:=FPath;
  94. Done:=False;
  95. Repeat
  96. if aPath<>'' then
  97. N:=aPath+'.'+aName
  98. else
  99. begin
  100. N:=aName;
  101. Done:=True;
  102. end;
  103. Result:=FValues.Values[N];
  104. if not Done then
  105. aPath:=Copy(aPath,1,RPos('.',aPath)-1);
  106. until (Result<>'') or Done;
  107. end;
  108. function TTestContext.MoveNextSectionItem(const aName: TMustacheString
  109. ): Boolean;
  110. Var
  111. L,P,Idx : Integer;
  112. N : String;
  113. begin
  114. L:=Length(FPath);
  115. if (L>0) and (FPath[L]=']') then
  116. begin
  117. P:=RPos('[',FPath)+1;
  118. Idx:=StrToIntDef(Copy(FPath,P,L-P),-1);
  119. N:=Copy(FPath,1,P-1)+IntToStr(Idx+1)+']';
  120. Result:=FValues.Values[N]<>''; // We could check for {}
  121. if Result then
  122. FPath:=N;
  123. end;
  124. end;
  125. function TTestContext.PushSection(const aName: TMustacheString): TMustacheSectionType;
  126. Var
  127. aPath,S : String;
  128. begin
  129. if FPath<>'' then
  130. FPath:=FPath+'.';
  131. aPath:=FPath+aName;
  132. S:=Values.Values[aPath];
  133. if S='{}' then
  134. begin
  135. FPath:=aPath;
  136. result:=mstSingle;
  137. end;
  138. if S='[]' then
  139. begin
  140. if Values.Values[aPath+'[0]']='' then
  141. Result:=mstNone
  142. else
  143. begin
  144. FPath:=aPath+'[-1]';
  145. result:=mstList;
  146. end;
  147. end
  148. else if (s='<null>') or (s='<false>') or (s='') then
  149. begin
  150. Result:=mstNone;
  151. end
  152. else
  153. begin
  154. FPath:=aPath;
  155. result:=mstSingle;
  156. end;
  157. end;
  158. procedure TTestContext.PopSection(const aName: TMustacheString);
  159. begin
  160. FPath:=Copy(FPath,1,RPos('.',FPath)-1);
  161. end;
  162. procedure TTestContext.SetValue(const aPath, aValue: string);
  163. begin
  164. Values.Values[aPath]:=aValue;
  165. end;
  166. { TBaseMustacheTest }
  167. procedure TBaseMustacheTest.SetUp;
  168. begin
  169. Inherited;
  170. FParser:=CreateParser;
  171. FParser.Partials:=TMustachePartialList.Create(metRoot,Nil,0);
  172. FParser.OnGetPartial:=@DoGetPartial;
  173. FPartials:=TStringList.Create;
  174. TStringList(FPartials).OwnsObjects:=True;
  175. end;
  176. procedure TBaseMustacheTest.TearDown;
  177. begin
  178. FreeAndNil(FPartials);
  179. FreeAndNil(FResult);
  180. FParser.Partials.Free;
  181. FreeAndNil(FParser);
  182. Inherited;
  183. end;
  184. procedure TBaseMustacheTest.DoGetPartial(const aName: TMustacheString;
  185. var aHandled: Boolean; var aValue: TMustacheString);
  186. begin
  187. aValue:=FPartials.Values[aName];
  188. aHandled:=FPartials.IndexOfName(aName)<>-1;
  189. end;
  190. class function TBaseMustacheTest.AssertElement(aParent: TMustacheElement;
  191. aIndex: Integer; aType: TMustacheElementType; aData: String;
  192. aClass: TMustacheElementClass): TMustacheElement;
  193. Var
  194. El : TMustacheElement;
  195. aChild : String;
  196. begin
  197. AssertNotNull('Have parent',aParent);
  198. AssertTrue(Format('Index %d in range 0..%d',[aIndex,aParent.ChildCount-1]),(aIndex>=0) and (aIndex<aParent.ChildCount));
  199. EL:=aParent.Children[aIndex];
  200. aChild:=Format('Child %d',[aIndex]);
  201. AssertNotNull('Have result '+aChild,El);
  202. AssertEquals(aChild+' has correct type',aType,El.ElementType);
  203. AssertEquals(aChild+' has correct data',aData,El.Data);
  204. if (aClass<>Nil) then
  205. AssertEquals(aChild+' has correct class',aClass,el.Classtype);
  206. Result:=El;
  207. end;
  208. function TBaseMustacheTest.AssertElement(aIndex: Integer;
  209. aType: TMustacheElementType; aData: String; aClass : TMustacheElementClass = Nil): TMustacheElement;
  210. begin
  211. AssertNotNull('Have result',FResult);
  212. Result:=AssertElement(FResult,aIndex,aType,aData,aClass);
  213. end;
  214. procedure TBaseMustacheTest.AssertResultCount(aCount: Integer);
  215. begin
  216. AssertNotNull('Have result',FResult);
  217. AssertEquals('Result count',aCount,FResult.ChildCount);
  218. end;
  219. procedure TBaseMustacheTest.CallParser;
  220. begin
  221. Parser.Template:=Template;
  222. FResult:=Parser.Parse;
  223. end;
  224. procedure TBaseMustacheTest.AddPartial(const aName, aText: TMustacheString);
  225. //Var
  226. // T : TMustacheTextElement;
  227. begin
  228. // T:=TMustacheTextElement.Create(metText,Nil,0);
  229. // T.Data:=aText;
  230. FPartials.Add(aName+'='+atext);
  231. end;
  232. class procedure TBaseMustacheTest.AssertEquals(Msg: String; aExpected,
  233. aActual: TMustacheElementType);
  234. begin
  235. AssertEquals(Msg,GetEnumName(typeInfo(TMustacheElementType),Ord(aExpected)),
  236. GetEnumName(typeInfo(TMustacheElementType),Ord(aActual)));
  237. end;
  238. end.