暫無描述

test-context.js 3.1KB

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