diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c346b13 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +bower_components/ +node_modules/ diff --git a/.travis.yml b/.travis.yml index 4fee055..1f369fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: node_js node_js: - "0.10" -install: "npm -g install jshint" -script: "jshint js/*" +install: "npm install" +script: "sh -e run_tests.sh" notifications: email: false irc: diff --git a/README.md b/README.md index 9798c44..424f8d8 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,8 @@ FAQ Development ----------- +Setup +^^^^^ Getting started with the development of Glowing Bear is really simple, partly because we don't have a build process (pure client-side JS, remember). All you have to do is clone the repository, fire up a webserver to host the files, and start fiddling around. You can try out your changes by reloading the page. Here's a simple example using the python simple web server: @@ -58,6 +60,22 @@ If you'd prefer a version hosted with HTTPS, GitHub serves that as well with an You can also use the latest and greatest development version of Glowing Bear at [https://latest.glowing-bear.org/](https://latest.glowing-bear.org/). +Running the tests +^^^^^^^^^^^^^^^^^ +Glowing Bear uses Karma and Jasmine to run its unit tests. To run the tests locally, you will first need to install `npm` on your machine. Check out the wonderful [nvm](https://github.com/creationix/nvm) if you don't know it already, it's highly recommended. + +Once this is done, you will need to retrieve the necessary packages for testing Glowing-Bear (first, you might want to use `npm link` on any packages you have already installed globally): + +`$ npm install` + +Finally, you can run the unit tests: + +`$ npm test` + +Or the end to end tests: +`$ npm run protractor` + + Contributing ------------ diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..8557a60 --- /dev/null +++ b/bower.json @@ -0,0 +1,15 @@ +{ + "name": "glowing-bear", + "description": "A webclient for WeeChat", + "version": "0.4.0", + "homepage": "https://github.com/glowing-bear/glowing-bear", + "license": "GPLv3", + "private": true, + "dependencies": { + "angular": "1.3.x", + "angular-route": "1.3.x", + "angular-loader": "1.3.x", + "angular-mocks": "~1.3.x", + "html5-boilerplate": "~4.3.0" + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..536fd28 --- /dev/null +++ b/package.json @@ -0,0 +1,35 @@ +{ + "name": "glowing-bear", + "private": true, + "version": "0.4.0", + "description": "A web client for Weechat", + "repository": "https://github.com/glowing-bear/glowing-bear", + "license": "GPLv3", + "devDependencies": { + "karma": "~0.10", + "protractor": "~0.20.1", + "http-server": "^0.6.1", + "bower": "^1.3.1", + "shelljs": "^0.2.6", + "jshint": "^2.5.2", + "karma-junit-reporter": "^0.2.2" + }, + "scripts": { + "postinstall": "bower install", + + "prestart": "npm install", + "start": "http-server -a localhost -p 8000", + + "pretest": "npm install", + "test": "karma start test/karma.conf.js", + "test-single-run": "karma start test/karma.conf.js --single-run", + + "preupdate-webdriver": "npm install", + "update-webdriver": "webdriver-manager update", + + "preprotractor": "npm run update-webdriver", + "protractor": "protractor test/protractor-conf.js", + + "update-index-async": "node -e \"require('shelljs/global'); sed('-i', /\\/\\/@@NG_LOADER_START@@[\\s\\S]*\\/\\/@@NG_LOADER_END@@/, '//@@NG_LOADER_START@@\\n' + cat('app/bower_components/angular-loader/angular-loader.min.js') + '\\n//@@NG_LOADER_END@@', 'app/index-async.html');\"" + } +} diff --git a/run_tests.sh b/run_tests.sh new file mode 100755 index 0000000..7ae7475 --- /dev/null +++ b/run_tests.sh @@ -0,0 +1,2 @@ +./node_modules/.bin/jshint js/*.js test/unit/*.js +npm test diff --git a/test/e2e/scenarios.js b/test/e2e/scenarios.js new file mode 100644 index 0000000..a1efb07 --- /dev/null +++ b/test/e2e/scenarios.js @@ -0,0 +1,26 @@ +'use strict'; + +/* https://github.com/angular/protractor/blob/master/docs/getting-started.md */ + +describe('Auth', function() { + + browser.get('index.html'); + var ptor = protractor.getInstance(); + it('auth should fail when trying to connect to an unused port', function() { + var host = ptor.findElement(protractor.By.model('host')); + var password = ptor.findElement(protractor.By.model('password')); + var port = ptor.findElement(protractor.By.model('port')); + var submit = ptor.findElement(protractor.By.tagName('button')); + // Fill out the form? + host.sendKeys('localhost'); + password.sendKeys('password'); + port.sendKeys(2462); + submit.click(); + + var error = ptor.findElement( + protractor.By.css('.alert.alert-danger > strong') + ) + + expect(error.getText()).toBeDefined(); + }); +}); diff --git a/test/karma.conf.js b/test/karma.conf.js new file mode 100644 index 0000000..379b976 --- /dev/null +++ b/test/karma.conf.js @@ -0,0 +1,34 @@ +module.exports = function(config){ + config.set({ + + basePath : '../', + + files : [ + 'bower_components/angular/angular.js', + 'bower_components/angular-route/angular-route.js', + 'bower_components/angular-mocks/angular-mocks.js', + 'js/**/*.js', + 'test/unit/**/*.js' + ], + + autoWatch : true, + + frameworks: ['jasmine'], + + browsers : ['PhantomJS'], + + singleRun: true, + + plugins : [ + 'karma-phantomjs-launcher', + 'karma-jasmine', + 'karma-junit-reporter' + ], + + junitReporter : { + outputFile: 'test_out/unit.xml', + suite: 'unit' + } + + }); +}; diff --git a/test/protractor-conf.js b/test/protractor-conf.js new file mode 100644 index 0000000..d5bf372 --- /dev/null +++ b/test/protractor-conf.js @@ -0,0 +1,19 @@ +exports.config = { + allScriptsTimeout: 11000, + + specs: [ + 'e2e/*.js' + ], + + capabilities: { + 'browserName': 'firefox' + }, + + baseUrl: 'http://localhost:8000/', + + framework: 'jasmine', + + jasmineNodeOpts: { + defaultTimeoutInterval: 30000 + } +}; diff --git a/test/unit/plugins.js b/test/unit/plugins.js new file mode 100644 index 0000000..774e724 --- /dev/null +++ b/test/unit/plugins.js @@ -0,0 +1,140 @@ +/* plugins go here */ + +var msg = function(msg) { + return {'text': msg }; +}; + +var metadata_name = function(message) { + if (message.metadata && message.metadata[0] && message.metadata[0].name) { + return message.metadata[0].name; + } + return null; +}; + +var expectTheseMessagesToContain = function(urls, pluginType, plugins) { + for (var i = 0; i < urls.length; i++) { + expect( + metadata_name( + plugins.PluginManager.contentForMessage(msg(urls[i])) + ) + ).toEqual(pluginType); + } +}; + +describe('filter', function() { + beforeEach(module('plugins')); + + describe('Plugins', function() { + beforeEach(module(function($provide) { + $provide.value('version', 'TEST_VER'); + })); + + it('should recognize spotify tracks', inject(function(plugins) { + expectTheseMessagesToContain([ + 'spotify:track:6JEK0CvvjDjjMUBFoXShNZ', + 'https://open.spotify.com/track/6JEK0CvvjDjjMUBFoXShNZ' + ], + 'Spotify track', + plugins); + })); + + + it('should recognize youtube videos', inject(function(plugins) { + expectTheseMessagesToContain([ + 'https://www.youtube.com/watch?v=dQw4w9WgXcQ', + 'http://www.youtube.com/watch?v=dQw4w9WgXcQ', + 'http://youtu.be/J6vIS8jb6Fs', + 'https://youtu.be/J6vIS8jb6Fs', + 'http://www.youtube.com/embed/dQw4w9WgXcQ', + 'https://www.youtube.com/embed/dQw4w9WgXcQ', + 'youtu.be/dQw4w9WgXcQ' + ], + 'YouTube video', + plugins); + })); + + it('should recognize dailymotion videos', inject(function(plugins) { + expectTheseMessagesToContain([ + 'dailymotion.com/video/test', + 'dailymotion.com/video/#video=asdf', + 'dai.ly/sfg' + ], + 'Dailymotion video', + plugins); + })); + + it('should recognize allocine videos', inject(function(plugins) { + expectTheseMessagesToContain([ + 'allocine.fr/videokast/video-12', + 'allocine.fr/cmedia=234' + ], + 'AlloCine video', + plugins); + })); + + it('should recognize images', inject(function(plugins) { + expectTheseMessagesToContain([ + 'http://i.imgur.com/BTNIDBR.gif', + 'https://i.imgur.com/1LmDmct.jpg', + 'http://i.imgur.com/r4FKrnu.jpeg', + 'https://4z2.de/gb-mobile-new.png', + 'http://static.weechat.org/images/screenshots/relay/medium/glowing-bear.png', + 'http://foo.bar/baz.php?img=trololo.png&dummy=yes', + 'https://tro.lo.lo/images/rick.png?size=123x45' + ], + 'image', + plugins); + })); + + it('should recognize cloud music', inject(function(plugins) { + expectTheseMessagesToContain([ + 'http://soundcloud.com/', + 'https://sadf.mixcloud.com/', + ], + 'cloud music', + plugins); + })); + + it('should recognize google map', inject(function(plugins) { + expectTheseMessagesToContain([ + 'https://www.google.com/maps/@48.0034139,-74.9129088,6z', + ], + 'Google Map', + plugins); + })); + + it('should recognize google map', inject(function(plugins) { + expectTheseMessagesToContain([ + 'https://asciinema.org/a/10625', + ], + 'ascii cast', + plugins); + })); + + it('should recognize meteograms', inject(function(plugins) { + expectTheseMessagesToContain([ + 'http://www.yr.no/sted/Canada/Quebec/Montreal/', + ], + 'meteogram', + plugins); + })); + + it('should recognize gists', inject(function(plugins) { + expectTheseMessagesToContain([ + 'https://gist.github.com/lorenzhs/e8c1a7d56fa170320eb8', + 'https://gist.github.com/e8c1a7d56fa170320eb8', + ], + 'Gist', + plugins); + })); + + it('should recognize tweets', inject(function(plugins) { + expectTheseMessagesToContain([ + 'https://twitter.com/DFB_Team_EN/statuses/488436782959448065', + ], + 'Tweet', + plugins); + })); + + }); +});