暂无描述

test-context.js 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. //@flow
  2. let tests: Array<TestCase> = []
  3. let RCTContext: ReactElement = null
  4. let props:any = {}
  5. let timeout = 30000
  6. let summary = {}
  7. export default class TestContext {
  8. static setTimeout (val) {
  9. timeout = val
  10. }
  11. static config(config) {
  12. return TestContext.describe.bind(config)
  13. }
  14. /**
  15. * Calling this method will push a test case into task queue.
  16. * @param {String} desc Description of test case.
  17. * @param {Function:Promise<any>} fn Body of test case, this function
  18. * should return a promise.
  19. * @return {void}
  20. */
  21. static describe (...args) {
  22. let { group, timeout, expand, run } = this || {}
  23. let desc, config, fn
  24. if([...args].length === 2) {
  25. [desc, fn] = [...args]
  26. }
  27. else if ([...args].length === 3) {
  28. [desc, config, fn] = [...args]
  29. group = config.group || group
  30. timeout = config.timeout || timeout
  31. expand = config.expand || expand
  32. run = config.run || run
  33. }
  34. let ctx = {
  35. group : group || 'common',
  36. status : 'waiting',
  37. run : run === false ? false : true,
  38. result : null,
  39. asserts : [],
  40. timeout : timeout || 15000,
  41. expired : false,
  42. running : false,
  43. executed : false,
  44. expand : expand || false,
  45. desc,
  46. fn,
  47. sn : tests.length,
  48. start : (i) => {
  49. TestContext.startTest.bind(
  50. tests[i],
  51. TestContext.update.bind(TestContext, i),
  52. TestContext.updateInternal.bind(TestContext, i)
  53. )()
  54. }
  55. }
  56. tests.push(ctx)
  57. }
  58. static prop (name:string, val:any):TestContext {
  59. if(name === undefined && val === undefined)
  60. return props
  61. if(val === undefined)
  62. return props[name]
  63. props[name] = val
  64. return TestContext
  65. }
  66. /**
  67. * Run test cases in sequence.
  68. * @param {ReactElement} context ReactElement instance context.
  69. * @return {void}
  70. */
  71. static run (context:ReactElement) {
  72. RCTContext = context
  73. let promise = Promise.resolve()
  74. // run test case sequently
  75. for(let i in tests) {
  76. if(tests[i].run === false) {
  77. tests[i].status = 'skipped'
  78. tests[i].executed = true
  79. promise = Promise.resolve()
  80. continue
  81. }
  82. promise = promise.then(
  83. TestContext.startTest.bind(
  84. tests[i],
  85. TestContext.update.bind(TestContext, i),
  86. TestContext.updateInternal.bind(TestContext, i)
  87. ))
  88. }
  89. return promise
  90. }
  91. static startTest(update, updateInternal, data) {
  92. return new Promise((resolve, reject) => {
  93. let expired = false
  94. updateInternal({
  95. running : true,
  96. })
  97. // set timeout timer
  98. let tm = setTimeout(() => {
  99. updateInternal({
  100. expired : true,
  101. executed : true,
  102. running : false
  103. })
  104. resolve('ETIMEOUT')
  105. }, this.timeout)
  106. // run test body
  107. new Promise((done) => {
  108. this.fn.bind(this)(update, done)
  109. })
  110. .then((...res) => {
  111. if(!expired) {
  112. clearTimeout(tm)
  113. updateInternal({
  114. executed : true,
  115. running : false
  116. })
  117. resolve(...res)
  118. }
  119. RCTContext.forceUpdate()
  120. }).catch((err) => {
  121. updateInternal({
  122. executed : true,
  123. running : false
  124. })
  125. })
  126. })
  127. }
  128. /**
  129. * Update test task result of given index.
  130. * @param {number} i Index of test case to be updated.
  131. * @param {ReactElement<Info | Assert>} ...data Assertion or Info of test.
  132. * @return {void}
  133. */
  134. static update(i, ...data) {
  135. let test = tests[i]
  136. let result = test.result || []
  137. // if new element have prop `uid`, we should replace it not appending it.
  138. for(let i in data) {
  139. if(data[i].props.uid) {
  140. for(let j in result) {
  141. if(result[j].uid === data[i].props.uid)
  142. result[j] = data[i]
  143. result.splice(j,1)
  144. break
  145. }
  146. }
  147. }
  148. Object.assign(test, {result : [...result, ...data]})
  149. RCTContext.forceUpdate()
  150. }
  151. static getTests() {
  152. return tests
  153. }
  154. /**
  155. * Update test result for testkit internal use
  156. * @param {[type]} i Index of test case to be updated.
  157. * @param {TestCaseContext} result Test case object
  158. * @return {void}
  159. */
  160. static updateInternal(i, result) {
  161. Object.assign(tests[i], result)
  162. RCTContext.forceUpdate()
  163. }
  164. }