Keine Beschreibung

reporter.js 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. import React, {Component} from 'react';
  2. import {
  3. AppRegistry,
  4. StyleSheet,
  5. Text,
  6. View,
  7. Platform,
  8. ScrollView,
  9. ListView,
  10. Image,
  11. TouchableOpacity,
  12. RecyclerViewBackedScrollView,
  13. } from 'react-native';
  14. import Assert from './assert.js'
  15. import RNTEST from '../index.js'
  16. export default class Reporter extends Component {
  17. constructor(props:any) {
  18. super(props)
  19. this.tests = {
  20. summary : [{}],
  21. common : []
  22. }
  23. this.testGroups = ['summary','common']
  24. this.ds = null
  25. this.updateDataSource()
  26. }
  27. componentWillUpdate(nextProps, nextState) {
  28. this.updateDataSource()
  29. }
  30. render() {
  31. return (
  32. <ListView
  33. style={styles.container}
  34. dataSource={this.ds}
  35. renderRow={this.renderTest.bind(this)}
  36. renderScrollComponent={props => <RecyclerViewBackedScrollView {...props} />}
  37. renderSectionHeader={(data, id) => {
  38. return (
  39. <View style={styles.sectionHeader}>
  40. <Text style={styles.sectionText}>{id}</Text>
  41. </View>
  42. )
  43. }}
  44. />)
  45. }
  46. renderTest(t, group) {
  47. let pass = true
  48. let foundActions = false
  49. let tests = RNTEST.TestContext.getTests()
  50. if(group === 'summary')
  51. {
  52. let passed = 0
  53. let executed = 0
  54. let count = 0
  55. for(let i in tests) {
  56. count++
  57. if(tests[i].executed)
  58. passed += tests[i].status === 'pass' ? 1 : 0
  59. }
  60. return (<View style={{flex : 1}}>
  61. <Text>{`${count} test cases`}</Text>
  62. <Text>{`${executed} tests executed`}</Text>
  63. <Text>{`${ParseFloat(pass/count).toFixed(2)}% tests passed`}</Text>
  64. </View>)
  65. }
  66. if(Array.isArray(t.result) && !t.expired) {
  67. t.result = t.result.map((r) => {
  68. if(r.type.name === 'Assert' || r.type.name === 'Info') {
  69. foundActions = true
  70. let comp = r.props.comparer ? r.props.comparer(r.props.expect, r.props.actual) : (r.props.actual === r.props.expect)
  71. pass = pass && comp
  72. }
  73. return React.cloneElement(r, {desc : r.key})
  74. })
  75. }
  76. if(tests[t.sn].running)
  77. t.status = 'running'
  78. else if(tests[t.sn].executed) {
  79. t.status = foundActions ? (pass ? 'pass' : 'fail') : 'skipped'
  80. t.status = t.expired ? 'timeout' : t.status
  81. }
  82. else
  83. t.status = 'waiting'
  84. return (
  85. <TouchableOpacity onPress={()=>{
  86. t.start(t.sn)
  87. }}>
  88. <View key={'rn-test-' + t.desc} style={{
  89. borderBottomWidth : 1.5,
  90. borderColor : '#DDD',
  91. }}>
  92. <View key={t.desc} style={{
  93. alignItems : 'center',
  94. flexDirection : 'row'
  95. }}>
  96. <Text style={[styles.badge, {flex : 1, borderWidth : 0, textAlign : 'left'}]}>{t.desc}</Text>
  97. <Text style={[styles.badge, this.getBadge(t.status)]}>{t.status}</Text>
  98. </View>
  99. <View key={t.desc + '-result'} style={{backgroundColor : '#F4F4F4'}}>
  100. {t.expand ? t.result : (t.status === 'pass' ? null : t.result)}
  101. </View>
  102. </View>
  103. </TouchableOpacity>)
  104. }
  105. updateDataSource() {
  106. this.tests = {
  107. common : []
  108. }
  109. this.testGroups = ['common']
  110. RNTEST.TestContext.getTests().forEach((t) => {
  111. if(t.group) {
  112. if(!this.tests[t.group]) {
  113. this.testGroups.push(t.group)
  114. this.tests[t.group] = []
  115. }
  116. this.tests[t.group].push(t)
  117. }
  118. else
  119. this.tests.common.push(t)
  120. })
  121. let listDataSource = new ListView.DataSource({
  122. rowHasChanged : (r1, r2) => r1 !== r2,
  123. sectionHeaderHasChanged: (s1, s2) => s1 !== s2
  124. })
  125. this.ds = listDataSource.cloneWithRowsAndSections(this.tests, this.testGroups)
  126. }
  127. getBadge(status: 'waiting' | 'running' | 'pass' | 'fail' | 'timeout') {
  128. return styles[status]
  129. }
  130. }
  131. const styles = StyleSheet.create({
  132. container: {
  133. flex: 1,
  134. },
  135. badge : {
  136. margin : 16,
  137. padding : 4,
  138. borderRadius : 4,
  139. borderWidth : 2,
  140. textAlign : 'center'
  141. },
  142. skipped: {
  143. borderColor : '#AAAAAA',
  144. color : '#AAAAAA'
  145. },
  146. sectionHeader : {
  147. padding : 16,
  148. backgroundColor : '#F4F4F4',
  149. },
  150. waiting: {
  151. borderColor : '#AAAAAA',
  152. color : '#AAAAAA'
  153. },
  154. pass: {
  155. borderColor : '#00a825',
  156. color : '#00a825'
  157. },
  158. running: {
  159. borderColor : '#e3c423',
  160. color : '#e3c423'
  161. },
  162. fail: {
  163. borderColor : '#ff0d0d',
  164. color : '#ff0d0d'
  165. },
  166. timeout: {
  167. borderColor : '#ff0d0d',
  168. color : '#ff0d0d'
  169. }
  170. });