Skip to content

Commit

Permalink
Merge pull request #3384 from karlcow/3380/1
Browse files Browse the repository at this point in the history
Fixes #3380 - Makes Wizard Form the default (python)
  • Loading branch information
Mike Taylor authored Jul 15, 2020
2 parents 74dd317 + 5c078a6 commit 9b39a45
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 85 deletions.
30 changes: 15 additions & 15 deletions tests/unit/test_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,22 +100,22 @@ def test_metadata_wrapping(self):

def test_radio_button_label(self):
"""Check that appropriate radio button label is returned."""
test_labels_list = [
('detection_bug', 'Desktop site instead of mobile site'),
('unknown_bug', 'Something else')
tests_labels_lists = [
[('detection_bug', 'i.svg', 'Desktop site instead of mobile site'),
('unknown_bug', 'b.svg', 'Something else')],
[('detection_bug', 'Desktop site instead of mobile site'),
('unknown_bug', 'Something else')],
]

r = form.get_radio_button_label('unknown_bug', test_labels_list)
self.assertEqual(r, 'Something else')

r = form.get_radio_button_label('detection_bug', test_labels_list)
self.assertEqual(r, 'Desktop site instead of mobile site')

r = form.get_radio_button_label(None, test_labels_list)
self.assertEqual(r, 'Unknown')

r = form.get_radio_button_label('failme', test_labels_list)
self.assertEqual(r, 'Unknown')
for test_labels_list in tests_labels_lists:
r = form.get_radio_button_label('unknown_bug', test_labels_list)
self.assertEqual(r, 'Something else')
r = form.get_radio_button_label('detection_bug', test_labels_list)
self.assertEqual(r, 'Desktop site instead of mobile site')
r = form.get_radio_button_label(None, test_labels_list)
self.assertEqual(r, 'Unknown')
r = form.get_radio_button_label('failme', test_labels_list)
self.assertEqual(r, 'Unknown')

def test_get_form(self):
"""Check we return the right form with the appropriate data."""
Expand All @@ -126,7 +126,7 @@ def test_get_form(self):
actual = form.get_form(form_data)
expected_browser = 'Firefox 48.0'
expected_os = 'Mac OS X 10.11'
self.assertIsInstance(actual, form.IssueForm)
self.assertIsInstance(actual, form.FormWizard)
self.assertEqual(actual.browser.data, expected_browser)
self.assertEqual(actual.os.data, expected_os)
self.assertEqual(actual.reported_with.data, 'desktop-reporter')
Expand Down
116 changes: 51 additions & 65 deletions webcompat/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
from flask_wtf.file import FileField
from markupsafe import Markup
from wtforms import HiddenField
from wtforms import Label
from wtforms import RadioField
from wtforms import StringField
from wtforms import TextAreaField
Expand All @@ -38,8 +37,6 @@
from webcompat.helpers import get_details_list
from webcompat.helpers import is_json_object

AUTH_REPORT = 'github-auth-report'
PROXY_REPORT = 'github-proxy-report'
SCHEMES = ('http://', 'https://')
BAD_SCHEMES = ('http:/', 'https:/', 'http:', 'https:')
GITHUB_HELP = '_From [webcompat.com](https://webcompat.com/) with ❤️_'
Expand Down Expand Up @@ -88,14 +85,6 @@
}
]

problem_choices = [
('detection_bug', 'Desktop site instead of mobile site'),
('site_bug', 'Site is not usable'),
('layout_bug', 'Design is broken'),
('video_bug', 'Video or audio doesn\'t play'),
('unknown_bug', 'Something else')
]

