Socket
Socket
Sign inDemoInstall

gulp-protractor-qa

Package Overview
Dependencies
107
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.1.19 to 0.2.0

.jscsrc

326

index.js

@@ -0,240 +1,164 @@

var util = require('util');
var gutil = require('gulp-util');
var fs = require('fs');
var chalk = require('chalk');
var Gaze = require('gaze').Gaze;
var glob = require("buster-glob");
var cheerio = require('cheerio');
var protractorQaUtil = require('./lib/util');
var async = require('async');
var EventEmitter = require('events');
var _ = require('underscore');
const PLUGIN_NAME = 'gulp-protractor-qa';
// `GulpProtractorQA` sub-modules dependecies
var storeFileContent = require('./lib/store-file-content');
var findSelectors = require('./lib/find-selectors');
var findViewMatches = require('./lib/find-view-matches');
var consoleOutput = require('./lib/console-output');
var watchFilesChange = require('./lib/watch-files-change');
var gulpProtractorQA = {
testFiles : [],
viewFiles : [],
totalNumOfElements : 0,
// Constant
var PLUGIN_NAME = 'gulp-protractor-qa';
ptorFindElements : {
regex : protractorQaUtil.getRegexList(),
foundList : []
},
// Define `GulpProtractorQA` class.
// @class
function GulpProtractorQA() {
this.testFiles = [];
this.viewFiles = [];
this.selectors = [];
this.watchIsRunning = 0;
this.isFirstLoad = 1;
}
findDotByMatches : function( path, contents ){
var _this = this,
results,
regexList = _this.ptorFindElements.regex;
// Inherit EventEmitter.
util.inherits(GulpProtractorQA, EventEmitter);
// lopp regexlist
for( var i = 0; i<regexList.length; i++ ){
// verify matches
while ((results = regexList[i].match.exec(contents)) !== null)
{
var res = {
at : results[0],
val : results[1],
type : regexList[i].type,
attrName : regexList[i].attrName,
fileName : path
};
// Init application.
//
// @param {Object} options
// @param {string} options.testSrc - Glob pattern string point to test files
// @param {string} options.viewSrc - Glob pattern string point to view files
// @param {boolean} options.runOnce - Flag to decide whether it should watch files changes or not
GulpProtractorQA.prototype.init = function(options) {
this.options = options || {};
_this.ptorFindElements.foundList.push( res );
if (!this.options.testSrc) {
throw new gutil.PluginError(PLUGIN_NAME, '`testSrc` required');
}
if (!this.options.viewSrc) {
throw new gutil.PluginError(PLUGIN_NAME, '`viewSrc` required!');
}
}
}
readFiles.call(this);
}
},
elementsCount : function( contents ){
var _this = this,
results,
elemRegex = /element[\.all\(|\()]/gi;
// Read `testSrc` and `viewSrc` files content.
function readFiles() {
var self = this;
while ((results = elemRegex.exec(contents)) !== null) {
_this.totalNumOfElements = _this.totalNumOfElements + 1;
async.waterfall([
function(callback) {
storeFileContent.init(self.options.testSrc, callback);
},
function(data, callback) {
self.testFiles = data;
storeFileContent.init(self.options.viewSrc, callback);
},
function(data, callback) {
self.viewFiles = data;
callback(null, 'success');
}
], function(err, data) {
findElementSelectors.call(self);
});
}
},
searchProtractorDotByContents : function( updatedTestFiles, beforeViewMatches ){
var _this = this;
for( var i = 0; i<updatedTestFiles.length; i++ ){
var obj = updatedTestFiles[i];
_this.findDotByMatches(obj.path, obj.contents);
_this.elementsCount( obj.contents );
}
// Loop through test files and find protractor
// selectors (e.g.: by.css('[href="/"]')).
function findElementSelectors() {
var self = this;
// reset selectors
this.selectors = [];
// log number of watched elements
if( typeof beforeViewMatches === 'function'){
beforeViewMatches();
}
this.testFiles.forEach(function(item) {
self.selectors = self.selectors.concat(findSelectors.init(item));
});
// verify matches
_this.verifyViewMatches( _this.ptorFindElements.foundList );
},
checkSelectorViewMatches.call(this);
}
updateFileContents : function( collection, filepath, newContent ){
function checkSelectorViewMatches() {
var self = this;
var _this = this;
// Set all selectors to not found
this.selectors.forEach(function(item) {
item.found = 0;
});
for( var i = 0; i < _this[ collection ].length; i++ ){
var obj = _this[ collection ][i];
if( typeof obj.path != 'undefined' ){
if( filepath.indexOf( obj.path.replace("./", "/") ) >= 0 ){
obj.contents = newContent;
break;
}
}
}
// Check if selectors are findable
this.viewFiles.forEach(function(item) {
findViewMatches(self.selectors, item.content);
});
// reset foundList and totalNumOfElements
_this.totalNumOfElements = 0;
_this.ptorFindElements.foundList = [];
outputResult.call(this);
}
// map protractor elements
_this.searchProtractorDotByContents( _this.testFiles );
},
function outputResult() {
var notFoundItems = _.filter(this.selectors, function(item) {
return (!item.found && !item.disabled);
});
bindExists : function( bind, contents ){
var results,
exists = false,
pattern = /{{(.*?)}}/gi;
consoleOutput.printFoundItems(notFoundItems);
while ( (results = pattern.exec(contents)) !== null ){
if( results[1].indexOf( bind ) >= 0 ){
exists = true;
}
}
// On first run warn watched selectors.
if (this.isFirstLoad) {
warnWatchedSelectors.call(this);
this.isFirstLoad = 0;
}
return exists;
},
if (!this.options.runOnce && !this.watchIsRunning) {
startWatchingFiles.call(this);
}
}
verifyViewMatches : function( foundList ){
function startWatchingFiles() {
this.watchIsRunning = 1;
var _this = this,
allElementsFound = true;
// Init gaze.
watchFilesChange.call(this);
for( var i = 0; i < foundList.length; i++ ){
// Listen to change event
this.on('change', onFileChange.bind(this));
}
var found = false;
var foundItem = foundList[i];
function onFileChange(data) {
if (data.fileType === 'test') {
updateSelectors.call(this, data);
}
for(var c = 0; c < _this.viewFiles.length; c++ ){
var obj = _this.viewFiles[c];
checkSelectorViewMatches.call(this);
}
$ = cheerio.load( obj.contents );
var selector = '';
function updateSelectors(data) {
var filtered = _.filter(this.selectors, function(selector) {
return !(selector.path === data.path);
});
var updatedTestFile = this.testFiles[data.index];
var newSelectors;
if( foundItem.type === "attr" ){
selector = [
'[', foundItem.attrName, '="', foundItem.val, '"], ',
'[data-', foundItem.attrName, '="', foundItem.val, '"]'
].join("");
if( foundItem.attrName === "ng-bind" ){
// search for {{bindings}}
if( _this.bindExists( foundItem.val, obj.contents ) ){
found = true;
}
}
} else if( foundItem.type === "cssAttr" ){
selector = [ '[', foundItem.val, ']' ].join("");
}
if ($(selector).length) {
found = true;
}
}
if( !found ){
allElementsFound = false;
gutil.log('[' + chalk.cyan(PLUGIN_NAME) + '] ' + chalk.red(foundItem.at) + ' at ' + chalk.bold(foundItem.fileName) + ' not found within view files!');
}
}
if( allElementsFound ){
gutil.log(
'[' + chalk.cyan(PLUGIN_NAME) + '] ' +
chalk.green("all test elements were successfully found!")
);
}
},
storeFileContents : function( src, collection, _cb ){
var _this = this;
// watch test files changes
var gaze = new Gaze(src);
gaze.on('all', function(event, filepath) {
fs.readFile(filepath, 'utf8', function(err, data){
if (err) { throw err; }
_this.updateFileContents(collection, filepath, data);
});
});
// async map file contents
var async = function async(arg, callback) {
fs.readFile(arg, 'utf8', function (err, data) {
if (err) { throw err; }
callback(arg, data);
});
};
glob.glob(src, function (er, files) {
files.forEach(function(item) {
async(item, function(filePath, data){
_this[ collection ].push(
{
path : filePath,
contents : data
}
);
if( _this[ collection ].length == files.length ) {
_cb();
}
});
});
});
},
bindStoreFileContents : function( _callback ){
var _this = this;
_this.storeFileContents( _this.options.testSrc, "testFiles", function(){
_this.storeFileContents( _this.options.viewSrc, "viewFiles", function(){
_callback();
});
});
if (updatedTestFile) {
newSelectors = findSelectors.init(updatedTestFile);
this.selectors = filtered.concat(newSelectors);
}
}
};
function warnWatchedSelectors() {
var total = this.selectors.length;
gulpProtractorQA.init = function( options ){
var globals = gulpProtractorQA;
globals.options = options || {};
if (typeof globals.options.testSrc == 'undefined') {
throw new gutil.PluginError(PLUGIN_NAME, '`testSrc` required');
}
if (typeof globals.options.viewSrc == 'undefined') {
throw new gutil.PluginError(PLUGIN_NAME, '`viewSrc` required!');
}
globals.bindStoreFileContents(function(){
globals.searchProtractorDotByContents(globals.testFiles, function beforeViewMatches(){
gutil.log( '[' + chalk.cyan(PLUGIN_NAME) + '] ' + chalk.gray( "// " + globals.ptorFindElements.foundList.length + " out of " + globals.totalNumOfElements + " element selectors are being watched" ) );
});
var filtered = _.filter(this.selectors, function(selector) {
return !selector.disabled;
});
};
// Output `X` out `total` are being watched.
consoleOutput.watchedLocators(filtered.length, total);
}
// Exporting the plugin main function
module.exports = gulpProtractorQA;
module.exports = new GulpProtractorQA();
{
"name": "gulp-protractor-qa",
"version": "0.1.19",
"version": "0.2.0",
"description": "Gulp Protractor QA warns you on the fly whether all element() selectors could be found or not within your AngularJS view files.",

@@ -28,3 +28,7 @@ "license": "MIT",

"cheerio": "0.15.0",
"buster-glob": "0.3.3"
"buster-glob": "0.3.3",
"ast-traverse": "^0.1.1",
"esprima": "^2.6.0",
"async": "^1.4.2",
"underscore": "^1.8.3"
},

@@ -31,0 +35,0 @@ "bugs": {

# [gulp](http://gulpjs.com)-protractor-qa [![NPM version](https://badge.fury.io/js/gulp-protractor-qa.svg)](http://badge.fury.io/js/gulp-protractor-qa) [![Build Status](https://travis-ci.org/ramonvictor/gulp-protractor-qa.svg?branch=master)](https://travis-ci.org/ramonvictor/gulp-protractor-qa)
<img src="https://raw.githubusercontent.com/ramonvictor/gulp-protractor-qa/master/assets/protractor-qa-logo.png" alt="Protractor Logo" />
<img src="https://raw.githubusercontent.com/ramonvictor/gulp-protractor-qa/master/assets/protractor-qa-logo.png" alt="Protractor QA Logo" />

@@ -12,3 +12,3 @@ Keeping end-to-end tests up-to-date can be really painful. Gulp Protractor QA warns you on the fly whether all element() selectors could be found or not within your application view files.

<img src="https://raw.githubusercontent.com/ramonvictor/gulp-protractor-qa/master/assets/gulp-protractor-qa.gif" alt="Video screen demo of gulp-protractor-qa in action!">
<img src="https://raw.githubusercontent.com/ramonvictor/gulp-protractor-qa/master/assets/gulp-protractor-qa.gif" width="720" height="auto" alt="Video screen demo of gulp-protractor-qa in action!">

@@ -18,4 +18,6 @@

<a href="http://bit.ly/1hceBSw" target="_blank"><img src="https://raw.githubusercontent.com/ramonvictor/gulp-protractor-qa/master/assets/screencast-gulp-protractor-qa.jpg" width="719" height="429" alt="How gulp-protractor-qa works?"></a>
<a href="http://bit.ly/1hceBSw" target="_blank"><img src="https://raw.githubusercontent.com/ramonvictor/gulp-protractor-qa/master/assets/screencast-gulp-protractor-qa.jpg" width="675" height="auto" alt="How gulp-protractor-qa works?"></a>
> TL;DR: a couple of new features and fixes have been added since this screencast publication.
## Install

@@ -26,3 +28,2 @@

```
[![NPM](https://nodei.co/npm/gulp-protractor-qa.png?downloads=true)](https://nodei.co/npm/gulp-protractor-qa/)

@@ -39,6 +40,7 @@ ## Example

gulp.task('protractor-qa', function() {
protractorQA.init({
testSrc : 'test/e2e/**/*Spec.js',
viewSrc : [ 'index.html', 'partials/*.html' ]
});
protractorQA.init({
runOnce: true, // optional
testSrc: 'test/e2e/**/*Spec.js',
viewSrc: [ 'index.html', 'partials/*.html' ]
});
});

@@ -59,2 +61,10 @@ ```

##### runOnce
Type: `Boolean`
Default: `false`
Optional: Set to `true` when you want to control yourself when to run task.
In other words, it won't watch files changes.
##### testSrc

@@ -76,13 +86,23 @@

Gulp-protractor-qa is currently watching the following `element()` selectors:
Gulp-protractor-qa is currently watching the following `element()` locators:
- `by.binding()`;
- `by.model()`;
- `by.binding()`;
- `by.css('[attr-name="attr-value"]')`;
- `by.repeater()`.
- `by.repeater()`;
- `by.css()`;
- `by.id()`;
- `by.className()`;
- `by.name()`;
**Help**: I need to extend this list by adding more regex rules ([see file](https://github.com/ramonvictor/gulp-protractor-qa/blob/master/lib/util.js)).
Interested to help? Fork the project and send a pull request! :)
Note: currently it can't find `by.css()` selectors with `:nth-child()`.
## Changelog
- **0.2.0** api completely rewritten, including:
- Introducing `runOnce` feature;
- Ignoring commented out element selectors;
- Handle any form of denormalized directives - except `ng:*` due to `cheerio` limitation;
- Fix a couple of bugs related to `by.css` old regex;
- Add suport for more protractor locators: `by.id()`, `by.className()` and `by.name()`.
- **0.1.19** improve `by.css` regex;

@@ -89,0 +109,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc