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