api-crash-reporter-spec.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. const assert = require('assert')
  2. const childProcess = require('child_process')
  3. const http = require('http')
  4. const multiparty = require('multiparty')
  5. const path = require('path')
  6. const temp = require('temp').track()
  7. const url = require('url')
  8. const {closeWindow} = require('./window-helpers')
  9. const {remote} = require('electron')
  10. const {app, BrowserWindow, crashReporter} = remote.require('electron')
  11. describe('crashReporter module', function () {
  12. var fixtures = path.resolve(__dirname, 'fixtures')
  13. var w = null
  14. var originalTempDirectory = null
  15. var tempDirectory = null
  16. beforeEach(function () {
  17. w = new BrowserWindow({
  18. show: false
  19. })
  20. tempDirectory = temp.mkdirSync('electronCrashReporterSpec-')
  21. originalTempDirectory = app.getPath('temp')
  22. app.setPath('temp', tempDirectory)
  23. })
  24. afterEach(function () {
  25. app.setPath('temp', originalTempDirectory)
  26. return closeWindow(w).then(function () { w = null })
  27. })
  28. if (process.mas) {
  29. return
  30. }
  31. it('should send minidump when renderer crashes', function (done) {
  32. if (process.platform !== 'darwin') return done()
  33. if (process.env.TRAVIS === 'true') return done()
  34. this.timeout(120000)
  35. startServer({
  36. callback (port) {
  37. const crashUrl = url.format({
  38. protocol: 'file',
  39. pathname: path.join(fixtures, 'api', 'crash.html'),
  40. search: '?port=' + port
  41. })
  42. w.loadURL(crashUrl)
  43. },
  44. processType: 'renderer',
  45. done: done
  46. })
  47. })
  48. it('should send minidump when node processes crash', function (done) {
  49. if (process.platform !== 'darwin') return done()
  50. if (process.env.TRAVIS === 'true') return done()
  51. this.timeout(120000)
  52. startServer({
  53. callback (port) {
  54. const crashesDir = path.join(app.getPath('temp'), `${app.getName()} Crashes`)
  55. const version = app.getVersion()
  56. const crashPath = path.join(fixtures, 'module', 'crash.js')
  57. childProcess.fork(crashPath, [port, version, crashesDir], {silent: true})
  58. },
  59. processType: 'browser',
  60. done: done
  61. })
  62. })
  63. describe('.start(options)', function () {
  64. it('requires that the companyName and submitURL options be specified', function () {
  65. assert.throws(function () {
  66. crashReporter.start({
  67. companyName: 'Missing submitURL'
  68. })
  69. }, /submitURL is a required option to crashReporter\.start/)
  70. assert.throws(function () {
  71. crashReporter.start({
  72. submitURL: 'Missing companyName'
  73. })
  74. }, /companyName is a required option to crashReporter\.start/)
  75. })
  76. it('can be called multiple times', function () {
  77. assert.doesNotThrow(function () {
  78. crashReporter.start({
  79. companyName: 'Umbrella Corporation',
  80. submitURL: 'http://127.0.0.1/crashes'
  81. })
  82. crashReporter.start({
  83. companyName: 'Umbrella Corporation 2',
  84. submitURL: 'http://127.0.0.1/more-crashes'
  85. })
  86. })
  87. })
  88. })
  89. describe('.get/setUploadToServer', function () {
  90. it('throws an error when called from the renderer process', function () {
  91. assert.throws(() => require('electron').crashReporter.getUploadToServer())
  92. })
  93. it('can be read/set from the main process', function () {
  94. if (process.platform === 'darwin') {
  95. crashReporter.start({
  96. companyName: 'Umbrella Corporation',
  97. submitURL: 'http://127.0.0.1/crashes',
  98. autoSubmit: true
  99. })
  100. assert.equal(crashReporter.getUploadToServer(), true)
  101. crashReporter.setUploadToServer(false)
  102. assert.equal(crashReporter.getUploadToServer(), false)
  103. } else {
  104. assert.equal(crashReporter.getUploadToServer(), true)
  105. }
  106. })
  107. })
  108. })
  109. const waitForCrashReport = () => {
  110. return new Promise((resolve, reject) => {
  111. let times = 0
  112. const checkForReport = () => {
  113. if (crashReporter.getLastCrashReport() != null) {
  114. resolve()
  115. } else if (times >= 10) {
  116. reject(new Error('No crash report available'))
  117. } else {
  118. times++
  119. setTimeout(checkForReport, 100)
  120. }
  121. }
  122. checkForReport()
  123. })
  124. }
  125. const startServer = ({callback, processType, done}) => {
  126. var called = false
  127. var server = http.createServer((req, res) => {
  128. server.close()
  129. var form = new multiparty.Form()
  130. form.parse(req, (error, fields) => {
  131. if (error) throw error
  132. if (called) return
  133. called = true
  134. assert.equal(fields.prod, 'Electron')
  135. assert.equal(fields.ver, process.versions.electron)
  136. assert.equal(fields.process_type, processType)
  137. assert.equal(fields.platform, process.platform)
  138. assert.equal(fields.extra1, 'extra1')
  139. assert.equal(fields.extra2, 'extra2')
  140. assert.equal(fields._productName, 'Zombies')
  141. assert.equal(fields._companyName, 'Umbrella Corporation')
  142. assert.equal(fields._version, app.getVersion())
  143. const reportId = 'abc-123-def-456-abc-789-abc-123-abcd'
  144. res.end(reportId, () => {
  145. waitForCrashReport().then(() => {
  146. assert.equal(crashReporter.getLastCrashReport().id, reportId)
  147. assert.notEqual(crashReporter.getUploadedReports().length, 0)
  148. assert.equal(crashReporter.getUploadedReports()[0].id, reportId)
  149. done()
  150. }, done)
  151. })
  152. })
  153. })
  154. let {port} = remote.process
  155. server.listen(port, '127.0.0.1', () => {
  156. port = server.address().port
  157. remote.process.port = port
  158. if (process.platform === 'darwin') {
  159. crashReporter.start({
  160. companyName: 'Umbrella Corporation',
  161. submitURL: 'http://127.0.0.1:' + port
  162. })
  163. }
  164. callback(port)
  165. })
  166. }