Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 1b3d347

Browse files
committed
test($anchorScroll): add e2e tests
1 parent d1ccf17 commit 1b3d347

File tree

1 file changed

+187
-6
lines changed

1 file changed

+187
-6
lines changed

src/ng/anchorScroll.js

+187-6
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ function $AnchorScrollProvider() {
7373
<example module="anchorScrollExample">
7474
<file name="index.html">
7575
<div id="scrollArea" ng-controller="ScrollController">
76-
<a ng-click="gotoBottom()">Go to bottom</a>
76+
<a id="top" ng-click="gotoBottom()">Go to bottom</a>
7777
<a id="bottom"></a> You're at the bottom!
7878
</div>
7979
</file>
@@ -102,6 +102,37 @@ function $AnchorScrollProvider() {
102102
margin-top: 2000px;
103103
}
104104
</file>
105+
<file name="protractor.js" type="protractor">
106+
function _isElemVisible() {
107+
var elem = document.getElementById(arguments[0]);
108+
var rect = elem.getBoundingClientRect();
109+
var docElem = document.documentElement;
110+
return (rect.top < docElem.clientHeight) &&
111+
(rect.bottom > 0) &&
112+
(rect.left < docElem.clientWidth) &&
113+
(rect.right > 0);
114+
}
115+
116+
function expectVisible(id, expected) {
117+
browser.driver.executeScript(_isElemVisible, id).then(function(isVisible) {
118+
expect(isVisible).toBe(expected);
119+
});
120+
}
121+
122+
function scrollToTop() {
123+
browser.driver.executeScript('window.scrollTo(0, 0);');
124+
}
125+
126+
it('should scroll to #bottom upon clicking #top', function() {
127+
scrollToTop();
128+
expectVisible('top', true);
129+
expectVisible('bottom', false);
130+
131+
element(by.id('top')).click();
132+
expectVisible('top', false);
133+
expectVisible('bottom', true);
134+
});
135+
</file>
105136
</example>
106137
*
107138
* <hr />
@@ -112,18 +143,19 @@ function $AnchorScrollProvider() {
112143
<example module="anchorScrollOffsetExample">
113144
<file name="index.html">
114145
<div class="fixed-header" ng-controller="headerCtrl">
115-
<a href="" ng-click="gotoAnchor(x)" ng-repeat="x in [1,2,3,4,5]">
116-
Go to anchor {{x}}
146+
<a href="" ng-click="gotoAnchor(x)" ng-repeat="x in [0,1,2,3,4]">
147+
Go to anchor {{$index + 1}}
117148
</a>
118149
</div>
119-
<div id="anchor{{x}}" class="anchor" ng-repeat="x in [1,2,3,4,5]">
120-
Anchor {{x}} of 5
150+
<div id="anchor{{y}}" class="anchor" ng-repeat="y in [0,1,2,3,4]">
151+
Anchor {{$index + 1}} of 5
121152
</div>
122153
</file>
123154
<file name="script.js">
124155
angular.module('anchorScrollOffsetExample', [])
125156
.run(['$anchorScroll', function($anchorScroll) {
126-
$anchorScroll.yOffset = 50; // always scroll by 50 extra pixels
157+
// scroll with a 50px offset from the top of the viewport
158+
$anchorScroll.yOffset = 50;
127159
}])
128160
.controller('headerCtrl', ['$anchorScroll', '$location', '$scope',
129161
function ($anchorScroll, $location, $scope) {
@@ -144,6 +176,8 @@ function $AnchorScrollProvider() {
144176
</file>
145177
<file name="style.css">
146178
body {
179+
height: 100%;
180+
margin: 0;
147181
padding-top: 50px;
148182
}
149183
@@ -164,6 +198,153 @@ function $AnchorScrollProvider() {
164198
margin: 5px 15px;
165199
}
166200
</file>
201+
<file name="protractor.js" type="protractor">
202+
function _isElemVisible() {
203+
var elem = document.getElementById(arguments[0]);
204+
var rect = elem.getBoundingClientRect();
205+
var docElem = document.documentElement;
206+
return (rect.top < docElem.clientHeight) &&
207+
(rect.bottom > 0) &&
208+
(rect.left < docElem.clientWidth) &&
209+
(rect.right > 0);
210+
}
211+
212+
function _getElemTop() {
213+
var elem = document.getElementById(arguments[0]);
214+
var rect = elem.getBoundingClientRect();
215+
return rect.top;
216+
}
217+
218+
function _getViewportHeight() {
219+
return window.document.documentElement.clientHeight;
220+
}
221+
222+
function _scrollElemIntoView() {
223+
var elem = document.getElementById(arguments[0]);
224+
elem.scrollIntoView();
225+
}
226+
227+
function execWithTempViewportHeight(tempHeight, fn) {
228+
setViewportHeight(tempHeight).then(function(oldHeight) {
229+
fn();
230+
setViewportHeight(oldHeight);
231+
});
232+
}
233+
234+
function execWithTempHash(tempHash, fn) {
235+
browser.driver.getCurrentUrl().then(function(oldUrl) {
236+
var newUrl = oldUrl + '#/#' + tempHash;
237+
browser.get(newUrl);
238+
fn();
239+
browser.get(oldUrl);
240+
});
241+
}
242+
243+
function expectVisible(id, expected) {
244+
browser.driver.executeScript(_isElemVisible, id).then(function(isVisible) {
245+
expect(isVisible).toBe(expected);
246+
});
247+
}
248+
249+
function expectTop(id, expected) {
250+
browser.driver.executeScript(_getElemTop, id).then(function(top) {
251+
expect(top).toBe(expected);
252+
});
253+
}
254+
255+
256+
function scrollIntoView(id) {
257+
browser.driver.executeScript(_scrollElemIntoView, id);
258+
}
259+
260+
function scrollTo(y) {
261+
browser.driver.executeScript('window.scrollTo(0, ' + y + ');');
262+
}
263+
264+
function scrollToTop() {
265+
scrollTo(0);
266+
}
267+
268+
function setViewportHeight(newHeight) {
269+
return browser.driver.executeScript(_getViewportHeight).then(function(oldHeight) {
270+
var heightDiff = newHeight - oldHeight;
271+
var win = browser.driver.manage().window();
272+
273+
return win.getSize().then(function(size) {
274+
var newWinHeight = size.height + heightDiff;
275+
276+
return win.setSize(size.width, newWinHeight).then(function() {
277+
return oldHeight;
278+
});
279+
});
280+
});
281+
}
282+
283+
describe('scrolling with 50px offset', function() {
284+
var yOffset = 50;
285+
286+
beforeEach(function() {
287+
scrollToTop();
288+
expectVisible('anchor0', true);
289+
expectTop('anchor0', yOffset);
290+
});
291+
292+
it('should scroll to the correct anchor when clicking each link', function() {
293+
var links = element.all(by.repeater('x in [0,1,2,3,4]'));
294+
var lastAnchor = element.all(by.repeater('y in [0,1,2,3,4]')).last();
295+
296+
// Make sure there is enough room to scroll the last anchor to the top
297+
lastAnchor.getSize().then(function(size) {
298+
var tempHeight = size.height - 10;
299+
execWithTempViewportHeight(tempHeight, function() {
300+
var idx = 0;
301+
links.each(function(link) {
302+
var targetAnchorId = 'anchor' + idx;
303+
link.click();
304+
expectVisible(targetAnchorId, true);
305+
expectTop(targetAnchorId, yOffset);
306+
idx++;
307+
});
308+
});
309+
});
310+
});
311+
312+
it('should automatically scroll when navigating to a URL with a hash', function() {
313+
var links = element.all(by.repeater('x in [0,1,2,3,4]'));
314+
var lastAnchor = element.all(by.repeater('y in [0,1,2,3,4]')).last();
315+
var targetAnchorId = 'anchor2';
316+
317+
// Make sure there is enough room to scroll the last anchor to the top
318+
lastAnchor.getSize().then(function(size) {
319+
var tempHeight = size.height - 10;
320+
execWithTempViewportHeight(tempHeight, function() {
321+
execWithTempHash(targetAnchorId, function() {
322+
expectVisible(targetAnchorId, true);
323+
expectTop(targetAnchorId, yOffset);
324+
});
325+
});
326+
});
327+
});
328+
329+
it('should not scroll "overzealously"', function () {
330+
var lastLink = element.all(by.repeater('x in [0,1,2,3,4]')).last();
331+
var lastAnchor = element.all(by.repeater('y in [0,1,2,3,4]')).last();
332+
var targetAnchorId = 'anchor4';
333+
334+
// Make sure there is not enough room to scroll the last anchor to the top
335+
lastAnchor.getSize().then(function(size) {
336+
var tempHeight = size.height + (yOffset / 2);
337+
execWithTempViewportHeight(tempHeight, function() {
338+
scrollIntoView(targetAnchorId);
339+
expectTop(targetAnchorId, yOffset / 2);
340+
lastLink.click();
341+
expectVisible(targetAnchorId, true);
342+
expectTop(targetAnchorId, yOffset);
343+
});
344+
});
345+
});
346+
});
347+
</file>
167348
</example>
168349
*/
169350
this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) {

0 commit comments

Comments
 (0)