Friday, 8 August 2014

Some Selenium Code Examples

Below are some Selenium code examples:
var driver = new FirefoxDriver();

// select an option on a dropdown list by its text
new SelectElement(driver.FindElement(By.Id("lstStatus"))).SelectByText("Active");
// another example
driver.FindElements(By.CssSelector("#dvSelectListItems li")).Where(elem => elem.Text.Trim() == "some text").FirstOrDefault().Click();

// get text from a table in its second row and second column
driver.FindElement(By.CssSelector("#tbSearchResults tr:nth-child(2) td:nth-child(2)")).Text

// check whether an element is displayed
driver.FindElement(By.CssSelector("div.accordionContent")).Displayed == false

// fill an input field with text
driver.FindElement(By.Id("Name")).SendKeys("Fullname");

// get a td element that has a particular title attribute value
driver.FindElement(By.CssSelector("td[title='a title']"));

// trick to do hover on a menu
Actions actions = new Actions(driver);
var profileMenu = driver.FindElement(By.LinkText("Profiles"));
actions.MoveToElement(profileMenu);
actions.Click();
actions.Perform(); 

// wait for maximum ten seconds until an element is displayed
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(d => d.FindElement(By.Id("divDashContainer")).Displayed);

// navigate to an url
driver.Navigate().GoToUrl("some url");

Monday, 21 July 2014

TFS 2013 - Limiting Users List in User DropDown

Below is an example of how to limit users in a user selection dropdown:
<field name="Assigned To" refname="System.AssignedTo" type="String" syncnamechanges="true" reportable="dimension">
   <!-- show users that are part of the team only -->
   <validuser group="[Project]\Contributors" />

   <!-- below is another way to do that
   <allowedvalues expanditems="true">
      <listitem value="[Project]\Contributors" />
   </allowedvalues> -->

   <default from="currentuser" />   <!-- this one to have the logged on user to be automatically selected by default -->
</field>

Thursday, 17 July 2014

Modifying and Creating Work Item Type in TFS 2013

To modify a work item type in TFS 2013, we need to these steps:
- export the work item type xml file to our machines
- modify that file
- then import back the modified xml file to the TFS server

To create a new work item type, we need to:
- create a new work item type xml file
- import the new xml file to TFS server

We use Visual Studio Command Prompt to do this.

To export work item type, run this command:
witadmin exportwitd /collection:[team project collection URI] /p:[project_name] /n:[work item type name] /f:[destination file]
examples:
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE>witadmin exportwitd 
/collection:"http://myTFSserver/tfs/DefaultCollection" /p:MyProject /n:Bug /f:C:\Users\me\Desktop\bug.xml

C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE>witadmin exportwitd 
/collection:"http://myTFSserver/tfs/DefaultCollection" /p:MyProject /n:"Product Backlog Item" /f:c:\Users\me\Desktop\pib.xml

To import work item type, run this command:
witadmin importwitd /collection:[team project collection URI] /p:[project_name] /f:[source file]
example:
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE>witadmin importwitd 
/collection:"http://myTFSserver/tfs/DefaultCollection" /p:MyProject /f:c:\Users\me\Desktop\task.xml

To delete work item type:
witadmin destroywitd /collection:[team project collection URI] /p:[project_name] /n:[work item type name]
example:
witadmin destroywitd /collection:"http://myTFSserver/tfs/DefaultCollection" /p:"My Project" /n:"Impediment"

To rename work item type:
witadmin renamewitd /collection:[team project collection URI] /p:[project_name] /n:[existing work item type name] 
/new:[new work item type name]
example:
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE>witadmin renamewitd 
/collection:"http://myTFSserver/tfs/DefaultCollection" /"My Project" /n:"Product Backlog Item" /new:"Enhancement"
Are you sure you want to rename the work item type Product Backlog Item to the new name of Enhancement? (Yes/No) Yes
The work item type was renamed. 

To export process configuration:
witadmin exportprocessconfig /collection:[team project collection URI] /p:[project_name] /f:[destination file]
example:
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE>witadmin exportprocessconfig 
/collection:"http://myTFSserver/tfs/DefaultCollection" /p:MyProject /f:c:/Users\me\Desktop\ProcessConfiguration.xml

To import process configuration:
witadmin importprocessconfig /collection:[team project collection URI] /p:[project_name] /f:[source file]
C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE>witadmin importprocessconfig  
/collection:"http://myTFSserver/tfs/DefaultCollection" /p:MyProject /f:c:/Users\me\Desktop\ProcessConfiguration.xml


Reference:
MSDN: Import, export, and manage work item types [witadmin]

Thursday, 26 June 2014

Watching Attribute Value with $observe

Below is an example of how to watch for an attribute's value and do something every time it has changed. To do this we would use $observe function.

