Coder Social home page Coder Social logo

test's Introduction

Test

Note: If you’re viewing the README file directly, a more complete version is available at this project’s web page.

Status: Build Status

Any update to this repository triggers an automated execution of all of the project’s unit tests. The status label above shows the result of those unit tests.

Introduction

This is a simple demonstration application inspired by a test problem The problem itself isn’t complex enough to warrant a full, production-quality web application, but it does provide a useful example to explore all of the tools and components that might make up a real app. Those tools include:

  • Javascript MVC framework
  • Full lint testing
  • Test-Driven Development configuration
  • All unit tests reusable from command line
  • Continuous integration runs all tests automatically on repository update
  • Style sheets developed using CSS preprocessor
  • HTML5 with semantic markup but backwards compatible with legacy browsers
  • Full accessibility
  • Responsive design supporting viewports from smartphone to desktop
  • Production-ready builds (concatenated and minified CSS and Javascript)

THe bulk of the project is a simple Javascript web app. An annotated walk-through of the app's source code is available.

Project Structure

There are four folders in the project. The /src folder holds the project’s source code. That source code include the HTML template, Javascript files, LESS style sheets, and third-party (vendor) libraries. The /test folder holds the unit test scaffolding, mostly third-party libraries. The unit tests themselves are contained in the single app-test.js file, and mocha.opts specifies the test options. The /docs folder has project documentation, and the /build folder stores the production version of the application. You can load the application directly in your browser via the URL http://sathomas.me/test/build/index.html.

/build
/docs
/src
/test

There are also a few independent files in the project root folder. These files are mostly project scaffolding and include .gitignore to specify local OS files (e.g. .DS_Store) not relevant to the project, .travis.yml to specify the continuous integration tests and package.json to indicate dependencies for those tests, this file (README.md), and tool settings (codekit-config.json for CodeKit and testem.json for Test’em)

.gitignore
.travis.yml
README.md
codekit-config.json
package.json
testem.json

The HTML Markup

The basic HTML for the project is a standard, valid HTML5 document. A single <div> with an id attribute of myApp contains the application.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Simple Test Application</title>
    
    <!-- All styles in single, minified stylesheet -->
    <link href="css/styles.min.css" rel="stylesheet" type="text/css">
    
</head>
<body>
<!--
    Use an empty <div> as a beacon so Javascript can tell when
    CSS styles are loaded and active.
 -->
    <div id="beacon"></div>
    
    <!-- The app's main view is rendered within the following <div> -->
    <div id="myApp"><div>
    
    <!-- All scripts in single, minified script file -->
    <script src="js/scripts.min.js"></script>
</body>
</html>

The HTML markup generated by the project is clean, semantic, and accessible. In particular, it fundamentally consists of a heading for the date, and an unordered list of events on that date. The resulting page is viewable and usable by text-only browsers and by screen readers for visually impaired users.

<h1>Sunday, June 9th 2013</h1>
<ul class="events">
    <li class="event">9:30 am to 11:30 am: Sample Item at Sample Location</li>
    <li class="event">6:00 pm to 7:00 pm: Sample Item at Sample Location</li>
    <li class="event">6:20 pm to 7:20 pm: Sample Item at Sample Location</li>
    <li class="event">7:10 pm to 8:10 pm: Sample Item at Sample Location</li>
</ul>

To further assist screen readers, specific times are wrapped in the HTML5 <time> element with full ISO-formatting as an attribute.

<time datetime="2013-06-09 09:30">9:30 am</time>

Additional <span> tags are wrapped around the elements to assist in styling.

Also, if the Javascript detects that CSS styles are available, it adds a .legend <div> to the markup that provides additional content when styled appropriately. The Javascript uses a #beacon element to test for CSS styling. If CSS styling is not available, the legend is not added so as not to unnecessarily confuse text-only browsers or screen readers. When the legend is inserted, its attributes include the ARIA role of presentation to ensure that screen readers don’t interpret it as content.

