From f8282ea8338c8b4e0a52f4f24dc4701aa3da4655 Mon Sep 17 00:00:00 2001 From: rhod williams Date: Thu, 31 May 2012 17:00:43 +0100 Subject: [PATCH 1/9] test pushing to github --- rhods new text file.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 rhods new text file.txt diff --git a/rhods new text file.txt b/rhods new text file.txt new file mode 100644 index 000000000000..e69de29bb2d1 From b3901b571431275857174b8dacce688d5ce7f831 Mon Sep 17 00:00:00 2001 From: rhod williams Date: Thu, 31 May 2012 17:01:00 +0100 Subject: [PATCH 2/9] Revert "test pushing to github" This reverts commit f8282ea8338c8b4e0a52f4f24dc4701aa3da4655. --- rhods new text file.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 rhods new text file.txt diff --git a/rhods new text file.txt b/rhods new text file.txt deleted file mode 100644 index e69de29bb2d1..000000000000 From ab934dd2e0f34f993273e5e6ba53310394be442a Mon Sep 17 00:00:00 2001 From: Tim Haines Date: Tue, 26 Jun 2012 15:54:19 +0100 Subject: [PATCH 3/9] Integration with cucumber. Allow describe blocks to be created and closed by the called (new method Describe start). Also added a description to the describe block. Updated rakefile so that css is always minified. --- Rakefile | 2 +- css/angular-scenario.css | 6 ++++++ src/ngScenario/Describe.js | 9 ++++++--- src/ngScenario/Runner.js | 24 +++++++++++++++++++++++- src/ngScenario/output/Html.js | 11 ++++++++++- 5 files changed, 46 insertions(+), 6 deletions(-) diff --git a/Rakefile b/Rakefile index 9c18da9dc728..36ec7675448f 100644 --- a/Rakefile +++ b/Rakefile @@ -237,7 +237,7 @@ end ## # generates css snippet from a given files and optionally applies simple minification rules # -def gen_css(cssFile, minify = false) +def gen_css(cssFile, minify = true) css = '' File.open(cssFile, 'r') do |f| css = f.read diff --git a/css/angular-scenario.css b/css/angular-scenario.css index b8d25c1c08d0..ab4c3180f00d 100644 --- a/css/angular-scenario.css +++ b/css/angular-scenario.css @@ -195,6 +195,12 @@ body { background-color: #efefef; } +#specs .description { + background-color: #EFEFEF; + padding-left: 20px; + font-style: italic; +} + #application { border: 1px solid #BABAD1; } diff --git a/src/ngScenario/Describe.js b/src/ngScenario/Describe.js index 4d52e9d58486..a95f341ab7c2 100644 --- a/src/ngScenario/Describe.js +++ b/src/ngScenario/Describe.js @@ -6,14 +6,16 @@ * * @param {string} descName Name of the block * @param {Object} parent describe or undefined if the root. + * @param {string} descDescription Description of the block */ -angular.scenario.Describe = function(descName, parent) { +angular.scenario.Describe = function(descName, parent, descDescription) { this.only = parent && parent.only; this.beforeEachFns = []; this.afterEachFns = []; this.its = []; this.children = []; this.name = descName; + this.description = descDescription; this.parent = parent; this.id = angular.scenario.Describe.id++; @@ -65,9 +67,10 @@ angular.scenario.Describe.prototype.afterEach = function(body) { * * @param {string} name Name of the block. Appended to the parent block's name. * @param {function()} body Body of the block. + * @param {string} description Description of the block. Appended to the parent block's name. */ -angular.scenario.Describe.prototype.describe = function(name, body) { - var child = new angular.scenario.Describe(name, this); +angular.scenario.Describe.prototype.describe = function(name, body, description) { + var child = new angular.scenario.Describe(name, this, description); this.children.push(child); body.call(child); }; diff --git a/src/ngScenario/Runner.js b/src/ngScenario/Runner.js index 06ad3aa184de..769f2396ddcf 100644 --- a/src/ngScenario/Runner.js +++ b/src/ngScenario/Runner.js @@ -12,10 +12,11 @@ angular.scenario.Runner = function($window) { this.rootDescribe = new angular.scenario.Describe(); this.currentDescribe = this.rootDescribe; this.api = { - it: this.it, + it: this.it, iit: this.iit, xit: angular.noop, describe: this.describe, + describeStart: this.describeStart, ddescribe: this.ddescribe, xdescribe: angular.noop, beforeEach: this.beforeEach, @@ -76,6 +77,27 @@ angular.scenario.Runner.prototype.describe = function(name, body) { }); }; +/** + * Defines a describe block of a spec, but allows the body to callback when the describe has been processed. + * + * @see Describe.js + * + * @param {string} name Name of the block + * @param {function()} body Body of the block + * @param {string} description Description of the block + */ +angular.scenario.Runner.prototype.describeStart = function(name, body, description) { + var self = this; + this.currentDescribe.describe(name, function() { + var parentDescribe = self.currentDescribe; + var endDescribeCallback = function() {self.currentDescribe = parentDescribe;}; + + self.currentDescribe = this; + body.call(this, endDescribeCallback); + }, + description); +}; + /** * Same as describe, but makes ddescribe the only blocks to run. * diff --git a/src/ngScenario/output/Html.js b/src/ngScenario/output/Html.js index 7f69a734db20..39a99d1d0459 100644 --- a/src/ngScenario/output/Html.js +++ b/src/ngScenario/output/Html.js @@ -133,11 +133,20 @@ angular.scenario.output('html', function(context, runner, model) { currentContext.find('> .test-children').append( '
' + '

