Browse Source

Change testkit API and function

Ben Hsieh 8 years ago
parent
commit
dad766f308

+ 32
- 18
test/react-native-testkit/components/reporter.js View File

@@ -25,23 +25,30 @@ export default class Reporter extends Component {
25 25
   }
26 26
 
27 27
   renderTests() {
28
-    return this.props.context.tests.map((t, i) => {
28
+    let tests = this.props.context.tests
29
+    return tests.map((t, i) => {
29 30
 
30 31
       let pass = true
31
-      let foundAssertions = false
32
+      let foundActions = false
32 33
 
33
-      if(Array.isArray(t.result)) {
34
+      if(Array.isArray(t.result) && !t.expired) {
34 35
         t.result = t.result.map((r) => {
35
-          if(r.type.name === 'Assert') {
36
-            foundAssertions = true
36
+          if(r.type.name === 'Assert' || r.type.name === 'Info') {
37
+            foundActions = true
37 38
             let comp = r.props.comparer ? r.props.comparer(r.props.expect, r.props.actual) : (r.props.actual === r.props.expect)
38 39
             pass = pass && comp
39 40
           }
40 41
           return React.cloneElement(r, {desc : r.key})
41 42
         })
42 43
       }
43
-
44
-      t.status = foundAssertions ? (pass ? 'pass' : 'fail') : 'pass'
44
+      if(tests[i].running)
45
+        t.status = 'running'
46
+      else if(this.props.context.tests[i].executed) {
47
+        t.status = foundActions ? (pass ? 'pass' : 'fail') : 'skipped'
48
+        t.status = t.expired ? 'timeout' : t.status
49
+      }
50
+      else
51
+        t.status = 'waiting'
45 52
 
46 53
       return (<View key={'rn-test-' + t.desc} style={{
47 54
         borderBottomWidth : 1.5,
@@ -52,7 +59,7 @@ export default class Reporter extends Component {
52 59
           flexDirection : 'row'
53 60
         }}>
54 61
           <Text style={[styles.badge, {flex : 1, borderWidth : 0, textAlign : 'left'}]}>{t.desc}</Text>
55
-          <Text style={[styles.badge, this.getBadge(t.status)]}>{t.status ? 'pass' : 'fail'}</Text>
62
+          <Text style={[styles.badge, this.getBadge(t.status)]}>{t.status}</Text>
56 63
         </View>
57 64
         <View key={t.desc + '-result'} style={{backgroundColor : '#F4F4F4'}}>
58 65
           {t.result}
@@ -61,13 +68,8 @@ export default class Reporter extends Component {
61 68
     })
62 69
   }
63 70
 
64
-  getBadge(status: 'running' | 'pass' | 'fail') {
65
-    if(status === 'running')
66
-      return styles.badgeWaiting
67
-    else if(status === 'pass')
68
-      return styles.badgePass
69
-    else
70
-      return styles.badgeFail
71
+  getBadge(status: 'waiting' | 'running' | 'pass' | 'fail' | 'timeout') {
72
+    return styles[status]
71 73
   }
72 74
 
73 75
 }
@@ -84,15 +86,27 @@ const styles = StyleSheet.create({
84 86
     borderWidth : 2,
85 87
     textAlign : 'center'
86 88
   },
87
-  badgePass: {
89
+  skipped: {
90
+    borderColor : '#AAAAAA',
91
+    color : '#AAAAAA'
92
+  },
93
+  waiting: {
94
+    borderColor : '#AAAAAA',
95
+    color : '#AAAAAA'
96
+  },
97
+  pass: {
88 98
     borderColor : '#00a825',
89 99
     color : '#00a825'
90 100
   },
91
-  badgeWaiting: {
101
+  running: {
92 102
     borderColor : '#e3c423',
93 103
     color : '#e3c423'
94 104
   },
95
-  badgeFail: {
105
+  fail: {
106
+    borderColor : '#ff0d0d',
107
+    color : '#ff0d0d'
108
+  },
109
+  timeout: {
96 110
     borderColor : '#ff0d0d',
97 111
     color : '#ff0d0d'
98 112
   }

+ 90
- 8
test/react-native-testkit/lib/test-context.js View File

@@ -1,37 +1,119 @@
1
+//@flow
1 2
 export default class TestContext {
2 3
 
4
+  test: Array<TestCase>;
5
+  context: ReactElement;
6
+
7
+  static timeout = 3000;
8
+
9
+  static setTimeout (val) {
10
+    this.timeout  = val
11
+  }
12
+
3 13
   constructor() {
4 14
     this.tests = []
5 15
     this.context = null
6 16
   }
7 17
 
8
-  describe (desc, fn) {
18
+  /**
19
+   * Calling this method will push a test case into task queue.
20
+   * @param  {String}   desc Description of test case.
21
+   * @param  {Function:Promise<any>} fn   Body of test case, this function
22
+   *         should return a promise.
23
+   * @return {void}
24
+   */
25
+  describe (desc:string, fn:() => Promise<any>) {
9 26
 
10 27
     this.tests.push({
11
-      status : 'running',
28
+      status : 'waiting',
12 29
       result : null,
13 30
       asserts : [],
31
+      timeout : 3000,
32
+      expired : false,
33
+      running : false,
34
+      executed : false,
14 35
       desc, fn,
15 36
     })
16 37
 
17 38
   }
18 39
 
19
-  run (context) {
40
+  /**
41
+   * Run test cases in sequence.
42
+   * @param  {ReactElement} context ReactElement instance context.
43
+   * @return {void}
44
+   */
45
+  run (context:ReactElement) {
20 46
     this.context = context
21 47
     let promise = Promise.resolve()
48
+    // run test case sequently
22 49
     for(let i in this.tests) {
23
-      promise = promise.then(function(update, data) {
24
-        return this.fn(update, data)
25
-      }.bind(
50
+      promise = promise.then(function(update, updateInternal, data) {
51
+        return new Promise((resolve, reject) => {
52
+
53
+          let expired = false
54
+          updateInternal({
55
+            running : true,
56
+          })
57
+
58
+          // set timeout timer
59
+          let tm = setTimeout(() => {
60
+            updateInternal({
61
+              expired : true,
62
+              executed : true,
63
+              running : false
64
+            })
65
+            resolve('ETIMEOUT')
66
+          }, this.timeout)
67
+
68
+          // run test body
69
+          this.fn.bind(this)(update, data).then((...res) => {
70
+            if(!expired) {
71
+              clearTimeout(tm)
72
+              updateInternal({
73
+                executed : true,
74
+                running : false
75
+              })
76
+              resolve(...res)
77
+            }
78
+          }).catch((err) => {
79
+            updateInternal({
80
+              executed : true,
81
+              running : false
82
+            })
83
+          })
84
+
85
+        })
86
+      }
87
+      .bind(
26 88
         this.tests[i],
27
-        this.update.bind(this, i)
89
+        this.update.bind(this, i),
90
+        this.updateInternal.bind(this, i)
28 91
       ))
29 92
     }
30 93
     return promise
31 94
   }
32 95
 
96
+  /**
97
+   * Update test task result of given index.
98
+   * @param  {number} i       Index of test case to be updated.
99
+   * @param  {ReactElement<Info | Assert>} ...data Assertion or Info of test.
100
+   * @return {void}
101
+   */
33 102
   update(i, ...data) {
34
-    Object.assign(this.tests[i], {result : [...data]})
103
+    let test = this.tests[i]
104
+    let result = test.result || []
105
+    Object.assign(test, {result : [...result, ...data]})
106
+    this.context.forceUpdate()
107
+  }
108
+
109
+  /**
110
+   * Update test result for testkit internal use
111
+   * @param  {[type]} i      Index of test case to be updated.
112
+   * @param  {TestCaseContext} result Test case object
113
+   * @return {void}
114
+   */
115
+  updateInternal(i, result) {
116
+    Object.assign(this.tests[i], result)
35 117
     this.context.forceUpdate()
36 118
   }
37 119