Skip to content

Commit ecc1700

Browse files
Natallia HarshunovaDevtools-frontend LUCI CQ
authored andcommitted
Make SyncSection fetch its own GDP profile
This change refactors the `SyncSection` component to fetch its own Google Developer Program (GDP) profile information instead of receiving it from the parent `SettingsScreen` component. This is necessary to allow the `SyncSection` to re-render and show the user's new profile information after they successfully sign up for the GDP. Previously, the `SettingsScreen` would fetch the profile and pass it down, but there was no mechanism to trigger a refresh after the sign-up flow was completed. The tests for `SyncSection` have been updated to mock the GDP profile fetching and ensure the component renders correctly in all states. Fixed: 443050804 Change-Id: I12e03a5bcd94506314a15099cc6317e187c54829 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6919150 Reviewed-by: Ergün Erdoğmuş <[email protected]> Commit-Queue: Natallia Harshunova <[email protected]>
1 parent d2147d3 commit ecc1700

File tree

5 files changed

+49
-24
lines changed

5 files changed

+49
-24
lines changed

front_end/core/host/GdpClient.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ describe('GdpClient', () => {
4141
sinon.assert.calledOnce(dispatchHttpRequestStub);
4242
});
4343

44+
it('should clear cache after creating a profile', async () => {
45+
await Host.GdpClient.GdpClient.instance().getProfile();
46+
await Host.GdpClient.GdpClient.instance().createProfile(
47+
{user: 'test', emailPreference: Host.GdpClient.EmailPreference.ENABLED});
48+
await Host.GdpClient.GdpClient.instance().getProfile();
49+
await Host.GdpClient.GdpClient.instance().getProfile();
50+
51+
sinon.assert.calledThrice(dispatchHttpRequestStub);
52+
});
53+
4454
describe('when the integration is disabled', () => {
4555
it('should not make a request', async () => {
4656
updateHostConfig({

front_end/core/host/GdpClient.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,16 +131,26 @@ export class GdpClient {
131131
return (await this.checkEligibility())?.createProfile === EligibilityStatus.ELIGIBLE;
132132
}
133133

134-
createProfile({user, emailPreference}: {user: string, emailPreference: EmailPreference}): Promise<Profile|null> {
135-
return makeHttpRequest({
134+
async createProfile({user, emailPreference}: {user: string, emailPreference: EmailPreference}):
135+
Promise<Profile|null> {
136+
const result = await makeHttpRequest<Profile>({
136137
service: SERVICE_NAME,
137138
path: '/v1beta1/profiles',
138139
method: 'POST',
139140
body: JSON.stringify({
140141
user,
141142
newsletter_email: emailPreference,
142-
})
143+
}),
143144
});
145+
if (result) {
146+
this.#clearCache();
147+
}
148+
return result;
149+
}
150+
151+
#clearCache(): void {
152+
this.#cachedProfilePromise = undefined;
153+
this.#cachedEligibilityPromise = undefined;
144154
}
145155

146156
createAward({name}: {name: string}): Promise<Award|null> {

front_end/panels/settings/SettingsScreen.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -336,19 +336,13 @@ export class GenericSettingsTab extends UI.Widget.VBox implements SettingsTab {
336336
this.#updateSyncSectionTimerId = -1;
337337
}
338338

339-
void Promise
340-
.all([
341-
new Promise<Host.InspectorFrontendHostAPI.SyncInformation>(
342-
resolve => Host.InspectorFrontendHost.InspectorFrontendHostInstance.getSyncInformation(resolve)),
343-
Root.Runtime.hostConfig.devToolsGdpProfiles?.enabled ? Host.GdpClient.GdpClient.instance().getProfile() :
344-
Promise.resolve(undefined),
345-
])
346-
.then(([syncInfo, gdpProfile]) => {
339+
void new Promise<Host.InspectorFrontendHostAPI.SyncInformation>(
340+
resolve => Host.InspectorFrontendHost.InspectorFrontendHostInstance.getSyncInformation(resolve))
341+
.then(syncInfo => {
347342
this.syncSection.data = {
348343
syncInfo,
349344
syncSetting: Common.Settings.moduleSetting('sync-preferences') as Common.Settings.Setting<boolean>,
350345
receiveBadgesSetting: Common.Settings.Settings.instance().moduleSetting('receive-gdp-badges'),
351-
gdpProfile: gdpProfile ?? undefined,
352346
};
353347
if (!syncInfo.isSyncActive || !syncInfo.arePreferencesSynced) {
354348
this.#updateSyncSectionTimerId = window.setTimeout(this.updateSyncSection.bind(this), 500);

front_end/panels/settings/components/SyncSection.test.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ describeWithLocale('SyncSection', () => {
150150
});
151151

152152
it('renders the sign-up state when the user does not have a GDP profile', async () => {
153+
const gdpClient = Host.GdpClient.GdpClient.instance();
154+
sinon.stub(gdpClient, 'getProfile').resolves(null);
155+
153156
const syncSetting = createFakeSetting<boolean>('setting', true);
154157
const receiveBadgesSetting = createFakeSetting<boolean>('receive-badges', true);
155158
const {shadowRoot} = await renderSyncSection({
@@ -160,7 +163,6 @@ describeWithLocale('SyncSection', () => {
160163
},
161164
syncSetting,
162165
receiveBadgesSetting,
163-
gdpProfile: undefined, // No profile
164166
});
165167
const gdpSection = shadowRoot.querySelector('.gdp-profile-container');
166168
assert.instanceOf(gdpSection, HTMLElement);
@@ -175,9 +177,14 @@ describeWithLocale('SyncSection', () => {
175177
});
176178

177179
it('renders the profile details with standard plan', async () => {
180+
const gdpClient = Host.GdpClient.GdpClient.instance();
181+
sinon.stub(gdpClient, 'getProfile').resolves({
182+
name: 'test-profile',
183+
activeSubscription: undefined,
184+
});
185+
178186
const syncSetting = createFakeSetting<boolean>('setting', true);
179187
const receiveBadgesSetting = createFakeSetting<boolean>('receive-badges', true);
180-
const gdpProfile: Host.GdpClient.Profile = {name: 'profile-name'}; // No active subscription
181188
const {shadowRoot} = await renderSyncSection({
182189
syncInfo: {
183190
isSyncActive: true,
@@ -186,7 +193,6 @@ describeWithLocale('SyncSection', () => {
186193
},
187194
syncSetting,
188195
receiveBadgesSetting,
189-
gdpProfile,
190196
});
191197

192198
const gdpSection = shadowRoot.querySelector('.gdp-profile-container');
@@ -229,15 +235,17 @@ describeWithLocale('SyncSection', () => {
229235

230236
for (const {tier, expectedText} of subscriptionTiers) {
231237
it(`renders the profile details with ${expectedText} plan`, async () => {
232-
const syncSetting = createFakeSetting<boolean>('setting', true);
233-
const receiveBadgesSetting = createFakeSetting<boolean>('receive-badges', true);
234-
const gdpProfile: Host.GdpClient.Profile = {
235-
name: 'profile-name',
238+
const gdpClient = Host.GdpClient.GdpClient.instance();
239+
sinon.stub(gdpClient, 'getProfile').resolves({
240+
name: 'test-profile',
236241
activeSubscription: {
242+
subscriptionTier: tier as Host.GdpClient.SubscriptionTier,
237243
subscriptionStatus: Host.GdpClient.SubscriptionStatus.ENABLED,
238-
subscriptionTier: tier,
239244
},
240-
};
245+
});
246+
247+
const syncSetting = createFakeSetting<boolean>('setting', true);
248+
const receiveBadgesSetting = createFakeSetting<boolean>('receive-badges', true);
241249
const {shadowRoot} = await renderSyncSection({
242250
syncInfo: {
243251
isSyncActive: true,
@@ -246,7 +254,6 @@ describeWithLocale('SyncSection', () => {
246254
},
247255
syncSetting,
248256
receiveBadgesSetting,
249-
gdpProfile,
250257
});
251258

252259
const gdpSection = shadowRoot.querySelector('.gdp-profile-container');

front_end/panels/settings/components/SyncSection.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,6 @@ export interface SyncSectionData {
117117
syncInfo: Host.InspectorFrontendHostAPI.SyncInformation;
118118
syncSetting: Common.Settings.Setting<boolean>;
119119
receiveBadgesSetting: Common.Settings.Setting<boolean>;
120-
gdpProfile?: Host.GdpClient.Profile;
121120
}
122121

123122
export class SyncSection extends HTMLElement {
@@ -132,7 +131,7 @@ export class SyncSection extends HTMLElement {
132131
this.#syncInfo = data.syncInfo;
133132
this.#syncSetting = data.syncSetting;
134133
this.#receiveBadgesSetting = data.receiveBadgesSetting;
135-
this.#gdpProfile = data.gdpProfile;
134+
void this.#updateGdpProfile();
136135
void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#render);
137136
}
138137

@@ -157,6 +156,11 @@ export class SyncSection extends HTMLElement {
157156
`, this.#shadow, {host: this});
158157
// clang-format on
159158
}
159+
160+
async #updateGdpProfile(): Promise<void> {
161+
this.#gdpProfile = await Host.GdpClient.GdpClient.instance().getProfile() ?? undefined;
162+
void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#render);
163+
}
160164
}
161165

162166
function renderSettingCheckboxIfNeeded(

0 commit comments

Comments
 (0)