Developing code to validate data and enforce business rules

As described in Lesson 1, it is important to define the right data type for each column on the tables in the database. A fundamental concern, therefore, is ensuring that the captured data is suitable for the column definitions in the Trips table. This type of validation on a single field is often referred to as a single-field edit.

Compass Travel has other operating policies that involve evaluating the values from more than one field. These validations, referred to as cross-field edits, are usually more difficult to program. To assure that new trips are uniformly captured, Compass Travel has published cross-field validations and single-field edits in its Compass Travel business rules.

The following table lists the Compass Travel business rules for capturing and editing trip information. This table identifies which rules requiring single or cross-field editing.
Compass Travel new trip policy
Edit type
1
All trips must be named.
single-field
2
All trips must be accompanied by a full description.
single-field
3
Each trip must be categorized by event type. Only valid event types (1-surfing, 2-mountain climbing, and so on) are permissible
single-field
4
Trip locations are required.
single-field
5
The maximum number of people permitted on the trip must be specified.
single-field
6
The trip departure and return dates must be specified for each trip.
All trip dates must be valid future dates. Departure date must precede return date.
single-field

cross-field
7
The trip's price and base cost are required. Both values are positive numeric values. The trip price must have at least a 20% markup over base cost.
cross-field
8
Any trip priced over $750 requires a deposit.
cross-field
9
A trip leader must be identified.
single-field
10
A photo must accompany all new trips. The photo image file must reside within the images directory of the Compass Travel website.
single-field

Ways to validate data

ColdFusion provides special tags to simply the process of enforcing business rules. Using ColdFusion, it is possible to enforce business rules in several places. For example, you can enforce some validation edits on the client. Other validation edits, you can enforce on the server after the data entry form is submitted. You will explore these options in the following sections.

Validating data using a server-side action page

The first approach you will take to enforce Compass Travel business rules is to develop an action page to validate the data collected on the data entry form. The action page receives a form variable for every field on the form that contains a value. You use the cfif tag to test the values of these fields to ensure that they adhere to Compass Travel business policy.

Using a cfif tag to enforce business rules

The cfif tag lets you create conditions that evaluate to either True or False. Therefore, to use the cfif tag to test whether a trip name was entered (business rule 1)on the Trip Edit form, you code the following cfif statement:

<cfif Form.tripName EQ "">
  <cfoutput> Trip Name cannot be blank. </cfoutput>
</cfif>

In the previous example, the cfif statement tests to see if the value of the form variable tripName is blank. If the trip name condition evaluates to True, ColdFusion sends "Trip name cannot be blank" to the browser.

Note:   The keyword EQ is an operator used to test for equality. For more information about the cfif tag and its operators, see Developing ColdFusion MX Applications with CFML.

Evaluating check box and radio button variables

Business rule 8 in the Compass Travel new trip policy requires you to test the value of the depositRequired check box form variable. Check box and radio button variables are only passed to the action page when the user selects these options on the form. Therefore, an error occurs if the action page tries to use a variable that was not been passed.

To insure an error does not occur, you will use the IsDefined function in a cfif statement to determine whether the user selected the Deposit Required check box option on the form:

<cfif not IsDefined("Form.depositRequired")>
  <cfset form.depositRequired = "No">
</cfif>

The cfif statement and the IsDefined function evaluate the value of the form variable depositRequired to determine if a value exists. The statement not IsDefined returns True if the specified variable is not found and the cfset statement sets the form variable to No. No indicates a deposit is not required; Yes indicates a deposit is required.

Evaluating whether business rules fail

The purpose of the tripeditaction.cfm action page is to update the Compass Travel database, so it is important to make certain that all the business rules are passed successfully before the database insert is executed. Failure of any one of the rules negates the insert.

One approach to ensuring that the action page considers each business rule is to create a local variable with a cfset tag within the action page that tests to see if any of the business rules failed.

The cfset tag lets you manipulate the value of a variable. For example, the following pseudocode initializes a variable to a specific value and checks the value using the cfif statement:

<cfset isOk = "Yes">
if rule 1 fails then
<cfset isOK = "No"
...
if Rule n fails then
<cfset isOk = "No">
...
<cfif isOk = "Yes">
update the database
</cfif>

In the previous example, cfset initializes the local variable isOk to Yes. If any rule fails, the variable isOK is set to No. The code then tests if isOk equals Yes, before executing the SQL insert logic.

