Skip to content

Commit 14c06c6

Browse files
Add test coverage for useIpAddressForGeolocation config fix (#348)
1 parent c0c21b4 commit 14c06c6

File tree

2 files changed

+184
-1
lines changed

2 files changed

+184
-1
lines changed

.github/workflows/node.js.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ jobs:
6565
working-directory: ./Samples/SimpleMixpanel/android
6666
script: ./gradlew
6767
- name: Test Android
68-
uses: reactivecircus/android-emulator-runner@v2.32.0
68+
uses: reactivecircus/android-emulator-runner@v2.35.0
6969
with:
7070
api-level: 34
7171
target: google_apis

__tests__/config.test.js

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
import { MixpanelConfig } from "mixpanel-react-native/javascript/mixpanel-config";
2+
3+
// Mock the dependencies
4+
jest.mock("mixpanel-react-native/javascript/mixpanel-logger", () => ({
5+
MixpanelLogger: {
6+
log: jest.fn(),
7+
},
8+
}));
9+
10+
jest.mock("mixpanel-react-native/javascript/mixpanel-constants", () => ({
11+
defaultServerURL: "https://api.mixpanel.com",
12+
defaultFlushInterval: 60000,
13+
defaultFlushBatchSize: 50,
14+
}));
15+
16+
describe("MixpanelConfig", () => {
17+
let config;
18+
const testToken = "test-token-123";
19+
20+
beforeEach(() => {
21+
// Clear singleton instance before each test
22+
MixpanelConfig.instance = undefined;
23+
config = MixpanelConfig.getInstance();
24+
});
25+
26+
describe("getUseIpAddressForGeolocation", () => {
27+
test("should return true by default when no config is set", () => {
28+
const result = config.getUseIpAddressForGeolocation(testToken);
29+
expect(result).toBe(true);
30+
});
31+
32+
test("should return false when explicitly set to false", () => {
33+
config.setUseIpAddressForGeolocation(testToken, false);
34+
const result = config.getUseIpAddressForGeolocation(testToken);
35+
expect(result).toBe(false);
36+
});
37+
38+
test("should return true when explicitly set to true", () => {
39+
config.setUseIpAddressForGeolocation(testToken, true);
40+
const result = config.getUseIpAddressForGeolocation(testToken);
41+
expect(result).toBe(true);
42+
});
43+
44+
test("should return 0 when set to 0 (falsy number)", () => {
45+
config.setUseIpAddressForGeolocation(testToken, 0);
46+
const result = config.getUseIpAddressForGeolocation(testToken);
47+
expect(result).toBe(0);
48+
});
49+
50+
test("should return 1 when set to 1 (truthy number)", () => {
51+
config.setUseIpAddressForGeolocation(testToken, 1);
52+
const result = config.getUseIpAddressForGeolocation(testToken);
53+
expect(result).toBe(1);
54+
});
55+
56+
test("should return null when set to null", () => {
57+
config.setUseIpAddressForGeolocation(testToken, null);
58+
const result = config.getUseIpAddressForGeolocation(testToken);
59+
expect(result).toBe(null);
60+
});
61+
62+
test("should return undefined when set to undefined", () => {
63+
config.setUseIpAddressForGeolocation(testToken, undefined);
64+
const result = config.getUseIpAddressForGeolocation(testToken);
65+
expect(result).toBe(undefined);
66+
});
67+
68+
test("should return empty string when set to empty string", () => {
69+
config.setUseIpAddressForGeolocation(testToken, "");
70+
const result = config.getUseIpAddressForGeolocation(testToken);
71+
expect(result).toBe("");
72+
});
73+
74+
test("should handle multiple tokens independently", () => {
75+
const token1 = "token-1";
76+
const token2 = "token-2";
77+
78+
config.setUseIpAddressForGeolocation(token1, false);
79+
config.setUseIpAddressForGeolocation(token2, true);
80+
81+
expect(config.getUseIpAddressForGeolocation(token1)).toBe(false);
82+
expect(config.getUseIpAddressForGeolocation(token2)).toBe(true);
83+
});
84+
85+
test("should preserve value after multiple sets", () => {
86+
config.setUseIpAddressForGeolocation(testToken, true);
87+
expect(config.getUseIpAddressForGeolocation(testToken)).toBe(true);
88+
89+
config.setUseIpAddressForGeolocation(testToken, false);
90+
expect(config.getUseIpAddressForGeolocation(testToken)).toBe(false);
91+
92+
config.setUseIpAddressForGeolocation(testToken, true);
93+
expect(config.getUseIpAddressForGeolocation(testToken)).toBe(true);
94+
});
95+
96+
test("should not affect other config properties when setting geolocation", () => {
97+
// Set some other config values first
98+
config.setFlushBatchSize(testToken, 100);
99+
config.setServerURL(testToken, "https://custom.mixpanel.com");
100+
101+
// Set geolocation
102+
config.setUseIpAddressForGeolocation(testToken, false);
103+
104+
// Verify other config values are preserved
105+
expect(config.getFlushBatchSize(testToken)).toBe(100);
106+
expect(config.getServerURL(testToken)).toBe("https://custom.mixpanel.com");
107+
expect(config.getUseIpAddressForGeolocation(testToken)).toBe(false);
108+
});
109+
});
110+
111+
describe("setUseIpAddressForGeolocation", () => {
112+
test("should create config object if it doesn't exist", () => {
113+
config.setUseIpAddressForGeolocation(testToken, false);
114+
expect(config._config[testToken]).toBeDefined();
115+
expect(config._config[testToken].useIpAddressForGeolocation).toBe(false);
116+
});
117+
118+
test("should preserve existing config when updating geolocation", () => {
119+
// Set initial config
120+
config._config[testToken] = {
121+
serverURL: "https://custom.mixpanel.com",
122+
flushBatchSize: 100,
123+
};
124+
125+
// Update geolocation
126+
config.setUseIpAddressForGeolocation(testToken, false);
127+
128+
// Verify all properties are preserved
129+
expect(config._config[testToken].serverURL).toBe("https://custom.mixpanel.com");
130+
expect(config._config[testToken].flushBatchSize).toBe(100);
131+
expect(config._config[testToken].useIpAddressForGeolocation).toBe(false);
132+
});
133+
});
134+
135+
describe("Regression tests for issue #315", () => {
136+
test("BUG FIX: should correctly return false instead of defaulting to true", () => {
137+
// This is the main bug that was fixed
138+
config.setUseIpAddressForGeolocation(testToken, false);
139+
const result = config.getUseIpAddressForGeolocation(testToken);
140+
141+
// Before fix, this would incorrectly return true
142+
expect(result).toBe(false);
143+
expect(result).not.toBe(true);
144+
});
145+
146+
test("BUG FIX: should handle all falsy values correctly", () => {
147+
const falsyValues = [false, 0, "", null, undefined, NaN];
148+
149+
falsyValues.forEach((value, index) => {
150+
const token = `token-falsy-${index}`;
151+
config.setUseIpAddressForGeolocation(token, value);
152+
const result = config.getUseIpAddressForGeolocation(token);
153+
154+
// Before fix, all these would incorrectly return true
155+
if (Number.isNaN(value)) {
156+
expect(Number.isNaN(result)).toBe(true);
157+
} else {
158+
expect(result).toBe(value);
159+
}
160+
});
161+
});
162+
});
163+
164+
describe("Integration with network layer", () => {
165+
test("should provide correct value for IP parameter in network requests", () => {
166+
// Test that the config value would be used correctly in network requests
167+
config.setUseIpAddressForGeolocation(testToken, false);
168+
169+
// This simulates what happens in mixpanel-core.js when sending requests
170+
const useIPAddressForGeoLocation = config.getUseIpAddressForGeolocation(testToken);
171+
const ipParam = +useIPAddressForGeoLocation; // Convert to number as done in network layer
172+
173+
expect(ipParam).toBe(0); // false should become 0
174+
175+
// Test with true
176+
config.setUseIpAddressForGeolocation(testToken, true);
177+
const useIPAddressForGeoLocationTrue = config.getUseIpAddressForGeolocation(testToken);
178+
const ipParamTrue = +useIPAddressForGeoLocationTrue;
179+
180+
expect(ipParamTrue).toBe(1); // true should become 1
181+
});
182+
});
183+
});

0 commit comments

Comments
 (0)