1 module feature_test.core;
2 
3 import feature_test.exceptions;
4 import feature_test.runner;
5 
6 import colorize;
7 
8 import std.stdio;
9 import std.algorithm;
10 
11 alias FTImplementation = void delegate(FeatureTest);
12 alias FTDelegate = void delegate();
13 
14 struct FeatureTestScenario {
15 	string name;
16 	FTDelegate implementation;
17 }
18 
19 class FeatureTest {
20 	alias info = FeatureTestRunner.info;
21 	
22 	@property ref string name() { return _name; }
23 	@property ref string description() { return _description; }
24 	@property string[] tags() { return _tags; }
25 	@property ref FeatureTestScenario[] scenarios() { return _scenarios; }
26 
27 	void addTags(string[] tags ...) {
28 		foreach(tag; tags) { if (!_tags.canFind(tag)) _tags ~= tag; }
29 	}
30 	
31 	final void addBeforeAll(FTDelegate d) {
32 		_beforeAllCallbacks ~= d;
33 	}
34 	
35 	final void addBeforeEach(FTDelegate d) {
36 		_beforeEachCallbacks ~= d;
37 	}
38 	
39 	final void addAfterEach(FTDelegate d) {
40 		_afterEachCallbacks ~= d;
41 	}
42 	
43 	final void addAfterAll(FTDelegate d) {
44 		_afterAllCallbacks ~= d;
45 	}
46 	
47 	// To be overridden 
48 	void beforeAll() {
49 	}
50 	
51 	// To be overridden 
52 	void beforeEach() {
53 	}
54 	
55 	// To be overridden 
56 	void afterEach() {
57 	}
58 	
59 	// To be overridden 
60 	void afterAll() {
61 	}
62 	
63 	void scenario(string name, FTDelegate implementation) {
64 		_scenarios ~= FeatureTestScenario(name, implementation);
65 	}
66 	
67 package:
68 	void _beforeAll() {
69 		beforeAll;
70 		runCallbacks(_beforeAllCallbacks);
71 	}
72 	
73 	void _beforeEach() {
74 		beforeEach;
75 		runCallbacks(_beforeEachCallbacks);
76 	}
77 	
78 	void _afterEach() {
79 		runCallbacks(_afterEachCallbacks);
80 		afterEach;
81 	}
82 	
83 	void _afterAll() {
84 		runCallbacks(_afterAllCallbacks);
85 		afterAll;
86 	}
87 	
88 private:
89 	string _name;
90 	string _description;
91 	string[] _tags;
92 	
93 	FeatureTestScenario[] _scenarios;
94 	FTDelegate[] _beforeEachCallbacks, _afterEachCallbacks, _beforeAllCallbacks, _afterAllCallbacks;
95 	
96 	void runCallbacks(FTDelegate[] callbacks) {
97 		foreach(callback; callbacks) callback();
98 	}
99 }
100 
101 void feature(T)(string name, string description, void delegate(T) implementation, string[] tags ...) {
102 	if (FeatureTestRunner.shouldInclude(tags)) {
103 		auto f = new T();
104 		f.name = name;
105 		f.description = description;
106 		f.addTags(tags);
107 		implementation(f);
108 		FeatureTestRunner.features ~= f;
109 	}
110 }
111 
112 void feature(T)(string name, void delegate(T) implementation, string[] tags ...) {
113 	feature!T(name, "", implementation, tags);
114 }
115 
116 void feature(string name, string description, void delegate(FeatureTest) implementation, string[] tags ...) {
117 	feature!FeatureTest(name, description, implementation, tags);
118 }
119 
120 void feature(string name, void delegate(FeatureTest) implementation, string[] tags ...) {
121 	feature!FeatureTest(name, "", implementation, tags);
122 }
123 
124 /// Marks a scenario as pending
125 void featureTestPending(string file = __FILE__, typeof(__LINE__) line = __LINE__) {
126 	throw new FeatureTestException(file, line);
127 }