Kaynağa Gözat

Add test cases for #45

Ben Hsieh 8 yıl önce
ebeveyn
işleme
cfbcdfbf05

+ 174
- 0
test/react-native-testkit/animate-text.js Dosyayı Görüntüle

@@ -0,0 +1,174 @@
1
+/**
2
+ * @author wkh237
3
+ * @version 0.1.1
4
+ */
5
+
6
+// @flow
7
+
8
+import React, { Component } from 'react';
9
+import {
10
+  Text,
11
+  View
12
+} from 'react-native';
13
+import Timer from 'react-timer-mixin';
14
+
15
+const HALF_RAD = Math.PI/2
16
+
17
+export default class AnimateNumber extends Component {
18
+
19
+  props : {
20
+    countBy? : ?number,
21
+    interval? : ?number,
22
+    steps? : ?number,
23
+    value : number,
24
+    timing : 'linear' | 'easeOut' | 'easeIn' | () => number,
25
+    formatter : () => {},
26
+    onProgress : () => {},
27
+    onFinish : () => {}
28
+  };
29
+
30
+  static defaultProps = {
31
+    interval : 14,
32
+    timing : 'linear',
33
+    steps : 45,
34
+    value : 0,
35
+    formatter : (val) => val,
36
+    onFinish : () => {}
37
+  };
38
+
39
+  static TimingFunctions = {
40
+
41
+    linear : (interval:number, progress:number):number => {
42
+      return interval
43
+    },
44
+
45
+    easeOut : (interval:number, progress:number):number => {
46
+      return interval * Math.sin(HALF_RAD*progress) * 5
47
+    },
48
+
49
+    easeIn : (interval:number, progress:number):number => {
50
+      return interval * Math.sin((HALF_RAD - HALF_RAD*progress)) * 5
51
+    },
52
+
53
+  };
54
+
55
+  state : {
56
+    value? : ?number,
57
+    displayValue? : ?number
58
+  };
59
+
60
+  /**
61
+   * Animation direction, true means positive, false means negative.
62
+   * @type {bool}
63
+   */
64
+  direction : bool;
65
+  /**
66
+   * Start value of last animation.
67
+   * @type {number}
68
+   */
69
+  startFrom : number;
70
+  /**
71
+  * End value of last animation.
72
+  * @type {number}
73
+   */
74
+  endWith : number;
75
+
76
+  constructor(props:any) {
77
+    super(props);
78
+    // default values of state and non-state variables
79
+    this.state = {
80
+      value : 0,
81
+      displayValue : 0
82
+    }
83
+    this.dirty = false;
84
+    this.startFrom = 0;
85
+    this.endWith = 0;
86
+  }
87
+
88
+  componentDidMount() {
89
+    this.startFrom = this.state.value
90
+    this.endWith = this.props.value
91
+    this.dirty = true
92
+    this.startAnimate()
93
+  }
94
+
95
+  componentWillUpdate(nextProps, nextState) {
96
+
97
+    // check if start an animation
98
+    if(this.props.value !== nextProps.value) {
99
+      this.startFrom = this.props.value
100
+      this.endWith = nextProps.value
101
+      this.dirty = true
102
+      this.startAnimate()
103
+      return
104
+    }
105
+    // Check if iterate animation frame
106
+    if(!this.dirty) {
107
+      return
108
+    }
109
+    if (this.direction === true) {
110
+      if(parseFloat(this.state.value) <= parseFloat(this.props.value)) {
111
+        this.startAnimate();
112
+      }
113
+    }
114
+    else if(this.direction === false){
115
+      if (parseFloat(this.state.value) >= parseFloat(this.props.value)) {
116
+        this.startAnimate();
117
+      }
118
+    }
119
+
120
+  }
121
+
122
+  render() {
123
+    return (
124
+      <Text {...this.props}>
125
+        {this.state.displayValue}
126
+      </Text>)
127
+  }
128
+
129
+  startAnimate() {
130
+
131
+    let progress = this.getAnimationProgress()
132
+
133
+    Timer.setTimeout(() => {
134
+
135
+      let value = (this.endWith - this.startFrom)/this.props.steps
136
+      if(this.props.countBy)
137
+        value = Math.sign(value)*Math.abs(this.props.countBy)
138
+      let total = parseFloat(this.state.value) + parseFloat(value)
139
+
140
+      this.direction = (value > 0)
141
+      // animation terminate conditions
142
+      if (((this.direction) ^ (total <= this.endWith)) === 1) {
143
+        this.dirty = false
144
+        total = this.endWith
145
+        this.props.onFinish(total, this.props.formatter(total))
146
+      }
147
+
148
+      if(this.props.onProgress)
149
+        this.props.onProgress(this.state.value, total)
150
+
151
+      this.setState({
152
+        value : total,
153
+        displayValue : this.props.formatter(total)
154
+      })
155
+
156
+    }, this.getTimingFunction(this.props.interval, progress))
157
+
158
+  }
159
+
160
+  getAnimationProgress():number {
161
+    return (this.state.value - this.startFrom) / (this.endWith - this.startFrom)
162
+  }
163
+
164
+  getTimingFunction(interval:number, progress:number) {
165
+    if(typeof this.props.timing === 'string') {
166
+      let fn = AnimateNumber.TimingFunctions[this.props.timing]
167
+      return fn(interval, progress)
168
+    } else if(typeof this.props.timing === 'function')
169
+      return this.props.timing(interval, progress)
170
+    else
171
+      return AnimateNumber.TimingFunctions['linear'](interval, progress)
172
+  }
173
+
174
+}

