How to test infinite scroll in a table? - protractor

I am testing Infinite scrolling in my angular application. The scroll is part of a table in the main page. The main page doesn't have any scroll bar of its own and if I hover the mouse over the table and scroll more elements will be loaded.
Initially, 50 rows are displayed on the screen out of which only 10 are visible on the table. On scrolling to the last element, the next 50 will be loaded in the UI. This will be continued until all the elements are retrieved.
I tried clicking on the first row of the table and used scroll
dashboard.Row1.click()
browser.executeScript("window.scrollBy(0,200)");
This doesn't scroll the table. I am not sure if this is the right approach to solve the problem. I also tried using offset but it didn't help either
This is my HTML:
<tbody infinite-scroll="$ctrl.loadInventories()" infinite-scroll-container="'.table-wrapper'" md-body="" class="md-body ng-isolate-scope">
<!-- ngRepeat: data in $ctrl.inventories | orderBy: myOrder -->
<tr class="" ng-repeat="data in $ctrl.inventories | orderBy: myOrder" style="">
<!-- ngRepeat: data in $ctrl.inventories | orderBy: myOrder -->
<tr class="" ng-repeat="data in $ctrl.inventories | orderBy: myOrder" style="">
<!-- ngRepeat: data in $ctrl.inventories | orderBy: myOrder -->
<tr class="" ng-repeat="data in $ctrl.inventories | orderBy: myOrder" style="">
<!-- ngRepeat: data in $ctrl.inventories | orderBy: myOrder -->
<tr class="" ng-repeat="data in $ctrl.inventories | orderBy: myOrder" style="">

You could try scrolling to the last row of the table using scrollIntoView(). It would be something like
const tableRows = element.all(by.css('tbody tr'));
browser.executeScript(e => e.scrollIntoView(), tableRows.last());
Or more compactly, perhaps less readable
browser.executeScript(e => e.scrollIntoView(), $$('tbody tr').last());

Related

How to test loading more rows in a table upon scroll?

