modules-spec.js 6.6 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. });