Skip to content
This repository was archived by the owner on Aug 17, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# IDE Files
.idea/*
angular-recaptcha.iml
.idea

# OS Files
.DS_Store

# Node, Grunt, Bower, general build process files
bower_components/*
node_modules/*
bower_components
node_modules

# Coverage folder
coverage
13 changes: 13 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
language: node_js

node_js:
- 'stable'

before_script:
- npm install -g grunt-cli bower
- bower install
- "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start"

script:
- grunt karma:ci
25 changes: 23 additions & 2 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,36 @@ module.exports = function (grunt) {
gitDescribeOptions: '--tags --always --abbrev=1 --dirty=-d' // options to use with '$ git describe'
}
},

karma: {
unit: {
configFile: 'karma.conf.js',
browsers: ['Chrome'],
singleRun: true
},
ci: {
configFile: 'karma.conf.js',
browsers: ['Chrome', 'Firefox', 'FirefoxNightly'],
singleRun: true
}
},
coveralls: {
options: {
coverageDir: 'coverage'
}
}
});

// Load the plugin that provides the needed tasks.
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-bump');
grunt.loadNpmTasks('grunt-karma');
grunt.loadNpmTasks('grunt-karma-coveralls');

// Default task(s).
grunt.registerTask('default', ['concat', 'uglify']);
grunt.registerTask('default', ['karma:unit', 'concat', 'uglify']);

// Unit Test task(s).
grunt.registerTask('test', ['karma:unit']);
grunt.registerTask('coverage', ['coveralls']);
};
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
AngularJS reCaptcha
===================

[![Build Status](https://travis-ci.org/VividCortex/angular-recaptcha.svg?branch=master)](https://travis-ci.org/VividCortex/angular-recaptcha)
[![Coverage Status](https://coveralls.io/repos/VividCortex/angular-recaptcha/badge.svg?branch=master)](https://coveralls.io/r/VividCortex/angular-recaptcha?branch=master)

Add a [reCaptcha](https://www.google.com/recaptcha/intro/index.html) to your [AngularJS](angularjs.org) project.


Expand Down
4 changes: 4 additions & 0 deletions bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,9 @@
],
"dependencies": {
"angular": "1.*"
},
"devDependencies": {
"angular-mocks": "~1.*",
"jquery": "~2.1.3"
}
}
78 changes: 78 additions & 0 deletions karma.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Karma configuration
// Generated on Wed Dec 24 2014 19:30:10 GMT-0200 (Horário brasileiro de verão)

module.exports = function (config) {
config.set({

// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '',


// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['jasmine'],


// list of files / patterns to load in the browser
files: [
'bower_components/jquery/dist/jquery.min.js',
'bower_components/angular/angular.js',

'bower_components/angular-mocks/angular-mocks.js',

'src/module.js',
'src/*.js',

'tests/*_test.js'
],


// list of files to exclude
exclude: [],


// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'src/*.js': 'coverage'
},

coverageReporter: {
type: 'lcov',
dir: 'coverage'
},


// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress', 'coverage'],


// web server port
port: 9876,


// enable / disable colors in the output (reporters and logs)
colors: true,


// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO,


// enable / disable watching file and executing tests whenever any file changes
autoWatch: true,


// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS', 'Chrome', 'IE', 'Safari', 'Firefox', 'FirefoxNightly', 'ChromeCanary'],


// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: false
});
};
16 changes: 15 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,27 @@
"type": "git",
"url": "git://github.com/vividcortex/angular-recaptcha.git"
},
"scripts": {
"test": "grunt test"
},
"devDependencies": {
"bower": "^1.3.3",
"grunt": "~0.4.2",
"grunt-bump": "0.0.13",
"grunt-cli": "~0.1.11",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-jshint": "~0.8.0",
"grunt-contrib-uglify": "~0.4.0"
"grunt-contrib-uglify": "~0.4.0",
"grunt-karma": "^0.10.1",
"grunt-karma-coveralls": "^2.5.3",
"jasmine-core": "^2.2.0",
"karma": "^0.12.31",
"karma-chrome-launcher": "^0.1.7",
"karma-coverage": "^0.2.7",
"karma-firefox-launcher": "^0.1.4",
"karma-ie-launcher": "^0.1.5",
"karma-jasmine": "^0.3.5",
"karma-phantomjs-launcher": "^0.1.4",
"karma-safari-launcher": "^0.1.1"
}
}
190 changes: 190 additions & 0 deletions tests/directive_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
describe('directive: vcRecaptcha', function () {
'use strict';


var $scope, $compile, $timeout, vcRecaptchaService,

TIMEOUT_SESSION_CAPTCHA = 2 * 60 * 1000, // 2 minutes
VALID_KEY = '1234567890123456789012345678901234567890';

beforeEach(function () {
module('vcRecaptcha');


inject(function ($rootScope, _$compile_, _$timeout_, _vcRecaptchaService_) {
$scope = $rootScope.$new();
$compile = _$compile_;
$timeout = _$timeout_;

vcRecaptchaService = _vcRecaptchaService_;
});
});

describe('invalid key', function () {
var elementHtml, expectedMessage;

afterEach(function () {
expect(function () {
var element = angular.element(elementHtml);

$compile(element)($scope);
$scope.$digest();
}).toThrow(new Error(expectedMessage));
});

it('should throw an error - no key', function () {
elementHtml = '<div vc-recaptcha></div>';
expectedMessage = 'You need to set the "key" attribute to your public reCaptcha key. If you don\'t have a key, please get one from https://www.google.com/recaptcha/admin/create';
});

it('should throw an error - key length is not 40 caracters long', function () {
elementHtml = '<div vc-recaptcha key="key"></div>';
expectedMessage = 'You need to set the "key" attribute to your public reCaptcha key. If you don\'t have a key, please get one from https://www.google.com/recaptcha/admin/create';

$scope.key = 'abc';
});

it('should throw an error - key length is not 40 caracters long - key changed', function () {
elementHtml = '<div vc-recaptcha key="key"></div>';
expectedMessage = 'You need to set the "key" attribute to your public reCaptcha key. If you don\'t have a key, please get one from https://www.google.com/recaptcha/admin/create';

$scope.key = 'abc1';
});
});

describe('widgetId', function () {
it('should be null at start', function () {
var element = angular.element('<div vc-recaptcha key="key"></div>');

$scope.key = VALID_KEY;

expect(function () {
$compile(element)($scope);
$scope.$digest();
}).not.toThrow();

expect(element.isolateScope().widgetId).toBeNull();
});
});

describe('form validation', function () {
beforeEach(function () {
$scope.key = VALID_KEY;
$scope.onCreate = jasmine.createSpy('onCreate');
$scope.onSuccess = jasmine.createSpy('onSuccess');
});

afterEach(function () {
expect(vcRecaptchaService.create).toHaveBeenCalled();
});

it('should change the validation to false, widget just created', function () {
var element = angular.element(
'<form name="form">' +
'<input type="text" ng-model="something" />' +
'<div vc-recaptcha key="key" on-create="onCreate({widgetId: widgetId})" />' +
'</form>'
),

_fakeCreate = function () {
return {
then: function (cb) {
var _widgetId = 'a';

cb(_widgetId);
}
};
};

spyOn(vcRecaptchaService, 'create').and.callFake(_fakeCreate);

$compile(element)($scope);
$scope.$digest();

expect($scope.form.$valid).toBeFalsy(); // widgetCreated
expect($scope.onCreate).toHaveBeenCalledWith({widgetId: 'a'});
});

it('should change the validation to true - first timeout flushed', function () {
var element = angular.element('<form name="form">' +
'<input type="text" ng-model="something" />' +
'<div vc-recaptcha key="k" on-create="onCreate()" on-success="onSuccess()"/>' +
'</form>'),

_fakeCreate = function (element, config) {
config.callback('response from google');

return {
then: function (cb) {
cb();
}
};
};

spyOn(vcRecaptchaService, 'create').and.callFake(_fakeCreate);

$compile(element)($scope);
$scope.$digest();

$timeout.flush(TIMEOUT_SESSION_CAPTCHA - 1);

expect($scope.form.$valid).toBeTruthy();
});

it('should change the validation to false - session expired', function () {
var element = angular.element('<form name="form">' +
'<input type="text" ng-model="something" />' +
'<div vc-recaptcha key="k" on-create="onCreate()" on-success="onSuccess()"/>' +
'</form>'),

_fakeCreate = function (element, config) {
// Call the expiration callback as recaptcha would do.
config['expired-callback']();

return {
then: function (cb) {
cb();
}
};
};

spyOn(vcRecaptchaService, 'create').and.callFake(_fakeCreate);


$compile(element)($scope);
$scope.$digest();

$timeout.flush(TIMEOUT_SESSION_CAPTCHA + 1);

expect($scope.form.$valid).toBeFalsy(); // widgetCreated
});

it('should call the onSuccess callback with the right params', function () {
var element = angular.element('<form name="form">' +
'<input type="text" ng-model="something" />' +
'<div vc-recaptcha key="key" on-create="onCreate()" on-success="onSuccess({response: response, widgetId: id})"/>' +
'</form>'),

_fakeCreate = function (element, config) {
config.callback('response from google');

return {
then: function (cb) {
cb();
}
};
};

spyOn(vcRecaptchaService, 'create').and.callFake(_fakeCreate);

$compile(element)($scope);
$scope.$digest();
$timeout.flush();

expect($scope.onSuccess).toHaveBeenCalledWith({
response: 'response from google',
widgetId: undefined
});
});
});
});
Loading