1 module tests.server;
2 
3 import unit_threaded;
4 import cucumber.server;
5 import vibe.data.json;
6 
7 
8 void testFail() {
9     //handleRequest!__MODULE__("fsafs").shouldThrow!JSONException;
10     shouldEqual(handleRequest!__MODULE__(`["fsafs"]`), `["fail"]`);
11     shouldEqual(handleRequest!__MODULE__(`["foo"]`), `["fail"]`);
12 }
13 
14 void testNoMatches() {
15     shouldEqual(handleRequest!__MODULE__(`["step_matches",{"name_to_match":"foo"}]`), `["success",[]]`);
16 }
17 
18 private string[] funcCalls;
19 
20 @Match(`^we're wired$`)
21 void match1() {
22     funcCalls ~= "match1";
23 }
24 
25 @Match(`^2nd match$`)
26 void match2() {
27     funcCalls ~= "match2";
28 }
29 
30 @Match(`^\drd .+`)
31 void match3() {
32     funcCalls ~= "match3";
33 }
34 
35 void checkSuccessJson(string str, in string id, in string[] args) {
36     import std.algorithm;
37     auto json = parseJson(str);
38     shouldEqual(json[0], "success");
39     auto obj = json[1][0];
40     shouldEqual(obj["id"], id);
41     string[] objArgs;
42     foreach(arg; obj["args"])
43         objArgs ~= arg.toString;
44     shouldEqual(objArgs, args);
45 }
46 
47 @SingleThreaded
48 void testMatchesNoDetails() {
49     checkSuccessJson(handleRequest!__MODULE__(`["step_matches",{"name_to_match":"we're wired"}]`),
50                      "1", []);
51     checkSuccessJson(handleRequest!__MODULE__(`["step_matches",{"name_to_match":"we're wired"}]`),
52                      "1", []);
53     checkSuccessJson(handleRequest!__MODULE__(`["step_matches",{"name_to_match":"we're wired"}]`),
54                      "1", []);
55     checkSuccessJson(handleRequest!__MODULE__(`["step_matches",{"name_to_match":"2nd match"}]`),
56                      "2", []);
57     checkSuccessJson(handleRequest!__MODULE__(`["step_matches",{"name_to_match":"3rd match"}]`),
58                      "3", []);
59 
60 }
61 
62 @SingleThreaded
63 void testMatchesDetails() {
64     {
65         auto reply = handleRequest!__MODULE__(`["step_matches",{"name_to_match":"we're wired"}]`, Yes.details);
66         const json = parseJson(reply); //reply can't be const
67         writelnUt("json is ", json);
68 
69         shouldEqual(json[0].get!string, "success");
70         shouldEqual(json[1].length, 1);
71 
72         shouldEqual(json[1][0]["id"].to!int, 1);
73         shouldEqual(json[1][0]["args"].length.to!int, 0);
74         shouldEqual(json[1][0]["source"].to!string, "tests.server.match1:19");
75         shouldEqual(json[1][0]["regexp"].to!string, "^we're wired$");
76     }
77     {
78         auto reply = handleRequest!__MODULE__(`["step_matches",{"name_to_match":"2nd match"}]`, Yes.details);
79         const json = parseJson(reply); //reply can't be const
80         writelnUt("json is ", json);
81 
82         shouldEqual(json[0].get!string, "success");
83         shouldEqual(json[1].length, 1);
84 
85         shouldEqual(json[1][0]["id"].to!int, 2);
86         shouldEqual(json[1][0]["args"].length.to!int, 0);
87         shouldEqual(json[1][0]["source"].to!string, "tests.server.match2:24");
88         shouldEqual(json[1][0]["regexp"].to!string, "^2nd match$");
89     }
90 }
91 
92 private auto jsonReply(string request) {
93     auto reply = handleRequest!__MODULE__(request);
94     return parseJson(reply);
95 }
96 
97 @Match(`das pending1`)
98 void pendingFunc1() {
99     funcCalls ~= "pending1";
100     pending("I'll do it later");
101 }
102 
103 @Match(`das pending2`)
104 void pendingFunc2() {
105     funcCalls ~= "pending2";
106     pending("But I'm le tired");
107 }
108 
109 
110 @SingleThreaded
111 void testInvokePending() {
112     {
113         const matchesReply = jsonReply(`["step_matches",{"name_to_match":"das pending1"}]`);
114         const id = matchesReply[1][0]["id"].to!string;
115         const beginReply = jsonReply(`["begin_scenario"]`);
116         shouldEqual(beginReply.toString(), `["success"]`);
117 
118         funcCalls = [];
119         const invokeReply = jsonReply(`["invoke", {"id": "` ~ id ~ `", "args": []}]`);
120         shouldEqual(funcCalls, ["pending1"]);
121         shouldEqual(invokeReply[0], "pending");
122         shouldEqual(invokeReply[1], "I'll do it later");
123     }
124     {
125         const matchesReply = jsonReply(`["step_matches",{"name_to_match":"das pending2"}]`);
126         const id = matchesReply[1][0]["id"].to!string;
127         const beginReply = jsonReply(`["begin_scenario"]`);
128         shouldEqual(beginReply.toString(), `["success"]`);
129 
130         funcCalls = [];
131         const invokeReply = jsonReply(`["invoke", {"id": "` ~ id ~ `", "args": []}]`);
132         shouldEqual(funcCalls, ["pending2"]);
133         shouldEqual(invokeReply[0], "pending");
134         shouldEqual(invokeReply[1], "But I'm le tired");
135     }
136 }
137 
138 @SingleThreaded
139 void testInvokePass() {
140     const matchesReply = jsonReply(`["step_matches",{"name_to_match":"we're wired"}]`);
141     writelnUt("Reply: ", matchesReply);
142 
143     const beginReply = jsonReply(`["begin_scenario"]`);
144     shouldEqual(beginReply.toString(), `["success"]`);
145 
146     funcCalls = [];
147     const id = matchesReply[1][0]["id"].to!string;
148     const invokeReply = jsonReply(`["invoke", {"id": "` ~ id ~ `", "args": []}]`);
149     writelnUt("Reply: ", invokeReply);
150 
151     shouldEqual(funcCalls, ["match1"]);
152     shouldEqual(invokeReply[0], "success");
153     shouldEqual(invokeReply.length, 1);
154 
155     const endReply = jsonReply(`["end_scenario"]`);
156     shouldEqual(endReply.toString(), `["success"]`);
157 }
158 
159 class TestException: Exception {
160     this(string msg) {
161         super(msg);
162     }
163 }
164 
165 @Given(`oops gonna fail`)
166 void gonnaFail() {
167     funcCalls ~= "gonna fail";
168     throw new TestException("I did it again");
169 }
170 
171 @SingleThreaded
172 void testInvokeFail() {
173     const matchesReply = jsonReply(`["step_matches",{"name_to_match":"oops gonna fail"}]`);
174     writelnUt("Reply: ", matchesReply);
175 
176     const beginReply = jsonReply(`["begin_scenario"]`);
177     shouldEqual(beginReply.toString(), `["success"]`);
178 
179     funcCalls = [];
180     const id = matchesReply[1][0]["id"].to!string;
181     const invokeReply = jsonReply(`["invoke", {"id": "` ~ id ~ `", "args": []}]`);
182     writelnUt("Reply: ", invokeReply);
183 
184     writelnUt("Start of the checks");
185     shouldEqual(funcCalls, ["gonna fail"]);
186     shouldEqual(invokeReply.length, 2);
187     shouldEqual(invokeReply[0], "fail");
188     shouldEqual(invokeReply[1]["message"].to!string, "I did it again");
189     shouldEqual(invokeReply[1]["exception"].to!string, "tests.server.TestException");
190 
191     const endReply = jsonReply(`["end_scenario"]`);
192     shouldEqual(endReply.toString(), `["success"]`);
193 }