Skip to content

Commit 21b8474

Browse files
Add ember-source version utility with getEmberSourceVersion and isVersionAtLeast
Co-authored-by: NullVoxPopuli <[email protected]>
1 parent 8661465 commit 21b8474

2 files changed

Lines changed: 177 additions & 0 deletions

File tree

lib/utils/ember-source-version.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
'use strict';
2+
3+
const fs = require('node:fs');
4+
5+
/**
6+
* Get the installed ember-source version by resolving its package.json.
7+
*
8+
* @param {string} [projectRoot] - Project root directory (defaults to process.cwd())
9+
* @returns {string|null} The installed ember-source version, or null if not found
10+
*/
11+
function getEmberSourceVersion(projectRoot) {
12+
try {
13+
// eslint-disable-next-line n/no-missing-require
14+
const pkgPath = require.resolve('ember-source/package.json', {
15+
paths: [projectRoot || process.cwd()],
16+
});
17+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
18+
return pkg.version || null;
19+
} catch {
20+
return null;
21+
}
22+
}
23+
24+
/**
25+
* Check if a semver version string meets a minimum major.minor requirement.
26+
*
27+
* @param {string} version - Semver version string (e.g. '6.8.0')
28+
* @param {number} major - Required minimum major version
29+
* @param {number} minor - Required minimum minor version
30+
* @returns {boolean} True if version >= major.minor
31+
*/
32+
function isVersionAtLeast(version, major, minor) {
33+
if (!version || typeof version !== 'string') {
34+
return false;
35+
}
36+
37+
const parts = version.split('.');
38+
const vMajor = Number.parseInt(parts[0], 10);
39+
const vMinor = Number.parseInt(parts[1], 10);
40+
41+
if (Number.isNaN(vMajor) || Number.isNaN(vMinor)) {
42+
return false;
43+
}
44+
45+
return vMajor > major || (vMajor === major && vMinor >= minor);
46+
}
47+
48+
module.exports = {
49+
getEmberSourceVersion,
50+
isVersionAtLeast,
51+
};
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
'use strict';
2+
3+
const fs = require('node:fs');
4+
const os = require('node:os');
5+
const path = require('node:path');
6+
const {
7+
getEmberSourceVersion,
8+
isVersionAtLeast,
9+
} = require('../../../lib/utils/ember-source-version');
10+
11+
describe('ember-source-version', () => {
12+
describe('isVersionAtLeast', () => {
13+
it('returns true when major version is greater', () => {
14+
expect(isVersionAtLeast('7.0.0', 6, 8)).toBe(true);
15+
});
16+
17+
it('returns true when major matches and minor is greater', () => {
18+
expect(isVersionAtLeast('6.10.0', 6, 8)).toBe(true);
19+
});
20+
21+
it('returns true when major and minor match exactly', () => {
22+
expect(isVersionAtLeast('6.8.0', 6, 8)).toBe(true);
23+
});
24+
25+
it('returns true when major and minor match with patch version', () => {
26+
expect(isVersionAtLeast('6.8.3', 6, 8)).toBe(true);
27+
});
28+
29+
it('returns false when major matches but minor is less', () => {
30+
expect(isVersionAtLeast('6.7.0', 6, 8)).toBe(false);
31+
});
32+
33+
it('returns false when major is less', () => {
34+
expect(isVersionAtLeast('5.12.0', 6, 8)).toBe(false);
35+
});
36+
37+
it('returns false for null', () => {
38+
expect(isVersionAtLeast(null, 6, 8)).toBe(false);
39+
});
40+
41+
it('returns false for undefined', () => {
42+
expect(isVersionAtLeast(undefined, 6, 8)).toBe(false);
43+
});
44+
45+
it('returns false for empty string', () => {
46+
expect(isVersionAtLeast('', 6, 8)).toBe(false);
47+
});
48+
49+
it('returns false for non-string input', () => {
50+
expect(isVersionAtLeast(123, 6, 8)).toBe(false);
51+
});
52+
53+
it('returns false for invalid version string', () => {
54+
expect(isVersionAtLeast('invalid', 6, 8)).toBe(false);
55+
});
56+
57+
it('handles pre-release versions', () => {
58+
expect(isVersionAtLeast('6.8.0-beta.1', 6, 8)).toBe(true);
59+
});
60+
61+
it('handles two-part version strings', () => {
62+
expect(isVersionAtLeast('6.8', 6, 8)).toBe(true);
63+
});
64+
65+
it('checks against 0.0 minimum', () => {
66+
expect(isVersionAtLeast('0.0.1', 0, 0)).toBe(true);
67+
});
68+
});
69+
70+
describe('getEmberSourceVersion', () => {
71+
let tmpDir;
72+
73+
beforeEach(() => {
74+
tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'eslint-plugin-ember-'));
75+
});
76+
77+
afterEach(() => {
78+
fs.rmSync(tmpDir, { recursive: true });
79+
});
80+
81+
it('returns null when ember-source is not installed', () => {
82+
expect(getEmberSourceVersion(tmpDir)).toBeNull();
83+
});
84+
85+
it('returns the version when ember-source is installed', () => {
86+
const emberSourceDir = path.join(tmpDir, 'node_modules', 'ember-source');
87+
fs.mkdirSync(emberSourceDir, { recursive: true });
88+
fs.writeFileSync(
89+
path.join(emberSourceDir, 'package.json'),
90+
JSON.stringify({ name: 'ember-source', version: '6.8.0' })
91+
);
92+
93+
expect(getEmberSourceVersion(tmpDir)).toBe('6.8.0');
94+
});
95+
96+
it('returns null when package.json has no version field', () => {
97+
const emberSourceDir = path.join(tmpDir, 'node_modules', 'ember-source');
98+
fs.mkdirSync(emberSourceDir, { recursive: true });
99+
fs.writeFileSync(
100+
path.join(emberSourceDir, 'package.json'),
101+
JSON.stringify({ name: 'ember-source' })
102+
);
103+
104+
expect(getEmberSourceVersion(tmpDir)).toBeNull();
105+
});
106+
107+
it('returns null when package.json is malformed', () => {
108+
const emberSourceDir = path.join(tmpDir, 'node_modules', 'ember-source');
109+
fs.mkdirSync(emberSourceDir, { recursive: true });
110+
fs.writeFileSync(path.join(emberSourceDir, 'package.json'), 'not json');
111+
112+
expect(getEmberSourceVersion(tmpDir)).toBeNull();
113+
});
114+
115+
it('handles pre-release versions', () => {
116+
const emberSourceDir = path.join(tmpDir, 'node_modules', 'ember-source');
117+
fs.mkdirSync(emberSourceDir, { recursive: true });
118+
fs.writeFileSync(
119+
path.join(emberSourceDir, 'package.json'),
120+
JSON.stringify({ name: 'ember-source', version: '7.0.0-beta.1' })
121+
);
122+
123+
expect(getEmberSourceVersion(tmpDir)).toBe('7.0.0-beta.1');
124+
});
125+
});
126+
});

0 commit comments

Comments
 (0)