Skip to content

Commit ccc9845

Browse files
authored
Merge pull request #16 from BlackishGreen33/bg/plugin/explicit-config-passing
refactor(plugin): replace global config state with explicit internal config passing
2 parents de753a2 + 345836d commit ccc9845

12 files changed

Lines changed: 570 additions & 423 deletions

plugin/__tests__/nativeAndroidMods.test.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { compileModsAsync } from 'expo/config-plugins';
2+
import withJPush from '../src';
13
import {
24
ANDROID_MANIFEST_PATH,
35
APP_BUILD_GRADLE_PATH,
@@ -9,6 +11,7 @@ import {
911
readFixtureFile,
1012
registerAndroidFixtureLifecycleHooks,
1113
} from './androidFixture';
14+
import { createExpoConfig, createPluginProps } from './testProps';
1215

1316
registerAndroidFixtureLifecycleHooks();
1417

@@ -201,4 +204,96 @@ describe('native Android config mods', () => {
201204
)
202205
).toBe(1);
203206
});
207+
208+
it('keeps Android config values isolated across independently configured plugin instances', async () => {
209+
const projectRootA = createProjectRoot();
210+
const projectRootB = createProjectRoot();
211+
const configA = withJPush(
212+
createExpoConfig(),
213+
createPluginProps({ packageName: 'com.example.alpha' })
214+
);
215+
const configB = withJPush(
216+
createExpoConfig(),
217+
createPluginProps({
218+
packageName: 'com.example.beta',
219+
vendorChannels: { huawei: { enabled: true } },
220+
})
221+
);
222+
223+
await compileModsAsync(configA, {
224+
projectRoot: projectRootA,
225+
platforms: ['android'],
226+
});
227+
await compileModsAsync(configB, {
228+
projectRoot: projectRootB,
229+
platforms: ['android'],
230+
});
231+
232+
const appBuildGradleA = readFixtureFile(projectRootA, APP_BUILD_GRADLE_PATH);
233+
const appBuildGradleB = readFixtureFile(projectRootB, APP_BUILD_GRADLE_PATH);
234+
const gradlePropertiesA = readFixtureFile(
235+
projectRootA,
236+
GRADLE_PROPERTIES_PATH
237+
);
238+
const gradlePropertiesB = readFixtureFile(
239+
projectRootB,
240+
GRADLE_PROPERTIES_PATH
241+
);
242+
243+
expect(appBuildGradleA).toContain('"com.example.alpha"');
244+
expect(appBuildGradleA).not.toContain(
245+
"implementation 'com.huawei.hms:push:6.13.0.300'"
246+
);
247+
expect(gradlePropertiesA).not.toContain('apmsInstrumentationEnabled=false');
248+
249+
expect(appBuildGradleB).toContain('"com.example.beta"');
250+
expect(appBuildGradleB).toContain(
251+
"implementation 'com.huawei.hms:push:6.13.0.300'"
252+
);
253+
expect(gradlePropertiesB).toContain('apmsInstrumentationEnabled=false');
254+
});
255+
256+
it('does not inject Huawei or FCM integrations when their enabled flags are false', async () => {
257+
const projectRoot = createProjectRoot();
258+
259+
await compileAndroidMods(projectRoot, {
260+
vendorChannels: {
261+
huawei: { enabled: false },
262+
fcm: { enabled: false },
263+
},
264+
});
265+
266+
const appBuildGradle = readFixtureFile(projectRoot, APP_BUILD_GRADLE_PATH);
267+
const projectBuildGradle = readFixtureFile(
268+
projectRoot,
269+
PROJECT_BUILD_GRADLE_PATH
270+
);
271+
const gradleProperties = readFixtureFile(
272+
projectRoot,
273+
GRADLE_PROPERTIES_PATH
274+
);
275+
276+
expect(appBuildGradle).not.toContain(
277+
"implementation 'com.huawei.hms:push:6.13.0.300'"
278+
);
279+
expect(appBuildGradle).not.toContain(
280+
"implementation 'com.google.firebase:firebase-messaging:24.1.0'"
281+
);
282+
expect(appBuildGradle).not.toContain(
283+
"apply plugin: 'com.google.gms.google-services'"
284+
);
285+
expect(appBuildGradle).not.toContain(
286+
"apply plugin: 'com.huawei.agconnect'"
287+
);
288+
expect(projectBuildGradle).not.toContain(
289+
"classpath 'com.google.gms:google-services:4.4.0'"
290+
);
291+
expect(projectBuildGradle).not.toContain(
292+
"classpath 'com.huawei.agconnect:agcp:1.9.3.302'"
293+
);
294+
expect(projectBuildGradle).not.toContain(
295+
"maven { url 'https://developer.huawei.com/repo/' }"
296+
);
297+
expect(gradleProperties).not.toContain('apmsInstrumentationEnabled=false');
298+
});
204299
});

