No Description

test-context.js 3.7KB

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