Skip to content

Commit b570bef

Browse files
authored
Merge branch 'main' into mntor-2836-1
2 parents 8fbe5e7 + 2c7d969 commit b570bef

File tree

27 files changed

+327
-127
lines changed

27 files changed

+327
-127
lines changed

config/nimbus.yaml

+1-15
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,6 @@ features:
3333
value: { "enabled": false }
3434
- channel: production
3535
value: { "enabled": false }
36-
automatic-removal-csat-survey:
37-
description: Show the CSAT survey for Plus users that have automatically removed broker results
38-
variables:
39-
enabled:
40-
description: If the feature is enabled
41-
type: Boolean
42-
default: false
43-
defaults:
44-
- channel: local
45-
value: { "enabled": true }
46-
- channel: staging
47-
value: { "enabled": true }
48-
- channel: production
49-
value: { "enabled": false }
5036
data-privacy-petition-banner:
5137
description: Show the data privacy petition banner to US users
5238
variables:
@@ -56,7 +42,7 @@ features:
5642
default: false
5743
defaults:
5844
- channel: local
59-
value: { "enabled": false }
45+
value: { "enabled": true }
6046
- channel: staging
6147
value: { "enabled": false }
6248
- channel: production

docs/dependency-updates.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,8 @@ Used to compile cronjob scripts. You can test this by running
200200
### `tsx`
201201

202202
Used to run cronjobs locally and compile them on the fly. You can verify this by
203-
running `npm run dev:cronjobs`; if the cronjobs run like in `main`, it's still
204-
working.
203+
running a cronjob like `npm run dev:cron:monthly-activity`; if the cronjobs run
204+
like in `main`, it's still working.
205205

206206
### `yaml`
207207

esbuild.cronjobs.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { build } from "esbuild";
1414
// own issues in Next.js. Thus, esbuild is a compromise that can resolve these
1515
// import specifiers for us.
1616
build({
17-
entryPoints: ["./src/scripts/cronjobs/**/*.tsx"],
17+
entryPoints: ["./src/scripts/cronjobs/**/*.tsx", "./src/scripts/cronjobs/**/*.ts"],
1818
tsconfig: "tsconfig.cronjobs.json",
1919
bundle: true,
2020
platform: "node",

package.json

+6-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
"type": "module",
1010
"scripts": {
1111
"dev": "npm run build-nimbus && next dev --port=6060",
12-
"dev:cronjobs": "tsx --tsconfig tsconfig.cronjobs.json src/scripts/cronjobs/*.tsx",
12+
"dev:cron:first-data-broker-removal-fixed": "tsx --tsconfig tsconfig.cronjobs.json src/scripts/cronjobs/firstDataBrokerRemovalFixed.tsx",
13+
"dev:cron:monthly-activity": "tsx --tsconfig tsconfig.cronjobs.json src/scripts/cronjobs/monthlyActivity.tsx",
14+
"dev:cron:db-delete-unverified-subscribers": "tsx --tsconfig tsconfig.cronjobs.json src/scripts/cronjobs/deleteUnverifiedSubscribers.ts",
15+
"dev:cron:onerep-limits-alert": "tsx --tsconfig tsconfig.cronjobs.json src/scripts/cronjobs/onerepStatsAlert.ts",
1316
"dev:nimbus": "node --watch-path config/nimbus.yaml src/scripts/build/nimbusTypes.js",
1417
"build": "npm run get-location-data && npm run build-glean && npm run build-nimbus && next build && npm run build-cronjobs",
1518
"cloudrun": "npm run db:migrate && npm start",
@@ -23,10 +26,10 @@
2326
"cron:first-data-broker-removal-fixed": "node dist/scripts/cronjobs/firstDataBrokerRemovalFixed.js",
2427
"cron:monthly-activity": "node dist/scripts/cronjobs/monthlyActivity.js",
2528
"cron:breach-alerts": "node src/scripts/emailBreachAlerts.js",
26-
"cron:db-delete-unverified-subscribers": "node scripts/delete-unverified-subscribers.js",
29+
"cron:db-delete-unverified-subscribers": "node dist/scripts/cronjobs/deleteUnverifiedSubscribers.js",
2730
"cron:db-pull-breaches": "node src/scripts/syncBreaches.js",
2831
"cron:remote-settings-pull-breaches": "node scripts/updatebreaches.js",
29-
"cron:onerep-limits-alert": "node src/scripts/onerepStatsAlert.js",
32+
"cron:onerep-limits-alert": "node dist/scripts/cronjobs/onerepStatsAlert.js",
3033
"db:migrate": "node -r dotenv-flow/config node_modules/knex/bin/cli.js migrate:latest --knexfile src/db/knexfile.js",
3134
"db:rollback": "node -r dotenv-flow/config node_modules/knex/bin/cli.js migrate:rollback --knexfile src/db/knexfile.js",
3235
"prepare": "husky",

scripts/delete-unverified-subscribers.js

-12
This file was deleted.

src/apiMocks/mockData.ts

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
} from "../utils/subscriberBreaches";
2020
import { Session } from "next-auth";
2121
import { HibpLikeDbBreach } from "../utils/hibp";
22+
import { SerializedSubscriber } from "../next-auth";
2223

2324
// Setting this to a constant value produces the same result when the same methods
2425
// with the same version of faker are called.
@@ -150,6 +151,9 @@ export function createUserWithPremiumSubscription(): Session["user"] {
150151
avatarDefault: true,
151152
subscriptions: ["monitor"],
152153
},
154+
subscriber: {
155+
id: 42,
156+
} as SerializedSubscriber,
153157
};
154158
}
155159

src/app/(proper_react)/(redesign)/(authenticated)/user/(dashboard)/dashboard/Dashboard.stories.tsx

+4-6
Original file line numberDiff line numberDiff line change
@@ -212,15 +212,13 @@ const DashboardWrapper = (props: DashboardWrapperProps) => {
212212
elapsedTimeInDaysSinceInitialScan={
213213
props.elapsedTimeInDaysSinceInitialScan
214214
}
215-
enabledFeatureFlags={
216-
props.enabledFeatureFlags ?? ["HowItWorksPage"]
217-
}
215+
enabledFeatureFlags={[
216+
...(props.enabledFeatureFlags ?? []),
217+
"HowItWorksPage",
218+
]}
218219
experimentData={
219220
props.experimentData ?? {
220221
...defaultExperimentData,
221-
"automatic-removal-csat-survey": {
222-
enabled: true,
223-
},
224222
"last-scan-date": {
225223
enabled: true,
226224
},

src/app/(proper_react)/(redesign)/(authenticated)/user/(dashboard)/dashboard/Dashboard.test.tsx

+113-38
Original file line numberDiff line numberDiff line change
@@ -3477,12 +3477,7 @@ describe("CSAT survey banner", () => {
34773477
render(
34783478
<ComposedDashboard
34793479
elapsedTimeInDaysSinceInitialScan={1}
3480-
experimentData={{
3481-
...defaultExperimentData,
3482-
"automatic-removal-csat-survey": {
3483-
enabled: true,
3484-
},
3485-
}}
3480+
enabledFeatureFlags={["AutomaticRemovalCsatSurvey"]}
34863481
/>,
34873482
);
34883483

@@ -3501,12 +3496,7 @@ describe("CSAT survey banner", () => {
35013496
render(
35023497
<ComposedDashboard
35033498
elapsedTimeInDaysSinceInitialScan={1}
3504-
experimentData={{
3505-
...defaultExperimentData,
3506-
"automatic-removal-csat-survey": {
3507-
enabled: true,
3508-
},
3509-
}}
3499+
enabledFeatureFlags={["AutomaticRemovalCsatSurvey"]}
35103500
/>,
35113501
);
35123502

@@ -3528,12 +3518,7 @@ describe("CSAT survey banner", () => {
35283518
render(
35293519
<ComposedDashboard
35303520
elapsedTimeInDaysSinceInitialScan={91}
3531-
experimentData={{
3532-
...defaultExperimentData,
3533-
"automatic-removal-csat-survey": {
3534-
enabled: true,
3535-
},
3536-
}}
3521+
enabledFeatureFlags={["AutomaticRemovalCsatSurvey"]}
35373522
/>,
35383523
);
35393524

@@ -3555,12 +3540,7 @@ describe("CSAT survey banner", () => {
35553540
render(
35563541
<ComposedDashboard
35573542
elapsedTimeInDaysSinceInitialScan={1}
3558-
experimentData={{
3559-
...defaultExperimentData,
3560-
"automatic-removal-csat-survey": {
3561-
enabled: true,
3562-
},
3563-
}}
3543+
enabledFeatureFlags={["AutomaticRemovalCsatSurvey"]}
35643544
/>,
35653545
);
35663546

@@ -3587,12 +3567,7 @@ describe("CSAT survey banner", () => {
35873567
render(
35883568
<ComposedDashboard
35893569
elapsedTimeInDaysSinceInitialScan={180}
3590-
experimentData={{
3591-
...defaultExperimentData,
3592-
"automatic-removal-csat-survey": {
3593-
enabled: true,
3594-
},
3595-
}}
3570+
enabledFeatureFlags={["AutomaticRemovalCsatSurvey"]}
35963571
/>,
35973572
);
35983573

@@ -3620,12 +3595,7 @@ describe("CSAT survey banner", () => {
36203595
<ComposedDashboard
36213596
activeTab="fixed"
36223597
elapsedTimeInDaysSinceInitialScan={185}
3623-
experimentData={{
3624-
...defaultExperimentData,
3625-
"automatic-removal-csat-survey": {
3626-
enabled: true,
3627-
},
3628-
}}
3598+
enabledFeatureFlags={["AutomaticRemovalCsatSurvey"]}
36293599
/>,
36303600
);
36313601

@@ -3684,7 +3654,10 @@ describe("CSAT survey banner", () => {
36843654
activeTab="fixed"
36853655
elapsedTimeInDaysSinceInitialScan={90}
36863656
hasFirstMonitoringScan
3687-
enabledFeatureFlags={["LatestScanDateCsatSurvey"]}
3657+
enabledFeatureFlags={[
3658+
"LatestScanDateCsatSurvey",
3659+
"AutomaticRemovalCsatSurvey",
3660+
]}
36883661
/>,
36893662
);
36903663

@@ -3703,7 +3676,10 @@ describe("CSAT survey banner", () => {
37033676
activeTab="fixed"
37043677
elapsedTimeInDaysSinceInitialScan={90}
37053678
hasFirstMonitoringScan
3706-
enabledFeatureFlags={["LatestScanDateCsatSurvey"]}
3679+
enabledFeatureFlags={[
3680+
"LatestScanDateCsatSurvey",
3681+
"AutomaticRemovalCsatSurvey",
3682+
]}
37073683
/>,
37083684
);
37093685

@@ -3721,6 +3697,98 @@ describe("CSAT survey banner", () => {
37213697
expect(cookies.get("csat_survey_3-months_dismissed")).toBeDefined();
37223698
expect(cookies.get("last_scan_date_plus-user_dismissed")).toBeDefined();
37233699
});
3700+
3701+
it("displays the petition CSAT survey for users in the control branch", async () => {
3702+
const user = userEvent.setup();
3703+
const ComposedDashboard = composeStory(
3704+
DashboardUsPremiumResolvedScanNoBreaches,
3705+
Meta,
3706+
);
3707+
render(
3708+
<ComposedDashboard
3709+
activeTab="fixed"
3710+
enabledFeatureFlags={["PetitionBannerCsatSurvey"]}
3711+
experimentData={{
3712+
...defaultExperimentData,
3713+
"data-privacy-petition-banner": {
3714+
enabled: false,
3715+
},
3716+
}}
3717+
/>,
3718+
);
3719+
3720+
const petitionCta = screen.queryByRole("link", {
3721+
name: "Sign petition",
3722+
});
3723+
expect(petitionCta).not.toBeInTheDocument();
3724+
3725+
const answerButton = screen.getByRole("button", {
3726+
name: "Neutral",
3727+
});
3728+
await user.click(answerButton);
3729+
const cookies = new Cookies(null, { path: "/" });
3730+
expect(cookies.get("petition_banner_plus-user_dismissed")).toBeDefined();
3731+
});
3732+
3733+
it("does not display the petition CSAT survey for users in the treatment branch before they interacted with the “Data privacy petition banner”", () => {
3734+
const ComposedDashboard = composeStory(
3735+
DashboardUsPremiumResolvedScanNoBreaches,
3736+
Meta,
3737+
);
3738+
render(
3739+
<ComposedDashboard
3740+
activeTab="fixed"
3741+
enabledFeatureFlags={["PetitionBannerCsatSurvey"]}
3742+
experimentData={{
3743+
...defaultExperimentData,
3744+
"data-privacy-petition-banner": {
3745+
enabled: true,
3746+
},
3747+
}}
3748+
/>,
3749+
);
3750+
3751+
const answerButton = screen.queryByRole("button", {
3752+
name: "Neutral",
3753+
});
3754+
expect(answerButton).not.toBeInTheDocument();
3755+
});
3756+
3757+
it("displays the petition CSAT survey for users in the treatment branch after they interacted with the “Data privacy petition banner”", async () => {
3758+
const user = userEvent.setup();
3759+
const ComposedDashboard = composeStory(
3760+
DashboardUsPremiumResolvedScanNoBreaches,
3761+
Meta,
3762+
);
3763+
const ComposedDashboardComponent = () => (
3764+
<ComposedDashboard
3765+
activeTab="fixed"
3766+
enabledFeatureFlags={["PetitionBannerCsatSurvey"]}
3767+
experimentData={{
3768+
...defaultExperimentData,
3769+
"data-privacy-petition-banner": {
3770+
enabled: true,
3771+
},
3772+
}}
3773+
/>
3774+
);
3775+
render(<ComposedDashboardComponent />);
3776+
3777+
const dismissCta = screen.getByRole("button", {
3778+
name: "No, thank you",
3779+
});
3780+
await user.click(dismissCta);
3781+
3782+
// The petition CSAT survey is only shown on the next visit of the dashboard
3783+
// so that the user is not being flashed directly with a second banner after
3784+
// interacting with the petition banner.
3785+
render(<ComposedDashboardComponent />);
3786+
3787+
const answerButton = screen.getByRole("button", {
3788+
name: "Neutral",
3789+
});
3790+
expect(answerButton).toBeInTheDocument();
3791+
});
37243792
});
37253793

37263794
describe("Data privacy petition banner", () => {
@@ -3731,6 +3799,7 @@ describe("Data privacy petition banner", () => {
37313799
);
37323800
render(
37333801
<ComposedDashboard
3802+
enabledFeatureFlags={["PetitionBannerCsatSurvey"]}
37343803
experimentData={{
37353804
...defaultExperimentData,
37363805
"data-privacy-petition-banner": {
@@ -3754,6 +3823,7 @@ describe("Data privacy petition banner", () => {
37543823
render(
37553824
<ComposedDashboard
37563825
activeTab="fixed"
3826+
enabledFeatureFlags={["PetitionBannerCsatSurvey"]}
37573827
experimentData={{
37583828
...defaultExperimentData,
37593829
"data-privacy-petition-banner": {
@@ -3777,6 +3847,7 @@ describe("Data privacy petition banner", () => {
37773847
render(
37783848
<ComposedDashboard
37793849
activeTab="fixed"
3850+
enabledFeatureFlags={["PetitionBannerCsatSurvey"]}
37803851
experimentData={{
37813852
...defaultExperimentData,
37823853
"data-privacy-petition-banner": {
@@ -3799,6 +3870,7 @@ describe("Data privacy petition banner", () => {
37993870
);
38003871
render(
38013872
<ComposedDashboard
3873+
enabledFeatureFlags={["PetitionBannerCsatSurvey"]}
38023874
experimentData={{
38033875
...defaultExperimentData,
38043876
"data-privacy-petition-banner": {
@@ -3818,6 +3890,7 @@ describe("Data privacy petition banner", () => {
38183890
const ComposedDashboard = composeStory(DashboardNonUsNoBreaches, Meta);
38193891
render(
38203892
<ComposedDashboard
3893+
enabledFeatureFlags={["PetitionBannerCsatSurvey"]}
38213894
experimentData={{
38223895
...defaultExperimentData,
38233896
"data-privacy-petition-banner": {
@@ -3852,6 +3925,7 @@ describe("Data privacy petition banner", () => {
38523925
render(
38533926
<ComposedDashboard
38543927
activeTab="fixed"
3928+
enabledFeatureFlags={["PetitionBannerCsatSurvey"]}
38553929
experimentData={{
38563930
...defaultExperimentData,
38573931
"data-privacy-petition-banner": {
@@ -3883,6 +3957,7 @@ describe("Data privacy petition banner", () => {
38833957
render(
38843958
<ComposedDashboard
38853959
activeTab="fixed"
3960+
enabledFeatureFlags={["PetitionBannerCsatSurvey"]}
38863961
experimentData={{
38873962
...defaultExperimentData,
38883963
"data-privacy-petition-banner": {

src/app/(proper_react)/(redesign)/(authenticated)/user/(dashboard)/dashboard/View.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ export const View = (props: Props) => {
454454
props.isEligibleForPremium &&
455455
((activeTab === "fixed" && hasPremium(props.user)) ||
456456
(activeTab === "action-needed" && !hasPremium(props.user))) && (
457-
<PetitionBanner />
457+
<PetitionBanner user={props.user} />
458458
)}
459459
<CsatSurvey
460460
user={props.user}

0 commit comments

Comments
 (0)