In: Categories » Computers and technology » AJAX » Testing a Dynamic Contract with Ajax
Coding the Contract Using Test-Driven Development Techniques
Coding the contract using agile and test-driven development techniques requires writing a number of tests and implementing aMock URL layer. Problem You want to code the contract using these development techniques. Solution To demonstrate, let’s define a use case, implement the use case as a contract, write a test case(s) to implement the contract, implement the contract in the Mock URL, and finally run the test. The example is XMLHttpRequest-based, as you’ll most likely be using XMLHttpRequest for your testing purposes. However, the contract and mock URLs are not integrated explicitly into the client or server code, so that you can verify any client. This article is about building Web services, and you can call Web services by an XMLHttpRequest client, by a mashup client, or by some server-side Web service aggregator. The example features a calculator application that contains only a single operation used to add two numbers together. What makes the calculator operation unique is that it uses temporary URLs to keep a history of past additions.
The use case is the addition of two numbers, but two things must happen to carry out the use case: redirection and addition. The details of managing redirections aren’t covered here but will be covered in the following section entitled “Testing a Dynamic Contract.” How the temporary URL is determined falls into the category of pixie dust, so let’s focus on the details of the contract that performs the addition. The following represents the HTTP request used to perform an addition:
POST /services/calculatorrest/operations/2364564565 HTTP/1.1
Content-type: application/json
User-Agent: Jakarta Commons-HttpClient/3.0
Host: localhost:8100
Content-Length: 25
In the request, an HTTP POST is executed, and the URL used is the temporary URL found in the redirection test. The HTTP headers Content-type and Content-Length are not optional and are used to define the type and length of the content sent with the POST request. The body of the request contains a buffer encoded using JavaScript Object Notation (JSON).13 Two data members are defined in the JSON request: number1 and number2. These two data members represent the numbers to be added. The following shows the appropriate response:
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 14
Server: Jetty(6.0.x)
{"result":3}
The headers Content-Type and Content-Length describe the content that is returned, which is encoded using JSON and contains a single data member. The single data member result is the result of adding two numbers together. As you look at the requests and responses and do some mental math, you’ll know that adding 1 and 2 results in the sum of 3. From the perspective of the contract, it would seem that everything is OK and that the system is implemented and works. In reality, however, the illustrated HTTP conversations were all faked. This leads to the following question: when developing a contract, how do you physically define the contract? A purist might say, “The contract is defined using some sort of tool that the client and server programmers then implement.” The purist answer sounds good and would be great if such a tool existed. Unfortunately, no tool allows you to design REST-based HTTP conversations that can serve as the basis of the test and Mock URL layer. Faced with the fact that you don’t have such a tool, using an editor to generate the HTTP conversation manually is incredibly error-prone and tedious. I don’t suggest that anybody should do that. However, you still need to define a contract, but you can’t do it without a tool or an editor. Without any sort of documentation, the contract literally remains a figment of your imagination.
And figments of imagination are rather difficult to create test cases for. The solution is to write the tests that make up the contracts, even though writing a bunch of tests does not make a contract. The tests have to serve a dual purpose that is, they have to provide tests as well as act as documentation for how the contracts are called and used. Therefore, it’s important that you structure the tests clearly and make them verbose. For programming purposes, you can code the test framework in any particular language that makes you comfortable. For the scope of this solution and this article, I use JavaScript and JsUnit to write my test scripts. However, there’s nothing stopping you from using Java, a .NET language, PHP, or Ruby. You can start the contract in one of two ways: You can implement the client side first, or you can implement the Mock URL layer first. If you implement the client side first, you’d be using a top-down approach, and if you implement the Mock URL side first, you’d be using a bottom-up approach. I’ve chosen a top-down approach and have implemented the client side first. Of course, many say that top-down is the best, but I try not to be so picky about it. The important thing is that you start with one, do a bit of coding, and then move to the other. Don’t code all of one and then implement the other. Remember that you’re trying to develop the contract in an agile manner using test-driven development techniques. The generated HTML page contains two buttons. You use the topmost button Run All Tests to run all available tests on the HTML page. You use the lower button Test Prototype to run a particular test. When you click the button, the status of the test is generated to the right of the button. In the example, the status of the test is “not run.” Below the button is trace output, which is used to display any messages or errors that occur as the tests are running. The source of the HTML page is defined as follows.
Source: /jaxson/trunk/website/ROOT/scripts/templates/testcontract.html
<html>
<head>
<title>Contract Test Page</title>
<script language="JavaScript" src="/scripts/common.js"></script>
<script language="JavaScript" src="/scripts/Synchronous.js"></script>
<script language="JavaScript" src="/scripts/commontest.js"></script>
<script language="javascript" src="/scripts/jsunit/jsUnitCore.js"></script>
</head>
<body>
<script language="javascript">
// Setup the output generator
setJsUnitTracer( new jsUnitTraceGenerator( "traceoutput"));
// Start of defined contract URLs
// Potentially define a URL as
// var baseURL = "/my/url";
// End of defined contract URLs
var testsToRun = {
// Start JavaScript code for test cases here
testPrototype : function() {
// Synchronous functions identically to Asynchronous
// but Synchronous waits for the request to complete
// Good for testing, but bad for production as the browser hangs
var request = new Synchronous();
request.complete = function( statusCode, statusText,
responseText, responseXML){
// Do something with the result
// Indicate that you are done, and define the output element
testManager.success( "statusPrototype");
}
// Do something with the request
}
// End JavaScript code for test cases
};
testManager.setTestCases( testsToRun);
</script>
<table>
<tr>
<td><h2>Available Tests</h2></td>
<td></td>
</tr>
<tr>
<td>
<input onclick="testManager.runAll()"
type="button" value="Run All Tests" />
</td>
<td></td>
</tr>
<tr>
<td>Test</td>
<td>Status</td>
</tr>
<!-- Insert GUI for test cases here -->
<tr>
<td>
<input onclick="testManager.testPrototype()" type="button"
value="Test Prototype" />
</td>
<td id="statusPrototype">Not run</td>
</tr>
<!-- End test cases here -->
</table>
hr />
table border="1">
<tr>
<td><h2>Trace output</h2></td>
</tr>
<tr>
<td id="traceoutput"></td>
</tr>
</table>
</body>
</html>
The code is relatively long, so I’ve highlighted the important pieces to make it simpler to understand. The test code uses the script tag to include a number of JavaScript files that provide the basis of the test code. After you load the base script, the first piece of highlighted code setJsUnitTracer redirects the generated warnings and informational and debug messages to the current HTML page. Specifically, the output is generated in the table element with the id traceoutput, which is shown in bold at the bottom of the HTML code.
The other bold source code is the variable baseURL, which represents a variable that references the contract URLs that will be used in the test script. It’s important to define all contract URLs in this area so that it’s clear which URLs need to be supported. If a URL cannot be determined ahead of time because of its dynamic nature, then you declare a variable and assign an empty string. The next pieces of bold text represent a variable (testsToRun) and a function (testPrototype). The function testPrototype is an example of how you could write a test. Remember these two important steps: Use Synchronous, and call the method testManager.success. Synchronous is a helper class that makes a synchronous XMLHttpRequest call. Normally, in your applications you would use the Asynchronous class, which makes asynchronous XMLHttpRequest calls. Let’s take a look at the differences between asynchronous and synchronous requests and discuss why you’d choose either.
When XMLHttpRequest is used to make a synchronous request, XMLHttpRequest waits for a response before returning control to the browser. Having XMLHttpRequest wait for an answer is a problem, because JavaScript is not multithreaded, causing the browser to lock. For a better user experience, you should always use asynchronous requests. Using asynchronous requests has its own problems. An asynchronous request doesn’t wait for the response and returns control to the JavaScript. When running tests, asynchronous requests are a problem because tests are executed sequentially, not concurrently. When writing Ajax and REST code, use the following rule of thumb: use asynchronous requests for applications, and use synchronous requests for testing. Getting back to the example function testPrototype, each test function must indicate whether or not the test was successful.
This is required because when the test manager runs all tests, the next test will run only when the current test was successful. In the example, a success is when the method testManager.success is called. Calling the method failed indicates a failure, and the method waiting indicates that the test involves multiple steps and needs to wait for an answer before determining success or failure. Moving on, in the example HTML source code file, the method testManager.setTestCases associates the tests with the test manager. The test manager iterates through all of the tests defined in the variable testsToRun and creates a proxy that is an encapsulation to the originally defined method. You can read more about this in Article 2. When running tests, don’t reference the variable testsToRun, but rather the test manager variable testManager. After the test manager method setTestCases completes initialization, you can execute the tests. In the example HTML source code, tables (<table>) are dynamically defined to contain references to the tests. The first table contains buttons used to execute the tests as a group or individually. To run all of the tests, call the method testManager.runAll(). To run an individual test, execute the method testManager.[testname]. The second table is used for generating the logging output.
Let’s first test the redirection and addition, as illustrated by the following code snippet.
Source: /jaxson/trunk/website/ROOT/calculator/testcontract.html
var entityURL = "";
var testsToRun = {
testVerifyAdd : function(){
info( "testVerifyAdd", "Running testVerifyRedirection first");
testsToRun.testVerifyRedirection();
info( "testVerifyAdd", "Finishing running testVerifyRedirection");
var state = new Object();
state.number1 = 1;
state.number2 = 2;
var buffer = JSON.stringify( state);
info( "testVerifyAdd", "JSON Buffer (" + buffer + ")");
var request = new Synchronous();
request.complete = function( statusCode, statusText,
responseText, responseXML) {
var response = JSON.parse( responseText);
info( "testVerifyAdd.complete", "Add Result (" + responseText + ")");
assertEquals( "JSON result", 3, response.result);
testManager.success( "addTest");
}
request.post( entityURL, "application/json", buffer.length, buffer);
}
};
...
<tr>
<td>
<input onclick="testManager.testVerifyAdd()"
type="button" value="Test Add" /></td>
<td id="addTest">Not run</td>
</tr>
The code snippet illustrates the JavaScript code that contains the test, and the HTML snippet shows how to call the test defined by the JavaScript. The variable entityURL references the contract URL used to perform an addition. The variable is not assigned a predefined URL, because the URL is created dynamically in another test not illustrated in the snippet. Contained within the definition of the variable testsToRun is a function testVerifyAdd that represents the test used to perform an addition. To run the test, the test manager calls the dynamically defined method testManager. testVerifyAdd, which calls testsToRun.testVerifyAdd. The purpose of creating a proxy to the test is to enable the test manager to manage the test harness that calls the test. In the implementation of testVerifyAdd, the not-illustrated test testVerifyRedirection is called. The testVerifyRedirection executes to verify that the variable entityURL will reference a valid URL. Notice how the not illustrated test is referenced using the variable testsToRun and not testManager.
Earlier, I stated that you should call testManager to run a test, and not the test directly. That rule of thumb only applies if you want to run a test and are not already running a test. The main reason why you wouldn’t use testManager is that if an exception is generated, you want the currently running test to exit. Calling a test using testManager within a test results in the exception being caught and the current test continuing as if everything went OK. Of course, this doesn’t mean that you might not want this behavior, and you could call a test from testManager. The choice is yours, but it’s more important to understand the reason for calling each. Having called the not-illustrated testVerifyRedirection test, the test of performing an addition has started. The test will verify that adding 1 and 2 results in the value of 3. The data is stored in a JavaScript object instance state that you instantiate and assign. You serialize the state of the object to the JSON format using the method JSON.stringify.
Once you convert the state into a string buffer, you send it to the server using the method request.post. The method request.post is an HTTP POST request, fulfilling the requirements of REST. When the request.post method responds, the method request.complete is called. In the anonymous method implementation of request.complete, the returned buffer is formatted using JSON. To convert the JSON buffer into a state, you call the method JSON.parse. You assign the returned state to the variable response. The state contains the value of the addition, and the value is tested using the method assertEquals. If the value is not 3, then the testing framework triggers, catches, and processes an exception. With either example, you can see which tests were successful and which tests failed. When a test fails, an error states why the test failed. Additionally, informational messages are generated so that you know what your tests are doing and what data is being sent. The test is written as a single test and doesn’t constitute a complete contract test. When you implement the client-side tests of your contract, you’ll want to employ test-driven development techniques that include tests that succeed and tests that fail. Now let’s shift focus from the client side to the server side. You don’t want to implement a complete working server-side implementation, but rather implement the Mock URL layer.
For the scope of this solution, Java is used. The purpose of the Mock URL layer is to imitate and implement server-side functionality. Imitating and implementing server-side functionality is tricky, because you can only implement targeted test cases. In the case of the example, that means implementing the case of adding 1 and 2. Of course, the addition of 1 and 2 is trivial, and in the case of the Mock URL, you could implement it within seconds. However, there are more complicated cases, so you shouldn’t be tempted to provide a solution. The focus of the Mock URL layer is to provide correct requests and responses for specific tests. By implementing logic, you’re setting yourself up for an error because the logic needs to be tested. Let’s put it this way: Imagine implementing the trivial addition of two numbers. How do you know that your implementation will work properly? The answer is that you write tests. However, that doesn’t answer the question properly, because how do you know that the tests are implemented properly? The answer is that you don’t, and that is the purpose of the Mock URL layer. The following source code implements the request and response of the add contract.
Source: /jaxson.java.tests/devspace/jaxson/tests/calculator/mockurl/DoMockAdd.java
public class DoMockAdd extends MockUrlTestCaseBase {
public void processRequest(HttpServletRequest request,
HttpServletResponse response) throws ServletException {
assertAreEqualJSONObject( request, "requestadd.json");
try {
FileWriter.writeFileObject( "application/json",
response, "responseadd.json");
}
catch( Exception e) {
throw new ServletException( "Could not write file response", e);
}
response.setStatus( 200);
}
}
Two method calls are shown in bold. The method assertAreEqualJSONObject compares the sent data stored by the Java servlet to the file requestadd.json. If the sent data matches the contents of the file, then the next method call writeFileObject is executed. The purpose of writeFileObject is to send the contents of the file responseadd.json to the client. The files requestadd.json and responseadd.json represent predefined contracts used to add two numbers together. The class DoMockAdd has no idea what the purpose of the operation is. It only knows that if the request matches a file, then a response based on another file is sent. The Mock URL layer implementation is simple but can only deal with a single case of adding two specific numbers and generating a single response. In the Mock URL layer example, you perform multiple tests to see which test case is matched. If a test case is matched, then the appropriate response is sent. If no test cases matches, then no response is sent, and an error is generated.
The method assertAreEqualJSONObject compares the JSON data that is sent to the JSON data in a file. Don’t be misled into believing that a byte-to-byte comparison is performed. The method assertAreEqualJSONObject performs a logical comparison based on the format of the data. This is important because otherwise, whitespace or other characters that don’t influence the state of the data could cause a test to fail. You don’t want a test failing because of a different formatting, unless of course you desire testing a specific formatting of the data. For example, XML is another technology where most likely you don’t want whitespace to cause the test to fail. After you’ve created the Mock URL layer, you can test the client scripts, which will verify the contracts. Based on the working client and server side, subbing in a working client or server implementation should not change the behavior. If the behavior is changed, then the client test scripts and Mock URL implementations are inconsistent. You want neither the client nor the server to know if it’s running against a test or an actual implementation. You should remember the following points when creating contracts:
• The Mock URL layer represents the definitive contract between the client and server.
• The Mock URL layer implements the contracts using predefined files for requests and responses.
• The Mock URL layer can only test targeted test cases and should not use any code that will be used in implementation, since the logic might have bugs.
• When comparing the sent data with the data in the file, use a logical comparison and not a byte-to-byte comparison. A byte-to-byte comparison could cause whitespace, which has nothing to do with the state of an object, and would cause a test to fail. The exception to this rule is if the test requires verifying the whitespace.
• The Mock URL layer performs multiple tests on which request is being sent and sends the appropriate response. In most cases, the request is tested using a file, and the response is based on another file.
• If you must implement logic in the Mock URL layer, make sure that it’s extremely well tested and stable, as that implementation will serve as a reference for how the contract between the client and server functions.
• The client-side tests that test the contract represent an implementation of how to use the contract and are used to verify the correctness of the server-side implementation.
• You develop the client-side contract tests and Mock URL layer together using testdriven development techniques.
• You can implement the client-side contract tests in any programming language, but since this article and most likely your application are JavaScript-based, it makes sense to use JavaScript.
• Neither the client- nor the server-side implementations or tests should ever have any dependencies on each other. This way, you can replace the client tests with the client implementation without causing problems in the Mock URL layer or server implementation. 1-4.Testing a Dynamic Contract The previous example, which illustrated how to create a contract, didn’t cover the dynamic aspect of the contract and the problem of redirection in particular. Redirection was not covered because redirection is a part of a bigger problem that is part of the Ajax and REST paradigm. Problem You want to test a contract that is dynamic. Solution The “Understanding the Definition and Philosophy of Ajax” section argued that Ajax allows you to create and manipulate content dynamically. The dynamism extends to the contract, which can involve the following techniques:
• Definition of a specific URL based on a general URL
• Definition of specific content based on a specific URL In either example, a general URL or general content reference is hard-coded or referenced in the client side. The hard-coded general reference is then converted into a specific reference. To understand what is involved, let’s focus on the calculator example and the redirection part of the addition operation. The following code represents the HTTP request that the client would make to convert the general addition operation URL into a specific addition operation URL: GET /services/calculatorrest/operations HTTP/1.1 User-Agent: Jakarta Commons-HttpClient/3.0 Host: localhost:8100 An HTTP GET is executed, and the URL /services/calculatorrest/operations is called using the HTTP 1.1 protocol. This part of the request is required. In the example, the HTTP headers are not required, but to implement the Permutations14 pattern, the headers most likely are required. For this test, the required response is as follows:
HTTP/1.1 201 Redirecting+a+user
Location: /services/calculatorrest/operations/2364564565
The response looks a bit odd, because the HTTP code 201, and not 307 or 302, is returned. For those readers who have no idea what the response codes mean, let me clarify. If you make a request and the server wants to redirect you to the real temporary URL, then you use a response code in the 3xx series. In the case of the calculator application, the redirect is temporary, as many addition operations could be performed. Therefore, the appropriate response would be either 307 or 302. However, that is not the correct answer for multiple reasons. Returning either a 307 or 302 is not correct in this case for the following reasons:
• The browser makes the redirection automatically and thus doesn’t give the XMLHttpRequest object the redirected URL.
• Doing an automatic redirection is not useful, because you may want to execute multiple queries and would not want to perform multiple redirections.
• When making a request on the base URL, you’re not doing a redirect to a known resource, but rather creating a resource that you need to redirect to. In the World Wide Web Consortium (W3C) HTTP 1.1 specification, the 201 response code is used to indicate that calling the original URL has created a new resource that can be referenced at the new URL, which is defined in the Location HTTP header. Therefore, even though you could have used 307 or 302, the more appropriate answer is 201. From an implementation perspective, the identifier 2364564565 is generated dynamically and cannot be predicted. From a testing perspective, this is a problem because you cannot write a test for the identifier 2364564565. If you were to do so, you’d violate the principle of being able to substitute the Mock URL layer for a server implementation. The reason is because the client test would expect a specific identifier that the server implementation cannot, nor should, generate. The solution is not to test for a specific identifier, but rather to test for the existence and format of the identifier, as illustrated by the following test.
Source: /jaxson/trunk/website/ROOT/calculator/testcontract.html
var baseURL = "/services/calculatorrest/operations";
var entityURL = "";
testVerifyRedirection : function(){
var request = new Synchronous();
request.complete = function( statusCode, statusText,
responseText, responseXML){
if ( statusCode != 201) {
fail( "Expected 201 received " + statusCode);
}
entityURL = this._xmlhttp.getResponseHeader( "Location");
if ( entityURL == null || entityURL.length <= baseURL.length) {
fail( "Redirected URL cannot be null");
}
info( "testVerifyRedirection", "Redirected URL is (" + entityURL + ")");
testManager.success( "urltest");
}
request.get( baseURL);
},
In the test, the hard-coded reference URL is stored in the variable baseURL. The dynamically created URL is stored in the variable entityURL, which is assigned an empty string. The test testVerifyRedirection has a single purpose and that is to call the hard-coded general reference. Calling the hard-coded general reference returns the specific dynamic reference. To implement the contract, you must test two things. The first is the return of the status code 201, and the second is the generation of the identifier. Testing for the status code 201 is simple and involves a decision. Testing for the dynamic identifier is a bit more complicated, but the approach taken in the test is simple. The test contains two verifications to test the existence of the dynamically generated identifier. The two verifications are the two lowest layers of testing a dynamic identifier. The following lists the verifications from the lowest to highest level of verifiability:
• Testing for the existence of the data: Typically, testing for the existence is a null or notnull test. If the test is not null, it doesn’t mean that the data is correct, but it does verify that there is data. The test assumes that the data contains the dynamic identifier.
• Testing for the existence of the identifier in the data: Testing for the existence means knowing about the nature of the dynamic identifier. Typically, that means knowing what the original data is and how the dynamically generated data should appear.
• Testing the formatting of the dynamically generated identifier: Testing the formatting means knowing something about the format of the identifier. This could mean knowing that the identifier is numeric, a certain length, or must contain certain characters. The calculator example doesn’t test for the correct formatting of the dynamically generated identifier, but if it had, the test would have been length-based and numerically based. Be careful when testing for the formatting, as the dynamic generation of temporary data might switch from one version to another. When testing dynamic data, start at the lowest level and perform the tests incrementally. Don’t start at the highest level right from the start. Doing so makes a dangerous assumption that dynamic data exists. For example, if you only test for correct formatting, you won’t be able to discern between the test failure of missing dynamic data and incorrectly formatted dynamic data. The following code illustrates a Java implementation of the URL redirection:
public class RedirectionImplementation extends MockUrlTestCaseBase {
public class RedirectionImplementation extends MockUrlTestCaseBase {
public void processRequest(HttpServletRequest request,
HttpServletResponse response) {
this.generateRedirection( response, 201,
request.getRequestURI() + "/2364564565");
}
}
The bold code illustrates how the redirection is implemented. Notice that the dynamic identifier is hard-coded. There is no logic. If the same client called the redirection multiple times, it would receive the same identifier. This appears to be a violation of the contract, yet it is not a violation. The contract for the calculator says to redirect to a resource that you can use to perform a calculation. The client cannot make assumptions, but the server can, because the server is in control of generating the dynamic identifiers. To turn the table, if the client has the responsibility to define the dynamic identifier, then the server must accept the dynamic identifier from the client and use it for Mock URL purposes. You could generate the dynamic identifier dynamically, but how would you test the correctness of the contract? This goes back to the problem illustrated in the previous section, which said the Mock URL layer has a dual role of defining what the contract needs to look like. If the Mock URL layer contains logic that is reused in the server implementation, then a correctness problem can exist. Therefore, if you must have variety in dynamic identifiers, create a few of them and then use a random number algorithm to choose between them. When testing dynamic contracts, remember the following points:
• Figure out who is responsible for generating the dynamic data and who consumes the dynamic data.
• The generator of dynamic data can define specific test cases and make assumptions about how the data is formatted.
• The consumer of the dynamic data is responsible for receiving the dynamic data and applying three levels of verification when verifying the correctness of the data.
• Test cases don’t always support dynamic data. For example, the provider might not support a reference made to a data format. In this case, the generator of the dynamic data must generate an error, and the consumer must verify that an error is generated. Don’t attempt to accommodate with warnings or informational messages. You would never expect a plumber to know how to fix a broken tooth.
legal notice
Our website is not responsible for the information contained by this article. Web-articles is a free articles resource.
Suggestion: If you need fresh, daily updated content for your website, feel free to use our service. Click here for more information.
Useful tools and features
related articles
The focus of this article is to provide solutions to some common, general problems and questions that are bound to arise before or during development of Asynchronous JavaScript and XML (Ajax) and Representational State Transfer (REST) applications. These common questions are not always technical in nature, often leaning more toward theory or philosophy of development. The problem with these kinds of questions is that once you begin to think about them, you keep going in a circle and end up where you star...
2. Understanding the Definition and Philosophy of Web Services and SOA
Understanding the Definition and Philosophy of Web Services and SOA Wikipedia offers the following definition of Web services:4 The W3C defines aWeb service as a software system designed to support interoperable machine-to-machine interaction over a network. This definition encompasses many different systems, but in common usage the term refers to those services that use SOAPformatted XML envelopes and have their interfaces described by WSDL. For ex...
3. Understanding the Definition and Philosophy of REST
Understanding the Definition and Philosophy of REST REST is a controversial topic among Web service enthusiasts, because it’s considered to stand for the opposite of what Web services and SOA are trying to achieve. The problem with this thinking is that REST is not in contradiction with the abstract definition of SOA and Web services. REST is in contradiction with technologies such as SOAP, WSDL, and WS-* specifications. The following offers a quick definition of REST:...
4. The Easiest Way to Get Started with Ajax and REST
The Easiest Way to Get Started with Ajax and REST Problem You want to know the best way to get started with writing Ajax and REST. Solution When developing an Ajax and REST application, you must decide on the tools and frameworks you’ll use. The choice is simple: Use whatever you’re using today, and write some Ajax applications. You don’t need to change the tools you’re using today. Whether you’re using ASP.NET, JavaServer Pages (JSP), PHP, Ruby, or Python, you...
5. Testing the Client Side Logic
Problem You want to effectively test your application’s client-side logic. Theory Testing GUI code tends not to be a productive task because of the complications that arise. The main complication is how to test the correctness of a user interface. Imagine a situation where clicking a button causes a table to be filled with data. Now imagine that when a check box is checked and the button is clicked again, a different table is filled with content. The fact that clicking the same button results in two ...
6. Understanding JavaScript and Types
Understanding JavaScript and Types Problem You want to work around the fact that JavaScript does not have types declared for its variables. Theory JavaScript code does not have any variables with a declared type. The lack of typed variables is apparent when you declare functions. That said, not having typed variable declarations does not mean JavaScript has no types or no type safety. Let’s start out with the simple declaration of a function, as illustrated by the following ex...
7. Coding Using Conventions and Not Configurations
Coding Using Conventions and Not Configurations Problem You want to make your JavaScript constructs more efficient by applying the Rails “convention over configuration” principle to them. Theory You may already be familiar with the programming platform Ruby on Rails, which is used to build Web applications. The focus of this recipe is not Ruby on Rails, but one aspect of Ruby on Rails namely, convention over configuration (see http://en.wikipedia.org/wiki/ Ruby_on_Rails for m...
8. Advantage of parameterless functions in JavaScript
Using Parameterless Functions Problem You want to take advantage of parameterless functions in JavaScript. Theory JavaScript functions for the most part have parameters. You may think that the previous sentence states the obvious after all, without parameters, what data could be passed to a function? JavaScript has the ability to declare functions that have no parameters, even though the caller of the function has passed parameters to the function. For example, let’s look at...
9. JavaScripot Functions
Treating Functions Like Objects Problem You want to take advantage of the fact that functions are objects (remember, everything is an object in JavaScript). Theory Many people think that a function is some keyword used in JavaScript. A function is also an object that can be manipulated. Knowing that a function is an object makes it very interesting from the perspective of writing JavaScript code, because the code can treat the function like another other object. This mean...