+ 12
- 7
test/react-native-testkit/components/reporter.js Dosyayı Görüntüle

@@ -13,6 +13,7 @@ import {
13 13
   RecyclerViewBackedScrollView,
14 14
 } from 'react-native';
15 15
 
16
+import AnimateNumber from '../animate-text.js'
16 17
 import Assert from './assert.js'
17 18
 import RNTEST from '../index.js'
18 19
 
@@ -51,7 +52,7 @@ export default class Reporter extends Component {
51 52
         passed += tests[i].status === 'pass' ? 1 : 0
52 53
     }
53 54
     let percent = passed / count
54
-    let color = `rgb(${Math.floor((1-percent) *255)},${Math.floor(percent *255)}, 0)`
55
+    let color = `rgb(${Math.floor((1-percent) *255)},${Math.floor(percent *192)}, 0)`
55 56
 
56 57
     return (
57 58
       <View style={{flex : 1}}>
@@ -64,8 +65,16 @@ export default class Reporter extends Component {
64 65
           <Text>{`${executed} tests executed`}</Text>
65 66
           <Text>{`${passed} test cases passed`}</Text>
66 67
           <Text>{`${count} test cases`}</Text>
67
-          <Text style={{color, fontSize : 120, textAlign : 'center'}} >{`${Math.floor(percent*100)}`}</Text>
68
-          <Text style={{color, fontSize : 30, textAlign :'right', marginTop : -54, marginRight : 40, backgroundColor : 'transparent'}} >{`%`}</Text>
68
+          <View style={{flexDirection : 'row', alignSelf : 'center', alignItems : 'flex-end'}}>
69
+            <AnimateNumber style={{
70
+              color,
71
+              fontSize : 100,
72
+              textAlign : 'right'
73
+            }}
74
+              value={Math.floor(passed / count*100)}
75
+              countBy={1}/>
76
+            <Text style={{color, fontSize : 30, textAlign : 'left'}} >{`%`}</Text>
77
+          </View>
69 78
         </View>
70 79
         <ListView
71 80
           style={[styles.container]}
@@ -109,9 +118,6 @@ export default class Reporter extends Component {
109 118
       t.status = 'waiting'
110 119
 
111 120
     return (
112
-      // <TouchableOpacity onPress={()=>{
113
-      //   t.start(t.sn)
114
-      // }}>
115 121
         <View key={'rn-test-' + t.desc} style={{
116 122
           borderBottomWidth : 1.5,
117 123
           borderColor : '#DDD',
@@ -127,7 +133,6 @@ export default class Reporter extends Component {
127 133
             {t.expand ? t.result : (t.status === 'pass' ? null : t.result)}
128 134
           </View>
129 135
         </View>)
130
-        {/*</TouchableOpacity>)*/}
131 136
   }
132 137
 
133 138
   updateDataSource() {

+ 1
- 0
test/react-native-testkit/lib/test-context.js Dosyayı Görüntüle

@@ -128,6 +128,7 @@ export default class TestContext {
128 128
           })
129 129
           resolve(...res)
130 130
         }
131
+        RCTContext.forceUpdate()
131 132
       }).catch((err) => {
132 133
         updateInternal({
133 134
           executed : true,

+ 28
- 20
test/test-0.5.1.js Dosyayı Görüntüle

@@ -194,36 +194,44 @@ RNTest.config({
194 194
   let filename = '22mb-dummy-' + Date.now()
195 195
   let begin = -1
196 196
   let begin2 = -1
197
+  let deb = Date.now()
197 198
   RNFetchBlob.config({
198 199
     fileCache : true
199 200
   })
200 201
   .fetch('GET', `${TEST_SERVER_URL}/public/22mb-dummy`)
201
-  // .progress((now, total) => {
202
-  //   if(begin === -1)
203
-  //     begin = Date.now()
204
-  //   report(<Info uid="200" key="progress">
205
-  //     <Text>
206
-  //       {`download ${now} / ${total} bytes (${Math.floor(now / (Date.now() - begin))} kb/s)`}
207
-  //     </Text>
208
-  //   </Info>)
209
-  // })
202
+  .progress((now, total) => {
203
+    if(begin === -1)
204
+      begin = Date.now()
205
+    if(Date.now() - deb < 1000)
206
+      return
207
+    deb = Date.now()
208
+    report(<Info uid="200" key="progress">
209
+      <Text>
210
+        {`download ${now} / ${total} bytes (${Math.floor(now / (Date.now() - begin))} kb/s)`}
211
+      </Text>
212
+    </Info>)
213
+  })
210 214
   .then((res) => {
215
+    deb = Date.now()
211 216
     return RNFetchBlob.fetch('POST', 'https://content.dropboxapi.com/2/files/upload', {
212 217
       Authorization : `Bearer ${DROPBOX_TOKEN}`,
213 218
       'Dropbox-API-Arg': '{\"path\": \"/rn-upload/'+filename+'\",\"mode\": \"add\",\"autorename\": true,\"mute\": false}',
214 219
       'Content-Type' : 'application/octet-stream',
215 220
     }, RNFetchBlob.wrap(res.path()))
216
-    // .progress((now, total) => {
217
-    //   if(begin2 === -1)
218
-    //     begin2 = Date.now()
219
-    //   let speed = Math.floor(now / (Date.now() - begin2))
220
-    //   report(<Info uid="100"  key="progress">
221
-    //     <Text>
222
-    //       {`upload ${now} / ${total} bytes (${speed} kb/s)`}
223
-    //       {` ${Math.floor((total-now)/speed/1000)} seconds left`}
224
-    //     </Text>
225
-    //   </Info>)
226
-    // })
221
+    .progress((now, total) => {
222
+      if(Date.now() - deb < 1000)
223
+        return
224
+      deb = Date.now()
225
+      if(begin2 === -1)
226
+        begin2 = Date.now()
227
+      let speed = Math.floor(now / (Date.now() - begin2))
228
+      report(<Info uid="100"  key="progress">
229
+        <Text>
230
+          {`upload ${now} / ${total} bytes (${speed} kb/s)`}
231
+          {` ${Math.floor((total-now)/speed/1000)} seconds left`}
232
+        </Text>
233
+      </Info>)
234
+    })
227 235
   })
228 236
   .then((res) => {
229 237
     report(<Assert

+ 40
- 1
test/test-0.6.2.js Dosyayı Görüntüle

@@ -19,7 +19,7 @@ const describe = RNTest.config({
19 19
   group : '0.6.2',
20 20
   run : true,
21 21
   expand : false,
22
-  timeout : 12000,
22
+  timeout : 30000,
23 23
 })
24 24
 const { TEST_SERVER_URL, TEST_SERVER_URL_SSL, DROPBOX_TOKEN, styles } = prop()
25 25
 const  dirs = RNFetchBlob.fs.dirs
@@ -29,6 +29,7 @@ let photo = null
29 29
 
30 30
 describe('upload asset from camera roll', (report, done) => {
31 31
   let imgName = `image-from-camera-roll-${Platform.OS}.jpg`
32
+  let tick = Date.now()
32 33
   CameraRoll.getPhotos({first : 10})
33 34
     .then((resp) => {
34 35
       let url = resp.edges[0].node.image.uri
@@ -38,6 +39,13 @@ describe('upload asset from camera roll', (report, done) => {
38 39
         'Dropbox-API-Arg': `{\"path\": \"/rn-upload/${imgName}\",\"mode\": \"add\",\"autorename\": false,\"mute\": false}`,
39 40
         'Content-Type' : 'application/octet-stream',
40 41
       }, RNFetchBlob.wrap(url))
42
+      .progress((now, total) => {
43
+        if(Date.now() - tick < 1000)
44
+        return
45
+        report(<Info key="progress" uid="pg1">
46
+          <Text>{`upload ${now} / ${total} ${Math.floor(now/total*100)}% `}</Text>
47
+        </Info>)
48
+      })
41 49
     })
42 50
     .then((resp) => {
43 51
       resp = resp.json()
@@ -147,3 +155,34 @@ describe('copy asset', (report, done) => {
147 155
       done()
148 156
     })
149 157
 })
158
+
159
+
160
+describe('upload file from assets',(report, done) => {
161
+  let assetName = fs.asset('test-asset1.json')
162
+  RNFetchBlob.fetch('POST', 'https://content.dropboxapi.com/2/files/upload', {
163
+    Authorization : `Bearer ${DROPBOX_TOKEN}`,
164
+    'Dropbox-API-Arg': `{\"path\": \"/rn-upload/file-from-asset-${Platform.OS}.json\",\"mode\": \"add\",\"autorename\": false,\"mute\": false}`,
165
+    'Content-Type' : 'application/octet-stream',
166
+  }, RNFetchBlob.wrap(assetName))
167
+  .then((resp) => {
168
+    resp = resp.json()
169
+    report(
170
+      <Assert key="file name check"
171
+        expect={`file-from-asset-${Platform.OS}.json`}
172
+        actual={resp.name}/>)
173
+    done()
174
+  })
175
+})
176
+
177
+describe('Check custom MIME type correctness',(report, done) => {
178
+  RNFetchBlob.fetch('POST', `${TEST_SERVER_URL}/mime`, null, [
179
+    { name : 'image', filename : 'image', type : 'image/jpeg', data : RNFetchBlob.base64.encode('123456') },
180
+    { name : 'mp3', filename : 'mp3', type : 'application/mp3', data : RNFetchBlob.base64.encode('123456') },
181
+    { name : 'mp3', filename : 'mp3', data : RNFetchBlob.base64.encode('123456') }
182
+  ])
183
+  .then((resp) => {
184
+    resp = resp.json()
185
+    report(<Assert key="check first mime" expect={'image/jpeg'} actual={resp[0]} />)
186
+    done()
187
+  })
188
+})

+ 1
- 1
test/test-android.js Dosyayı Görüntüle

@@ -17,7 +17,7 @@ const { Assert, Comparer, Info, prop } = RNTest
17 17
 const describe = RNTest.config({
18 18
   group : 'Android only functions',
19 19
   run : Platform.OS === 'android',
20
-  expand : true,
20
+  expand : false,
21 21
 })
22 22
 const { TEST_SERVER_URL, FILENAME, DROPBOX_TOKEN, styles } = prop()
23 23
 

+ 7
- 6
test/test-init.js Dosyayı Görüntüle

@@ -51,10 +51,11 @@ describe('GET image from server', (report, done) => {
51 51
     })
52 52
 })
53 53
 
54
-require('./test-0.1.x-0.4.x')
55
-require('./test-0.5.1')
56
-require('./test-0.5.2')
57
-require('./test-0.6.0')
54
+
55
+// require('./test-0.1.x-0.4.x')
56
+// require('./test-0.5.1')
57
+// require('./test-0.5.2')
58
+// require('./test-0.6.0')
58 59
 require('./test-0.6.2')
59
-require('./test-fs')
60
-require('./test-android')
60
+// require('./test-fs')
61
+// require('./test-android')