modules-spec.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. const chai = require('chai')
  2. const dirtyChai = require('dirty-chai')
  3. const Module = require('module')
  4. const path = require('path')
  5. const fs = require('fs')
  6. const { remote } = require('electron')
  7. const { BrowserWindow } = remote
  8. const { closeWindow } = require('./window-helpers')
  9. const features = process.electronBinding('features')
  10. const { expect } = chai
  11. chai.use(dirtyChai)
  12. const nativeModulesEnabled = remote.getGlobal('nativeModulesEnabled')
  13. describe('modules support', () => {
  14. const fixtures = path.join(__dirname, 'fixtures')
  15. describe('third-party module', () => {
  16. (nativeModulesEnabled ? describe : describe.skip)('echo', () => {
  17. it('can be required in renderer', () => {
  18. require('echo')
  19. })
  20. it('can be required in node binary', function (done) {
  21. if (!features.isRunAsNodeEnabled()) {
  22. this.skip()
  23. done()
  24. }
  25. const echo = path.join(fixtures, 'module', 'echo.js')
  26. const child = require('child_process').fork(echo)
  27. child.on('message', (msg) => {
  28. expect(msg).to.equal('ok')
  29. done()
  30. })
  31. })
  32. if (process.platform === 'win32') {
  33. it('can be required if electron.exe is renamed', () => {
  34. const { execPath } = remote.process
  35. const testExecPath = path.join(path.dirname(execPath), 'test.exe')
  36. fs.copyFileSync(execPath, testExecPath)
  37. try {
  38. const fixture = path.join(fixtures, 'module', 'echo-renamed.js')
  39. expect(fs.existsSync(fixture)).to.be.true()
  40. const child = require('child_process').spawnSync(testExecPath, [fixture])
  41. expect(child.status).to.equal(0)
  42. } finally {
  43. fs.unlinkSync(testExecPath)
  44. }
  45. })
  46. }
  47. })
  48. // TODO(alexeykuzmin): Disabled during the Chromium 62 (Node.js 9) upgrade.
  49. // Enable it back when "ffi" module supports Node.js 9.
  50. // https://github.com/electron/electron/issues/11274
  51. xdescribe('ffi', () => {
  52. before(function () {
  53. if (!nativeModulesEnabled || process.platform === 'win32' ||
  54. process.arch === 'arm64') {
  55. this.skip()
  56. }
  57. })
  58. it('does not crash', () => {
  59. const ffi = require('ffi')
  60. const libm = ffi.Library('libm', {
  61. ceil: ['double', ['double']]
  62. })
  63. expect(libm.ceil(1.5)).to.equal(2)
  64. })
  65. })
  66. describe('q', () => {
  67. const Q = require('q')
  68. describe('Q.when', () => {
  69. it('emits the fullfil callback', (done) => {
  70. Q(true).then((val) => {
  71. expect(val).to.be.true()
  72. done()
  73. })
  74. })
  75. })
  76. })
  77. describe('coffeescript', () => {
  78. it('can be registered and used to require .coffee files', () => {
  79. expect(() => {
  80. require('coffeescript').register()
  81. }).to.not.throw()
  82. expect(require('./fixtures/module/test.coffee')).to.be.true()
  83. })
  84. })
  85. })
  86. describe('global variables', () => {
  87. describe('process', () => {
  88. it('can be declared in a module', () => {
  89. expect(require('./fixtures/module/declare-process')).to.equal('declared process')
  90. })
  91. })
  92. describe('global', () => {
  93. it('can be declared in a module', () => {
  94. expect(require('./fixtures/module/declare-global')).to.equal('declared global')
  95. })
  96. })
  97. describe('Buffer', () => {
  98. it('can be declared in a module', () => {
  99. expect(require('./fixtures/module/declare-buffer')).to.equal('declared Buffer')
  100. })
  101. })
  102. })
  103. describe('Module._nodeModulePaths', () => {
  104. describe('when the path is inside the resources path', () => {
  105. it('does not include paths outside of the resources path', () => {
  106. let modulePath = process.resourcesPath
  107. expect(Module._nodeModulePaths(modulePath)).to.deep.equal([
  108. path.join(process.resourcesPath, 'node_modules')
  109. ])
  110. modulePath = process.resourcesPath + '-foo'
  111. const nodeModulePaths = Module._nodeModulePaths(modulePath)
  112. expect(nodeModulePaths).to.include(path.join(modulePath, 'node_modules'))
  113. expect(nodeModulePaths).to.include(path.join(modulePath, '..', 'node_modules'))
  114. modulePath = path.join(process.resourcesPath, 'foo')
  115. expect(Module._nodeModulePaths(modulePath)).to.deep.equal([
  116. path.join(process.resourcesPath, 'foo', 'node_modules'),
  117. path.join(process.resourcesPath, 'node_modules')
  118. ])
  119. modulePath = path.join(process.resourcesPath, 'node_modules', 'foo')
  120. expect(Module._nodeModulePaths(modulePath)).to.deep.equal([
  121. path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules'),
  122. path.join(process.resourcesPath, 'node_modules')
  123. ])
  124. modulePath = path.join(process.resourcesPath, 'node_modules', 'foo', 'bar')
  125. expect(Module._nodeModulePaths(modulePath)).to.deep.equal([
  126. path.join(process.resourcesPath, 'node_modules', 'foo', 'bar', 'node_modules'),
  127. path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules'),
  128. path.join(process.resourcesPath, 'node_modules')
  129. ])
  130. modulePath = path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules', 'bar')
  131. expect(Module._nodeModulePaths(modulePath)).to.deep.equal([
  132. path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules', 'bar', 'node_modules'),
  133. path.join(process.resourcesPath, 'node_modules', 'foo', 'node_modules'),
  134. path.join(process.resourcesPath, 'node_modules')
  135. ])
  136. })
  137. })
  138. describe('when the path is outside the resources path', () => {
  139. it('includes paths outside of the resources path', () => {
  140. const modulePath = path.resolve('/foo')
  141. expect(Module._nodeModulePaths(modulePath)).to.deep.equal([
  142. path.join(modulePath, 'node_modules'),
  143. path.resolve('/node_modules')
  144. ])
  145. })
  146. })
  147. })
  148. describe('require', () => {
  149. describe('when loaded URL is not file: protocol', () => {
  150. let w
  151. beforeEach(() => {
  152. w = new BrowserWindow({
  153. show: false,
  154. webPreferences: {
  155. nodeIntegration: true
  156. }
  157. })
  158. })
  159. afterEach(async () => {
  160. await closeWindow(w)
  161. w = null
  162. })
  163. it('searches for module under app directory', async () => {
  164. w.loadURL('about:blank')
  165. const result = await w.webContents.executeJavaScript('typeof require("q").when')
  166. expect(result).to.equal('function')
  167. })
  168. })
  169. })
  170. })