For more information about using the cfset and cfif tags and the IsDefined function, see Developing ColdFusion MX Applications with CFML or the CFML Reference.

Exercise: create an action page with server-side validation

In this exercise you build an action page (tripeditaction.cfm)to validate the data passed to the ColdFusion Server from the tripedit.cfm data entry page. You use the cfif and cfset tags to build edits that ensure the data passed is valid per the Compass Travel business rules. Additionally, you will use the ColdFusion IsDefined function to check to see if data was entered in the data entry form (tripedit.cfm).

To build trip edit action page and validate data passed:

  1. Open an editor and create a new page called tripeditaction.cfm in the my_app directory. The new page appears as follows:
    <html>
    <head>
      <title>Untitled</title>
    </head>
    
    <body>
    </body>
    </html>
    
  2. To ensure that Compass Travel business rule 7 is met, insert the following code above the <html> tag on the tripeditaction.cfm page. For your convenience, business rule 7 is repeated.

    Business rule 7: The trip's price and base cost are required. Both values are positive numeric values. The trip price must have at least a 20% markup over base cost.

    <!--- Base Cost is Required and must be Numeric --->
    <cfif Form.baseCost EQ "" or IsNumeric(Form.baseCost) EQ False>
      <cfset IsOk = "No">
      <cfoutput>Base cost must be a number and cannot be blank.</cfoutput>
    <cfelse>
      <!--- Price must be 20% greater than Base Cost --->
      <cfif Form.baseCost * 1.2 GT  #Form.price#>
        <cfset IsOk = "No">
        <cfoutput>Price must be marked up at least 20% above cost.</cfoutput><br>
      </cfif>
    </cfif>
    

    Note:   The code for business rule 7 uses ColdFusion cfif and cfelse conditional processing tags. The code inside the cfif tags only executes when the condition evaluates to True. To perform other actions when the condition evaluates to False, the cfelse tag is used. For more information about using conditional processing tags, see Developing ColdFusion MX Applications with CFML.

  3. Save the page.
  4. Use the following steps to test the code to see if it meets the objective of business rule 7:
    1. View the tripedit.cfm page in the browser.
    2. In the form, enter the number 500 in both the Price and Base cost fields.
    3. Click the Save button.

      The trip price error message displays: "Price must be marked up at least 20% above cost."

    4. Click the browser Back button to return to the tripedit.cfm page.
    5. To avoid the error, enter the number 800 in the Price field and click Save.
  5. Complete all the business rules using server-side validation. You must insert the code for each business rule above the <html> tag. As an example, see the tripeditaction1.cfm page in the solutions directory.

    Tip:   You can either modify your new tripeditaction.cfm page to include the code necessary to meet all 10 business rules or you can copy the tripeditaction1.cfm page from the solutions directory to tripeditaction.cfm in the my_app directory.

  6. Test various combinations to make sure all the Compass Travel business rules are enforced by filling out the fields on the form and clicking save.

    Testing recommendations:

Drawbacks of validating data on the server-side

Validating data on the server-side has two drawbacks. First, since the action page is used for validation, the form page is not in the browser context when the error is trapped. The user will, therefore, not get immediate feedback from the page where the data was entered. Second, because data capture occurs on the client and validation on the server, the number of round-trips to the server is increased. This can cause increased traffic on the network and the server. If the data is validated on the client, then only valid data is posted to the server and traffic is reduced.

Validating data on the client using ColdFusion form tags

An alternative approach to server-side editing is to use client-side scripting. Client-side scripting lets you validate the form data entered on the client prior to posting it to the server. CFML provides alternative versions of standard HTML form tags that provide advantages of client-side data validation.These data input tags include cfinput text, cfinput radio, cfinput checkbox, cfselect, and others.

Among the improvements over standard HTML tags, ColdFusion form tags offer the following attributes:
Attribute
Description
validate
The data type that the field tag validates against. Values include: integer, date, time, telephone, zipcode.
message
The error message displayed if validation fails.
range
The range of permissible values for this tag.
required
An indicator of whether data is required for the corresponding tag.

Examples of using the improved ColdFusion form tags

To use the improved form tags, you must replace the HTML form tag with the cfform tag. The following code snippets show the use of the improved ColdFusion form tags. The first code snippet shows how the duration field is validated on the server. The second code snippet shows how ColdFusion form tags simplify field validation on the client.