' + + ' ' + '
' + '
    ' + '
    ' ); - context.find('#' + id).find('> h2').text('describe: ' + defn.name); + context.find('#' + id).find('> h2').text(defn.name); + + // Add the description if it exists + if(!!defn.description) + { + var $description = context.find('#' + id).find('> .description'); + $description.text(defn.description); + $description.show(); + } } currentContext = context.find('#' + id); }); From 93e0724c6e478a55c8725eaae5946064464df1e5 Mon Sep 17 00:00:00 2001 From: Maciej Borzecki Date: Fri, 3 Aug 2012 09:45:36 +0100 Subject: [PATCH 4/9] Changing angular.scenario.Application.prototype.executeAction method so it calls AngularInit when application is manually bootstrapped. Original code works only with auto bootstrapped applications (by using ng-app directive). This work is part of blinkbox tfs ticket 23957. --- src/ngScenario/Application.js | 58 ++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/src/ngScenario/Application.js b/src/ngScenario/Application.js index 2ca6c8fdf555..f37af5a90583 100644 --- a/src/ngScenario/Application.js +++ b/src/ngScenario/Application.js @@ -81,27 +81,43 @@ angular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorF * @param {function()} action The callback to execute. function($window, $document) * $document is a jQuery wrapped document. */ -angular.scenario.Application.prototype.executeAction = function(action) { - var self = this; - var $window = this.getWindow_(); - if (!$window.document) { - throw 'Sandbox Error: Application document not accessible.'; - } - if (!$window.angular) { - return action.call(this, $window, _jQuery($window.document)); - } - angularInit($window.document, function(element) { - var $injector = $window.angular.element(element).injector(); - var $element = _jQuery(element); +angular.scenario.Application.prototype.executeAction = function(action) +{ + var self = this; + var $window = this.getWindow_(); + if (!$window.document) { + throw 'Sandbox Error: Application document not accessible.'; + } + + if (!$window.angular) { + return action.call(this, $window, _jQuery($window.document)); + } + + var initialisedWithNgAppDirective = false; + + // angularInit calls this function only if ng-app directive is detected + var initFn = function(element) { + initialisedWithNgAppDirective = true; + + var $injector = $window.angular.element(element).injector(); + var $element = _jQuery(element); + + $element.injector = function() { + return $injector; + }; + + $injector.invoke(function($browser) { + $browser.notifyWhenNoOutstandingRequests(function() { + action.call(self, $window, $element); + }); + }); + }; - $element.injector = function() { - return $injector; - }; + // original implementation searches for ng-app and attaches to angular if found + angularInit($window.document, initFn); - $injector.invoke(function($browser){ - $browser.notifyWhenNoOutstandingRequests(function() { - action.call(self, $window, $element); - }); - }); - }); + if (!initialisedWithNgAppDirective) { + // ng-app not found so manually attaching to the root of document + initFn($window.document); + } }; From 02094eff94f943010cc550bd77a40df14ba3ec86 Mon Sep 17 00:00:00 2001 From: rhod williams Date: Tue, 7 Aug 2012 10:45:53 +0100 Subject: [PATCH 5/9] add ability to disable html history functionality in the browser service. --- src/ng/browser.js | 16 +++++++++++++--- src/ng/location.js | 3 +++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/ng/browser.js b/src/ng/browser.js index 3925348317ce..245b6417ce6d 100644 --- a/src/ng/browser.js +++ b/src/ng/browser.js @@ -29,7 +29,8 @@ function Browser(window, document, $log, $sniffer) { history = window.history, setTimeout = window.setTimeout, clearTimeout = window.clearTimeout, - pendingDeferIds = {}; + pendingDeferIds = {}, + useHtml5HistoryMode = false; self.isMock = false; @@ -151,7 +152,7 @@ function Browser(window, document, $log, $sniffer) { if (url) { if (lastBrowserUrl == url) return; lastBrowserUrl = url; - if ($sniffer.history) { + if ($sniffer.history && useHtml5HistoryMode) { if (replace) history.replaceState(null, '', url); else { history.pushState(null, '', url); @@ -212,7 +213,7 @@ function Browser(window, document, $log, $sniffer) { // changed by push/replaceState // html5 history api - popstate event - if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange); + if ($sniffer.history && useHtml5HistoryMode) jqLite(window).bind('popstate', fireUrlChange); // hashchange event if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange); // polling @@ -352,6 +353,15 @@ function Browser(window, document, $log, $sniffer) { return false; }; + self.html5HistoryMode = function(mode) { + if (isDefined(mode)) { + useHtml5HistoryMode = mode; + return this; + } else { + return useHtml5HistoryMode; + } + }; + } function $BrowserProvider(){ diff --git a/src/ng/location.js b/src/ng/location.js index cf50952d53c3..3c8b9752ba75 100644 --- a/src/ng/location.js +++ b/src/ng/location.js @@ -514,6 +514,9 @@ function $LocationProvider(){ initUrlParts = matchUrl(initUrl), appBaseUrl; + // Apply the html5Mode setting to the $browser service + $browser.html5HistoryMode(html5Mode); + if (html5Mode) { basePath = $browser.baseHref() || '/'; pathPrefix = pathPrefixFromBase(basePath); From 4b7c65fbe554bff4e0ff33d8f105d3b3c6694dc8 Mon Sep 17 00:00:00 2001 From: Nisheeth Kashyap Date: Fri, 28 Sep 2012 16:11:48 +0100 Subject: [PATCH 6/9] Angular test fixed --- test/ngScenario/output/HtmlSpec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/ngScenario/output/HtmlSpec.js b/test/ngScenario/output/HtmlSpec.js index 442e596dd9f3..b066f82c5cd6 100644 --- a/test/ngScenario/output/HtmlSpec.js +++ b/test/ngScenario/output/HtmlSpec.js @@ -31,8 +31,8 @@ describe('angular.scenario.output.html', function() { it('should create nested describe context', function() { runner.emit('SpecBegin', spec); expect(context.find('#describe-20 #describe-10 > h2').text()). - toEqual('describe: child'); - expect(context.find('#describe-20 > h2').text()).toEqual('describe: parent'); + toEqual('child'); + expect(context.find('#describe-20 > h2').text()).toEqual('parent'); expect(context.find('#describe-10 .tests > li .test-info .test-name').text()). toEqual('test spec'); expect(context.find('#describe-10 .tests > li').hasClass('status-pending')). From 273828e55df25bb9f62d7bca6643281f44a6e468 Mon Sep 17 00:00:00 2001 From: Nisheeth Kashyap Date: Fri, 28 Sep 2012 16:12:36 +0100 Subject: [PATCH 7/9] space added in jstestdriver coverage plugin configuration --- gen_jstd_configs.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gen_jstd_configs.js b/gen_jstd_configs.js index 842cfe2100d6..c8227ff12b43 100755 --- a/gen_jstd_configs.js +++ b/gen_jstd_configs.js @@ -31,8 +31,8 @@ fs.readFile('angularFiles.js', function(err, data) { fs.writeFile('./jsTestDriver-coverage.conf', prefix + combine(angularFiles.jstd, angularFiles.jstdExclude) + '\n\nplugin:\n- name: "coverage"\n' + - 'jar: "lib/jstestdriver/coverage.jar"\n' + - 'module: "com.google.jstestdriver.coverage.CoverageModule"'); + ' jar: "lib/jstestdriver/coverage.jar"\n' + + ' module: "com.google.jstestdriver.coverage.CoverageModule"'); }); function combine(load, exclude) { From 8b4f2ce01f94f97520a87303f4754c0b7690740f Mon Sep 17 00:00:00 2001 From: Nisheeth Kashyap Date: Tue, 9 Oct 2012 15:57:29 +0100 Subject: [PATCH 8/9] Detect whether history.pushState update location Detect whether history.pushState update location correctly rather then relying on browser userAgent string. --- src/ng/sniffer.js | 36 +++++++++++++++++++++++++++++------- test/ng/snifferSpec.js | 13 +++++++++++-- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/src/ng/sniffer.js b/src/ng/sniffer.js index a7d73716b05d..81efef0bc54c 100644 --- a/src/ng/sniffer.js +++ b/src/ng/sniffer.js @@ -13,16 +13,38 @@ * This is very simple implementation of testing browser's features. */ function $SnifferProvider() { + var historyPushStateUpdatesURL; + this.$get = ['$window', function($window) { - var eventSupport = {}, - android = int((/android (\d+)/.exec(lowercase($window.navigator.userAgent)) || [])[1]); + var eventSupport = {}; + + // Android has history.pushState, but it does not update location correctly + // so let's not use the history API at all. + // http://code.google.com/p/android/issues/detail?id=17471 + // https://github.com/angular/angular.js/issues/904 + // + // Detect this issue by checking whether browser history.pushState changes URL + // rather then relying on browser userAgent string. + if(historyPushStateUpdatesURL === undefined){ + historyPushStateUpdatesURL = !!($window.history && $window.history.pushState); + + if(historyPushStateUpdatesURL){ + var urlToken = '__ANGULARJS__'; + var originalHref = $window.location.href; + var originalTitle = $window.document.title; + + $window.history.pushState(null, '', urlToken); + historyPushStateUpdatesURL = $window.location.href.indexOf(urlToken) > -1; + + if (historyPushStateUpdatesURL) + { + $window.history.replaceState(null, originalTitle, originalHref); + } + } + } return { - // Android has history.pushState, but it does not update location correctly - // so let's not use the history API at all. - // http://code.google.com/p/android/issues/detail?id=17471 - // https://github.com/angular/angular.js/issues/904 - history: !!($window.history && $window.history.pushState && !(android < 4)), + history: !!historyPushStateUpdatesURL, hashchange: 'onhashchange' in $window && // IE8 compatible mode lies (!$window.document.documentMode || $window.document.documentMode > 7), diff --git a/test/ng/snifferSpec.js b/test/ng/snifferSpec.js index a34a19750e11..18fd43dd65df 100644 --- a/test/ng/snifferSpec.js +++ b/test/ng/snifferSpec.js @@ -8,8 +8,17 @@ describe('$sniffer', function() { } describe('history', function() { - it('should be true if history.pushState defined', function() { - expect(sniffer({history: {pushState: noop, replaceState: noop}}).history).toBe(true); + it('should be true if history.pushState is defined and it affects location.href', function() { + var mockWindow = { + document: {title : ''}, + location: {href: ''}, + history: { + pushState: function(state, title, url){ mockWindow.location.href = url }, + replaceState: noop + } + }; + + expect(sniffer(mockWindow).history).toBe(true); }); it('should be false if history or pushState not defined', function() { From 620ea2d6b18fb3c6912afa106157233979e2fe77 Mon Sep 17 00:00:00 2001 From: Nisheeth Kashyap Date: Tue, 9 Oct 2012 15:59:38 +0100 Subject: [PATCH 9/9] Remove unnecessary comma from object to fix test Remove unnecessary comma from object to fix test --- test/ng/httpSpec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ng/httpSpec.js b/test/ng/httpSpec.js index bb4de3c1a5e2..b7dc50eaa8cc 100644 --- a/test/ng/httpSpec.js +++ b/test/ng/httpSpec.js @@ -362,7 +362,7 @@ describe('$http', function() { }).respond(''); $http({url: '/url', method: 'GET', headers: { - 'Custom': 'header', + 'Custom': 'header' }}); $httpBackend.flush();