Skip to content

Commit

Permalink
fix(core): add support for finding electron for npm 7 workspaces (#2446)
Browse files Browse the repository at this point in the history
  • Loading branch information
malept authored Aug 14, 2021
1 parent 677cf9d commit 4c60151
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 61 deletions.
16 changes: 8 additions & 8 deletions packages/api/core/src/util/electron-version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import findUp from 'find-up';
import fs from 'fs-extra';
import path from 'path';
import semver from 'semver';
import yarnOrNpm, { hasYarn } from './yarn-or-npm';
import yarnOrNpm from './yarn-or-npm';

const d = debug('electron-forge:electron-version');

Expand All @@ -22,13 +22,13 @@ async function findAncestorNodeModulesPath(
dir: string,
packageName: string,
): Promise<string | undefined> {
if (hasYarn()) {
const yarnLockPath = await findUp('yarn.lock', { cwd: dir, type: 'file' });
if (yarnLockPath) {
const nodeModulesPath = path.join(path.dirname(yarnLockPath), 'node_modules', packageName);
if (await fs.pathExists(nodeModulesPath)) {
return nodeModulesPath;
}
d('Looking for a lock file to indicate the root of the repo');
const lockPath = await findUp(['package-lock.json', 'yarn.lock', 'pnpm-lock.yaml'], { cwd: dir, type: 'file' });
if (lockPath) {
d(`Found lock file: ${lockPath}`);
const nodeModulesPath = path.join(path.dirname(lockPath), 'node_modules', packageName);
if (await fs.pathExists(nodeModulesPath)) {
return nodeModulesPath;
}
}

Expand Down
132 changes: 79 additions & 53 deletions packages/api/core/test/fast/electron-version_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import os from 'os';
import path from 'path';
import { getElectronModulePath, getElectronVersion, updateElectronDependency } from '../../src/util/electron-version';
import { devDeps, exactDevDeps } from '../../src/api/init-scripts/init-npm';
import { hasYarn } from '../../src/util/yarn-or-npm';

describe('updateElectronDependency', () => {
it('adds an Electron dep if one does not already exist', () => {
Expand Down Expand Up @@ -76,84 +75,111 @@ describe('getElectronVersion', () => {
return expect(await getElectronVersion('', packageJSON)).to.be.equal('1.0.0');
});

it('works with a non-exact version and yarn workspaces', async () => {
const fixtureDir = path.resolve(__dirname, '..', 'fixture', 'yarn-workspace', 'packages', 'subpackage');
const packageJSON = {
devDependencies: { electron: '^4.0.4' },
};
if (hasYarn()) {
describe('with yarn workspaces', () => {
before(() => {
process.env.NODE_INSTALLER = 'yarn';
});

it('works with a non-exact version', async () => {
const fixtureDir = path.resolve(__dirname, '..', 'fixture', 'yarn-workspace', 'packages', 'subpackage');
const packageJSON = {
devDependencies: { electron: '^4.0.4' },
};

expect(await getElectronVersion(fixtureDir, packageJSON)).to.be.equal('4.0.9');
} else {
expect(getElectronVersion(fixtureDir, packageJSON)).to.eventually.be.rejectedWith('Cannot find the package');
}
});

after(() => {
delete process.env.NODE_INSTALLER;
});
});
});

describe('getElectronModulePath', () => {
let tempDir: string;
before(async () => {
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'electron-forge-test-'));
});

it('fails without devDependencies', () => expect(getElectronModulePath('', {})).to.eventually.be.rejectedWith('does not have any devDependencies'));

it('fails without electron devDependencies', () => expect(getElectronModulePath('', { devDependencies: {} })).to.eventually.be.rejectedWith('Electron packages in devDependencies'));

it('fails with no electron installed', async () => {
const fixtureDir = path.resolve(__dirname, '..', 'fixture', 'dummy_app');
await fs.copy(fixtureDir, tempDir);
return expect(getElectronModulePath(tempDir, { devDependencies: { electron: '^4.0.2' } })).to.eventually.be.rejectedWith('Cannot find the package');
describe('with no electron installed', () => {
let tempDir: string;
before(async () => {
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'electron-forge-test-'));
});

it('throws an error saying it cannot find electron', async () => {
const fixtureDir = path.resolve(__dirname, '..', 'fixture', 'dummy_app');
await fs.copy(fixtureDir, tempDir);
return expect(getElectronModulePath(tempDir, { devDependencies: { electron: '^4.0.2' } })).to.eventually.be.rejectedWith('Cannot find the package');
});

after(async () => {
await fs.remove(tempDir);
});
});

it('works with electron', () => {
const fixtureDir = path.resolve(__dirname, '..', 'fixture', 'non-exact');
return expect(getElectronModulePath(fixtureDir, { devDependencies: { electron: '^4.0.2' } })).to.eventually.equal(path.join(fixtureDir, 'node_modules', 'electron'));
});

it('works with yarn workspaces', async () => {
const workspaceDir = path.resolve(__dirname, '..', 'fixture', 'yarn-workspace');
const fixtureDir = path.join(workspaceDir, 'packages', 'subpackage');
const packageJSON = {
devDependencies: { electron: '^4.0.4' },
};
describe('with npm workspaces', () => {
before(() => {
process.env.NODE_INSTALLER = 'npm';
});

it('finds the top-level electron module', async () => {
const workspaceDir = path.resolve(__dirname, '..', 'fixture', 'npm-workspace');
const fixtureDir = path.join(workspaceDir, 'packages', 'subpackage');
const packageJSON = {
devDependencies: { electron: '^4.0.4' },
};

if (hasYarn()) {
expect(await getElectronModulePath(fixtureDir, packageJSON)).to.be.equal(path.join(workspaceDir, 'node_modules', 'electron'));
} else {
expect(getElectronModulePath(fixtureDir, packageJSON)).to.eventually.be.rejectedWith('Cannot find the package');
}
});

after(() => {
delete process.env.NODE_INSTALLER;
});
});

it('works when yarn workspaces create additional node_modules folder inside package', async () => {
const workspaceDir = path.resolve(__dirname, '..', 'fixture', 'yarn-workspace');
const fixtureDir = path.join(workspaceDir, 'packages', 'with-node-modules');
const packageJSON = {
devDependencies: { electron: '^4.0.4' },
};
describe('with yarn workspaces', () => {
before(() => {
process.env.NODE_INSTALLER = 'yarn';
});

it('finds the top-level electron module', async () => {
const workspaceDir = path.resolve(__dirname, '..', 'fixture', 'yarn-workspace');
const fixtureDir = path.join(workspaceDir, 'packages', 'subpackage');
const packageJSON = {
devDependencies: { electron: '^4.0.4' },
};

if (hasYarn()) {
expect(await getElectronModulePath(fixtureDir, packageJSON)).to.be.equal(path.join(workspaceDir, 'node_modules', 'electron'));
} else {
expect(getElectronModulePath(fixtureDir, packageJSON)).to.eventually.be.rejectedWith('Cannot find the package');
}
});
});

it('works with yarn workspaces in ala nohoist mode', async () => {
const workspaceDir = path.resolve(__dirname, '..', 'fixture', 'yarn-workspace');
const fixtureDir = path.join(workspaceDir, 'packages', 'electron-folder-in-node-modules');
const packageJSON = {
devDependencies: { electron: '^13.0.0' },
};
it('finds the top-level electron module despite the additional node_modules folder inside the package', async () => {
const workspaceDir = path.resolve(__dirname, '..', 'fixture', 'yarn-workspace');
const fixtureDir = path.join(workspaceDir, 'packages', 'with-node-modules');
const packageJSON = {
devDependencies: { electron: '^4.0.4' },
};

expect(await getElectronModulePath(fixtureDir, packageJSON)).to.be.equal(path.join(workspaceDir, 'node_modules', 'electron'));
});

it('finds the correct electron module in nohoist mode', async () => {
const workspaceDir = path.resolve(__dirname, '..', 'fixture', 'yarn-workspace');
const fixtureDir = path.join(workspaceDir, 'packages', 'electron-folder-in-node-modules');
const packageJSON = {
devDependencies: { electron: '^13.0.0' },
};

if (hasYarn()) {
expect(await getElectronModulePath(fixtureDir, packageJSON)).to.be.equal(path.join(fixtureDir, 'node_modules', 'electron'));
expect(await getElectronModulePath(fixtureDir, packageJSON)).not.to.be.equal(path.join(workspaceDir, 'node_modules', 'electron'));
} else {
expect(getElectronModulePath(fixtureDir, packageJSON)).to.eventually.be.rejectedWith('Cannot find the package');
}
});
});

after(async () => {
await fs.remove(tempDir);
after(() => {
delete process.env.NODE_INSTALLER;
});
});
});

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Empty file.
5 changes: 5 additions & 0 deletions packages/api/core/test/fixture/npm-workspace/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"workspaces": [
"packages/subpackage"
]
}
Empty file.

0 comments on commit 4c60151

Please sign in to comment.