API Docs for: 0.9.1
Show:

File: lib/loader/tap.js

// Copyright 2014, Yahoo! Inc.
// Copyrights licensed under the Mit License. See the accompanying LICENSE file for terms.

var AbstractLoader = require('../abstractLoader');
var fs = require('fs');
var Promise = require('promise');
var _ = require('underscore');

/**
 * @class TapLoader
 * @extends AbstractLoader
 * @constructor
 *
 * @property {int} _length Length of test
 * @property {int} _counter Current number of tests found
 */
var TapLoader = AbstractLoader.extend(

	{
		/**
		 * Processes a single file
		 *
		 * @method _processFile
		 * @param {string} parentId
		 * @param {string} file
		 * @return {Promise}
		 * @private
		 */
		_processFile: function (parentId, file) {

			this._length = 0;
			this._counter = 0;

			return new Promise(function (resolve, reject) {

				fs.readFile(file, function (err, data) {

					var lines,
						i, len,
						id,
						reporter;

					if (err) {
						reject(err);

					} else {
						lines = data.toString().split("\n");

						_.each(lines, function (line) {
							this._processLine(parentId, line);
						}, this);


						// Make sure that missing tests will also be reported
						reporter = this.getReporter();

						len = this._length - this._counter;
						for(i = 0; i < len; i++) {

							id = this.newId() + '';

							reporter.testStart(id, parentId, 'Untitled Test');
							reporter.testFailed(id, 'Failed');
						}

						resolve();
					}

				}.bind(this));
			}.bind(this));
		},

		/**
		 * Process a single line
		 *
		 * @param {string} parentId
		 * @param {string} line
		 * @private
		 */
		_processLine: function (parentId, line) {

			var matches,
				success,
				name,
				state,
				message,

				id,
				reporter,

				planRegex = /\s*(\d+)(\.{2})(\d+)\s*(#\s*(SKIP|skip)\s*([^#]+))?\s*(#\s*(.*))?/,
				resultRegex = /\s*(ok|not ok)\s*(\d*)\s*([^#]*)?\s*(#\s*(SKIP|skip|TODO|todo)\s*([^#]+))?\s*(#\s*(.*))?/;

			if (line.match(planRegex)) {
				matches = line.match(planRegex);
				this._length = parseInt(matches[3], 10) - parseInt(matches[1], 10) + 1;

			} else if (line.match(resultRegex)) {
				matches = line.match(resultRegex);

				// Get values
				success = (matches[1].toLowerCase() === 'ok');
				name = (matches[3] || '').trim() || 'Untitled Test';
				state = (matches[5] || '').trim().toLowerCase();
				message = (matches[6] || '').trim();

				// Prepare values
				id = this.newId() + '';
				reporter = this.getReporter();

				// Start test
				reporter.testStart(id, parentId, name);

				this._counter++;

				// Complete test
				if (success) { // On success

					if (state === 'skip') { // When skipped
						reporter.testSkipped(id, message.length ? message : 'Skipped');

					} else if (state === 'todo') { // When incomplete
						reporter.testIncomplete(id);

					} else {
						reporter.testPassed(id);
					}

				} else { // On failure

					if (state === 'skip') { // When skipped
						reporter.testSkipped(id, message.length ? message : 'Skipped');

					} else if (state === 'todo') { // When incomplete
						reporter.testIncomplete(id);

					} else { // When really failed
						reporter.testFailed(id, message.length ? message : 'Failed');
					}
				}
			}
		}
	});

module.exports = TapLoader;