Web Development
- Expected duration
- 8–10 hours
- Deadline
- 2300 on Lesson 28
- Points
- 75 points
- Submission
- Canvas
Learning Objectives
- Create an eXtensible Markup Language (XML) document that is well-formed and valid
- Create a website that uses HTML and Cascading Style Sheets (CSS)
- Validate user input using client-side scripting (i.e., JavaScript)
- Analyze XPath expressions to identify and to resolve failures in automated tests for a website
Help Policy
- Authorized Resources
- Any, except posted solutions and working together with classmates.
- Notes
- Never copy another person’s work and submit it as your own.
-
Do not jointly work on this programming exercise (PEX), but you may ask classmates syntax questions. There are no restrictions regarding discussion of the XPath expressions used in automated tests, including how to interpret these expressions or how to reproduce the test cases manually.
-
You must document all help received from all sources, including the instructor and instructor-provided course materials (including your textbook), except for the following:
- Resources related to HTML, CSS, or JavaScript syntax unless received from a classmate or an AI system (e.g., ChatGPT)
Instructions
Use the provided link (distributed separately) to access the assignment in GitHub Classroom.
This assignment has two parts. The first provides practice with the eXtensible Markup Language (XML). The second covers client-side web technologies, specifically the Hypertext Markup Language (HTML), Cascading Style Sheets (CSS), and JavaScript. Each part is described in turn.
XML
All these files will reside in the src/xml
directory of the Git repository.
- Create an XML file,
schedule.xml
, to store your semester’s academic schedule. The root element of this XML document should beschedule
. - Include a personal information element,
personal
, with the following elements:name
,squadron
, andyear
. -
Detail your schedule in a
classes
element, which comprises one or moreclass
elements. Eachclass
element must include the following child elements:name
- Name of the course
period
- M1, M2, …, T7
score
- Current grade in the course
In addition, each
class
element must have anid
attribute with the course number. For example, theid
for this course is “Comp Sci 364” and the content of thename
element should be “Databases and Applications”.
An XML Schema Definition (XSD) is included in the repository
(src/xml/schedule.xsd
). Your XML document must validate against this XSD for
complete credit for this portion of the assignment. (Your XML document will be
validated automatically when you push changes to GitHub as part of the
automated tests.)
HTML, CSS, and JavaScript
All these files will reside in the src/web
directory of the Git repository.
This assignment is designed for you to learn and practice how to create web pages with HTML to include submitting data via forms and presenting data via tables, use CSS to control and standardize the presentation of the website, and use JavaScript to validate form data prior to submission.
Requirements
The Cadet Service Learning (CSL) office needs to gather information for its database of volunteers. They would like you to develop an initial website that provides information about the CSL program, lists some of the partner service organizations, and provides a form to collect information about volunteers.
The specific (enumerated) requirements for this project are as follows:
- The website shall provide separate pages to describe the CSL program
(
index.html
), list the partner service organizations (partners.html
), and gather information from volunteers (volunteer.html
).-
The description of the CSL program shall include the provided picture (
csl-logo.jpg
) to add interest to the description. The description shall comprise the following text at a minimum:The Cadet Service Learning program is designed to foster and facilitate service learning activities for cadets at the United States Air Force Academy.
-
The listing of partner service organizations shall include a table with the name, location, and phone number for each of the following organizations:
Name Location Phone Habitat for Humanity 2802 N. Prospect St., Colorado Springs, CO 80907 (719) 475-7800 Salvation Army Soup Kitchen 908 Yuma St., Colorado Springs, CO 80909 (719) 636-3891 Big Brothers Big Sisters of Colorado 111 S. Tejon St., Suite 302, Colorado Springs, CO 80903 (719) 633-2443 Keep Colorado Springs Beautiful Inc. 20 E. Rio Grande St., Colorado Springs, CO 80903 (719) 577-9111 You may include additional organizations, but these must be listed.
- The information gathered for volunteers shall be the first name, last
name, email, age, gender, and whether they have access to a car.
- The gender input shall be radio buttons with (at least) the values of “male” and “female”.
- The carAccess input shall be a checkbox.
- The gathered information for volunteers shall be validated against the
following criteria with invalid data flagged and the user forced to
correct it for successful submission.
- First and last names shall include only letters, spaces, and hyphens and each will be no more than 50 characters.
- Email addresses shall include only letters, digits, hyphens, underscores, periods, and one (and only one) at sign (“@”) and no more than 50 characters.
- Age shall be numeric and in the range of 17 to 29 (inclusive).
HTML 5’s form validation isn’t directly supported by the Selenium framework, which may cause the automated tests to fail. If using HTML 5’s built-in form validation, include the following attribute on your
form
element so that the automated tests trigger the validation:onsubmit="return this.checkValidity()"
.The
maxlength
attribute can be bypassed by the automated tests because constraint validation is only applied when the value is changed by the user. An alternative is including a quantifier on thepattern
attribute to ensure that the number of characters does not exceed the desired maximum (or minimum). - Validated information for volunteers shall be passed to the provided
demo.php
page.
-
- All pages in the website shall have a consistent layout and structure to
include on each page:
- The site title, “Cadet Service Learning Program”
- A page title—“CSL Introduction,” “CSL Service Partners,” and “CSL Volunteer Form” for each respective page
- Direct navigation to all other pages
- Consistent background color, font, and font color
- Two distinct presentation color schemes shall be provided. Include the
provided JavaScript file (
script.js
) so a “toggle button” will appear in the lower right corner of the screen to display the current page in the alternate style. Be sure to include the “defer” attribute so that the script does not execute until after the HTML document has been parsed. - The website will follow the design quality guidelines specified in the HTML and CSS lesson.
- Add additional feature(s) to your website based upon research on W3Schools or seeing how other websites implement cool features (use “View Source” to see the implementation of a page). These features could include cool graphics, interactive features implemented via JavaScript, embedded video, background audio, …. (Note: This is not a “great requirement” as it is very subjective, but it is serving a higher purpose).
Be sure to use the correct input type for gender and car access. While different types may provide comparable functionality, they will not pass the automated tests.
To better understand the requirements for this project, the following use case is provided. It describes a usage scenario for the CSL website to provide a better understanding of “what” is needed.
Cadet Service Learning (CSL) Web Access
- Summary
- USAFA cadets access the CSL website to learn about the CSL program, determine who the service partners are, and submit their information.
- Preconditions
- Cadets either know the CSL website URL or are provided a link.
- Cadets know their personal information.
- Trigger
- Cadet opens the CSL website in a browser.
- Actors
- Cadet who accesses the CSL website and
demo.php
that responds to submitted cadet information- Scenario
- Cadet accesses the CSL website via a browser.
- Cadet is immediately able to read about the CSL program.
- Cadet navigates to separate page listing service partners.
- Cadet accesses the form for providing the requested information.
- Cadet enters and submits information that is validated with any errors or omissions highlighted.
- Cadet corrects errors and omissions and resubmits.
- Alternatives
- Cadets can move directly (via one click) between the introduction page, service partner page, and information form page.
- Success Condition(s):
- Cadet provides validated information that is echoed back to them.
- Failure Condition(s):
- Cadet is not able to retrieve a copy of their information after form submission.
- Exceptions
- Cadet information echoed from
demo.php
will not be within the same layout and navigation structure used by the rest of the site.
Design
The design of the Cadet Service Learning website will be provided as structural design, user interface design, external interface design, and component logic design.
Structural Design
The CSL website consists of three web pages that share a common layout,
navigation structure, and presentation format. The three pages are Introduction
(index.html
), Service Partners (partners.html
), and Volunteer Information
Form (volunteer.html
). They are organized in a linear structure. The
Volunteer Information Form page has an external interface to the provided PHP
file (demo.php
) that will echo back the provided information. Details of this
interface are provided later in the design.
User Interface Design
The layout of the pages needs to be consistent and follow proper design quality guidelines. Normally, we would show this layout in the design document. However, for this assignment, we want to give you freedom to specify your own design so we just show a notional layout and leave it to you to customize and tailor.
+--------------------------------------------------------+
| Cadet Service Learning Program | <- header, with site
+------------------+------------------+------------------+ title
| CSL Intro | Service Partners | Volunteer Info | <- navigation bar
+------------------+------------------+------------------+
| Page Title | <- title of current
| | page
| Page Content |
| |
+--------------------------------------------------------+
The presentation design is to be based upon a single, common Cascading Style
Sheet (CSS) that specifies the background colors, font styles, font colors,
font sizes, and other characteristics (as desired) for each type of region
(site title, page title, navigation bar, and content area) on the website.
There will be two CSS files, each of which provides a significantly different
look to the site. These files should be named csl.css
and csl-alt.css
for
the primary and alternative style sheets, respectively. By including the
provided JavaScript file (script.js
), a “toggle button” will be provided in
the lower right corner of the screen to display the current page in the
alternate style.
The service partner listings will be implemented with an HTML table with distinct headings (i.e., different from that for the entries).
External Interface Design
The external interface between the volunteer information form and demo.php
is
provided via a HTTP POST method triggered on the HTML form submit action. The
parameters passed with this post are to be named as follows:
- firstName
- lastName
- emailAddress
- age
- gender
- carAccess
The values provided by the POST method for these parameters are echoed back by
demo.php
via an HTML-formatted response. This page will not be part of the
CSL website so the user will need to either click on the link provided on that
page to return to the CSL site or use the “Back” button in the browser.
Component Logic Design
The only programming logic implemented for the CSL website is the JavaScript
routine to validate the volunteer information form data. This routine will
return true
if all the form data meets the criteria or false
if any
information fails validation. That return code will then be used by the browser
to determine whether to call demo.php
(if result is true
) or simply return
to the form for corrections (if the result is false
).
Function Validate_Info_Form_Data()
Set errorsWithForm to False
Check for missing lastName, firstName, email, age
Check and report character and length errors with lastName
Check and report character and length errors with firstName
Check and report character errors with email
Check and report numeric and range errors with age
Return errorsWithForm
End Validate_Info_Form_Data
Testing
This section documents how the CSL website will be verified against its stated requirements.
Test Environment
The test environment will be the website and demo.php
running under a Linux,
Apache, MySQL, PHP (LAMP) stack and the Mozilla Firefox browser used for access
(although your site should render on any standard-compliant browser, including
Google Chrome, Safari, Internet Explorer, and Microsoft Edge).
For automated tests, the test environment – running on GitHub Actions – uses PHP’s built-in web server with the Selenium framework for web testing and ChromeDriver for headless execution of the Chromium web browser. This environment should be comparable to serving the website using LAMP and viewing it in Mozilla Firefox.
See the prior admonition if using HTML 5’s form validation, which may cause spurious failures from the automated tests. A workaround is required to trigger the form validation when data is entered using the Selenium framework.
Test Procedures
The following test procedures will be used to verify each requirement is satisfied.
Test Case | Requirement | Action | Expected Response |
---|---|---|---|
1 | 1 | Access the CSL website from the browser | Website loads and displays |
2 | 1a | Read the content for the description of the CSL program and verify there is a picture | Description and image found and determined to be appropriate |
3 | 1b | Navigate to the Service Partners page and verify that there is a nicely formatted entry for each partner to include name, location, and phone number | Service partner entries are present and complete with appropriate formatting |
4 | 1c | Navigate to the Volunteer Information form and verify that there are means to input first name, last name, email, age, gender, and whether they have access to a car | Form controls for all data items are present |
5 | 1d | Submit Volunteer Information form with missing last name, first name, email, and age | All four data items are reported as missing |
6 | 1di | Submit Volunteer Information form with a last name that has at least one of each type of valid character and no invalid characters | Entered data is accepted and echoed back by demo.php |
7 | 1di | Submit Volunteer Information form with a last name that has an invalid character | Error is detected and reported with demo.php not called |
8 | 1di | Submit Volunteer Information form with last name that is 51 characters long | Error is detected and reported with demo.php not called |
9 | 1di | Submit Volunteer Information form with a first name that has at least one of each type of valid character and no invalid characters | Entered data is accepted and echoed back by demo.php |
10 | 1di | Submit Volunteer Information form with a first name that has an invalid character | Error is detected and reported with demo.php not called |
11 | 1di | Submit Volunteer Information form with first name that is 51 characters long | Error is detected and reported with demo.php not called |
12 | 1dii | Submit Volunteer Information form with an email address that has at least one of each type of valid character and no invalid characters | Entered data is accepted and echoed back by demo.php |
13 | 1dii | Submit Volunteer Information form with an email address that has an invalid character | Error is detected and reported with demo.php not called |
14 | 1dii | Submit Volunteer Information form with an email address that is 51 characters long | Error is detected and reported with demo.php not called |
15 | 1dii | Submit Volunteer Information form with an email address that does not have an at sign (“@”) | Error is detected and reported with demo.php not called |
16 | 1diii | Submit Volunteer Information form with a valid age | Entered data is accepted and echoed back by demo.php |
17 | 1diii | Submit Volunteer Information form with an age that is not numeric | Error is detected and reported with demo.php not called |
18 | 1diii | Submit Volunteer Information form with an age of 16 | Error is detected and reported with demo.php not called |
19 | 1diii | Submit Volunteer Information form with an age of 30 | Error is detected and reported with demo.php not called |
20 | 1e | Submit Volunteer Information form with all valid data | Entered data is accepted and echoed back by demo.php |
21 | 2 | View each page and check for website title, page title, direct navigation to others pages, same image or background style, same background color, font color, and font style | Anticipated elements and consistency is present |
22 | 3 | Swap CSS and repeat Test Case #21 | Anticipated elements and consistency is present |
23 | 4 | Subjective assessment against design guidelines | Scored based upon degree of compliance |
Test locally before attempting the automated tests. For example, the
volunteer form should not be submitted when no data is entered. If the form
validation has a syntax error, then the form will be submitted because the
onsubmit
handler did not return false
. You can see any JavaScript errors
using the console in your web browser.
Submission
Create an archive of your Git repository (you can use GitHub’s “Clone or download” button when viewing your repository for this purpose) and submit that archive to Canvas. Be sure to include your documentation statement as part of the submission and a brief description of the additional features implemented for the website.
GitHub Classroom also tags the latest commit at the due date for the assignment.
Grading
The following grading rubric will be used for this assignment:
Description | Points |
---|---|
XML | 10 |
XML academic schedule | 5 |
Validation of schedule against XSD | 5 |
HTML, CSS, and JavaScript | 65 |
Automated testing (page content and functionality) | 50 |
Consistent layout and navigation | 5 |
Alternative CSS | 5 |
Additional features (graphics, embedded video, interactive JavaScript, etc.) | 5 |
The automated tests, including XML validation, will be executed automatically by GitHub Actions when you push to your GitHub repository. The remainder of the points, which pertain to visual aesthetics, will be assigned by the instructor by viewing your website. You are strongly encouraged to complete this assignment several days prior to the due date so that you have time to resolve any failures for the automated tests. If you have questions regarding how to interpret their output, do not hesitate to ask the instructor.
Each test case is worth the same amount. No partial credit will be awarded for content and functionality covered by the automated tests (unless you can prove that a test case rejected valid input)!
Automated Tests
GitHub Actions tests your code when you push your changes to GitHub (i.e., continuous integration). The entire class shares the resources provided for auto-grading; more specifically, there is a maximum number of minutes per month for GitHub Actions, and each job counts toward that maximum. You should test locally before pushing to GitHub.
Because GitHub Actions resources are shared, each workflow run in excess of 25 will incur a 1-point penalty.
To encourage judicious use of our shared resources, the aforementioned penalty will be applied as a deterrent against pushing changes that are not correct. For example, if you pass all the tests and your repository has 22 workflow runs, then you will receive full credit, but if you pass all the tests and your repository has 30 workflow runs, then you will incur a 5-point penalty and receive only 70 points for this assignment. You may check the number of workflow runs by clicking on the “Actions” tab of your repository.
Interpreting the output from the automated tests can be non-trivial, and in many cases a single character makes the difference between passing and failing a particular test case. The following examples illustrate how to read the test output.
The following example illustrates a failure where index.html
does not contain
the required description of the CSL program:
________________ TestIndex.test_contains_description_and_image _________________
self = <web.test_index.TestIndex object at 0x10c1a0d50>
selenium = <selenium.webdriver.chrome.webdriver.WebDriver (session="8631a4f5a3263616288f31eb8f9351b0")>
def test_contains_description_and_image(self, selenium):
description = ('The Cadet Service Learning program is designed to '
'foster and facilitate service learning activities for '
'cadets at the United States Air Force Academy.')
xpath = ('//body/descendant::*[text()[contains('
'normalize-space(.),"{}")]]'.format(description))
locator = (by.By.XPATH, xpath)
> assert base.has_element(selenium, *locator), \
self._create_message('Missing CSL description', locator=locator)
E AssertionError: Missing CSL description
E url = http://localhost:8000/index.html
E locator = xpath://body/descendant::*[text()[contains(normalize-space(.),"The Cadet Service Learning program is designed to foster and facilitate service learning activities for cadets at the United States Air Force Academy.")]]
E assert False
E + where False = <function has_element at 0x10c17cde8>(<selenium.webdriver.chrome.webdriver.WebDriver (session="8631a4f5a3263616288f31eb8f9351b0")>, *('xpath', '//body/descendant::*[text()[contains(normalize-space(.),"The Cadet Service Learning program is designed to foster and facilitate service learning activities for cadets at the United States Air Force Academy.")]]'))
E + where <function has_element at 0x10c17cde8> = base.has_element
tests/web/test_index.py:24: AssertionError
------------------------------- pytest-selenium --------------------------------
Driver log: /private/var/folders/g0/365fv8xd31s1vkddd10vnybr0000gn/T/pytest-of-jcoffman/pytest-250/test_contains_description_and_0/driver.log
URL: http://localhost:8000/index.html
The lines of interest are those prefixed by E
. The message states, “Missing
CSL description” and provides the following information:
- url
- the location of the page being viewed (i.e.,
http://localhost:8000/index.html
) - locator
- the search parameters used to (try to) find the element on the page, which in
this case is an XPath expression (i.e.,
//body/descendant::*[text()[contains(normalize-space(.),"The Cadet Service Learning program is designed to foster and facilitate service learning activities for cadets at the United States Air Force Academy.")]]
)
In this particular instance, the page being tested contained a typographical mistake: “United Stated Air Force Academy” appeared instead of “United States Air Force Academy.”
Many of the automated tests rely on XPath expressions to interact with elements
on the web page. You can enter these expressions into your web browser to see
if they identify the intended element to assist with debugging. For example, in
Google Chrome, entering $x('xpath-expression')
in the JavaScript console
returns all elements that match xpath-expression – i.e.,
> $x('//body/descendant::*[text()[contains(normalize-space(.),"United States Air Force Academy")]]')
<- [p]
where the >
indicates the console prompt where an XPath expression in entered
and <-
indicates the return value, which is a single paragraph element that
matched the XPath expression. To debug the prior example, small portions of the
search string were validated individually until “United States Air Force
Academy” failed to match any elements, at which point the typographical mistake
became apparent.
As a second example, consider the following output for testing the volunteer form’s input validation:
________ TestVolunteer.test_form_validation_lastname_invalid_character _________
self = <web.test_volunteer.TestVolunteer object at 0x105d2c210>
selenium = <selenium.webdriver.chrome.webdriver.WebDriver (session="672434e84e3a2aa3ad05a42bcfd23db9")>
def test_form_validation_lastname_invalid_character(self, selenium):
for value in ['1', '_', '.', '[', 'invalid 1', 'invalid_']:
> self._test_form_validation(selenium, 'lastName', value)
tests/web/test_volunteer.py:96:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <web.test_volunteer.TestVolunteer object at 0x105d2c210>
selenium = <selenium.webdriver.chrome.webdriver.WebDriver (session="672434e84e3a2aa3ad05a42bcfd23db9")>
name = 'lastName', value = 'invalid 1', path = '/volunteer.html'
def _test_form_validation(self, selenium, name, value, path=None):
if path is None:
path = self.path
self._input_form_values(selenium)
xpath = ('//form[@action="demo.php"]//input[@name="{}"]').format(name)
inputElement = selenium.find_element(by.By.XPATH, xpath)
base.set_input_value(selenium, xpath, value)
inputElement.submit()
> assert path == urlparse.urlparse(selenium.current_url).path, \
'Volunteer form submission with {} = "{}"'.format(name, value)
E AssertionError: Volunteer form submission with lastName = "invalid 1"
E assert '/volunteer.html' == '/demo.php'
E - /volunteer.html
E + /demo.php
tests/web/test_volunteer.py:76: AssertionError
------------------------------- pytest-selenium --------------------------------
Driver log: /private/var/folders/g0/365fv8xd31s1vkddd10vnybr0000gn/T/pytest-of-jcoffman/pytest-256/test_form_validation_lastname_0/driver.log
URL: http://localhost:8000/demo.php
Again, the lines prefixed with E
contain the relevant information. The error
message, “Volunteer form submission with lastName = ‘invalid 1’,” indicates
that an illegal last name was entered (in this case, one that contained
digits), but the JavaScript validation did not prevent the submission of the
form – i.e., the form was submitted to demo.php
.
As a reminder, asking for assistance to interpret the XPath expressions and – more generally – how to replicate a particular test case is explicitly permitted by this assignment’s help policy. (You must, however, document such assistance.)