Finally, the Javascript adds data- attributes to the list items with relative positioning information. The CSS styles can use that information as appropriate to adjust the elements’ display. There are a couple of notable features about these attributes. First, the attribute values are specified as percentages rather than absolute pixels. This approach fully supports fluid layouts, relieving the Javascript of any concerns related to presentation. Secondly, the positioning information is added to the <li> elements as data- attributes rather than as properties of the elements. This lets the CSS decide whether or not to use the positioning information and is critical for responsive design.

<li class="event" data-top="4%" data-left="0%" data-height="16%" data-width="100%"></li>

Styles

The project’s styles are defined using LESS to augment standard CSS with variables and mixins. The most extensive mixins are in the layout.less file, which provides the functionality to style elements based on their data attributes. In the particular, the layout() mixin makes use of LESS parameters and guards. If the parameter is one of the four defined values (height, width, top, or left), then the mixin looks for data- attributes corresponding to the parameter value. If any are present, then it defines the corresponding style using the data- attribute value.

.layout(@attr) when (@attr=height) {
    &[data-height="0%"]   { height:   0%; }
    &[data-height="1%"]   { height:   1%; }
    ...

The main styles for the project use this mixin simply by including it as a property when desired. For example, the desktop styles for .event list items use all four of the layout properties.

.event {
    position: absolute;
    .layout(height);
    .layout(width);
    .layout(top);
    .layout(left);
}

The smartphone styles for these same .event list items do not use the data- attributes for styling.

.event {
    position: static;
    height: auto;
    width: 100% !important;
    top: 0;
    left: 0;
}

The primary styles for the project are included in the events.less file, which specifies both desktop and smartphone styles. The styles themselves are relatively straightforward and don’t warrant additional commentary.

To see the resulting web application (e.g. in a desktop browser) use this link (in a separate window). The <iframe> below contains the smartphone view of the same data. (It simply loads the same URL in an <iframe> of fixed height and width.)

Note: Because of GitHub restrictions, the embedded <iframe> is only visible on the web page version of this file.

<iframe height="480" width="320" src="http://sathomas.me/test/build/index.html" style="border: 2px #888 solid"></iframe>

Javascript

The bulk of the project consist of a single Javascript file, app.js. That file implements a standard set of Backbone.js models, views, and collections. Although the problem specifies a single, static set of events, the code supports a REST API for server interaction, multiple day support, and dynamic creation or modification of events.

Comments within that file provide extensive documentation. That documentation is viewable as a separate web page. The code also relies heavily on Underscore.js to implement a functional programming paradigm. I’ve described Underscore’s support for functional programming in this blog post.

The full suite of unit tests for the app are contained in the app-test.js. Those tests are self-documenting by design. For a thorough description of my unit testing strategy, tools, and process, you can check out this blog post. A sample unit test output is shown below.

  Application
     creates a global variable for the name space

  Event Model
    Initialization
       should default the title to an empty string
       should default the location to an empty string
       should default the start time to now
       should default the end time to now
       should default the position to first (e.g. left-most)
       should default the overlap to none
    Parsing
       should convert minutes since 9:00am to a moment object
       should convert Unix seconds to a moment object
       should convert Unix milliseconds to a moment object

  Event List Item View
     render() should return the view object
     should update automatically on model changes
    Template
       should render as a list item
      Event Times
         should include times for the event
        Start Time
           should include the start time
           should have the correct start time
           should the ISO-formatted start time as a datetime attribute
        End Time
           should include the end time
           should have the correct end time
           should the ISO-formatted end time as a datetime attribute
      Event Title
         should include the event title
         should have the correct title
      Event Location
         should include the event location
         should have the correct title
      Data Attributes
         should include the event position
         should include the event overlap

  Events Collection
     should accept direct initialization of models
    Layout Calculation
       should identify overlapping event times
       should not overlap back-to-back events
       should not overlap different days
       should calculate positions
       should position earliest starting events first
       should fill in position gaps
       should calculate event height
       should calculate event vertical position
       should calculate height for early events
       should calculate vertical position for early events
       should calculate height for late events
       should calculate vertical position for late events

  Events List View
     render() should return the view object
     should render as an unordered list
     should include list items for all models in collection
     should dynamically add list items as events are added to the collection
     should filter models based on date


  44 tests complete (257 ms)

test's People

Contributors

sathomas avatar

Watchers

 avatar  avatar

Forkers

richsua

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.