<!-- origin markup in the view -->
enter a colour: <input class="observe-test" data-ng-model="inputValue" title="{{inputValue}}"/> 
<br />
value typed: <span></span>

// directive codes
myApp.directive('observeTest', function () {
    return {
        restrict: 'C',
        link: function (scope, element, attrs) {
            attrs.$observe('title', function (newValue) {
              attrs.$set('style', 'color:' + newValue);
              element.parent().find('span').text(newValue);
            })
        }
    }
});

See the example in Plunker

Monday, 23 June 2014

More Advanced AngularJs Directive

Isolate Scope
scope option is useful for creating directive's internal variables or functions from outer values or functions.
<!-- origin markup in the view -->
<scopetest a-value="controllerData" the-value="{{controllerData}}" show-value="showPopup()"></scopetest>

// these codes are inside the controller
$scope.controllerData = 'Oii';
$scope.showPopup = function () {
    alert($scope.controllerData);
}

// directive codes
myApp.directive('scopetest', function () {  // would work as well if I had used myApp.directive('showValue' . . . restrict: 'A'
    return {
        restrict: 'E',
        template: "<p>controllerData: {{controllerData}}</p> <p>data: {{data}}</p> <p>theData: {{theData}}</p> <p>sameData: {{sameData}}</p> <button type='button' ng-click='showData()'>Click Me!</button>",
        scope: {
            data: "=aValue",
            theData: "@theValue",
            sameData: "&aValue",    // doesn't work. Seems only work for method.
            showData: "&showValue"
        }
    }
})

See the example in Plunker

In this example we use '=' to pass the value of an outer variable specified in an attribute in the origin markup. I.e., data: "=aValue" will create an internal variable called 'data' and get the value of the outer variable (an AngularJs $scope variable) specified in the 'a-value' attribute in the origin markup. The attribute name referred to follows the same matching pattern as the matching pattern of a directive name (i.e, 'aValue' matches 'a-value' in the origin markup).

'@' is used if we want to copy the literal value (copy the text) of an attribute in the origin markup. If we want to pass a value of an AngularJs variable then we need to use {{ . . . }} to get the value first before passing it to the directive. I.e., <scopetest the-value="{{controllerData}}" />

'&' is used to pass a function of an attribute in the origin markup.

If the attribute name being referred to is the same as the internal variable name then when defining the internal variable, we don't need to specify the attribute name after the symbol. E.g., aValue: "="; is the same as aValue: "=aValue";

When we are using isolate scope, external variables will not be available inside the directive. Only the variables that are declared inside scope: { . . . } will be available.


Transclude
This option is used to pass the matched origin markup and its inner content into a directive template. The parent-to-be element in the template needs to be decorated with ng-transclude attribute. All the inner content of the parent-to-be element will be overwritten with the passed markup. The directive also needs to set transclude: true to activate this option.

<!-- origin markup in the view -->
<trancsludetest>
  <div>
 This is a content from origin markup. 
 <br />
 Try to print a value: {{value}}
  </div>
</trancsludetest>

// code inside controller
$scope.value = 'controller value';

// directive codes
myApp.directive('transcludetest', function () {
  return {
    restrict: 'E',
    transclude: true,
    template: '<div class="fancy-class" style="border: 2px solid black; padding: 2px"><div class="another--class" style="border: 1px dashed blue" ng-transclude>content inside this div will be ignored</div></div>',
    link: function (scope, element) {
      scope.value = 'directive value';
    },
    //scope: {}   // if this is used then only external values are considered
  };
})

See the example in Plunker


Priority and Terminal
priority option is useful for directives (more than one) that are defined in a single DOM element. The option is used to determine the order of how they are going to be applied, especially for their link and compile functions. The compile and pre-link functions are executed from the greatest number while post-link functions are executed from the smallest number.

If not defined, the priority default value is 0. If the directives have same priority values then it seems that they are executed in alphabetical order.

If terminal option is used then directives that have lower priorities will be disregarded.

<!-- origin markup in the view -->
<div second-priority first-priority></div>

// directive codes
myApp.directive('secondPriority', function () {
    return {
        restrict: 'A',
        link: {
          pre: function (scope, element, attrs) {
            alert('preLink - two');
            element.append("<br/>preLink - two");
          },
          post: function (scope, element, attrs) {
            alert('postLink - two');
            element.append("<br/>postLink - two");
          }
        },
        priority: 1
    }
})
.directive('firstPriority', function () {
    return {
        restrict: 'A',
        link: {
                pre: function (scope, element, attrs) {
                  alert('preLink - one');
                  element.append("preLink - one");
                },
                post: function (scope, element, attrs) {
                  alert('postLink - one');
                  element.append("<br/>postLink - one");
                }
        },
        priority: 2,
        //terminal: true
    }
});

