-
Notifications
You must be signed in to change notification settings - Fork 0
/
selenography.cy
129 lines (106 loc) · 3.67 KB
/
selenography.cy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// selenography - unit testing for iPhone apps/extensions via Cycript
// Include NSLog.
NSLog_ = dlsym(RTLD_DEFAULT, "NSLog")
NSLog = function() { var types = 'v', args = [], count = arguments.length; for (var i = 0; i != count; ++i) { types += '@'; args.push(arguments[i]); } new Functor(NSLog_, types).apply(null, args); }
var passes = 0;
var fails = 0;
// => LOGGERS
// Lets you output test results in various ways
var NSLogLogger = new function InternalNSLogLogger() {
this.log = function(str) { NSLog(str); }
this.terminate = function(c) {}
}
var FileLogger = new function InternalFileLogger() {
this.buffer = [new NSString init];
this.log = function(str) { this.buffer += str + "\n"; }
this.terminate = function(c) {
[this.buffer writeToFile:"/tmp/Tests_"+c+".log" atomically:YES];
this.buffer = [new NSString init];
}
}
var CombinedLogger = new function InternalCombinedLogger() {
this.log = function(str) {
FileLogger.log(str);
NSLogLogger.log(str);
}
this.terminate = function(c) { FileLogger.terminate(c); }
}
// Default logger: combination of saving to a file in /tmp and logging to NSLog
var desiredLogger = CombinedLogger;
// => CONTEXTS
function beginContext(context) {
desiredLogger.log("Running tests for context '"+context+"'...");
}
function endContext(context) {
desiredLogger.log("" + passes + " assertions passed, " + fails + " assertions failed");
desiredLogger.terminate(context);
passes = 0; fails = 0;
}
function context(name, scope) {
beginContext(name);
scope();
endContext(name);
}
function pass() {
passes++;
}
function fail(desc) {
fails++;
desiredLogger.log(" * [FAILED] " + desc);
}
// => ASSERTIONS
// Now all based on the assertBlock helper, mostly stolen from JSUnitTest.
function assertBlock(block, desc) {
try {
block() ? pass() : fail(desc);
} catch (e) { fail(desc) }
}
// Stuff that would work in plain-old JS.
function assertTrue(t, desc) {
assertBlock(function() { return t == true; }, desc);
}
function assertFalse(t, desc) {
assertBlock(function() { return t == false; }, desc);
}
function assertEquals(something, whatItShouldEqual, desc) {
assertBlock(function() { return something == whatItShouldEqual; }, desc);
}
function assertNotEquals(something, whatItShouldEqual, desc) {
assertBlock(function() { return something != whatItShouldEqual; }, desc);
}
// Obj-C/Cycript-specific assertions.
function assertRespondsToSelector(obj, sel, desc) {
assertBlock(function() { return [obj respondsToSelector:(new Selector(sel))]; }, desc);
}
function assertIsKindOfClass(obj, className, desc) {
assertBlock(function() { return [obj isKindOfClass:(objc_getClass(className))]; }, desc);
}
function assertNotKindOfClass(obj, className, desc) {
assertBlock(function() { return ![obj isKindOfClass:objc_getClass(className)]; }, desc);
}
// => BENCHMARKS
// JS date objects are known to be up to 15ms off. Take that into consideration.
function assertRunsFasterThan(block, ms, iterations, desc) {
// "On average, $block() runs faster than $ms milliseconds over $iterations iterations"
var sum = 0;
for (var i = 1; i <= iterations; i++) {
var start = new Date();
block();
var end = new Date();
sum += end - start;
}
assertBlock(function() { return (sum / iterations) < ms; }, desc);
}
function assertAlwaysRunsFasterThan(block, ms, iterations, desc) {
// "Over $iterations iterations, $block() always ran faster than $ms milliseconds"
assertBlock(function() {
for (var i=1; i<= iterations; i++) {
var start = new Date();
block();
var end = new Date();
var delta = end - start;
if (delta >= ms) return false;
}
return true;
}, desc);
}