1 module dshould;
2 
3 import dshould.ShouldType;
4 
5 public import dshould.basic;
6 public import dshould.contain;
7 public import dshould.empty;
8 public import dshould.stringcmp;
9 public import dshould.thrown;
10 
11 // dispatch based on type
12 void equal(Should, T)(Should should, T value, string file = __FILE__, size_t line = __LINE__)
13 if (isInstanceOf!(ShouldType, Should))
14 {
15     static if (is(typeof(should.data.lhs()) == string) && is(T == string) && !Should.hasWord!"not")
16     {
17         dshould.stringcmp.equal(should, value, file, line);
18     }
19     else
20     {
21         dshould.basic.equal(should, value, file, line);
22     }
23 }
24 
25 auto equal(Should)(Should should)
26 if (isInstanceOf!(ShouldType, Should))
27 {
28     return should.basic.equal(should);
29 }
30 
31 template throwA(T : Throwable)
32 {
33     void throwA(Should, string file = __FILE__)(Should should, string msgTest, size_t line = __LINE__)
34     if (isInstanceOf!(ShouldType, Should))
35     {
36         dshould.thrown.throwA!T(should, file, line).where.its.msg.should.equal(msgTest, file, line);
37     }
38 
39     auto throwA(Should, string file = __FILE__)(Should should, size_t line = __LINE__)
40     if (isInstanceOf!(ShouldType, Should))
41     {
42         return dshould.thrown.throwA!T(should, file, line);
43     }
44 }
45 
46 alias throwAn = throwA;
47 
48 @("compares messages in throwA string overload")
49 unittest
50 {
51     2.should.be(5).because("string A")
52         .should.throwA!FluentException("string B")
53         .should.throwA!FluentException;
54 }
55 
56 unittest
57 {
58     2.should.be(5).should.throwA!FluentException("test failed: expected 5, but got 2");
59 }
60 
61 @("prints informative errors for int comparison")
62 unittest
63 {
64     2.should.be(3).should.throwA!FluentException("test failed: expected 3, but got 2");
65 }
66 
67 @("prints informative errors for object comparison")
68 unittest
69 {
70     Object obj;
71 
72     obj.should.not.be(null)
73         .should.throwA!FluentException("test failed: expected non-null, but got null");
74 
75     obj = new Object;
76 
77     obj.should.be(null)
78         .should.throwA!FluentException("test failed: expected null, but got object.Object");
79 
80     obj.should.not.be(obj)
81         .should.throwA!FluentException(
82             "test failed: expected different reference than object.Object, but got object.Object");
83 
84     obj.should.be(new Object)
85         .should.throwA!FluentException(
86             "test failed: expected same reference as object.Object, but got object.Object");
87 }
88 
89 @("prints informative errors for inequalities")
90 unittest
91 {
92     2.should.be.greater.equal(5)
93         .should.throwA!FluentException("test failed: expected value >= 5, but got 2");
94 
95     2.should.not.be.smaller.equal(5)
96         .should.throwA!FluentException("test failed: expected value not <= 5, but got 2");
97 }
98 
99 @("prints informative errors for array emptiness")
100 unittest
101 {
102     [].should.not.be.empty
103         .should.throwA!FluentException("test failed: expected nonempty array");
104 
105     [5].should.be.empty
106         .should.throwA!FluentException("test failed: expected empty array, but got [5]");
107 }
108 
109 @("prints informative errors for approximate checks")
110 unittest
111 {
112     2.should.approximately(0.5).be(4)
113         .should.throwA!FluentException("test failed: expected 4 ± 0.5, but got 2");
114 
115     (2.4).should.not.approximately(0.5).be(2)
116         .should.throwA!FluentException("test failed: expected value outside 2 ± 0.5, but got 2.4");
117 }
118 
119 @("asserts when forgetting to terminate should expression")
120 unittest
121 {
122     import core.exception : AssertError;
123 
124     void test()
125     {
126         2.should;
127     }
128 
129     test.should.throwAn!AssertError("unterminated should-chain!");
130 }