api-deprecate-spec.ts 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. import { expect } from 'chai'
  2. import { deprecate } from 'electron'
  3. describe('deprecate', () => {
  4. beforeEach(() => {
  5. deprecate.setHandler(null)
  6. process.throwDeprecation = true
  7. })
  8. it('allows a deprecation handler function to be specified', () => {
  9. const messages: string[] = []
  10. deprecate.setHandler(message => {
  11. messages.push(message)
  12. })
  13. deprecate.log('this is deprecated')
  14. expect(messages).to.deep.equal(['this is deprecated'])
  15. })
  16. it('returns a deprecation handler after one is set', () => {
  17. const messages = []
  18. deprecate.setHandler(message => {
  19. messages.push(message)
  20. })
  21. deprecate.log('this is deprecated')
  22. expect(deprecate.getHandler()).to.be.a('function')
  23. })
  24. it('renames a property', () => {
  25. let msg
  26. deprecate.setHandler(m => { msg = m })
  27. const oldProp = 'dingyOldName'
  28. const newProp = 'shinyNewName'
  29. let value = 0
  30. const o: Record<string, number> = { [newProp]: value }
  31. expect(o).to.not.have.property(oldProp)
  32. expect(o).to.have.property(newProp).that.is.a('number')
  33. deprecate.renameProperty(o, oldProp, newProp)
  34. o[oldProp] = ++value
  35. expect(msg).to.be.a('string')
  36. expect(msg).to.include(oldProp)
  37. expect(msg).to.include(newProp)
  38. expect(o).to.have.property(newProp).that.is.equal(value)
  39. expect(o).to.have.property(oldProp).that.is.equal(value)
  40. })
  41. it('doesn\'t deprecate a property not on an object', () => {
  42. const o: any = {}
  43. expect(() => {
  44. deprecate.removeProperty(o, 'iDoNotExist')
  45. }).to.throw(/iDoNotExist/)
  46. })
  47. it('deprecates a property of an object', () => {
  48. let msg
  49. deprecate.setHandler(m => { msg = m })
  50. const prop = 'itMustGo'
  51. const o = { [prop]: 0 }
  52. deprecate.removeProperty(o, prop)
  53. const temp = o[prop]
  54. expect(temp).to.equal(0)
  55. expect(msg).to.be.a('string')
  56. expect(msg).to.include(prop)
  57. })
  58. it('warns exactly once when a function is deprecated with no replacement', () => {
  59. let msg
  60. deprecate.setHandler(m => { msg = m })
  61. function oldFn () { return 'hello' }
  62. const deprecatedFn = deprecate.removeFunction(oldFn, 'oldFn')
  63. deprecatedFn()
  64. expect(msg).to.be.a('string')
  65. expect(msg).to.include('oldFn')
  66. })
  67. it('warns exactly once when a function is deprecated with a replacement', () => {
  68. let msg
  69. deprecate.setHandler(m => { msg = m })
  70. function oldFn () { return 'hello' }
  71. function newFn () { return 'goodbye' }
  72. const deprecatedFn = deprecate.renameFunction(oldFn, newFn)
  73. deprecatedFn()
  74. expect(msg).to.be.a('string')
  75. expect(msg).to.include('oldFn')
  76. expect(msg).to.include('newFn')
  77. })
  78. it('warns only once per item', () => {
  79. const messages: string[] = []
  80. deprecate.setHandler(message => messages.push(message))
  81. const key = 'foo'
  82. const val = 'bar'
  83. const o = { [key]: val }
  84. deprecate.removeProperty(o, key)
  85. for (let i = 0; i < 3; ++i) {
  86. expect(o[key]).to.equal(val)
  87. expect(messages).to.have.length(1)
  88. }
  89. })
  90. it('warns if deprecated property is already set', () => {
  91. let msg
  92. deprecate.setHandler(m => { msg = m })
  93. const oldProp = 'dingyOldName'
  94. const newProp = 'shinyNewName'
  95. const o: Record<string, number> = { [oldProp]: 0 }
  96. deprecate.renameProperty(o, oldProp, newProp)
  97. expect(msg).to.be.a('string')
  98. expect(msg).to.include(oldProp)
  99. expect(msg).to.include(newProp)
  100. })
  101. it('throws an exception if no deprecation handler is specified', () => {
  102. expect(() => {
  103. deprecate.log('this is deprecated')
  104. }).to.throw(/this is deprecated/)
  105. })
  106. it('warns when a function is deprecated in favor of a property', () => {
  107. const warnings: string[] = []
  108. deprecate.setHandler(warning => warnings.push(warning))
  109. const newProp = 'newProp'
  110. const mod: any = {
  111. _oldGetterFn () { return 'getter' },
  112. _oldSetterFn () { return 'setter' }
  113. }
  114. deprecate.fnToProperty(mod, 'newProp', '_oldGetterFn', '_oldSetterFn')
  115. mod['oldGetterFn']()
  116. mod['oldSetterFn']()
  117. expect(warnings).to.have.lengthOf(2)
  118. expect(warnings[0]).to.include('oldGetterFn')
  119. expect(warnings[0]).to.include(newProp)
  120. expect(warnings[1]).to.include('oldSetterFn')
  121. expect(warnings[1]).to.include(newProp)
  122. })
  123. describe('moveAPI', () => {
  124. beforeEach(() => {
  125. deprecate.setHandler(null)
  126. })
  127. it('should call the original method', () => {
  128. const warnings = []
  129. deprecate.setHandler(warning => warnings.push(warning))
  130. let called = false
  131. const fn = () => {
  132. called = true
  133. }
  134. const deprecated = deprecate.moveAPI(fn, 'old', 'new')
  135. deprecated()
  136. expect(called).to.equal(true)
  137. })
  138. it('should log the deprecation warning once', () => {
  139. const warnings: string[] = []
  140. deprecate.setHandler(warning => warnings.push(warning))
  141. const deprecated = deprecate.moveAPI(() => null, 'old', 'new')
  142. deprecated()
  143. expect(warnings).to.have.lengthOf(1)
  144. deprecated()
  145. expect(warnings).to.have.lengthOf(1)
  146. expect(warnings[0]).to.equal('\'old\' is deprecated and will be removed. Please use \'new\' instead.')
  147. })
  148. })
  149. describe('promisify', () => {
  150. const expected = 'Hello, world!'
  151. let promiseFunc: (param: any) => Promise<any>
  152. let warnings: string[]
  153. const enableCallbackWarnings = () => {
  154. warnings = []
  155. deprecate.setHandler(warning => warnings.push(warning))
  156. process.enablePromiseAPIs = true
  157. }
  158. beforeEach(() => {
  159. deprecate.setHandler(null)
  160. process.throwDeprecation = true
  161. promiseFunc = param => new Promise((resolve, reject) => resolve(param))
  162. })
  163. it('acts as a pass-through for promise-based invocations', async () => {
  164. enableCallbackWarnings()
  165. promiseFunc = deprecate.promisify(promiseFunc)
  166. const actual = await promiseFunc(expected)
  167. expect(actual).to.equal(expected)
  168. expect(warnings).to.have.lengthOf(0)
  169. })
  170. it('only calls back an error if the callback is called with (err, data)', async () => {
  171. enableCallbackWarnings()
  172. const erringPromiseFunc = deprecate.promisify(
  173. () => new Promise((resolve, reject) => {
  174. reject(new Error('fail'))
  175. })
  176. )
  177. {
  178. const [err, data] = await new Promise(resolve => {
  179. (erringPromiseFunc as any)((err: Error | undefined, data: any) => {
  180. resolve([err, data])
  181. }).catch(() => { /* silence deprecation warning */ })
  182. });
  183. expect(data).to.be.undefined()
  184. expect(err).to.be.an.instanceOf(Error).with.property('message', 'fail')
  185. }
  186. {
  187. const data = await new Promise(resolve => {
  188. (erringPromiseFunc as any)(((data: any) => { resolve(data) }))
  189. .catch(() => { /* silence deprecation warning */ })
  190. })
  191. expect(data).to.be.undefined()
  192. }
  193. })
  194. it('warns exactly once for callback-based invocations', (done) => {
  195. enableCallbackWarnings()
  196. promiseFunc = deprecate.promisify(promiseFunc)
  197. let callbackCount = 0
  198. const invocationCount = 3
  199. const callback = (actual: number) => {
  200. expect(actual).to.equal(expected)
  201. expect(warnings).to.have.lengthOf(1)
  202. expect(warnings[0]).to.include('promiseFunc')
  203. callbackCount += 1
  204. if (callbackCount === invocationCount) {
  205. done()
  206. }
  207. }
  208. for (let i = 0; i < invocationCount; i += 1) {
  209. (promiseFunc as any)(expected, callback)
  210. }
  211. })
  212. })
  213. })