Skip to content

Commit 32df95a

Browse files
authored
Enable state-level enhanced CPS runs (#2226)
* feat: Update DatasetSelector, RegionSelector, and PolicyRightSidebar to enable dataset query param * fix: Remove testing code * feat: Ensure that sim reruns when dataset changes * fix: Re-add metadata filter for enhanced_us to PolicyRightSidebar * fix: Display text on bottom bar based on dataset * feat: Update Reproduce in Python for datasets * feat: Update cliff impact display to use dataset * feat: Integrate dataset into user policy display * fix: Fix failing tests * chore: Lint
1 parent 59e4c74 commit 32df95a

File tree

11 files changed

+137
-92
lines changed

11 files changed

+137
-92
lines changed

src/__tests__/data/reformDefinitionCode.test.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ describe("Test getReproducibilityCodeBlock", () => {
2727
reformPolicyUS,
2828
"us",
2929
2024,
30+
null,
3031
householdUS,
3132
);
3233

@@ -245,6 +246,19 @@ describe("Test getImplementationCode", () => {
245246
expect(output).toBeInstanceOf(Array);
246247
expect(output).toContain("baseline = Microsimulation(reform=baseline)");
247248
});
249+
test("If dataset provided, return lines with dataset", () => {
250+
const output = getImplementationCode(
251+
"policy",
252+
"us",
253+
2024,
254+
baselinePolicyUS,
255+
"enhanced_cps",
256+
);
257+
expect(output).toBeInstanceOf(Array);
258+
expect(output).toContain(
259+
"baseline = Microsimulation(dataset='enhanced_cps_2024')",
260+
);
261+
});
248262
});
249263