See the example in Plunker


Require
This option is used to pass other directive's controller into the link function of the directive where the option is specified. The other directive could be a sibling directive or a directive in one of parent elements.
The require option can take a single string or an array of strings of directive names to be found.
The string name can be:
- not prefixed - to find a sibling directive
- prefixed with '?' - return 'null' if the intended sibling directive is not found
- prefixed with '^' - find the directive in one of parent elements
- prefixed with '^?' - return 'null' if the intended directive is not found in any parent elements

<!-- origin markup in the view -->
<div parent-directive>
  <div>
 <div>
   <div sibling-directive require-test></div>
 </div>
  </div>
</div>

// directive codes
myApp.directive('parentDirective', function () {
    return {
      restrict: 'A',
      controller: function ($scope) {
        this.parentData = "<br />parentDirective data.. ";
        this.parentFunction = function(param) {
            return param + "<br />   - Hi there, this is parentDirective";
        };
      }
    };
})
.directive('siblingDirective', function () {
    return {
      restrict: 'A',
      require: '^parentDirective',
      link: function (scope, element, attrs, controller)
      {
        element.append(controller.parentData);
        var test = controller.parentFunction('<br />Hello this is siblingDirective');
        element.append(test);
      },
      controller: function ($scope) {
        this.siblingFunction = function(param) {
            return param + "<br />   - Hi there, this is your sibling directive";
        };
      }
    };
})
.directive('requireTest', function () {
    return {
        restrict: 'A',
        require: ['?^parentDirective','siblingDirective'],
        link: function (scope, element, attrs, controller)
        {
          element.append(controller[0].parentData);
          var test = controller[0].parentFunction('<br />Hello this is requireTest');
          element.append(test);
          test = controller[1].siblingFunction('<br />Hello this is requireTest');
          element.append(test);
        }
    };
});

See the example in Plunker

Thursday, 15 May 2014

Basic AngularJs Directive

Below is a basic example of using AngularJs directive:
<!--HTML markup-->
<div my-directive></div>

//JavaScript codes
var myApp = angular.module('myApp', []);

myApp.directive('myDirective', function () {
    return {
        restrict: 'A',      // possible values: A, C, E, M
        template: "{{controllerData}} <mark>This is my custom directive. '{{directiveData}}'</mark>",
        link: function (scope, element, attrs) {
            //execute a function then assign a value
            scope.directiveData = "Good morning!";
            // can change any scope value in the outside as well
            // scope.controllerData = "test";

            element.on('mouseover', function () {
                element.css('font-size', '18px');
        },
        replace: false  // remove the outer container
    };
});
restrict property is used to determine which part of origin HTML markup to be matched. The possible values are:
- A - attribute
- C - class, i.e. <div class="my-directive"/>
- E - element, i.e. <my-directive/>
- M - comment, i.e. <!--directive:my-directive-->
The values can also be combined.

template property is used to specify the markup to be added as part of the directive. The markup will be added to the existing container or replace it depending on the replace property value.
Note from the example that we can pass data that is specific to the directive or data from the controller.
If the additional markup is much then we should use templateUrl property instead.

link is used to manipulate scope variables and the directive markup (after being combined with the additional markup inside template or templateUrl property if used). It accepts three required and one optional parameters:
- scope - this is the AngularJs scope object
- element - the origin element that is matched, if it is replaced then the new element from the template
According to AngularJs documentation, the element is actually a jqLite (a light version of jQuery library from AngularJs) wrapped element. The library contains core functionalities of jQuery and has almost identical API.
However, important to note that if jQuery library is loaded prior to AngularJs libraries then the element will be jQuery wrapped instead so it will have full jQuery functionalities.
- attrs - attributes of the origin element that is matched, if it is replaced then the attributes of the new element from the template
- controller [optional] - to pass the directive's controller instance to be accessible inside the function

On the next post, we will see more advanced examples of AngularJs directive.


References:
AngularJs Developer Guide - Directives
GitHub - AngularJs - Understanding Directives

Friday, 25 April 2014

Passing Objects in JSON through ViewBag

Below is an example of how to pass a collection of objects in JSON format through ViewBag.
List<Student> studentsList = new List<Student>();
studentsList = GetStudents();
ViewBag.Students = System.Web.Helpers.Json.Encode(studentsList);
We use System.Web.Helpers.Json.Encode() function to do the formatting and on the view, we just need to render the passed content like this:
@Html.Raw((String)ViewBag.Students)

A different way to do this is by passing the collection directly through ViewBag
ViewBag.Students = studentsList;
then we do the formatting on the view
@Html.Raw(Json.Encode((IList<Student>)ViewBag.Students))
However this way is less efficient than the earlier one.