Repository: mdn/kuma

Issue:
T - Add opt-in checkbox for marketing email to account creation page. 
**Acceptance Criteria**

- [ ] Add opt-in checkbox for marketing email to account creation page. 
- [ ] Upon acct creation opt-in/out value is stored in our database for the given user

**Design comp**
- see comp [https://app.zenhub.com/workspaces/mdn-dev-5d6ea9fb3fe11605a63cea86/issues/mdn/sprints/313$](https://app.zenhub.com/workspaces/mdn-dev-5d6ea9fb3fe11605a63cea86/issues/mdn/sprints/3134)
T - Add opt-in checkbox for marketing email to the Edit Profile Page. 
**Acceptance Criteria**

- [ ] Add opt-in checkbox for marketing email to the Edit Profile Page
- [ ] Saves user's selection (opt-in/out) to the database
- [ ] Stub out functionality: add user to correct email group in sendinblue (*feedback needed from Kadir)
- [ ] Update 'Publish' button to read 'Save', see comps
- [ ] Update 'Delete Account' to be a button, see comps
- [ ] This functionality should be behind a waffle flag allowing us to turn on once sendinblue is official

**Comps**
[https://app.zenhub.com/workspaces/mdn-dev-5d6ea9fb3fe11605a63cea86/issues/mdn/sprints/3136](https://app.zenhub.com/workspaces/mdn-dev-5d6ea9fb3fe11605a63cea86/issues/mdn/sprints/3136)



Discussion:

I think the wrong issues are linked here, 3136 seems super unrelated 🙃

Also it's imo missing the tasks:
- add/remove user from sendinblue contacts when the subscribe/unsubscribe

isn't that what this is about as well?
right you are, it was in the sprints repo. updated the link above!
what about this?

> Also it's imo missing the tasks:
> 
>     * add/remove user from sendinblue contacts when the subscribe/unsubscribe
> 
> 
> isn't that what this is about as well?


Good point @Gregoor!

@atopal - should we add the sendinblue integration here (or at least stub it out?) - since we are not _officially_ using them yet?
it should be implemented behind a flag, so that we can turn it on the moment the contract is signed.
Heyall, I've made an executive logistical engineering decision: Downgraded this to an estimate of 1, moving all of the sendinblue stuff to #7024

Why? It neatly separates frontend changes from sendinblue synchronization. The latter of which should be reviewed in bulk, to make sure we're not missing any edge cases. And just like the newsletter signup during registration, the one in edit profile can go up without sendinblue being there yet. So imo it makes a lot of sense to treat it separately (and makes my life easier yay)

Resolving patch:
diff --git a/kuma/users/forms.py b/kuma/users/forms.py
--- a/kuma/users/forms.py
+++ b/kuma/users/forms.py
@@ -117,6 +117,7 @@ class UserEditForm(forms.ModelForm):
             }
         ),
     )
+    is_newsletter_subscribed = forms.BooleanField(required=False)
 
     class Meta:
         model = User
@@ -137,6 +138,7 @@ class Meta:
             "facebook_url",
             "discourse_url",
             "username",
+            "is_newsletter_subscribed",
         )
 
     def __init__(self, *args, **kwargs):


Test patch:
diff --git a/kuma/users/tests/test_views.py b/kuma/users/tests/test_views.py
--- a/kuma/users/tests/test_views.py
+++ b/kuma/users/tests/test_views.py
@@ -787,6 +787,7 @@ def _get_current_form_field_values(doc):
         "location",
         "irc_nickname",
         "is_github_url_public",
+        "is_newsletter_subscribed",
     )
     form = dict()
     lookup_pattern = '#{prefix}edit *[name="{prefix}{field}"]'
@@ -1041,6 +1042,30 @@ def test_user_edit_github_is_public(wiki_user, wiki_user_github_account, user_cl
     assert wiki_user.is_github_url_public
 
 
+def test_user_edit_is_newsletter_subscribed(
+    wiki_user, wiki_user_github_account, user_client
+):
+    """A user can set that they want their GitHub to be public."""
+    assert not wiki_user.is_newsletter_subscribed
+    url = reverse("users.user_edit", args=(wiki_user.username,))
+    response = user_client.get(url)
+    assert response.status_code == 200
+    assert_no_cache_header(response)
+    form = _get_current_form_field_values(pq(response.content))
+    assert not form["user-is_newsletter_subscribed"]
+    form["user-is_newsletter_subscribed"] = True
+    # Filter out keys with `None` values
+    form = {k: v for k, v in form.items() if v is not None}
+    response = user_client.post(url, form)
+    assert response.status_code == 302
+    assert_no_cache_header(response)
+    assert response["Location"].endswith(
+        reverse("users.user_detail", args=(wiki_user.username,))
+    )
+    wiki_user.refresh_from_db()
+    assert wiki_user.is_newsletter_subscribed
+
+
 @pytest.mark.parametrize("case", ("DOMAIN", "WIKI_HOST"))
 def test_404_logins(db, client, case):
     """A login link should display within the body on the wiki 404 page."""