api-crash-reporter-spec.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. const assert = require('assert')
  2. const http = require('http')
  3. const multiparty = require('multiparty')
  4. const path = require('path')
  5. const temp = require('temp').track()
  6. const url = require('url')
  7. const {closeWindow} = require('./window-helpers')
  8. const {remote} = require('electron')
  9. const {app, BrowserWindow, crashReporter} = remote.require('electron')
  10. const isCI = remote.getGlobal('isCi')
  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 (isCI) return done()
  33. this.timeout(120000)
  34. var called = false
  35. var server = http.createServer(function (req, res) {
  36. server.close()
  37. var form = new multiparty.Form()
  38. form.parse(req, function (error, fields) {
  39. if (error) throw error
  40. if (called) return
  41. called = true
  42. assert.equal(fields['prod'], 'Electron')
  43. assert.equal(fields['ver'], process.versions.electron)
  44. assert.equal(fields['process_type'], 'renderer')
  45. assert.equal(fields['platform'], process.platform)
  46. assert.equal(fields['extra1'], 'extra1')
  47. assert.equal(fields['extra2'], 'extra2')
  48. assert.equal(fields['_productName'], 'Zombies')
  49. assert.equal(fields['_companyName'], 'Umbrella Corporation')
  50. assert.equal(fields['_version'], app.getVersion())
  51. const reportId = 'abc-123-def-456-abc-789-abc-123-abcd'
  52. res.end(reportId, () => {
  53. waitForCrashReport().then(() => {
  54. assert.equal(crashReporter.getLastCrashReport().id, reportId)
  55. assert.notEqual(crashReporter.getUploadedReports().length, 0)
  56. assert.equal(crashReporter.getUploadedReports()[0].id, reportId)
  57. done()
  58. }, done)
  59. })
  60. })
  61. })
  62. var port = remote.process.port
  63. server.listen(port, '127.0.0.1', function () {
  64. port = server.address().port
  65. remote.process.port = port
  66. const crashUrl = url.format({
  67. protocol: 'file',
  68. pathname: path.join(fixtures, 'api', 'crash.html'),
  69. search: '?port=' + port
  70. })
  71. if (process.platform === 'darwin') {
  72. crashReporter.start({
  73. companyName: 'Umbrella Corporation',
  74. submitURL: 'http://127.0.0.1:' + port
  75. })
  76. }
  77. w.loadURL(crashUrl)
  78. })
  79. })
  80. describe('.start(options)', function () {
  81. it('requires that the companyName and submitURL options be specified', function () {
  82. assert.throws(function () {
  83. crashReporter.start({
  84. companyName: 'Missing submitURL'
  85. })
  86. }, /submitURL is a required option to crashReporter\.start/)
  87. assert.throws(function () {
  88. crashReporter.start({
  89. submitURL: 'Missing companyName'
  90. })
  91. }, /companyName is a required option to crashReporter\.start/)
  92. })
  93. it('can be called multiple times', function () {
  94. assert.doesNotThrow(function () {
  95. crashReporter.start({
  96. companyName: 'Umbrella Corporation',
  97. submitURL: 'http://127.0.0.1/crashes'
  98. })
  99. crashReporter.start({
  100. companyName: 'Umbrella Corporation 2',
  101. submitURL: 'http://127.0.0.1/more-crashes'
  102. })
  103. })
  104. })
  105. })
  106. describe('.get/setUploadToServer', function () {
  107. it('throws an error when called from the renderer process', function () {
  108. assert.throws(() => require('electron').crashReporter.getUploadToServer())
  109. })
  110. it('can be read/set from the main process', function () {
  111. if (process.platform === 'darwin') {
  112. crashReporter.start({
  113. companyName: 'Umbrella Corporation',
  114. submitURL: 'http://127.0.0.1/crashes',
  115. autoSubmit: true
  116. })
  117. assert.equal(crashReporter.getUploadToServer(), true)
  118. crashReporter.setUploadToServer(false)
  119. assert.equal(crashReporter.getUploadToServer(), false)
  120. } else {
  121. assert.equal(crashReporter.getUploadToServer(), true)
  122. }
  123. })
  124. })
  125. })
  126. const waitForCrashReport = () => {
  127. return new Promise((resolve, reject) => {
  128. let times = 0
  129. const checkForReport = () => {
  130. if (crashReporter.getLastCrashReport() != null) {
  131. resolve()
  132. } else if (times >= 10) {
  133. reject(new Error('No crash report available'))
  134. } else {
  135. times++
  136. setTimeout(checkForReport, 100)
  137. }
  138. }
  139. checkForReport()
  140. })
  141. }