250264
describe("Test sanitizeStringToPython", () => {

src/__tests__/pages/policy/PolicyRightSidebar.test.js

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -175,32 +175,6 @@ describe("Enhanced CPS selector", () => {
175175
"ant-switch-disabled",
176176
);
177177
});
178-
test("Should not be enabled when region is a state", async () => {
179-
const testSearchParams = {
180-
focus: "gov",
181-
region: "ar",
182-
};
183-
184-
useSearchParams.mockImplementation(() => {
185-
return [new URLSearchParams(testSearchParams), jest.fn()];
186-
});
187-
188-
// Declare props
189-
const props = {
190-
metadata: {
191-
...metadataUS,
192-
countryId: "us",
193-
},
194-
policy: standardPolicyUS,
195-
defaultOpen: true,
196-
};
197-
198-
const { getByTestId } = render(<PolicyRightSidebar {...props} />);
199-
200-
expect(getByTestId("enhanced_cps_switch").classList).toContain(
201-
"ant-switch-disabled",
202-
);
203-
});
204178
test("Should change region when selected", () => {
205179
const testSearchParams = {
206180
focus: "gov",
@@ -209,7 +183,8 @@ describe("Enhanced CPS selector", () => {
209183

210184
const expectedSearchParams = {
211185
focus: "gov",
212-
region: "enhanced_us",
186+
region: "us",
187+
dataset: "enhanced_cps",
213188
};
214189

215190
const mockSetSearchParams = jest.fn();

src/data/countries.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,12 @@ export const STATUS_TEXT_COLORS = {
5353
Pending: colors.BLACK,
5454
};
5555

56-
// Map region entries to default datasets;
57-
// at the moment, this only applies to the
58-
// "enhanced_us" region selection
56+
// Map dataset keywords to their equivalents
57+
// in the actual US package; at the moment,
58+
// this only applies to the "enhanced_cps"
59+
// dataset selection
5960
export const DEFAULT_DATASETS = {
60-
enhanced_us: "enhanced_cps_2024",
61+
enhanced_cps: "enhanced_cps_2024",
6162
};
6263

6364
const DEFAULT_US_HOUSEHOLD = {

src/data/reformDefinitionCode.js

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export function getReproducibilityCodeBlock(
99
policy,
1010
region,
1111
year,
12+
dataset = null,
1213
householdInput = null,
1314
earningVariation = null,
1415
) {
@@ -27,7 +28,7 @@ export function getReproducibilityCodeBlock(
2728
householdInput,
2829
earningVariation,
2930
),
30-
...getImplementationCode(type, region, year, policy),
31+
...getImplementationCode(type, region, year, policy, dataset),
3132
];
3233
}
3334

@@ -156,37 +157,51 @@ export function getSituationCode(
156157
return lines;
157158
}
158159

159-
export function getImplementationCode(type, region, timePeriod, policy) {
160+
export function getImplementationCode(
161+
type,
162+
region,
163+
timePeriod,
164+
policy,
165+
dataset,
166+
) {
160167
if (type !== "policy") {
161168
return [];
162169
}
163170

164171
const hasBaseline = Object.keys(policy?.baseline?.data).length > 0;
165172
const hasReform = Object.keys(policy?.reform?.data).length > 0;
166173

167-
// Check if the region has a dataset specified
168-
const hasDatasetSpecified = Object.keys(DEFAULT_DATASETS).includes(region);
169-
const dataset = hasDatasetSpecified ? DEFAULT_DATASETS[region] : "";
174+
// Check if the region has a dataset specified; enhanced_us is legacy implemntation
175+
// whereby enhanced_us region correlated with enhanced_cps dataset
176+
const hasDatasetSpecified =
177+
Object.keys(DEFAULT_DATASETS).includes(dataset) || region === "enhanced_us";
178+
179+
let formattedDataset = null;
180+
if (region === "enhanced_us") {
181+
formattedDataset = "enhanced_cps_2024";
182+
} else if (hasDatasetSpecified) {
183+
formattedDataset = DEFAULT_DATASETS[dataset];
184+
}
170185

171186
return [
172187
"",
173188
"",
174189
`baseline = Microsimulation(${
175190
hasDatasetSpecified && hasBaseline
176-
? `reform=baseline, dataset='${dataset}'`
191+
? `reform=baseline, dataset='${formattedDataset}'`
177192
: hasBaseline
178193
? `reform=baseline`
179194
: hasDatasetSpecified
180-
? `dataset='${dataset}'`
195+
? `dataset='${formattedDataset}'`
181196
: ""
182197
})`,
183198
`reformed = Microsimulation(${
184199
hasDatasetSpecified && hasReform
185-
? `reform=reform, dataset='${dataset}'`
200+
? `reform=reform, dataset='${formattedDataset}'`
186201
: hasReform
187202
? `reform=reform`
188203
: hasDatasetSpecified
189-
? `dataset='${dataset}'`
204+
? `dataset='${formattedDataset}'`
190205
: ""
191206
})`,
192207
`baseline_income = baseline.calculate("household_net_income", period=${timePeriod || defaultYear})`,

src/pages/UserProfilePage.jsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -443,11 +443,17 @@ function UserProfileSection(props) {
443443
function PolicySimulationCard(props) {
444444
const { metadata, userPolicy, keyValue } = props;
445445

446+
console.log(userPolicy);
447+
446448
const CURRENT_API_VERSION = metadata?.version;
447449
const geography =
448450
metadata.economy_options.region.filter(
449451
(region) => region.name === userPolicy.geography,
450452
)[0]?.label || "Unknown";
453+
const datasetName =
454+
metadata.economy_options.datasets.filter(
455+
(dataset) => dataset.name === userPolicy.dataset,
456+
)[0]?.label || "Unknown";
451457

452458
const apiVersion = userPolicy.api_version;
453459
const dateAdded = userPolicy.added_date;
@@ -480,7 +486,12 @@ function PolicySimulationCard(props) {
480486
return (
481487
<Link
482488
key={keyValue}
483-
to={`/${userPolicy.country_id}/policy?focus=policyOutput.policyBreakdown&reform=${userPolicy.reform_id}&baseline=${userPolicy.baseline_id}&timePeriod=${userPolicy.year}&region=${userPolicy.geography}`}
489+
to={
490+
`/${userPolicy.country_id}/policy?focus=policyOutput.policyBreakdown` +
491+
`&reform=${userPolicy.reform_id}&baseline=${userPolicy.baseline_id}` +
492+
`&timePeriod=${userPolicy.year}&region=${userPolicy.geography}` +
493+
`${userPolicy.dataset ? `&dataset=${userPolicy.dataset}` : ""}`
494+
}
484495
style={{ height: "100%" }}
485496
>
486497
<Card
@@ -516,7 +527,12 @@ function PolicySimulationCard(props) {
516527
Simulated in{" "}
517528
<span style={{ fontWeight: 500 }}>{userPolicy.year}</span> over{" "}
518529
<span style={{ fontWeight: 500 }}>{geography}</span> against{" "}
519-
<span style={{ fontWeight: 500 }}>{userPolicy.baseline_label}</span>.
530+
<span style={{ fontWeight: 500 }}>{userPolicy.baseline_label}</span>
531+
{userPolicy.dataset ? (
532+
<span style={{ fontWeight: 500 }}> ({datasetName})</span>
533+
) : (
534+
"."
535+
)}
520536
</p>
521537
<p>
522538
<span style={{ fontWeight: 500 }}>

src/pages/household/output/HouseholdReproducibility.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export default function HouseholdReproducibility(props) {
1212
const [earningVariation, setEarningVariation] = useState(false);
1313
const [searchParams] = useSearchParams();
1414
const region = searchParams.get("region");
15+
const dataset = searchParams.get("dataset");
1516
const mobile = useMobile();
1617

1718
let lines = getReproducibilityCodeBlock(
@@ -20,6 +21,7 @@ export default function HouseholdReproducibility(props) {
2021
policy,
2122
region,
2223
year,
24+
dataset,
2325
householdInput,
2426
earningVariation,
2527
);

src/pages/policy/PolicyRightSidebar.jsx

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,9 @@ function RegionSelector(props) {
3434
return { value: region.name, label: region.label };
3535
});
3636

37-
// This is a temporary solution that will need to be superseded by
38-
// an improved back end design; removing this value allows
39-
// DatasetSelector to handle choosing between enhanced CPS data and
40-
// standard US data
37+
// The below allows backward compatibility with a past design where enhanced_cps
38+
// was also a region value
4139
options = options.filter((option) => option.value !== "enhanced_us");
42-
43-
// These lines are also a temporary solution; if user accesses the component
44-
// with the enhanced_us region via URL, the component should instead display
45-
// the US
4640
let inputRegion = searchParams.get("region");
4741
if (inputRegion === "enhanced_us") {
4842
inputRegion = "us";
@@ -415,62 +409,65 @@ function FullLiteToggle() {
415409
}
416410

417411
/**
418-
* A (hopefully temporary) component meant to abstract away the fact
419-
* that the US enhanced CPS data is defined as a region within the US
420-
* country package; this displays the enhanced CPS as a dataset on the
421-
* right-hand policy panel
412+
* This displays the enhanced CPS as a dataset on the right-hand policy panel
422413
* @param {Object} props
423-
* @param {String} presentRegion The region, taken from the searchParams
414+
* @param {String} presentDataset The dataset, taken from the searchParams
424415
* @param {Number|String} timePeriod The year the simulation should run over
425416
* @returns {import("react").ReactElement}
426417
*/
427418
function DatasetSelector(props) {
428-
const { presentRegion, timePeriod } = props;
419+
const { presentDataset, timePeriod } = props;
420+
const [isChecked, setIsChecked] = useState(confirmIsChecked(presentDataset));
429421
const [searchParams, setSearchParams] = useSearchParams();
430422
const displayCategory = useDisplayCategory();
431423

432-
// Determine whether slider should be enabled or disabled
433-
function shouldEnableSlider(presentRegion, timePeriod) {
434-
// Define the regions the slider should be enabled
435-
const showRegions = ["enhanced_us", "us", null];
424+
function confirmIsChecked(presentDataset) {
425+
// Define presentDataset value that activates check
426+
const checkValue = "enhanced_cps";
427+
if (presentDataset === checkValue) {
428+
return true;
429+
}
430+
return false;
431+
}
436432

437-
// Define the times the slider should NOT be enabled
438-
const dontShowTimes = ["2021"];
433+
// Determine whether slider should be enabled or disabled
434+
function shouldEnableSlider(timePeriod) {
435+
// Define earliest year slider should be shown for
436+
const sliderStartYear = 2024;
439437

440438
// Return whether or not slider should be enabled
441-
if (
442-
showRegions.includes(presentRegion) &&
443-
!dontShowTimes.includes(String(timePeriod))
444-
) {
439+
// Null timePeriod reflects no URL param setting yet -
440+
// this is actually default behavior
441+
if (!timePeriod || timePeriod >= sliderStartYear) {
445442
return true;
446443
}
447444

448445
return false;
449446
}
450447

451-
/**
452-
* Switch change handler
453-
* @param {Boolean} isChecked Whether or not the switch is "checked";
454-
* note that the event is not passed to the handler by default
455-
* @returns {undefined|null} Returns null as a safety check in cases where
456-
* switch shouldn't be active in the first place
457-
*/
458-
function handleChange(isChecked) {
459-
// Define our desired states; item 0 corresponds to
460-
// "true" and 1 to "false", since bools can't be used as keys
461-
const outputStates = ["enhanced_us", "us"];
462-
448+
function handleChange() {
463449
// First, safety check - if the button isn't even
464450
// supposed to be shown, do nothing
465-
if (!shouldEnableSlider(presentRegion, timePeriod)) {
451+
if (!shouldEnableSlider(timePeriod)) {
466452
return;
467453
}
468454

469455
// Duplicate the existing search params
470456
let newSearch = copySearchParams(searchParams);
471457

472458
// Set params accordingly
473-
newSearch.set("region", isChecked ? outputStates[0] : outputStates[1]);
459+
if (isChecked) {
460+
newSearch.delete("dataset");
461+
// Allows for backwards compatibility with a past design
462+
// where enhanced_cps was also a region value
463+
if (searchParams.get("region") === "enhanced_us") {
464+
newSearch.set("region", "us");
465+
}
466+
setIsChecked(false);
467+
} else {
468+
newSearch.set("dataset", "enhanced_cps");
469+
setIsChecked(true);
470+
}
474471
setSearchParams(newSearch);
475472
}
476473

@@ -488,17 +485,15 @@ function DatasetSelector(props) {
488485
data-testid="enhanced_cps_switch"
489486
size={displayCategory !== "mobile" && "small"}
490487
onChange={handleChange}
491-
disabled={!shouldEnableSlider(presentRegion, timePeriod)}
492-
checked={presentRegion === "enhanced_us" ? true : false}
488+
disabled={!shouldEnableSlider(timePeriod)}
489+
checked={presentDataset === "enhanced_cps" ? true : false}
493490
/>
494491
<p
495492
style={{
496493
margin: 0,
497494
fontSize: displayCategory !== "mobile" && "0.95em",
498-
color:
499-
!shouldEnableSlider(presentRegion, timePeriod) && "rgba(0,0,0,0.5)",
500-
cursor:
501-
!shouldEnableSlider(presentRegion, timePeriod) && "not-allowed",
495+
color: !shouldEnableSlider(timePeriod) && "rgba(0,0,0,0.5)",
496+
cursor: !shouldEnableSlider(timePeriod) && "not-allowed",
502497
}}
503498
>
504499
Use Enhanced CPS (beta)
@@ -804,6 +799,14 @@ export default function PolicyRightSidebar(props) {
804799
const focus = searchParams.get("focus") || "";
805800
const stateAbbreviation = focus.split(".")[2];
806801
const hasHousehold = searchParams.get("household") !== null;
802+
803+
let dataset = searchParams.get("dataset");
804+
// This allows backward compatibility with a past
805+
// design where enhanced_cps was also a region value
806+
if (region === "enhanced_us" && !dataset) {
807+
dataset = "enhanced_cps";
808+
}
809+
807810
const options = metadata.economy_options.region.map((stateAbbreviation) => {
808811
return { value: stateAbbreviation.name, label: stateAbbreviation.label };
809812
});
@@ -1100,7 +1103,7 @@ export default function PolicyRightSidebar(props) {
11001103
</div>
11011104
{metadata.countryId === "us" && (
11021105
<DatasetSelector
1103-
presentRegion={region}
1106+
presentDataset={dataset}
11041107
timePeriod={timePeriod}
11051108
/>
11061109
)}

0 commit comments

Comments
 (0)