plugin/__tests__/nativeIosMods.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import * as fs from 'fs';
2+
import { compileModsAsync } from 'expo/config-plugins';
3+
import withJPush from '../src';
24
import {
35
APP_BRIDGING_HEADER_PATH,
46
J_PUSH_IMPORTS,
@@ -13,6 +15,7 @@ import {
1315
removeBridgingHeaderBuildSetting,
1416
writeInfoPlist,
1517
} from './iosFixture';
18+
import { createExpoConfig, createPluginProps } from './testProps';
1619

1720
registerIosFixtureLifecycleHooks();
1821

@@ -124,4 +127,34 @@ describe('native iOS config mods', () => {
124127
)
125128
).toBe(true);
126129
});
130+
131+
it('keeps iOS Info.plist values isolated across independently configured plugin instances', async () => {
132+
const projectRootA = createProjectRoot();
133+
const projectRootB = createProjectRoot();
134+
const configA = withJPush(
135+
createExpoConfig(),
136+
createPluginProps({ appKey: 'ios-a', channel: 'chan-a' })
137+
);
138+
const configB = withJPush(
139+
createExpoConfig(),
140+
createPluginProps({ appKey: 'ios-b', channel: 'chan-b' })
141+
);
142+
143+
await compileModsAsync(configA, {
144+
projectRoot: projectRootA,
145+
platforms: ['ios'],
146+
});
147+
await compileModsAsync(configB, {
148+
projectRoot: projectRootB,
149+
platforms: ['ios'],
150+
});
151+
152+
const infoPlistA = readInfoPlist(projectRootA);
153+
const infoPlistB = readInfoPlist(projectRootB);
154+
155+
expect(infoPlistA.JPUSH_APPKEY).toBe('ios-a');
156+
expect(infoPlistA.JPUSH_CHANNEL).toBe('chan-a');
157+
expect(infoPlistB.JPUSH_APPKEY).toBe('ios-b');
158+
expect(infoPlistB.JPUSH_CHANNEL).toBe('chan-b');
159+
});
127160
});

plugin/__tests__/withJPush.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,30 @@ describe('withJPush', () => {
6363
});
6464
}).toThrow('[MX_JPush_Expo] apsForProduction 必须是布尔值');
6565
});
66+
67+
it('should require vendorChannels.huawei.enabled when Huawei config is present', () => {
68+
expect(() => {
69+
validateProps({
70+
appKey: 'test-app-key',
71+
channel: 'test-channel',
72+
packageName: 'com.example.test',
73+
vendorChannels: {
74+
huawei: {} as any,
75+
},
76+
});
77+
}).toThrow('[MX_JPush_Expo] vendorChannels.huawei.enabled 必须存在且为布尔值');
78+
});
79+
80+
it('should require vendorChannels.fcm.enabled to be a boolean when FCM config is present', () => {
81+
expect(() => {
82+
validateProps({
83+
appKey: 'test-app-key',
84+
channel: 'test-channel',
85+
packageName: 'com.example.test',
86+
vendorChannels: {
87+
fcm: { enabled: 'true' as any },
88+
},
89+
});
90+
}).toThrow('[MX_JPush_Expo] vendorChannels.fcm.enabled 必须存在且为布尔值');
91+
});
6692
});

0 commit comments

Comments
 (0)