I am testing infinity scroll using protractor on an angular application. The table initially have 50 rows that are displayed upon loading the url. Once I scroll the next 50 rows are displayed. similarly 800-900 rows are displayed. That means I have to scroll atleast 16 to 18 times. There is also some load time of approximately 3 seconds for next 50 rows to be loaded. How do I test this using Protractor?
I am using scroll into View to load the rows.
var tableRows = element.all(by.css('tbody tr'));
let lastCount = 0
let count = -1
const go = () => tableRows.count().then(function (rowCount) {
lastCount = count
count = rowCount
console.log("Count:" +count)
console.log("lastCount: "+lastCount)
browser.executeScript(e => e.scrollIntoView(), tableRows.last());
browser.sleep(3000)
if (lastCount !== count) {
console.log("going again")
go()
}
else{
console.log("In Else")
callback();
Here is my HTML
<tbody infinite-scroll="$ctrl.loadInventories()" infinite-scroll-container="'.table-wrapper'" md-body="" class="md-body ng-isolate-scope">
<!-- ngRepeat: data in $ctrl.inventories | orderBy: myOrder -->
<tr class="" ng-repeat="data in $ctrl.inventories | orderBy: myOrder" style="">
<!-- ngRepeat: data in $ctrl.inventories | orderBy: myOrder -->
<tr class="" ng-repeat="data in $ctrl.inventories | orderBy: myOrder" style="">
<!-- ngRepeat: data in $ctrl.inventories | orderBy: myOrder -->
<tr class="" ng-repeat="data in $ctrl.inventories | orderBy: myOrder" style="">
<!-- ngRepeat: data in $ctrl.inventories | orderBy: myOrder -->
<tr class="" ng-repeat="data in $ctrl.inventories | orderBy: myOrder" style="">
You can try taking the tr count .If the initial tr count is not equal to final tr count continue the loop and if the count matches then we can confirm that all the rows are loaded and no more is left. Hope it helps yous

Accordion Bootstrap table with spacebars

I have seen questions pertaining to accordion but not entirely to my specific need. My table is populated using spacebars, more specific a nested each loop like this:
<tbody>
{{#each piece in pieces}}
<tr id="{{piece._id}}" class="itemList table-warning">
<th class="name tText">{{piece.name}} {{piece._id}}</th>
<td class="pdf tText" style="text-align: center"><a class ="pdf" href="{{piece.pdf}}" target="_blank"><i class="fa fa-file-text-o" aria-hidden="true"></i></a></td>
<td class="audio tText" style="text-align: center"><a class="audio" href="{{piece.audio}}" target="_blank"><i class="fa fa-volume-up" aria-hidden="true"></i></a></td>
<td class="format tText">{{piece.instrumentation}}</td>
<th class="price tText" >${{piece.price}}</th>
<td><input class ="qty" type ="number" name ="quantity" value="0" min="0"></td>
</tr>
<!-- Row that is being clicked-->
<tr class="partsList">
<td colspan="3"></td>
<th class="partName tText">{{piece.name}} Parts</th>
<td colspan="2"></td>
</tr>
{{#each part in piece.parts}}
<!-- Rows that should accordion -->
<!-- Currently ALL rows accordion on click. Need to accordion based on _id-->
<tr class="partList">
<td colspan="3"></td>
<td class="pname tText">{{piece.name}}: {{part.pname}}</td>
<td class="price tText">${{part.pprice}}</td>
<td><input class="qty" type="number" name="quantity" value="0" min="0"></td>
</tr>
{{/each}}
{{/each}}
</tbody>
I have a click function like so:
'click .partsList': function(e){
e.preventDefault();
$('.partList').nextUntil('tr.itemList').toggle();
}
The accordion function works, however it works with every instance of the each loop. i.e. every tr class ="partsList" will accordion at the same time on click.
To my understanding of the each loop, I can access the _id of a document using {{piece._id}}. If I set the table row id to equal that however, it only reads the _id of the FIRST document in the collection.
What I need is on click for the <tr class="partList"> to accordion based on _id. Or perhaps you would go about this a different way than bootstrap tables?
Please let me know if my question needs clarification.
You could filter the clicked .partslist using a data-* attribute. This causes jQuery to select only this specific items. Note that you need to attach the data-* attribute to the row that is clicked and to the rows that should collapse:
<tbody>
{{#each piece in pieces}}
...
<!-- Row that is being clicked-->
<!-- use the _id value of the piece context as data attribute -->
<tr class="partsList" data-id="{{piece._id}}">
<td colspan="3"></td>
<th class="partName tText">{{piece.name}} Parts</th>
<td colspan="2"></td>
</tr>
{{#each part in piece.parts}}
<!-- Rows that should accordion -->
<!-- Currently ALL rows accordion on click. Need to accordion based on _id-->
<!-- use the _id value of the piece context as data attribute -->
<tr class="partList" data-target="{{piece._id}}">
...
</tr>
{{/each}}
{{/each}}
</tbody>
'click .partsList': function(e, templateInstance){
e.preventDefault();
// get the data-id attribute of the clicked row
const targetId = templateInstance.$(e.currentTarget).data('id')
// skip if this row is not intended to toggle
if (!targetId) return
// toggle based on data-target attribute
templateInstance.$(`.partList[data-target="${targetId}"]`).nextUntil('tr.itemList').toggle();
}

Issue when implementing multiple cell inputs in Angular2

I have a table where each td has an input (like a spreadsheet).
My html template the code as follows:
<tr *ngFor="let project of projects" (click)="onSelect(project)">
<th class="panel fixed">{{project.id}}</th>
<th class="panel fixed">{{project.name}}</th>
<td *ngFor="let load of projectLoads[project.code]; let d=index" class="cell panel scrolling">
<input class="load" [(ngModel)]="projectLoads[project.code][d]" title="{{project.code+' . '+d}}" />
</td>
…
When I fill one cell in with a number, for example 1, the number is repeated in the next cell.
How it comes?
(Note that there is no ngForm in my current code.)

<ionic-content> / <ion-nav-view> not scrolling

I'm making a simple app that keeps track of my hours at work. I'm developing the app for android and I'm having a problem with the scrolling.
Structure of the App:
I have a header bar and a footer which are both outside of the < ion-content > tab, so I don't expect that to be scrollable. Within the < ion-content > I have used an < ion-side-menus > tab and finally within the < ion-side-menu-content > tab I have put in a < ion-nav-view > tab which is controlled by my state provider.
Everything works fine, the menu is operational and the views change according to their design. Within one of my views I have a list that exceeds the size HERE IS WHERE THE PROBLEM BEGINS!. When using a computer, I can pull the page down (as if I were trying to refresh it) but when I try to scroll down the page goes straight to the top of the list unless I keep dragging and have my finger on the left click. Furthermore the rest of the content in the list is not loaded. The listed is literally cropped to where it stopped before I dragged down. When I export it to an android app I cant even drag to scroll. The scrolling is literally non-functional.
I've attached some code
var app = angular.module('starter', ['ionic'])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if (window.StatusBar) {
StatusBar.styleDefault();
}
});
})
.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('home', {
url: '/',
templateUrl: "views/home.html",
controller: "MainController"
})
.state('rotas', {
url: '/rotas',
templateUrl: "views/rotas.html",
controller: "MainController"
})
.state('update', {
url: '/update',
templateUrl: "views/update.html",
controller: "UpdateController"
});
$urlRouterProvider.otherwise('/');
});
.scroll {
height: 100%;
}
/* Before i put in this CSS element, the content in the view was cropped SIGNIFICANTLY. not sure exactly what it does but it solved my problem. All other CSS elements are colour changes*/
index.html
<html>
<head>...</head>
<body ng-app="starter" ng-controller="MainController">
<ion-pane>
<ion-header-bar class="bar-stable">
<!--header bar -->
<h1 class="title">Shiftwiz.{{controllerCheck}}</h1>
</ion-header-bar>
<div class="bar bar-footer bar-stable">
<!--footer-->
<table id="footer-table">
<tr>
<td>
<a ui-sref="rotas" ng-click="activity.doRotas()">
<div>Rotas</div>
</a>
</td>
<td>
<a ui-sref="update" ng-click="activity.doUpdate()">
<div>Update</div>
</a>
</td>
</tr>
</table>
</div>
<ion-content>
<ion-side-menus>
<ion-side-menu-content overflow-scroll="true">
<!--menu-->
<button class="button button-full button-positive" ng-click="toggleLeft()">
Rotas: {{activity.rotas}} Update: {{activity.update}}
</button>
<ion-nav-view overflow-scroll="true"></ion-nav-view>
</ion-side-menu-content>
<ion-side-menu side="left">
<ion-item>Next Week</ion-item>
<ion-item ng-click="toggleLeft(); activity.chooseThisWeek(); calcDates()">This Week</ion-item>
<div id="further-weeks" ng-show="activity.rotas">
<ion-item>Last Week</ion-item>
<ion-item>Last Two</ion-item>
<ion-item>Last Three</ion-item>
</div>
</ion-side-menu>
</ion-side-menus>
</ion-content>
</ion-pane>
</body>
</html>
update.html
<!-- this view contains the list which isn't rendering-->
<div class="card" ng-repeat="day in unPublishedRota">
<a ng-click="day.toggleState()">
<div class="item item-divider">
<p class="day">{{ day.date | date:"EEEE" }}
<br />{{day.date | date:"d, MMM y"}}</p>
<p class="times">{{day.start}} | {{day.finish}}
<br />{{day.hours}} hrs</p>
</div>
</a>
Your update.html contents should be wrapped in <ion-view> and <ion-content> elements.
<ion-view>
<ion-content>
<div class="card" ng-repeat="day in unPublishedRota">
<a ng-click="day.toggleState()">
<div class="item item-divider">
<p class="day">{{ day.date | date:"EEEE" }}
<br />{{day.date | date:"d, MMM y"}}</p>
<p class="times">{{day.start}} | {{day.finish}}
<br />{{day.hours}} hrs</p>
</div>
</a>
</div>
</ion-content>
</ion-view>
You can also have a look at a working sidemenu example by Ionic.

GWT: switching from <table> to g:LayoutPanel and g:layer disable all input

I'm using uiBinder to layout my views in a gwt project and I've been using a regular table to handle the basic layout of the view. It became kinda messy and static so I was looking into using layers inside a layoutPanel instead. This seemed like a better way of doing it. So before I had the structure:
docklayoutpanel
center
tablayoutpanel
tab
table
// tabel rows and cells with various content
and now the table with its rows and columns has been replaced with a layoutPanel with layers. At first it seemed to work fine, looking almost exactly the same (just some margins and padding were off), but then I noticed that all the content inside the layers were completely disabled. Not only buttons and textFields, but I can't even select static text. It's like there's an invisible glass pane over everything. What is causing this and how do I fix it?
Throwing in some code as well. This is what the beginning looked like before (working fine):
<g:DockLayoutPanel unit="EM" height="100%">
<g:center>
<g:TabLayoutPanel barUnit='EM' barHeight='3'
ui:field="tabs">
<!-- TABB 1 -->
<g:tab>
<g:header styleName="viewSubtitleText">
<!-- Flikrubrik -->
View Person
</g:header>
<g:LayoutPanel>
<g:layer>
<g:ScrollPanel>
<g:HTMLPanel>
<table>
<tr>
<td valign="top">
<g:HTMLPanel styleName="roundedBox">
<g:HTMLPanel styleName="viewSubtitleText">People</g:HTMLPanel>
<table>
<tr>
<td>
<table>
<tr>
<td>
<g:HTML>Search </g:HTML>
</td>
<td>
<j:DemiaSuggestBox ui:field="sgtPerson"></j:DemiaSuggestBox>
</td>
And it was replaced by this:
<g:DockLayoutPanel unit="EM" height="100%">
<g:center>
<g:TabLayoutPanel barUnit='EM' barHeight='3'
ui:field="tabs">
<!-- TABB 1 -->
<g:tab>
<g:header styleName="viewSubtitleText">
<!-- Flikrubrik -->
View Person
</g:header>
<g:LayoutPanel>
<g:layer styleName="roundedBox">
<g:HTMLPanel>
<g:HTMLPanel styleName="viewSubtitleText">People</g:HTMLPanel>
<table>
<tr>
<td>
<table>
<tr>
<td>
<g:HTML>Search </g:HTML>
</td>
<td>
<j:DemiaSuggestBox ui:field="sgtPerson"></j:DemiaSuggestBox>
</td>
So it turned out I just forgot to specify the dimension of the layers, e.g:
<g:layer left="1em" top="1em" bottom="1em" width="42em">