Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FYST-792: ID Grocery Credit #4897

Open
wants to merge 53 commits into
base: main
Choose a base branch
from
Open

FYST-792: ID Grocery Credit #4897

wants to merge 53 commits into from

Conversation

mrotondo
Copy link
Contributor

@mrotondo mrotondo commented Oct 22, 2024

Link to pivotal/JIRA issue

Is PM acceptance required? (delete one)

  • Yes - don't merge until JIRA issue is accepted!
    Reminder: merge main into this branch and get green tests before merging to main

What was done?

  • Added the Idaho grocery credit - two new pages, calculator code, and XML + PDF output
  • We used the form & controller code from NameDob and AzSeniorDependents as examples

How to test?

  • We both tested manually and added automated unit tests for most scenarios
  • Risk Assessment
  • We added parameters to our "question-with-follow-up" javascript, so please also test some other places in the app where subsequent questions are revealed based on answers to make sure we didn't break them

Screenshots (for visual changes)

image image image

@mrotondo mrotondo added the wip denotes a work in progress that isn't ready for formal review label Oct 22, 2024
Copy link

Heroku app: https://gyr-review-app-4897-3d3a6ab9ef27.herokuapp.com/
View logs: heroku logs --app gyr-review-app-4897 (optionally add --tail)

app/javascript/lib/honeycrisp.js Fixed Show fixed Hide fixed
app/javascript/lib/honeycrisp.js Fixed Show fixed Hide fixed
Copy link
Contributor

@arinchoi03 arinchoi03 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had a few questions! My head's spinning a bit tbh, might need to pair review tomorrow

config/locales/en.yml Show resolved Hide resolved
app/lib/efile/id/id40_calculator.rb Show resolved Hide resolved
app/views/hub/clients/_client_header.html.erb Outdated Show resolved Hide resolved
app/javascript/lib/honeycrisp.js Outdated Show resolved Hide resolved
@mrotondo mrotondo removed the wip denotes a work in progress that isn't ready for formal review label Oct 29, 2024
mrotondo and others added 15 commits October 30, 2024 12:27
…due to the existing override of honeycrisp's list--bulleted used elsewhere
… xml, and synchronize filers from json by default
…use that in Idaho to allow primary and spouse name and dob to be configured in tests
…ing primary/spouse info if it was provided to the factory
… overrides of default json contents with nil
Copy link
Contributor

@arinchoi03 arinchoi03 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a few more q's to clarify my understanding...this story got complex 😵

updated_dependent_data = dependents_attributes

# set household member "has months" answers to no if household "has months" answer is no
if base_attrs[:household_has_grocery_credit_ineligible_months] == 'no'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is just a non-related question that I also discussed just now with Drew, but why do we use enum instead of boolean for these types of fields?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enums let us track yes/no/unfilled instead of just true/false, which I think is primarily useful when generating output for optional pages, though we don't check the unfilled value of this answer anywhere IIRC. Someone who's been on the team longer than me can give a better answer here :) I don't feel very strongly about it either way, mostly just following convention.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DrewProebstel for more context