Server-side validation approach (no ColdFusion form tag)

The following code is on the client (tripedit.cfm page):

<input size=3 name=duration>
Code on the server (tripeditaction.cfm page):
<!--- Duration is Required and must be Numeric --->
<cfif Form.numberPeople EQ "" or IsNumeric(Form.numberPeople) EQ False>
  <cfset IsOk = "No">
  <cfoutput>The number of people must be a number and cannot be blank.
  </cfoutput>
</cfif>

Code
Explanation
<cfif Form.numberPeople EQ "" or
IsNumeric(Form.numberPeople) EQ False>
The cfif tag evaluates the value of the form variable numberPeople to determine if the user entered a value. The IsNumeric function checks whether the value entered on the form was a numeric value.

Client-side validation approach using ColdFusion form tag

The following code is on the client:

<cfinput  name="duration" message="Duration must be a number and cannot be blank."
validate="integer" required="Yes" size="3" maxlength="3">

Code
Explanation
<cfinput  name="duration"
message="Duration must be a number and
cannot be blank." validate="integer"
required="Yes" size="3" maxlength="3">
Use the cfinput tag to create the duration input entry field within a cfform. The validate attribute defines the field as an integer. The required attribute indicates that the field must have an entry. If the data is not entered or data entered is not an integer, the message attribute specifies that the message, "Duration must be...." appears.

Exercise: modify Trip Edit page to exploit ColdFusion form tags

In this exercise, you will use the ColdFusion form tags to move the validation of many business rules from the server to the client. To do this, you will change the HTML form tags in the tripedit.cfm page to ColdFusion form tags that validate these fields on the client side. Next, you will remove the unneeded server-side single-field validation code from tripeditaction.cfm page. Finally, you will test the form to ensure the client side validation is working correctly.

To exploit the ColdFusion form tags on the Trip Edit page:

  1. Open the tripedit.cfm in the my_app directory in your editor.
  2. Locate and change the <form> and </form> tags to <cfform> and </cfform>, respectively.
  3. Change the <input> tags to <cfinput> tags and <select> tags to <cfselect> tags. Note that the input type for the Submit button must remain a standard input rather than cfinput.
  4. For each ColdFusion form tag (cfinput, and cfselect), assign the appropriate values:
    Attribute value
    Description
    required
    Use this attribute for fields that must be filled out or selected.
    validate
    Use this attribute for fields that requires a specific data type for validation. Values include: integer, date, time, telephone, and zip code.
    message
    Use this attribute for fields that require an error message to be displayed if validation fails. The message reflects the text that describes the business rule.

    For example, the Trip Name field requires the following code:

    <cfinput maxlength = "50" size = "50" required = "Yes" name= "tripName" 
    message = "Trip name must not be blank">
    

    Tip:   For additional help, review the completed code in the tripedit2.cfm within the solutions directory. For more details about using ColdFusion form tags and their attributes, see Developing ColdFusion MX Applications with CFML.

  5. In your editor, open the tripeditaction.cfm in the my_app directory and delete the code for the following single-field validation rule:

    Tip:   You can either remove the single-field validations yourself or use tripeditaction2.cfm file in the solutions directory. The file tripeditaction2.cfm in the solutions directory is a copy of tripeditaction with the single-field edits deleted. Copy tripeditaction2.cfm in the solutions directory to tripeditaction.cfm in the my_app directory.

  6. When you finish deleting the single-field validation rules, save the file.

    The modified tripeditaction.cfm page appears as follows:

    <!--- Action Page to edit and save Trip information for Compass Travel. --->
    <!--- Single field edits have been removed in favor of client-side edits. --->
    <!--- Make the passportRequired variable be No if it is not set 
        (check box is empty) --->
    <cfset isOk = "Yes">
    <cfif not isdefined("Form.depositRequired")>
       <cfset form.depositRequired = "No">
    </cfif>
    <cfif Form.price GT 750 AND Form.depositRequired EQ "No">
      <cfset IsOk = "No">
      <cfoutput>Deposit is required for trips priced over $750.</cfoutput>
    </cfif>
    <cfif Form.basecost * 1.2 GT #Form.price#>
      <cfset IsOk = "No">
      <cfoutput>Price must be marked up at least 20% above cost.</cfoutput>
    </cfif>
    <cfif form.departureDate GT form.returnDate>
      <cfset isOk = "No">
      <cfoutput>Return date cannot precede departure date. Please re-enter.</cfoutput>
    </cfif><html>
    <head>
    <title>Trip Maintenance Confirmation</title>
    </head>
    
    <body>
    
    <cfif isOk EQ "Yes">
      <h1>Trip Added</h1>
      <cfoutput>You have added #Form.TripName# to the trips database.
      </cfoutput>
    </cfif>
    </body>
    </html>
    
  7. View the tripedit.cfm page in a browser and test the client- and server-side field validations by filling out the fields on the form and clicking Save.

    Testing recommendations:

Using cfselect tag to present valid event types

Currently the event types in tripedit.cfm are hard coded:

<!--- Field: eventType --->
<tr>
  <td valign="top">  Type of Event
  </td>
  <td>
<cfselect size="1" name="eventType" required="Yes" message="Type of
event must be selected.">
    <option value="1" selected>Surfing</option>
    <option value="2">Mountain Climbing</option>
    <option value="3">Mountain Biking</option>
    </cfselect>
  </td>
</tr>

As described in Lesson 1, the tutorial application design includes a database table that holds event types. The event type in the Trips table is an identifier used as a foreign key to the eventtypes table (which holds the actual event names). In the previous code, each option tag contains a value attribute and option text, such as Surfing. These values come from the eventtypes table so that they are not hard-coded. The eventtypes table column eventTypeID is used for the value attribute and the eventType for the literal value that is displayed in the select box. To retrieve the data from this table, you must include the following cfquery:

<cfquery name="GetEvents" datasource="CompassTravel">
  SELECT  eventType, eventTypeID 
  FROM eventtypes        
</cfquery>

To exploit the query in the option tags, you can replace the HTML select tag with cfselect.

The cfselect tag

The cfselect tag is an improved version of the HTML select tag. Like other ColdFusion form tags, the cfselect tag provides the required and message attributes that validate the data entered. Using the cfselect tag and the preceding cfquery, you can implement the eventType field data entry as follows:

<!--- Field: eventType --->
  <tr>
    <td valign="top">  Type of Event
    </td>
    <td>
    <cfselect size="1" name="eventType" required="Yes" 
    message="Type of event must be selected.">
    <cfoutput query="GetEvents">
    <option value="#GetEvents.eventTypeID#">
              #GetEvents.eventType#
    </option>
    </cfoutput>
    /cfselect>
    </td>
  </tr>

Exercise: use eventtypes table to load event types

Do the following steps to modify the Trip Edit page to display a list of event types from the eventtypes table and add validation.

To display a list of event types from the eventtypes table and add validation:

  1. View the tripedit.cfm page in a browser. Select the event types drop-down list. Notice that only three event types appear in the list.
  2. Open the tripedit.cfm in the my_app directory in your editor.
  3. Add the following code above the <html> tag:
    <cfquery name="GetEvents" datasource="CompassTravel">
      SELECT  eventType, eventTypeID 
      FROM eventtypes        
    </cfquery>
    
  4. Replace the following eventtypes code lines:
    <cfselect size="1" name="eventType" required="Yes" 
    message="Type of event must be selected.">
      <option value="1" selected>Surfing</option>
      <option value="2">Mountain Climbing</option>
      <option value="3">Mountain Biking</option>
    </cfselect>
    

    with these lines:

    <cfselect size="1" name="eventType" required="Yes" 
    message="Type of event must be selected.">
      <cfoutput query="GetEvents">
        <option value="#GetEvents.eventTypeID#">
          #GetEvents.eventType#
        </option>
      </cfoutput>
    </cfselect>
    
  5. View the tripedit.cfm page in a browser. Select the event types drop-down list. Notice that all seven event types appear in the list.

Using other client-side script to reduce edits on the server

If you were interested in moving as much of the business rule logic to the client as possible, you might use other client-side scripting languages, such as JavaScript. By exploiting ColdFusion form tags, you moved most of the responsibility for the business rule checking from the server to the client. This section explains how to migrate cross-field business rules to the client using JavaScript.

Web browsers can execute scripts based on events triggered on the current page. One of the most popular scripting languages is JavaScript. ColdFusion Form tags include an onValidate attribute that lets you specify your own JavaScript function for custom validation.

The JavaScript form object, input object, and input object value are passed to the specified JavaScript function. The function returns True if validation succeeds and False otherwise. The onValidate and validate attributes are mutually exclusive.

