Skip to content

Commit b75f45f

Browse files
fix: use 0.0.0 as fallback when package.json unavailable (#674)
1 parent 0cbfdf7 commit b75f45f

File tree

2 files changed

+137
-89
lines changed

2 files changed

+137
-89
lines changed

lib/utils/analytics/getSDKVersions.js

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,28 @@ const fs = require('fs');
22
const path = require('path');
33
const sdkCode = 'M'; // Constant per SDK
44

5+
function readSdkSemver() {
6+
const pkgJsonPath = path.join(__dirname, '../../../package.json');
7+
try {
8+
const pkgJSONFile = fs.readFileSync(pkgJsonPath, 'utf-8');
9+
return JSON.parse(pkgJSONFile).version
10+
} catch (e) {
11+
if (e.code === 'ENOENT') {
12+
return '0.0.0'
13+
}
14+
return 'n/a';
15+
}
16+
}
17+
518
/**
619
* @description Gets the relevant versions of the SDK(package version, node version and sdkCode)
720
* @param {'default' | 'x.y.z' | 'x.y' | string} useSDKVersion Default uses package.json version
821
* @param {'default' | 'x.y.z' | 'x.y' | string} useNodeVersion Default uses process.versions.node
922
* @return {{sdkSemver:string, techVersion:string, sdkCode:string}} A map of relevant versions and codes
1023
*/
1124
function getSDKVersions(useSDKVersion = 'default', useNodeVersion = 'default') {
12-
const pkgJSONFile = fs.readFileSync(path.join(__dirname, '../../../package.json'), 'utf-8');
13-
1425
// allow to pass a custom SDKVersion
15-
const sdkSemver = useSDKVersion === 'default' ? JSON.parse(pkgJSONFile).version : useSDKVersion;
26+
const sdkSemver = useSDKVersion === 'default' ? readSdkSemver() : useSDKVersion;
1627

1728
// allow to pass a custom techVersion (Node version)
1829
const techVersion = useNodeVersion === 'default' ? process.versions.node : useNodeVersion;
Lines changed: 123 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
const path = require('path');
22
const mock = require('mock-fs');
3-
const cloudinary = require('../../../cloudinary');
43
const assert = require("assert");
4+
const sinon = require("sinon");
5+
const fs = require('fs');
6+
7+
const cloudinary = require('../../../cloudinary');
8+
59
const TEST_CLOUD_NAME = require('../../testUtils/testConstants').TEST_CLOUD_NAME;
610

711
describe('SDK url analytics', () => {
@@ -12,132 +16,165 @@ describe('SDK url analytics', () => {
1216

1317
processVersions = process.versions;
1418
delete process.versions;
15-
16-
const file = path.join(__dirname, '../../../package.json');
17-
18-
mock({
19-
[file]: '{"version":"1.24.0"}'
20-
});
2119
});
2220

2321
after(() => {
24-
mock.restore();
2522
process.versions = processVersions;
2623
});
2724

28-
it('can be turned off via options', () => {
29-
process.versions = {
30-
node: '12.0.0'
31-
};
25+
describe('when package json is available', () => {
26+
before(() => {
27+
const file = path.join(__dirname, '../../../package.json');
3228

33-
const imgStr = cloudinary.image("hello", {
34-
format: "png",
35-
analytics: false
29+
mock({
30+
[file]: '{"version":"1.24.0"}'
31+
});
3632
});
3733

38-
assert.ok(!imgStr.includes('MAlhAM0'))
39-
});
34+
after(() => {
35+
mock.restore();
36+
});
37+
38+
it('can be turned off via options', () => {
39+
process.versions = {
40+
node: '12.0.0'
41+
};
4042

41-
it('defaults to true even if analytics is not passed as an option', () => {
42-
process.versions = {
43-
node: '12.0.0'
44-
};
43+
const imgStr = cloudinary.image("hello", {
44+
format: "png",
45+
analytics: false
46+
});
4547

46-
const imgStr = cloudinary.image("hello", {
47-
format: "png"
48+
assert.ok(!imgStr.includes('MAlhAM0'))
4849
});
4950

50-
assert.ok(imgStr.includes('MAlhAM0'))
51-
});
51+
it('defaults to true even if analytics is not passed as an option', () => {
52+
process.versions = {
53+
node: '12.0.0'
54+
};
5255

53-
it('reads from process.versions and package.json (Mocked)', () => {
54-
process.versions = {
55-
node: '12.0.0'
56-
};
56+
const imgStr = cloudinary.image("hello", {
57+
format: "png"
58+
});
5759

58-
const imgStr = cloudinary.image("hello", {
59-
format: "png",
60-
analytics: true
60+
assert.ok(imgStr.includes('MAlhAM0'))
6161
});
6262

63-
assert.ok(imgStr.includes('?_a=BAMAlhAM0'));
64-
});
63+
it('reads from process.versions and package.json (Mocked)', () => {
64+
process.versions = {
65+
node: '12.0.0'
66+
};
6567

66-
it('reads from process.versions and package.json (Mocked) - Responsive', () => {
67-
process.versions = {
68-
node: '12.0.0'
69-
};
68+
const imgStr = cloudinary.image("hello", {
69+
format: "png",
70+
analytics: true
71+
});
7072

71-
const imgStr = cloudinary.image("hello", {
72-
format: "png",
73-
responsive: true,
74-
analytics: true
73+
assert.ok(imgStr.includes('?_a=BAMAlhAM0'));
7574
});
7675

77-
assert.ok(imgStr.includes('?_a=BAMAlhAMA'));
78-
});
76+
it('reads from process.versions and package.json (Mocked) - Responsive', () => {
77+
process.versions = {
78+
node: '12.0.0'
79+
};
7980

80-
it('reads from tracked analytics configuration', () => {
81-
process.versions = {
82-
node: '12.0.0'
83-
};
84-
85-
const imgStr = cloudinary.image("hello", {
86-
format: "png",
87-
analytics: true,
88-
sdk_code: "X",
89-
sdk_semver: "7.3.0",
90-
tech_version: "3.4.7",
91-
product: 'B'
81+
const imgStr = cloudinary.image("hello", {
82+
format: "png",
83+
responsive: true,
84+
analytics: true
85+
});
86+
87+
assert.ok(imgStr.includes('?_a=BAMAlhAMA'));
9288
});
9389

94-
assert.ok(imgStr.includes('?_a=BBXAEzGT0'));
95-
});
90+
it('reads from tracked analytics configuration', () => {
91+
process.versions = {
92+
node: '12.0.0'
93+
};
9694

97-
it('should still accept analytics param passed as camel case', () => {
98-
process.versions = {
99-
node: '12.0.0'
100-
};
101-
102-
const imgStr = cloudinary.image("hello", {
103-
format: "png",
104-
urlAnalytics: true,
105-
sdkCode: "X",
106-
sdkSemver: "7.3.0",
107-
techVersion: "3.4.7",
108-
product: 'B'
109-
});
95+
const imgStr = cloudinary.image("hello", {
96+
format: "png",
97+
analytics: true,
98+
sdk_code: "X",
99+
sdk_semver: "7.3.0",
100+
tech_version: "3.4.7",
101+
product: 'B'
102+
});
110103

111-
assert.ok(imgStr.includes('?_a=BBXAEzGT0'));
112-
});
104+
assert.ok(imgStr.includes('?_a=BBXAEzGT0'));
105+
});
113106

114-
describe('with two different casings', () => {
115-
it('should treat camel case analytics param as more important than snake case', () => {
107+
it('should still accept analytics param passed as camel case', () => {
116108
process.versions = {
117109
node: '12.0.0'
118110
};
119111

120-
const imgStr1 = cloudinary.image("hello", {
112+
const imgStr = cloudinary.image("hello", {
121113
format: "png",
122114
urlAnalytics: true,
123-
analytics: false,
124115
sdkCode: "X",
125116
sdkSemver: "7.3.0",
126117
techVersion: "3.4.7",
127118
product: 'B'
128119
});
129-
assert.ok(imgStr1.includes('?_a=BBXAEzGT0'));
130120

131-
const imgStr2 = cloudinary.image("hello", {
121+
assert.ok(imgStr.includes('?_a=BBXAEzGT0'));
122+
});
123+
124+
describe('with two different casings', () => {
125+
it('should treat camel case analytics param as more important than snake case', () => {
126+
process.versions = {
127+
node: '12.0.0'
128+
};
129+
130+
const imgStr1 = cloudinary.image("hello", {
131+
format: "png",
132+
urlAnalytics: true,
133+
analytics: false,
134+
sdkCode: "X",
135+
sdkSemver: "7.3.0",
136+
techVersion: "3.4.7",
137+
product: 'B'
138+
});
139+
assert.ok(imgStr1.includes('?_a=BBXAEzGT0'));
140+
141+
const imgStr2 = cloudinary.image("hello", {
142+
format: "png",
143+
analytics: true,
144+
sdkCode: "X",
145+
sdkSemver: "7.3.0",
146+
techVersion: "3.4.7",
147+
tech_version: "1.2.3",
148+
product: 'B'
149+
});
150+
assert.ok(imgStr2.includes('?_a=BBXAEzGT0'));
151+
});
152+
});
153+
});
154+
155+
describe('when package.json is unavailable', () => {
156+
before(() => {
157+
const enoent = new Error('ENOENT');
158+
enoent.code = 'ENOENT';
159+
sinon.stub(fs, 'readFileSync').throws(enoent);
160+
});
161+
162+
after(() => {
163+
sinon.restore();
164+
});
165+
166+
it('uses 0.0.0 as fallback sdk semver', () => {
167+
process.versions = {
168+
node: '12.0.0'
169+
};
170+
171+
const urlWithToken = cloudinary.url("hello", {
132172
format: "png",
133-
analytics: true,
134-
sdkCode: "X",
135-
sdkSemver: "7.3.0",
136-
techVersion: "3.4.7",
137-
tech_version: "1.2.3",
138-
product: 'B'
173+
analytics: true
139174
});
140-
assert.ok(imgStr2.includes('?_a=BBXAEzGT0'));
175+
176+
const [url, analyticsToken] = urlWithToken.split('?_a=');
177+
assert.strictEqual(analyticsToken, 'BAMAAAAM0');
141178
});
142179
});
143180
});

0 commit comments

Comments
 (0)