Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/dashboard/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,12 @@ def clean(self) -> None:
if errors:
raise ValidationError(errors)

def save(self, *args: Any, **kwargs: Any) -> Person:
if "airport_iata" in self.changed_data:
self.instance.country = ""
self.instance.timezone = ""
return super().save(*args, **kwargs)


class GetInvolvedForm(forms.ModelForm[TrainingProgress]):
"""Trainee-facing form for submitting training progress.
Expand Down
73 changes: 73 additions & 0 deletions src/dashboard/tests/test_autoupdate_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,76 @@ def test_update_profile(self) -> None:
updated_consents_by_term_slug[slug].term_option.pk, # type: ignore
consent_data[f"consents-{slug}"],
)

def _build_profile_data(self) -> dict[str, object]:
"""Build minimal valid POST data for autoupdate_profile."""
term_slugs = [
TermEnum.MAY_CONTACT,
TermEnum.MAY_PUBLISH_NAME,
TermEnum.PUBLIC_PROFILE,
]
terms_by_term_slug = {
term.slug: term for term in Term.objects.filter(slug__in=term_slugs).active().prefetch_active_options()
}
consent_data = {
f"consents-{slug}": terms_by_term_slug[slug].active_options[0].pk # type: ignore[attr-defined]
for slug in term_slugs
}
return {
"personal": "user",
"middle": "",
"family": "User",
"email": "user@example.org",
"gender": Person.UNDISCLOSED,
"airport_iata": "CDG",
"country": "PL",
"timezone": "Europe/Warsaw",
"github": "",
"twitter": "",
"bluesky": "",
"mastodon": "",
"url": "",
"username": "user",
"affiliation": "",
"languages": [],
"domains": [],
"lessons": [],
"consents-person": self.user.pk,
**consent_data,
}

def test_update_profile__airport_change_clears_overrides(self) -> None:
"""When airport changes, country and timezone overrides should be cleared."""
self.user.airport_iata = "CDG"
self.user.country = "PL"
self.user.timezone = "Europe/Warsaw"
self.user.save()

data = self._build_profile_data()
data["airport_iata"] = "LAX"

rv = self.client.post(reverse("autoupdate_profile"), data, follow=True)
self.assertEqual(rv.status_code, 200)
self.assertNotIn("Fix errors below", rv.content.decode("utf-8"))

self.user.refresh_from_db()
self.assertEqual(self.user.country, "")
self.assertEqual(self.user.timezone, "")

def test_update_profile__airport_unchanged_keeps_overrides(self) -> None:
"""When airport stays the same, country and timezone overrides are preserved."""
self.user.airport_iata = "CDG"
self.user.country = "PL"
self.user.timezone = "Europe/Warsaw"
self.user.save()

data = self._build_profile_data()
# airport_iata stays as "CDG" — same as saved

rv = self.client.post(reverse("autoupdate_profile"), data, follow=True)
self.assertEqual(rv.status_code, 200)
self.assertNotIn("Fix errors below", rv.content.decode("utf-8"))

self.user.refresh_from_db()
self.assertEqual(self.user.country, "PL")
self.assertEqual(self.user.timezone, "Europe/Warsaw")
6 changes: 6 additions & 0 deletions src/workshops/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -836,6 +836,12 @@ def clean(self) -> None:
if errors:
raise ValidationError(errors)

def save(self, *args: Any, **kwargs: Any) -> Person:
if "airport_iata" in self.changed_data:
self.instance.country = ""
self.instance.timezone = ""
return super().save(*args, **kwargs)


class PersonCreateForm(PersonForm):
comment = MarkdownxFormField(
Expand Down
27 changes: 27 additions & 0 deletions src/workshops/tests/test_person.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,33 @@ def test_edit_person_email_when_airport_not_set(self) -> None:
form = PersonForm(data, instance=self.spiderman)
self.assertFalse(form.is_valid(), form.errors)

def test_edit_person__airport_change_clears_country_and_timezone(self) -> None:
"""When airport changes, country and timezone overrides should be cleared."""
self.ron.country = "PL"
self.ron.timezone = "Europe/Warsaw"
self.ron.save()

data = PersonForm(instance=self.ron).initial
data["airport_iata"] = "LAX"
form = PersonForm(data, instance=self.ron)
self.assertTrue(form.is_valid(), form.errors)
person = form.save()
self.assertEqual(person.country, "")
self.assertEqual(person.timezone, "")

def test_edit_person__airport_unchanged_keeps_country_and_timezone(self) -> None:
"""When airport stays the same, country and timezone overrides are preserved."""
self.ron.country = "PL"
self.ron.timezone = "Europe/Warsaw"
self.ron.save()

data = PersonForm(instance=self.ron).initial
form = PersonForm(data, instance=self.ron)
self.assertTrue(form.is_valid(), form.errors)
person = form.save()
self.assertEqual(person.country, "PL")
self.assertEqual(person.timezone, "Europe/Warsaw")

def test_edit_person_empty_family_name(self) -> None:
data = {
"family": "", # family name cannot be empty
Expand Down
Loading