Recall the Compass Travel New Trip business rule 6:
The trip departure and return dates must be specified for each trip.
All trip dates must be valid future dates. Departure date must precede return date.

The trip departure and return dates must be specified for each trip.

All trip dates must be valid future dates. Departure date must precede return date.

One reason this rule is a good candidate for a JavaScript function is that the test for a future date cannot be done using the ColdFusion form tags attributes such as validate and range. The following JavaScript function (isitFutureDate) tests whether a date is a valid future date.

function isitFutureDate(oForm, oTag, dateString) {
/*
  function isitFutureDate 
  parameters: oForm, oTag, dateString 
  returns: boolean

  oForm is the CFForm object.  All onvalidate calls pass this argument.  
This function ignores it.
  oTag is the CFForm current tag object.  All onvalidate calls pass this
argument.  This function ignores it.
  dateString is the value of the current tag object. It should be a date passed
as a string in the following
  format: MM/DD/YYYY. This means that months and days require leading zeros!!
 
  Returns true if the date passed is greater than today's date
  Returns false if the date passed is NOT greater than todays
  date.
*/

  // Check to make sure the date is zero filled with 4 digit year and 
  //therefore 10 characters long. 
  if (dateString.length != 10)
    return false;
var now = new Date();
  var today = new Date(now.getYear(),now.getMonth(),now.getDate());
var testdate = new Date(dateString.substring(6,10),
          dateString.substring(0,2)-1,
          dateString.substring(3,5));
    if (testdate > now)  
      return true;
    else
      return false;
}

Another reason that rule 6 requires JavaScript scripting is that it tests the values of more than one field in a single edit. You must ensure that the return date field is greater than departure date field. To do this, you add a JavaScript function to validate the trip date range entered, and specify the function on the onValidate attribute of the returnDate cfinput tag.

function validateTripDateRange(oForm, oTag, dateString)
{
  /*
  parameters: oForm, oTag, dateString 
  returns: boolean
  
  oForm is the CFForm object.  All onvalidate calls pass this argument. 
    This function ignores it.
  oTag is the CFForm current tag object.  All onvalidate calls pass this argument.
    This function ignores it.
  dateString is the value of the current tag object. It should be a date 
    passed as a string in the following
  format: MM/DD/YYYY. This means that months and days require leading zeros!!
 
  Returns true if the date passed is a future date greater than the departure date
  Returns false if the date passed is NOT a future date greater than departure
    date.
*/

//Edit to make sure that Return date is Later than departure date.
  var returnDateString;
   
  //First check to see if the departure Date is a valid future date
  if (isitFutureDate(oForm, oTag, dateString) == false)
    return false;
     
  var departureDate = new Date(dateString.substring(6,10),
        dateString.substring(0,2)-1,
        dateString.substring(3,5));
                      
  returnDateString = document.forms(0).item("returnDate").value;
                      
  var returnDate = new Date(returnDateString.substring(6,10),
        returnDateString.substring(0,2)-1,
        returnDateString.substring(3,5));
   
  if (departureDate < returnDate)  
    return true;
  else
    return false;
}

The important point about the preceding JavaScript is that you can use two functions, isitFutureDate and validateTripDateRange, to verify whether a date is in the future and the trip date range is valid, respectively.

Exercise: add JavaScript-based validation code

In this exercise you will modify the Trip Insert page to validate the departure and return dates using the JavaScript functions provided.

To validate the departure and return dates using JavaScript functions:

  1. Open tripedit.cfm in your editor and do one of the following:

    Copy example code provided  Copy the tripsedit3.cfm file from the solutions directory and rename it to tripedit.cfm in the my_app subdirectory

    or

    Add JavaScript-based validation code to tripedit.cfm  Follow these steps to modify the tripedit.cfm page:

    1. Copy and insert the text from the scriptvalidation.txt in the solutions directory right before the HTML body tag in tripedit.cfm.
    2. Modify the departureDate and returnDate input tags to include the onValidate attributes as follows:
        <cfinput name="departureDate" size="10" validate="date"
      onvalidate="isitFutureDate" message="Departure date must be a valid
      future date (mm/dd/yyyy).">
        <cfinput size="10" name="returnDate" validate="date"
      onvalidate="validateTripDateRange" message="Return date must be a valid
      date greater than departure date (mm/dd/yyyy).">
      
    3. Save the tripedit.cfm in the my_app directory.
  2. Test this page by opening the tripedit.cfm page in your browser.
  3. Test the date validation by checking that each of the following tasks fail:
    1. Enter a date in the past for the departure date field; for example, 01/01/2000.
    2. Enter a departure date greater than the return date; for example, enter 02/01/2004 for the departure date, and 01/01/2004 for the return date.
  4. Test the date validation and ensure that the proper data succeeds; for example, enter 01/01/2004 for the departure date, and 01/14/2004 for the return date.
  5. Test for an invalid date by entering 12/32/2002 for the return date.

    You would expect the application to reject this date. It does not. This is because the validate attribute of a cfinput tag (returnDate in this example) is ignored when there is a JavaScript routine specified in the onValidate attribute. To correct this, you must write a test to validate the date using JavaScript (not addressed in this tutorial).

