├── Procfile ├── example └── max.js ├── static-server.js ├── .gitignore ├── package.json ├── index.js ├── test.html ├── test └── test.js ├── README.md └── testling-webhook-payload.txt /Procfile: -------------------------------------------------------------------------------- 1 | web: node static-server.js 2 | -------------------------------------------------------------------------------- /example/max.js: -------------------------------------------------------------------------------- 1 | var maxBy = require('../'); 2 | var n = maxBy([9,3,4], function (x) { return x % 3 }); 3 | console.log(n); -------------------------------------------------------------------------------- /static-server.js: -------------------------------------------------------------------------------- 1 | var http = require('http'); 2 | var index = require('fs').readFileSync(__dirname+'/test.html'); 3 | http.createServer(function (req, res) { 4 | console.log("URL:",req.url); 5 | res.writeHead(200, {'Content-Type': 'text/html'}); 6 | res.end(index); 7 | }).listen(process.env.PORT || 3000); 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # .gignore from: https://raw.githubusercontent.com/github/gitignore/master/Node.gitignore 2 | # Logs 3 | logs 4 | *.log 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 18 | .grunt 19 | 20 | # Compiled binary addons (http://nodejs.org/api/addons.html) 21 | build/Release 22 | 23 | # Dependency directory 24 | # Commenting this out is preferred by some people, see 25 | # https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git 26 | node_modules 27 | 28 | # Users Environment Variables 29 | .lock-wscript -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "learn-testling", 3 | "version": "0.0.2", 4 | "description": "Simple Testling CI Tutorial", 5 | "main": "index.js", 6 | "directories": { 7 | "example": "example", 8 | "test": "test" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git://github.com/nelsonic/learn-testling.git" 13 | }, 14 | "keywords": [ 15 | "Testling", 16 | "CI", 17 | "Tutorial" 18 | ], 19 | "author": "@nelsonic", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/nelsonic/learn-testling/issues" 23 | }, 24 | "homepage": "https://github.com/nelsonic/learn-testling", 25 | "devDependencies": { 26 | "ordem": "^1.0.6", 27 | "qunit-tap": "^1.5.0", 28 | "qunitjs": "^1.18.0" 29 | }, 30 | "scripts": { 31 | "test": "node test/test.js", 32 | "start":"static-server.js" 33 | }, 34 | "testling": { 35 | "html": "test.html", 36 | "browsers": [ 37 | "ie/6..latest", 38 | "chrome/22..latest", 39 | "firefox/16..latest", 40 | "safari/latest", 41 | "opera/11.0..latest", 42 | "iphone/6", 43 | "ipad/6", 44 | "android-browser/latest" 45 | ] 46 | }, 47 | "dependencies": {} 48 | } 49 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 2 | // IE reduce polyfill 3 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce#Browser_compatibility 4 | if ( 'function' !== typeof Array.prototype.reduce ) { 5 | Array.prototype.reduce = function( callback /*, initialValue*/ ) { 6 | 'use strict'; 7 | if ( null === this || 'undefined' === typeof this ) { 8 | throw new TypeError( 9 | 'Array.prototype.reduce called on null or undefined' ); 10 | } 11 | if ( 'function' !== typeof callback ) { 12 | throw new TypeError( callback + ' is not a function' ); 13 | } 14 | var t = Object( this ), len = t.length >>> 0, k = 0, value; 15 | if ( arguments.length >= 2 ) { 16 | value = arguments[1]; 17 | } else { 18 | while ( k < len && ! k in t ) k++; 19 | if ( k >= len ) 20 | throw new TypeError('Reduce of empty array with no initial value'); 21 | value = t[ k++ ]; 22 | } 23 | for ( ; k < len ; k++ ) { 24 | if ( k in t ) { 25 | value = callback( value, t[k], k, t ); 26 | } 27 | } 28 | return value; 29 | }; 30 | } 31 | 32 | 33 | module.exports = function (xs, f) { 34 | if (typeof(xs.reduce) !== "undefined") { 35 | return xs.reduce(function (max, x) { 36 | return f(x) > f(max) ? x : max; 37 | }); 38 | } else { 39 | 40 | } 41 | }; -------------------------------------------------------------------------------- /test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Learn Testling 6 | 7 | 8 | 9 | 10 |
11 |
12 | 13 | 14 | 15 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | var ordenado = require('ordem'); // load the module 2 | var QUnit = require('qunitjs'); // require QUnit and all its friends 3 | require('qunit-tap')(QUnit, console.log); // tell qunit-tap to use console.log for test output 4 | 5 | test("run module without callback function", function(assert) { 6 | var expected = "Second argument to ordenado must be a callback function"; 7 | var err = ordenado('dont supply callback function'); 8 | assert.equal(err.message, expected, 'Expected ERROR: '+ expected); 9 | }); 10 | 11 | test("run module with string in place of tasks array", function(assert) { 12 | 13 | var expected = "First argument to ordenado must be an array of functions"; 14 | // exercise the function with a string instead of an array 15 | ordenado('this should fail array checks!', function callback(err, result) { 16 | // result now equals 'done' 17 | assert.equal(err.message, expected, 'Expected ERROR: '+ expected); 18 | }); 19 | 20 | }); 21 | 22 | test("run module without any tasks (expect error message)", function(assert) { 23 | // var done = assert.async(); // see: https://api.qunitjs.com/async/ 24 | var expected = "ordenado expects at least one task (function) to run"; 25 | 26 | // exercise the function without any tasks 27 | ordenado([], function callback(err, result) { 28 | assert.equal(err.message, expected, 'Expected: '+ expected); 29 | // done(); 30 | }); 31 | }); 32 | 33 | 34 | test("Simulate error in one of the tasks", function(assert) { 35 | var done = assert.async(); // see: https://api.qunitjs.com/async/ 36 | var actual = []; 37 | var expected = [ 'only one' ]; // only the first task succeeds 38 | 39 | // exercise the function 40 | ordenado([ 41 | function(callback){ 42 | actual.push('only one'); 43 | callback(null, 'only one'); 44 | }, 45 | function(arg, callback){ 46 | var err = new Error('second task failed'); 47 | return callback(err); 48 | }, 49 | function(arg1, callback){ 50 | // this task will never get run! 51 | actual.push('this will never get pushed'); 52 | callback(null, 'second task failed so this never runs!'); 53 | } 54 | ], function callback(err, result) { 55 | // result now equals 'done' 56 | // console.log(err); 57 | assert.equal(err.message, 'second task failed', 'Second task failed (as expected!)'); 58 | assert.deepEqual(actual, expected, 'Expected: Only one task succeeded'); 59 | done(); 60 | }); 61 | }); 62 | 63 | 64 | test("Results appear in the order we expect them", function(assert) { 65 | var done = assert.async(); // see: https://api.qunitjs.com/async/ 66 | var actual = []; 67 | var expected = [ 'one', 'two', 'three' ]; 68 | 69 | // exercise the function 70 | ordenado([ 71 | function(callback){ 72 | actual.push('one'); 73 | callback(null, 'one', 'two'); 74 | }, 75 | function(arg1, arg2, callback){ 76 | actual.push('two'); 77 | callback(null, 'three'); 78 | }, 79 | function(arg1, callback){ 80 | // arg1 now equals 'three' 81 | actual.push('three'); 82 | callback(null, 'done'); 83 | } 84 | ], function callback(err, result) { 85 | if(err) { 86 | console.log(err); 87 | } 88 | // result now equals 'done' 89 | for(i=0; i Come back to this if we get any reply on StackOverflow, Twitter or GitHub! until then, SauceLabs... 25 | 26 | ## Note 27 | 28 | To run this project you will need to sign up to **Browserling**: 29 | https://www.browserling.com/ 30 | at the time of writing the API is available by invite. 31 | Once you've registered, send browserling an email to get access. 32 | 33 | ![browserling-live-api-email-reply](https://cloud.githubusercontent.com/assets/194400/7678534/cb346b82-fd4c-11e4-899d-6736556a2d23.png) 34 | 35 | 36 | ## Environment Variables 37 | 38 | ```sh 39 | export BROWSERLING_EMAIL= 40 | export BROWSERLING_PASSWORD= 41 | ``` 42 | 43 | 44 |
45 |
46 | 47 | # tl;dr 48 | 49 | > Currently getting the following error while trying to run **testling** CLI locally: 50 | 51 | ![Testling TypeError](http://i.imgur.com/VsSdwWv.png) 52 | 53 | > Submitted issue: https://github.com/substack/testling/issues/82 54 | > Sent tweet to @substack: https://twitter.com/nelsonic/statuses/469425224770146304 55 | 56 | 57 | [![browser support](https://ci.testling.com/nelsonic/learn-testling.png) 58 | ](https://ci.testling.com/nelsonic/learn-testling) 59 | 60 | Quick intro to Testling CI (Cross Browser Testing) 61 | 62 | If you've never heard of testling (or been *too busy* to try it out) 63 | in the next 10 minutes you will learn everything you need to get started. 64 | 65 | ### What is Testling? 66 | 67 | [Tesling][] is an automated browser testing tool (brother of [Browserling][]) 68 | that lets you "***run your browser tests on every push***". 69 | 70 | Testling will not *magically* make your app work in all browsers. :tired_face:
71 | You will still need to write (unit) tests, Testling will run them for you 72 | in any browser you specify in your package.json configuration file. 73 | 74 | ### Get Started 75 | 76 | Since there's no registration required for open-source projects, 77 | you can just dive in by following: https://ci.testling.com/guide/quick_start 78 | 79 | 80 | ### Result! 81 | 82 | https://ci.testling.com/nelsonic/learn-testling 83 | 84 | Sadly Internet Explorer 6, 7 & 8 does not pass... 85 | 86 | https://twitter.com/nelsonic/statuses/465651619070500864 87 | 88 | 89 | 90 | > ***Next***: Investigate Tape https://ci.testling.com/guide/tape 91 | 92 | > [ ] Fix build! 93 | 94 | 95 | ### Background Info 96 | 97 | [Tesling][] is Made by Peteris Krumins [@pkrumins](https://github.com/pkrumins) 98 | and James Halliday [@substack](https://github.com/substack) who you may 99 | know from Nodeschool's [Stream Adventure][] 100 | 101 | 102 | ### Hurdles 103 | 104 | Got Stuck adding WebHook URL ...
105 | Sent tweet to Substack: https://twitter.com/nelsonic/statuses/465249089605881857
106 | Submitted issue to: https://github.com/substack/testling/issues/81 107 | 108 | #### Responsive Founders 109 | 110 | Got Stuck adding a WebHook URL ...
111 | Sent tweet to Substack: https://twitter.com/nelsonic/statuses/465249089605881857
112 | and submitted an issue to: https://github.com/substack/testling/issues/81 113 | 114 | Its always a good sign when (busy) founders answer queries: 115 | 116 | ![Twitter Reply from Substack](http://i.imgur.com/9ynfYGf.png) 117 | 118 | See: https://twitter.com/substack/statuses/465599077342654464 119 | 120 | [Tesling]: https://ci.testling.com/ 121 | [Browserling]: https://browserling.com 122 | [Stream Adventure]: http://nodeschool.io/#stream-adventure 123 | 124 | Got Stuck adding WebHook URL ...
125 | Sent tweet to Substack: https://twitter.com/nelsonic/statuses/465249089605881857
126 | Submitted issue to: https://github.com/substack/testling/issues/81 127 | -------------------------------------------------------------------------------- /testling-webhook-payload.txt: -------------------------------------------------------------------------------- 1 | { 2 | "ref": "refs/heads/master", 3 | "before": "a446e1a9a7963b7b1710cacbe6c50e7a56bac0be", 4 | "after": "b87134707d5e5db7b3c3c192506aaf7b7d3b4fcb", 5 | "created": false, 6 | "deleted": false, 7 | "forced": false, 8 | "base_ref": null, 9 | "compare": "https://github.com/nelsonic/learn-testling/compare/a446e1a9a796...b87134707d5e", 10 | "commits": [ 11 | { 12 | "id": "b87134707d5e5db7b3c3c192506aaf7b7d3b4fcb", 13 | "distinct": true, 14 | "message": "updates package.json to use html instead of file https://ci.testling.com/guide/advanced_configuration", 15 | "timestamp": "2015-05-18T18:02:35+01:00", 16 | "url": "https://github.com/nelsonic/learn-testling/commit/b87134707d5e5db7b3c3c192506aaf7b7d3b4fcb", 17 | "author": { 18 | "name": "nelsonic", 19 | "email": "contact.nelsonic@gmail.com", 20 | "username": "nelsonic" 21 | }, 22 | "committer": { 23 | "name": "nelsonic", 24 | "email": "contact.nelsonic@gmail.com", 25 | "username": "nelsonic" 26 | }, 27 | "added": [ 28 | 29 | ], 30 | "removed": [ 31 | 32 | ], 33 | "modified": [ 34 | "package.json" 35 | ] 36 | } 37 | ], 38 | "head_commit": { 39 | "id": "b87134707d5e5db7b3c3c192506aaf7b7d3b4fcb", 40 | "distinct": true, 41 | "message": "updates package.json to use html instead of file https://ci.testling.com/guide/advanced_configuration", 42 | "timestamp": "2015-05-18T18:02:35+01:00", 43 | "url": "https://github.com/nelsonic/learn-testling/commit/b87134707d5e5db7b3c3c192506aaf7b7d3b4fcb", 44 | "author": { 45 | "name": "nelsonic", 46 | "email": "contact.nelsonic@gmail.com", 47 | "username": "nelsonic" 48 | }, 49 | "committer": { 50 | "name": "nelsonic", 51 | "email": "contact.nelsonic@gmail.com", 52 | "username": "nelsonic" 53 | }, 54 | "added": [ 55 | 56 | ], 57 | "removed": [ 58 | 59 | ], 60 | "modified": [ 61 | "package.json" 62 | ] 63 | }, 64 | "repository": { 65 | "id": 19635048, 66 | "name": "learn-testling", 67 | "full_name": "nelsonic/learn-testling", 68 | "owner": { 69 | "name": "nelsonic", 70 | "email": "contact.nelsonic@gmail.com" 71 | }, 72 | "private": false, 73 | "html_url": "https://github.com/nelsonic/learn-testling", 74 | "description": "Quick intro to Testling CI (Cross Browser Testing)", 75 | "fork": false, 76 | "url": "https://github.com/nelsonic/learn-testling", 77 | "forks_url": "https://api.github.com/repos/nelsonic/learn-testling/forks", 78 | "keys_url": "https://api.github.com/repos/nelsonic/learn-testling/keys{/key_id}", 79 | "collaborators_url": "https://api.github.com/repos/nelsonic/learn-testling/collaborators{/collaborator}", 80 | "teams_url": "https://api.github.com/repos/nelsonic/learn-testling/teams", 81 | "hooks_url": "https://api.github.com/repos/nelsonic/learn-testling/hooks", 82 | "issue_events_url": "https://api.github.com/repos/nelsonic/learn-testling/issues/events{/number}", 83 | "events_url": "https://api.github.com/repos/nelsonic/learn-testling/events", 84 | "assignees_url": "https://api.github.com/repos/nelsonic/learn-testling/assignees{/user}", 85 | "branches_url": "https://api.github.com/repos/nelsonic/learn-testling/branches{/branch}", 86 | "tags_url": "https://api.github.com/repos/nelsonic/learn-testling/tags", 87 | "blobs_url": "https://api.github.com/repos/nelsonic/learn-testling/git/blobs{/sha}", 88 | "git_tags_url": "https://api.github.com/repos/nelsonic/learn-testling/git/tags{/sha}", 89 | "git_refs_url": "https://api.github.com/repos/nelsonic/learn-testling/git/refs{/sha}", 90 | "trees_url": "https://api.github.com/repos/nelsonic/learn-testling/git/trees{/sha}", 91 | "statuses_url": "https://api.github.com/repos/nelsonic/learn-testling/statuses/{sha}", 92 | "languages_url": "https://api.github.com/repos/nelsonic/learn-testling/languages", 93 | "stargazers_url": "https://api.github.com/repos/nelsonic/learn-testling/stargazers", 94 | "contributors_url": "https://api.github.com/repos/nelsonic/learn-testling/contributors", 95 | "subscribers_url": "https://api.github.com/repos/nelsonic/learn-testling/subscribers", 96 | "subscription_url": "https://api.github.com/repos/nelsonic/learn-testling/subscription", 97 | "commits_url": "https://api.github.com/repos/nelsonic/learn-testling/commits{/sha}", 98 | "git_commits_url": "https://api.github.com/repos/nelsonic/learn-testling/git/commits{/sha}", 99 | "comments_url": "https://api.github.com/repos/nelsonic/learn-testling/comments{/number}", 100 | "issue_comment_url": "https://api.github.com/repos/nelsonic/learn-testling/issues/comments{/number}", 101 | "contents_url": "https://api.github.com/repos/nelsonic/learn-testling/contents/{+path}", 102 | "compare_url": "https://api.github.com/repos/nelsonic/learn-testling/compare/{base}...{head}", 103 | "merges_url": "https://api.github.com/repos/nelsonic/learn-testling/merges", 104 | "archive_url": "https://api.github.com/repos/nelsonic/learn-testling/{archive_format}{/ref}", 105 | "downloads_url": "https://api.github.com/repos/nelsonic/learn-testling/downloads", 106 | "issues_url": "https://api.github.com/repos/nelsonic/learn-testling/issues{/number}", 107 | "pulls_url": "https://api.github.com/repos/nelsonic/learn-testling/pulls{/number}", 108 | "milestones_url": "https://api.github.com/repos/nelsonic/learn-testling/milestones{/number}", 109 | "notifications_url": "https://api.github.com/repos/nelsonic/learn-testling/notifications{?since,all,participating}", 110 | "labels_url": "https://api.github.com/repos/nelsonic/learn-testling/labels{/name}", 111 | "releases_url": "https://api.github.com/repos/nelsonic/learn-testling/releases{/id}", 112 | "created_at": 1399703272, 113 | "updated_at": "2015-05-17T20:01:20Z", 114 | "pushed_at": 1431968559, 115 | "git_url": "git://github.com/nelsonic/learn-testling.git", 116 | "ssh_url": "git@github.com:nelsonic/learn-testling.git", 117 | "clone_url": "https://github.com/nelsonic/learn-testling.git", 118 | "svn_url": "https://github.com/nelsonic/learn-testling", 119 | "homepage": null, 120 | "size": 368, 121 | "stargazers_count": 4, 122 | "watchers_count": 4, 123 | "language": "JavaScript", 124 | "has_issues": true, 125 | "has_downloads": true, 126 | "has_wiki": true, 127 | "has_pages": false, 128 | "forks_count": 1, 129 | "mirror_url": null, 130 | "open_issues_count": 1, 131 | "forks": 1, 132 | "open_issues": 1, 133 | "watchers": 4, 134 | "default_branch": "master", 135 | "stargazers": 4, 136 | "master_branch": "master" 137 | }, 138 | "pusher": { 139 | "name": "nelsonic", 140 | "email": "contact.nelsonic@gmail.com" 141 | }, 142 | "sender": { 143 | "login": "nelsonic", 144 | "id": 194400, 145 | "avatar_url": "https://avatars.githubusercontent.com/u/194400?v=3", 146 | "gravatar_id": "", 147 | "url": "https://api.github.com/users/nelsonic", 148 | "html_url": "https://github.com/nelsonic", 149 | "followers_url": "https://api.github.com/users/nelsonic/followers", 150 | "following_url": "https://api.github.com/users/nelsonic/following{/other_user}", 151 | "gists_url": "https://api.github.com/users/nelsonic/gists{/gist_id}", 152 | "starred_url": "https://api.github.com/users/nelsonic/starred{/owner}{/repo}", 153 | "subscriptions_url": "https://api.github.com/users/nelsonic/subscriptions", 154 | "organizations_url": "https://api.github.com/users/nelsonic/orgs", 155 | "repos_url": "https://api.github.com/users/nelsonic/repos", 156 | "events_url": "https://api.github.com/users/nelsonic/events{/privacy}", 157 | "received_events_url": "https://api.github.com/users/nelsonic/received_events", 158 | "type": "User", 159 | "site_admin": false 160 | } 161 | } 162 | --------------------------------------------------------------------------------