also @jenny-heath @embarnard @mpidcock @tahsinaislam if there was more reasoning for this choice (unfilled is similar to nil, no?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I think that the decision to move away from using "unfilled" rather than nil as a default value in the app is well outside the scope of this PR, so discussion on that should probably happen elsewhere for posterity & visibility

end

updated_dependent_data = updated_dependent_data.to_h do |k, v|
credit_count_key = v.key?(:id_months_ineligible_for_grocery_credit)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we call this has_credit_count_key to be more clear

app/models/df_json_wrapper.rb Show resolved Hide resolved
selector_info => { type:, key: }
key_path = key.split
case type
when :date
Copy link
Contributor

@arinchoi03 arinchoi03 Nov 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we also handle setting a boolean value ("true") or a money_amount value (& convert to the two decimal amount)? Just seeing that you handled the date and wondering why that one specifically

Copy link
Contributor Author

@mrotondo mrotondo Nov 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe but am not sure that dates are the only value whose string representation doesn't just already look the way we want, so they were the only one that needed extra formatting. But I was pretty deep into this story by the time I did this and was just trying to finish up, so maybe the others do need to be there! We don't use this for anything but strings & dates yet, in any case.

</div>

<div class="reveal">
<p><a href="#" class="reveal__link"><%= t('.donate_impact_heading') %></a></p>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change to <button class="reveal__button"> after merging in main

</div>

<div class="reveal">
<p><a href="#" class="reveal__link"><%= t('.why_are_you_asking_heading') %></a></p>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change to <button class="reveal__button"> after merging main

@@ -36,6 +36,10 @@ def initialize(json)
@data = JSON.parse(json || "{}")
end

def to_s
@data.to_s
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this added?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. I originally added it because I incorrectly used it on state_file_id_intakes.rb:122 instead of to_json, but now that I look more closely, I introduced a bug when I switched over to calling to_json, as it's now returning a json string of the entire DirectFileJsonData object (i.e. it has {data: {...}}) instead of just its stored json object. So this needs to be changed to a to_json that exposes @data, e.g.

def to_json
  @data.to_json
end

or

delegate :to_json, to: :data

@anisharamnani
Copy link
Contributor

since @mrotondo is out today & we spent time working on this, i am going to give it a go addressing merge conflicts & handle some of the questions. 🤞

@mrotondo
Copy link
Contributor Author

mrotondo commented Nov 4, 2024

Thanks for hopping in @anisharamnani! Just popping my head up to answer a few questions.

# Conflicts:
#	app/javascript/lib/honeycrisp.js
#	app/lib/efile/id/id40_calculator.rb
#	app/lib/efile/line_data.yml
#	app/lib/navigation/state_file_id_question_navigation.rb
#	app/lib/pdf_filler/id40_pdf.rb
#	app/lib/submission_builder/ty2024/states/id/documents/id40.rb
#	app/models/state_file_base_intake.rb
#	app/models/state_file_id_intake.rb
#	config/locales/en.yml
#	config/locales/es.yml
#	db/schema.rb
#	spec/factories/state_file_id_intakes.rb
#	spec/features/state_file/complete_intake_spec.rb
#	spec/lib/efile/id/id40_calculator_spec.rb
#	spec/lib/submission_builder/ty2024/states/id/documents/id40_spec.rb
#	spec/models/efile_error_spec.rb
#	spec/models/state_file_id_intake_spec.rb
app/javascript/lib/honeycrisp.js Fixed Show fixed Hide fixed
app/javascript/lib/honeycrisp.js Fixed Show fixed Hide fixed
@anisharamnani
Copy link
Contributor

hello @mrotondo! this is just a note for when you return, @mpidcock and i were able to make a merge in main and resolve the merge conflicts. 🎉

we've found that this issue you mentioned in slack is still occurring where if you select yes, then select no, the calculations still appear on the following page.

something may have changed with the merge conflicts to create this error? i am not sure, but we felt like we got as far as we could go with it.

$(this).find('input').each(function (index, input) {
if ($(this).attr('data-follow-up') != null) {
if ($(this).is(':checked')) {
$($(this).attr('data-follow-up')).find('input, select').attr('disabled', false);

Check warning

Code scanning / CodeQL

DOM text reinterpreted as HTML Medium

DOM text
is reinterpreted as HTML without escaping meta-characters.

Copilot Autofix AI 17 minutes ago

To fix the problem, we need to ensure that the value extracted from the data-follow-up attribute is treated as a plain text string and not as HTML. This can be achieved by using a method that safely escapes any HTML meta-characters in the attribute value before using it in a jQuery selector.

The best way to fix this issue without changing existing functionality is to use the $.escapeSelector method provided by jQuery. This method escapes any characters that have special meaning in a CSS selector, thus preventing the possibility of XSS.

Suggested changeset 1
app/javascript/lib/honeycrisp.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/app/javascript/lib/honeycrisp.js b/app/javascript/lib/honeycrisp.js
--- a/app/javascript/lib/honeycrisp.js
+++ b/app/javascript/lib/honeycrisp.js
@@ -107,7 +107,7 @@
                         if ($(this).is(':checked')) {
-                            $($(this).attr('data-follow-up')).find('input, select').attr('disabled', false);
-                            $($(this).attr('data-follow-up')).show();
+                            $($.escapeSelector($(this).attr('data-follow-up'))).find('input, select').attr('disabled', false);
+                            $($.escapeSelector($(this).attr('data-follow-up'))).show();
                         } else {
-                            $($(this).attr('data-follow-up')).find('input, select').attr('disabled', true);
-                            $($(this).attr('data-follow-up')).hide();
+                            $($.escapeSelector($(this).attr('data-follow-up'))).find('input, select').attr('disabled', true);
+                            $($.escapeSelector($(this).attr('data-follow-up'))).hide();
                         }
EOF
@@ -107,7 +107,7 @@
if ($(this).is(':checked')) {
$($(this).attr('data-follow-up')).find('input, select').attr('disabled', false);
$($(this).attr('data-follow-up')).show();
$($.escapeSelector($(this).attr('data-follow-up'))).find('input, select').attr('disabled', false);
$($.escapeSelector($(this).attr('data-follow-up'))).show();
} else {
$($(this).attr('data-follow-up')).find('input, select').attr('disabled', true);
$($(this).attr('data-follow-up')).hide();
$($.escapeSelector($(this).attr('data-follow-up'))).find('input, select').attr('disabled', true);
$($.escapeSelector($(this).attr('data-follow-up'))).hide();
}
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
if ($(this).attr('data-follow-up') != null) {
if ($(this).is(':checked')) {
$($(this).attr('data-follow-up')).find('input, select').attr('disabled', false);
$($(this).attr('data-follow-up')).show();

Check warning

Code scanning / CodeQL

DOM text reinterpreted as HTML Medium

DOM text
is reinterpreted as HTML without escaping meta-characters.

Copilot Autofix AI 17 minutes ago

To fix the problem, we need to ensure that the value of the data-follow-up attribute is safely used as a selector without the risk of executing arbitrary HTML or JavaScript. One way to achieve this is by using the $.find method instead of $, which interprets the value strictly as a CSS selector and not as HTML.

  • Replace the usage of $($(this).attr('data-follow-up')) with $(self).find($(this).attr('data-follow-up')) to ensure that the value is treated as a CSS selector within the context of the current element.
  • This change should be made on lines 109, 111, 132, and 133.
Suggested changeset 1
app/javascript/lib/honeycrisp.js

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/app/javascript/lib/honeycrisp.js b/app/javascript/lib/honeycrisp.js
--- a/app/javascript/lib/honeycrisp.js
+++ b/app/javascript/lib/honeycrisp.js
@@ -107,7 +107,7 @@
                         if ($(this).is(':checked')) {
-                            $($(this).attr('data-follow-up')).find('input, select').attr('disabled', false);
-                            $($(this).attr('data-follow-up')).show();
+                            $(self).find($(this).attr('data-follow-up')).find('input, select').attr('disabled', false);
+                            $(self).find($(this).attr('data-follow-up')).show();
                         } else {
-                            $($(this).attr('data-follow-up')).find('input, select').attr('disabled', true);
-                            $($(this).attr('data-follow-up')).hide();
+                            $(self).find($(this).attr('data-follow-up')).find('input, select').attr('disabled', true);
+                            $(self).find($(this).attr('data-follow-up')).hide();
                         }
@@ -131,4 +131,4 @@
                     if (/^[a-zA-Z0-9_\-#\.]+$/.test(followUpSelector)) {
-                        $(followUpSelector).show();
-                        $(followUpSelector).find('input, select').attr('disabled', false);
+                        $container.find(followUpSelector).show();
+                        $container.find(followUpSelector).find('input, select').attr('disabled', false);
                     }
EOF
@@ -107,7 +107,7 @@
if ($(this).is(':checked')) {
$($(this).attr('data-follow-up')).find('input, select').attr('disabled', false);
$($(this).attr('data-follow-up')).show();
$(self).find($(this).attr('data-follow-up')).find('input, select').attr('disabled', false);
$(self).find($(this).attr('data-follow-up')).show();
} else {
$($(this).attr('data-follow-up')).find('input, select').attr('disabled', true);
$($(this).attr('data-follow-up')).hide();
$(self).find($(this).attr('data-follow-up')).find('input, select').attr('disabled', true);
$(self).find($(this).attr('data-follow-up')).hide();
}
@@ -131,4 +131,4 @@
if (/^[a-zA-Z0-9_\-#\.]+$/.test(followUpSelector)) {
$(followUpSelector).show();
$(followUpSelector).find('input, select').attr('disabled', false);
$container.find(followUpSelector).show();
$container.find(followUpSelector).find('input, select').attr('disabled', false);
}
Copilot is powered by AI and may make mistakes. Always verify output.
Positive Feedback
Negative Feedback

Provide additional feedback

Please help us improve GitHub Copilot by sharing more details about this comment.

Please select one or more of the options
app/javascript/lib/honeycrisp.js Dismissed Show dismissed Hide dismissed
app/javascript/lib/honeycrisp.js Dismissed Show dismissed Hide dismissed
…erify that we fixed the nested followups/honeycrisp update bug
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants