Skip to content

Commit df78789

Browse files
committed
Add test for recent bug
This test case would result in an invalid state previously: > it should show a call to the manual resolution flow for free users with > existing scans, when the `FreeOnly` flag is enabled
1 parent cb57b47 commit df78789

File tree

1 file changed

+213
-0
lines changed

1 file changed

+213
-0
lines changed
Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
import { jest, it, expect } from "@jest/globals";
6+
import { OnerepScanRow } from "knex/types/tables";
7+
import { render, screen } from "@testing-library/react";
8+
import { DashboardTopBanner, DashboardTopBannerProps } from "./index";
9+
import { TestComponentWrapper } from "../../../../../../../../TestComponentWrapper";
10+
import {
11+
createRandomScanResult,
12+
createUserWithPremiumSubscription,
13+
} from "../../../../../../../../apiMocks/mockData";
14+
import { DashboardSummary } from "../../../../../../../functions/server/dashboard";
15+
16+
const TopBannerWrapper = (props: DashboardTopBannerProps) => {
17+
return (
18+
<TestComponentWrapper>
19+
<DashboardTopBanner {...props} />
20+
</TestComponentWrapper>
21+
);
22+
};
23+
24+
const mockedExposure = {
25+
// shared
26+
emailAddresses: 0,
27+
phoneNumbers: 0,
28+
29+
// data brokers
30+
addresses: 0,
31+
familyMembers: 0,
32+
33+
// data breaches
34+
socialSecurityNumbers: 0,
35+
ipAddresses: 0,
36+
passwords: 0,
37+
creditCardNumbers: 0,
38+
pins: 0,
39+
securityQuestions: 0,
40+
bankAccountNumbers: 0,
41+
};
42+
43+
const mockedBannerData: DashboardSummary = {
44+
dataBreachTotalNum: 10,
45+
dataBreachTotalDataPointsNum: 10,
46+
dataBreachFixedDataPointsNum: 10,
47+
dataBrokerTotalNum: 10,
48+
dataBrokerTotalDataPointsNum: 8,
49+
dataBrokerAutoFixedDataPointsNum: 8,
50+
dataBrokerAutoFixedNum: 10,
51+
dataBrokerInProgressDataPointsNum: 10,
52+
dataBrokerInProgressNum: 10,
53+
dataBrokerManuallyResolvedDataPointsNum: 0,
54+
totalDataPointsNum: 10,
55+
allDataPoints: mockedExposure,
56+
unresolvedDataPoints: mockedExposure,
57+
inProgressDataPoints: mockedExposure,
58+
fixedDataPoints: mockedExposure,
59+
manuallyResolvedDataBrokerDataPoints: mockedExposure,
60+
unresolvedSanitizedDataPoints: [],
61+
fixedSanitizedDataPoints: [],
62+
dataBreachUnresolvedNum: 0,
63+
dataBreachResolvedNum: 0,
64+
dataBrokerManuallyResolvedNum: 0,
65+
dataBrokerRemovalUnderMaintenance: 0,
66+
};
67+
68+
const mockedPlusUser = createUserWithPremiumSubscription();
69+
const mockedFreeUser = {
70+
...mockedPlusUser,
71+
fxa: {
72+
locale: "us",
73+
twoFactorAuthentication: false,
74+
metricsEnabled: false,
75+
avatar: "https://profile.stage.mozaws.net/v1/avatar/e",
76+
avatarDefault: true,
77+
subscriptions: [],
78+
},
79+
};
80+
81+
const mockedFreeStepDeterminationData = {
82+
user: mockedFreeUser,
83+
countryCode: "us",
84+
latestScanData: null,
85+
subscriberBreaches: [],
86+
};
87+
const mockedPlusStepDeterminationData = {
88+
...mockedFreeStepDeterminationData,
89+
user: mockedPlusUser,
90+
};
91+
92+
const mockedScan: OnerepScanRow = {
93+
created_at: new Date(Date.UTC(1998, 2, 31)),
94+
updated_at: new Date(Date.UTC(1998, 2, 31)),
95+
id: 0,
96+
onerep_profile_id: 0,
97+
onerep_scan_id: 0,
98+
onerep_scan_reason: "initial",
99+
onerep_scan_status: "finished",
100+
};
101+
102+
it("renders no text if we got into an invalid state somehow", () => {
103+
// When we get into an invalid state, we log both a warning and an error.
104+
// We should probably stop doing that, but this test was added after the fact.
105+
// Thus, for now, suppress the test failure after logging calls:
106+
jest.spyOn(console, "warn").mockImplementation(() => undefined);
107+
jest.spyOn(console, "error").mockImplementation(() => undefined);
108+
109+
render(
110+
<TopBannerWrapper
111+
bannerData={mockedBannerData}
112+
// hasExposures can't be `false` if either `hasUnresolvedBreaches`
113+
// or `hasUnresolvedBrokers` is `true`; thus, this triggers an invalid state:
114+
hasExposures={false}
115+
hasUnresolvedBreaches={true}
116+
hasUnresolvedBrokers={false}
117+
isEligibleForFreeScan={false}
118+
isEligibleForPremium={false}
119+
isPremiumUser={false}
120+
scanInProgress={false}
121+
stepDeterminationData={{
122+
...mockedFreeStepDeterminationData,
123+
countryCode: "nl",
124+
}}
125+
tabType="action-needed"
126+
onShowFixed={() => {}}
127+
monthlySubscriptionUrl="/arbitrary"
128+
subscriptionBillingAmount={{ monthly: 13.37 }}
129+
totalNumberOfPerformedScans={0}
130+
enabledFeatureFlags={[]}
131+
/>,
132+
);
133+
134+
const summary = screen.getByRole("region", {
135+
name: "Dashboard summary",
136+
});
137+
expect(summary.textContent).toBe("");
138+
});
139+
140+
it("should show a call to the manual resolution flow for free users with existing scans, when the `FreeOnly` flag is enabled", () => {
141+
render(
142+
<TopBannerWrapper
143+
bannerData={mockedBannerData}
144+
hasExposures={true}
145+
hasUnresolvedBreaches={false}
146+
hasUnresolvedBrokers={true}
147+
isEligibleForFreeScan={false}
148+
isEligibleForPremium={false}
149+
isPremiumUser={false}
150+
scanInProgress={false}
151+
stepDeterminationData={{
152+
...mockedFreeStepDeterminationData,
153+
latestScanData: {
154+
scan: mockedScan,
155+
results: [
156+
createRandomScanResult({ manually_resolved: false, status: "new" }),
157+
],
158+
},
159+
}}
160+
tabType="action-needed"
161+
onShowFixed={() => {}}
162+
monthlySubscriptionUrl="/arbitrary"
163+
subscriptionBillingAmount={{ monthly: 13.37 }}
164+
totalNumberOfPerformedScans={1}
165+
enabledFeatureFlags={["FreeOnly"]}
166+
/>,
167+
);
168+
169+
const cta = screen.getByRole("link", {
170+
name: "Let’s keep going",
171+
});
172+
expect(cta.getAttribute("href")).toBe(
173+
"/user/dashboard/fix/data-broker-profiles/manual-remove",
174+
);
175+
});
176+
177+
it("tells Plus users without breaches that there's nothing left to do but to see what's happened", () => {
178+
render(
179+
<TopBannerWrapper
180+
bannerData={mockedBannerData}
181+
hasExposures={true}
182+
hasUnresolvedBreaches={false}
183+
hasUnresolvedBrokers={false}
184+
isEligibleForFreeScan={false}
185+
isEligibleForPremium={false}
186+
isPremiumUser={true}
187+
scanInProgress={false}
188+
stepDeterminationData={{
189+
...mockedPlusStepDeterminationData,
190+
latestScanData: {
191+
scan: mockedScan,
192+
results: [
193+
createRandomScanResult({
194+
manually_resolved: false,
195+
status: "removed",
196+
}),
197+
],
198+
},
199+
}}
200+
tabType="action-needed"
201+
onShowFixed={() => {}}
202+
monthlySubscriptionUrl="/arbitrary"
203+
subscriptionBillingAmount={{ monthly: 13.37 }}
204+
totalNumberOfPerformedScans={1}
205+
enabledFeatureFlags={["FreeOnly"]}
206+
/>,
207+
);
208+
209+
const cta = screen.getByRole("button", {
210+
name: "See what’s fixed",
211+
});
212+
expect(cta).toBeInTheDocument();
213+
});

0 commit comments

Comments
 (0)