problem_choices_wizard = [
('detection_bug', 'svg-problem-mobile-vs-desktop.svg',
'Desktop site instead of mobile site'),
Expand Down Expand Up @@ -176,77 +165,69 @@


class PrefixedRadioField(RadioField):
"""Prefix radio field label with an image."""
"""Prefix radio field label with an image.
This renders the radio elements with a specific html markup.
"""
def __init__(self, *args, **kwargs):
prefixed_choices = kwargs.pop('choices')
template = '<div class={css_class}><img src={src}/></div> {text}'
choices = []

css_class = 'icon-container'
for slug, img, text in prefixed_choices:
filename = 'img/svg/icons/{img}'.format(img=img)
filename = f'img/svg/icons/{img}'
src = url_for('static', filename=filename)
label = Markup(template.format(
src=src, css_class=css_class, text=text)
)
t = f'<div class="icon-container"><img src="{src}"/></div> {text}'
label = Markup(t)
choice = (slug, label)
choices.append(choice)

kwargs['choices'] = choices
super().__init__(*args, **kwargs)


class IssueForm(FlaskForm):
"""Define form fields and validation for our bug reporting form."""

url = StringField(url_label,
[InputRequired(message=url_message)])
browser = StringField('Is this information correct?', [Optional()])
os = StringField('Operating System', [Optional()])
# A dummy field to trap common bots. Users do not see that.
username = StringField('Username',
[Length(max=0, message=username_message)])
# Field for people who want to be contacted, but do not want to login
# regex for GitHub usernames
username_pattern = r"^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$"
# Field definition
class FormWizard(FlaskForm):
"""IssueForm to a multi step wizard form.
Attributes notes:
* contact:
Field for people who want to be contacted,
but do not want to login
github_username_pattern defines regex for GitHub usernames
* image:
We filter allowed type in uploads.py
We don't use the label programatically for this input[type=file],
any changes here need to be updated in form.html.
* username:
A dummy field to trap common bots. Users do not see that.
"""
steps = NEW_ISSUE_STEPS
github_username_pattern = r"^[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38}$"
# Hidden Form Fields
console_logs_url = HiddenField()
description = HiddenField()
details = HiddenField()
extra_labels = HiddenField()
reported_with = HiddenField()
submit_type = HiddenField()
ua_header = HiddenField()
# Visible Form Fields
browser = StringField(
u'Browser',
[Optional()]
)
browser_test = RadioField(browser_test_label, [Optional()],
choices=tested_elsewhere)
contact = StringField(
contact_label,
[Regexp(username_pattern,
[Regexp(github_username_pattern,
flags=re.IGNORECASE,
message=contact_message)])
description = StringField(desc_label,
[InputRequired(message=desc_message)])

steps_reproduce = TextAreaField(textarea_label, [Optional()])
problem_category = RadioField([InputRequired(message=radio_message)],
choices=problem_choices)
browser_test = RadioField(browser_test_label, [Optional()],
choices=tested_elsewhere)
# we filter allowed type in uploads.py
# Note, we don't use the label programtically for this input[type=file],
# any changes here need to be updated in form.html.
image = FileField('Attach a screenshot image',
[Optional(),
FileAllowed(ImageUpload.ALLOWED_FORMATS,
image_message)])
details = HiddenField()
reported_with = HiddenField()
ua_header = HiddenField()
submit_type = HiddenField()
extra_labels = HiddenField()
console_logs_url = HiddenField()


class FormWizard(IssueForm):
"""Re-designed version of IssueForm to a multi step wizard form."""

steps = NEW_ISSUE_STEPS

browser = StringField(u'Browser', [Optional()])
os = StringField('Operating System', [Optional()])
description = HiddenField()

steps_reproduce = TextAreaField(textarea_label, [Optional()])
url = StringField(url_label, [InputRequired(message=url_message)])
# Steps Form Fields
problem_category = PrefixedRadioField(
[InputRequired(message=radio_message)],
choices=problem_choices_wizard
Expand Down Expand Up @@ -275,9 +256,12 @@ class FormWizard(IssueForm):
[InputRequired(message=radio_message)],
choices=browser_choices
)
# Bots Trap
username = StringField('Username',
[Length(max=0, message=username_message)])


def get_form(form_data, form=IssueForm):
def get_form(form_data, form=FormWizard):
"""Return an instance of flask_wtf.FlaskForm.
It receives a dictionary of everything which needs to be fed to the form.
Expand Down Expand Up @@ -334,6 +318,8 @@ def build_details(details):

def get_radio_button_label(field_value, label_list):
"""Return human-readable label for problem choices form value."""
if len(label_list[0]) == 3:
label_list = [(value, text) for value, icon, text in label_list]
for value, text in label_list:
if value == field_value:
return text
Expand All @@ -349,7 +335,7 @@ def get_problem_summary(category):
else:
# Return the usual message in lowercase
# because it is not at the start of the summary.
return get_radio_button_label(category, problem_choices).lower()
return get_radio_button_label(category, problem_choices_wizard).lower()


def wrap_metadata(metadata):
Expand Down Expand Up @@ -524,7 +510,7 @@ def build_formdata(form_object):
'browser': normalize_metadata(form_object.get('browser')),
'os': normalize_metadata(form_object.get('os')),
'problem_type': get_radio_button_label(
form_object.get('problem_category'), problem_choices),
form_object.get('problem_category'), problem_choices_wizard),
'browser_test_type': get_radio_button_label(form_object.get(
'browser_test'), tested_elsewhere),
'description': form_object.get('description'),
Expand Down
1 change: 0 additions & 1 deletion webcompat/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import requests
from ua_parser import user_agent_parser

from webcompat import api
from webcompat import app
from webcompat import github

Expand Down
6 changes: 2 additions & 4 deletions webcompat/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,8 @@
from webcompat.api.endpoints import proxy_issue
from webcompat.db import session_db
from webcompat.db import User
from webcompat.form import AUTH_REPORT
from webcompat.form import get_form
from webcompat.form import FormWizard
from webcompat.form import PROXY_REPORT
from webcompat.form import normalize_url
from webcompat.helpers import ab_active
from webcompat.helpers import ab_current_experiments
Expand Down Expand Up @@ -305,7 +303,7 @@ def create_issue():
msg = app.config['IS_DARKNET_DOMAIN'].format(form['url'])
flash(msg, 'notimeout')
return redirect(url_for('index'))
if form.get('submit_type') == PROXY_REPORT:
if form.get('submit_type') == 'github-proxy-report':
if not app.config['ANONYMOUS_REPORTING_ENABLED']:
abort(400)
# Checking blocked domains
Expand All @@ -319,7 +317,7 @@ def create_issue():
return redirect(
url_for('show_issue', number=json_response.get('number')))
# Authenticated reporting
if form.get('submit_type') == AUTH_REPORT:
if form.get('submit_type') == 'github-auth-report':
if g.user: # If you're already authed, submit the bug.
json_response = report_issue(form)
session['show_thanks'] = True
Expand Down

0 comments on commit 9b39a45

Please sign in to comment.