Validating the existence of the trip photo file

At this point, you have a more efficient application. The client is handling much of the validation of the Compass Travel new trip business rules. Except for the trip photo file, the server receives only valid data.

The trip photo file business rule does not fit nicely into this design, however. The last trip photo business rule has two parts:

You used the required attribute for the photo cfinput tag to ensure that a file name is entered. Now you must make sure that the file exists in the right directory so the application can display it to customers.

Since browser clients are prohibited from doing standard file I/O (input/output) on the web server, the Trips Maintenance application will use server-side validation to ensure the existence of the photo file. You will add the business rule for the photo file to the tripeditaction.cfm page.

To check to see if a file exists, ColdFusion provides a FileExists function. The syntax of this function is:

  FileExists(absolute_path)

This function returns True if the file specified in the argument does exist; otherwise, it returns False. Assume that a data entry page has an input tag named "testFileName". If a user types in a valid file name, the action page snippet from the following example would display the message "The test file exists":

<cfset fileLocation = "c:\inetpub\wwwroot\images\">
<cfif IsDefined("form.testFileName")> 
    <cfif form.testFileName is not ""> 
  <!---Concatenate the File Location with the FileName passed in--->
    <cfset fileLocation = fileLocation  & form.testFileName> 
      <cfif FileExists(fileLocation)> 
        <cfoutput> The test file exists. </cfoutput>    
      </cfif>
    </cfif>
</cfif>

Note:   The trip photo images are stored in the following path relative to your web root directory: \cfdocs\getting_ started\photos. Therefore, if your web root is C:\inetpub\wwwroot, then the photos are stored in the C:\inetpub\wwwroot\cfdocs\getting_ started\photos directory.

For more information about the FileExists function, see CFML Reference.

Reviewing the code

The following table describes the code used to verify whether a file exists:
Code
Explanation
<cfif IsDefined("form.testFileName")> 
The cfif tag checks to see if the form variable testFileName has been entered.
<cfset fileLocation = fileLocation  & form.testFileName>
The ColdFusion & operator in the cfset tag combines the original value for fileLocation from the first source line
("c:\inetpub\wwwroot\images\") with the value of the testFileName form variable.
<cfif FileExists(fileLocation)> 

FileExists checks to see if the file indicated by the fileLocation variable exists at the specified disk location.

Exercise: use FileExists function to verify the existence of photo file name

In this exercise, you will use the Cold Fusion FileExists function to ensure that the photo file name entered in the Trip Edit page exists in the location specified.

To verify that the photo file name exists:

  1. Open the tripeditaction.cfm in the my_app directory in your editor.
  2. In the tripeditaction.cfm page, do the following:
    1. Add logic to check that the user entered a valid photo file name by copying the code from the photofilecheck.txt file in the solutions directory pasting it immediately following the first <cfset isOk = "Yes"> statement.
    2. Verify that code you copied in step a is pointing to the correct photolocation path. The path is specified in the <cfset PhotoLocation = "C:..."> tag.

      For example, depending on your web server configuration, the photolocation path might be:

  3. Save the page and test it by opening the tripedit.cfm page in your browser.

    Testing recommendations:

    1. In the Trip Edit page entering valid information in all the required fields but the Photo File field.
    2. In the Photo File field, enter nowhere.jpg and click Save.

      The following error message appears: Trip photo does not exist.

    3. To avoid the error, replace the invalid photo file name in the Trip Edit page with somewhere.jpg and click Save.

      The following message appears: Trip added.

Comments