<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Lawrence Song</title>
	<atom:link href="http://lawrencesong.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://lawrencesong.net</link>
	<description>ruby, Java, c#, javascript</description>
	<pubDate>Fri, 03 Apr 2009 17:40:45 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
	<language>en</language>
			<item>
		<title>i18n label in rails (monkey patch)</title>
		<link>http://lawrencesong.net/2009/04/i18n-label-in-rails-monkey-patch/</link>
		<comments>http://lawrencesong.net/2009/04/i18n-label-in-rails-monkey-patch/#comments</comments>
		<pubDate>Fri, 03 Apr 2009 17:38:37 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://lawrencesong.net/?p=50</guid>
		<description><![CDATA[I18n label is still not supported in rails 2.3.2. Here is the patch to make it work. However, I don&#8217;t want to change the source code of rails. Hence, I create a monkey patch.

module ActionView
  module Helpers
    class InstanceTag
      def to_label_tag_with_i18n(text = nil, options = {})
 [...]]]></description>
			<content:encoded><![CDATA[<p>I18n label is still not supported in rails 2.3.2. <a title="form label should use i18n" href="http://i18n.lighthouseapp.com/projects/14948/tickets/10-form-lael-should-use-i18n">Here</a> is the patch to make it work. However, I don&#8217;t want to change the source code of rails. Hence, I create a monkey patch.</p>
<pre class="syntax-highlight:ruby">
module ActionView
  module Helpers
    class InstanceTag
      def to_label_tag_with_i18n(text = nil, options = {})
        text ||= object.class.human_attribute_name(method_name) if object.class.respond_to?(:human_attribute_name)

        to_label_tag_without_i18n(text, options)
      end

      alias_method_chain :to_label_tag, :i18n
  end
end
end
</pre>
<p>Load the file in the environment.rb or any file in confit/initializers will make it work.</p>
]]></content:encoded>
			<wfw:commentRss>http://lawrencesong.net/2009/04/i18n-label-in-rails-monkey-patch/feed/</wfw:commentRss>
		</item>
		<item>
		<title>activerecord sqlserver_adapter bug - ORDER BY items must appear in the select list if SELECT DISTINCT is specified.</title>
		<link>http://lawrencesong.net/2009/02/activerecord-sqlserver_adapter-bug-order-by-items-must-appear-in-the-select-list-if-select-distinct-is-specified/</link>
		<comments>http://lawrencesong.net/2009/02/activerecord-sqlserver_adapter-bug-order-by-items-must-appear-in-the-select-list-if-select-distinct-is-specified/#comments</comments>
		<pubDate>Wed, 11 Feb 2009 08:24:36 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://lawrencesong.net/?p=34</guid>
		<description><![CDATA[ORDER BY items must appear in the select list if SELECT DISTINCT is specified.
Add the following code at the end of method add_limit_offset!(sql, options) in sqlserver_adapter.rb

if options[:order]
order_fields = options[:order].split(&#039;,&#039;).collect do &#124;field&#124;
column_name = field.split(&#34; &#34;)[0]
&#34;#{column_name} AS #{column_name.gsub(&#039;.&#039;, &#039;_&#039;)}&#34;
end
sql.gsub!(/^\s*SELECT(\s+DISTINCT)(.*?) FROM/i, &#34;SELECT\\1 \\2, #{order_fields.join(&#039;, &#039;)} FROM&#34;)
end

]]></description>
			<content:encoded><![CDATA[<p>ORDER BY items must appear in the select list if SELECT DISTINCT is specified.</p>
<p>Add the following code at the end of method add_limit_offset!(sql, options) in sqlserver_adapter.rb</p>
<pre class="syntax-highlight:ruby">
if options[:order]
order_fields = options[:order].split(&#039;,&#039;).collect do |field|
column_name = field.split(&quot; &quot;)[0]
&quot;#{column_name} AS #{column_name.gsub(&#039;.&#039;, &#039;_&#039;)}&quot;
end
sql.gsub!(/^\s*SELECT(\s+DISTINCT)(.*?) FROM/i, &quot;SELECT\\1 \\2, #{order_fields.join(&#039;, &#039;)} FROM&quot;)
end
</pre>
]]></content:encoded>
			<wfw:commentRss>http://lawrencesong.net/2009/02/activerecord-sqlserver_adapter-bug-order-by-items-must-appear-in-the-select-list-if-select-distinct-is-specified/feed/</wfw:commentRss>
		</item>
		<item>
		<title>rspec - match arguments with code block</title>
		<link>http://lawrencesong.net/2009/02/rspec-match-arguments-with-code-block/</link>
		<comments>http://lawrencesong.net/2009/02/rspec-match-arguments-with-code-block/#comments</comments>
		<pubDate>Fri, 06 Feb 2009 13:45:28 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://lawrencesong.net/?p=32</guid>
		<description><![CDATA[In rspec, I usually need to define a matcher to match arguments. I don&#8217;t want to create a match for every should_receive method. I just want to assert the arguments I care. I try to define a code block to assert my call arguments. I google it for a while and could not find an [...]]]></description>
			<content:encoded><![CDATA[<p>In rspec, I usually need to define a matcher to match arguments. I don&#8217;t want to create a match for every should_receive method. I just want to assert the arguments I care. I try to define a code block to assert my call arguments. I google it for a while and could not find an answer.</p>
<p>I want to do something like:</p>
<pre class="syntax-highlight:ruby">

User.should_receive(:find).with(assert_that(lambda { |args
  options = args.pop
  options[:include].should == expected_include
  options[:limit].should == 100
}).and_return(:users)
</pre>
<p>After reading rspec source code, I finger out rspec should_receive argument allow code block. That&#8217;s easier than what I expect. The finial code is:</p>
<pre class="syntax-highlight:ruby">

User.should_receive(:find).with do |*args|
  options = args.pop
  options[:include].should == expected_include
  options[:limit].should == 100
  true
end.and_return(:users)
</pre>
<p>remember to return true at the end if all assertions pass.</p>
]]></content:encoded>
			<wfw:commentRss>http://lawrencesong.net/2009/02/rspec-match-arguments-with-code-block/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Enable i18n in will_paginate Plugin</title>
		<link>http://lawrencesong.net/2009/01/enable-i18n-in-will_paginate-plugin/</link>
		<comments>http://lawrencesong.net/2009/01/enable-i18n-in-will_paginate-plugin/#comments</comments>
		<pubDate>Sun, 18 Jan 2009 02:58:49 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://lawrencesong.net/?p=24</guid>
		<description><![CDATA[The current will_paginate plugin doesn&#8217;t support localization. Adding the following code into the application_helper will enable i18n for will_paginate.


include WillPaginate::ViewHelpers

def will_paginate_with_i18n(collection, options = {})
will_paginate_without_i18n(collection, options.merge(:previous_label =&#62; I18n.t(:previous), :next_label =&#62; I18n.t(:next)))
end

alias_method_chain :will_paginate, :i18n

And add &#8216;next&#8217; and &#8216;previous&#8217; attribute in the locales file.
for example zh.yml under RAILS_ROOT/config/locales

zh:
previous: &#039;前一页&#039;
next: &#039;下一页&#039;

]]></description>
			<content:encoded><![CDATA[<p>The current <a title="will_paginate" href="http://wiki.github.com/mislav/will_paginate" target="_blank">will_paginate plugin</a> doesn&#8217;t support localization. Adding the following code into the application_helper will enable i18n for will_paginate.</p>
<pre class="syntax-highlight:ruby">

include WillPaginate::ViewHelpers

def will_paginate_with_i18n(collection, options = {})
will_paginate_without_i18n(collection, options.merge(:previous_label =&gt; I18n.t(:previous), :next_label =&gt; I18n.t(:next)))
end

alias_method_chain :will_paginate, :i18n
</pre>
<p>And add &#8216;next&#8217; and &#8216;previous&#8217; attribute in the locales file.</p>
<p>for example zh.yml under RAILS_ROOT/config/locales</p>
<pre class="syntax-highlight:php">
zh:
previous: &#039;前一页&#039;
next: &#039;下一页&#039;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://lawrencesong.net/2009/01/enable-i18n-in-will_paginate-plugin/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Enable Case Sensitive Field in Mysql (Ruby on Rails)</title>
		<link>http://lawrencesong.net/2008/12/enable-case-sensitive-field-in-mysql-ruby-on-rails/</link>
		<comments>http://lawrencesong.net/2008/12/enable-case-sensitive-field-in-mysql-ruby-on-rails/#comments</comments>
		<pubDate>Tue, 30 Dec 2008 11:49:31 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Rails]]></category>

		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://lawrencesong.net/?p=15</guid>
		<description><![CDATA[SEO has become a hot topic in the Internet.  I am working in my personal project which I&#8217;d like to have a friendly URL. I need to create a slug as my friend URL. But, the slug is case sensitive in my case. for example, word &#8216;fisher&#8217; is different to name &#8216;Fisher&#8217; in a dictionary. [...]]]></description>
			<content:encoded><![CDATA[<p>SEO has become a hot topic in the Internet.  I am working in my personal project which I&#8217;d like to have a friendly URL. I need to create a slug as my friend URL. But, the slug is case sensitive in my case. for example, word &#8216;fisher&#8217; is different to name &#8216;Fisher&#8217; in a dictionary. unfortunately, MySQL is case sensitive by default. So I need to change the setting for the slug field in my table.</p>
<p>I change my slug field in MySQL by adding the following code into my migration script:</p>
<pre class="syntax-highlight:ruby">

execute %{ALTER TABLE TABLE_NAME MODIFY slug varchar(255) COLLATE utf8_bin NOT NULL}
</pre>
<p>That works fine in my production database which is MySQL. However, I am using sqlite3 in test which is case sensitive by default. So I need to modify the field only in MySQL database. The finial code I put in my migration script is following:</p>
<pre class="syntax-highlight:ruby">

if ActiveRecord::Base.configurations[RAILS_ENV][&#039;adapter&#039;] == &#039;mysql&#039;
execute %{ALTER TABLE words MODIFY slug varchar(255) COLLATE utf8_bin NOT NULL}
end
</pre>
<p>COLLATE options in MySQL:</p>
<ul>
<li><strong>utf8_bin</strong>: compare strings by the binary value of each character</li>
<li><strong>utf8_general_ci</strong>: compare strings using general language rules, case insensitive</li>
<li><strong>utf8_general_cs</strong>: compare strings using general language case sensitive</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://lawrencesong.net/2008/12/enable-case-sensitive-field-in-mysql-ruby-on-rails/feed/</wfw:commentRss>
		</item>
		<item>
		<title>iWeb Tools Online</title>
		<link>http://lawrencesong.net/2008/11/iweb-tools-online/</link>
		<comments>http://lawrencesong.net/2008/11/iweb-tools-online/#comments</comments>
		<pubDate>Thu, 27 Nov 2008 08:28:38 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://lawrencesong.net/?p=12</guid>
		<description><![CDATA[50 days ago, I&#8217;ve launched my personal website. I spend 2 months of my spare time to build this web application based on ruby on rails. There&#8217;re 5 tools available at the moment.
1. RSS Feed Icon Generator
     
2. Javascript Optimizer / Optimiser

3. Ajax Activity Indicator Generator

4. Css Optimizer / Optimiser
5. HTML [...]]]></description>
			<content:encoded><![CDATA[<p>50 days ago, I&#8217;ve launched my personal <a title="iWeb Tools Online" href="http://www.iwebtoolsonline.com">website</a>. I spend 2 months of my spare time to build this web application based on ruby on rails. There&#8217;re 5 tools available at the moment.</p>
<p>1. <a href="http://www.iwebtoolsonline.com/rss-feed-icon-generator">RSS Feed Icon Generator</a></p>
<p><img class="alignnone" title="rss default icon" src="http://www.iwebtoolsonline.com/rss-feed-icon-generator/image/transparent/294FDA/FFFFFF/96/default.png" alt="" width="96" height="96" /> <img class="alignnone" title="rss icon" src="http://www.iwebtoolsonline.com/rss-feed-icon-generator/image/transparent/29A8DA/FFFFFF/64/standard.png" alt="" width="64" height="64" /> <img class="alignnone" title="rss icon 3" src="http://www.iwebtoolsonline.com/rss-feed-icon-generator/image/transparent/294FDA/E8E895/64/standard.png" alt="" width="64" height="64" /> <img class="alignnone" title="rss icon 2" src="http://www.iwebtoolsonline.com/rss-feed-icon-generator/image/transparent/294FDA/FFFFFF/64/standard.png" alt="" width="64" height="64" /> <img class="alignnone" title="rss icon 4" src="http://www.iwebtoolsonline.com/rss-feed-icon-generator/image/transparent/294FDA/FFFFFF/48/standard.png" alt="" width="48" height="48" /> <img class="alignnone" title="rss icon 5" src="http://www.iwebtoolsonline.com/rss-feed-icon-generator/image/transparent/294FDA/FFFFFF/32/standard.png" alt="" width="32" height="32" /></p>
<p>2. <a href="http://www.iwebtoolsonline.com/javascript-optimizer">Javascript Optimizer / Optimiser</a></p>
<p><img class="alignnone" title="javascript optimizer" src="http://www.iwebtoolsonline.com/images/uploads/javascript-optimizer-screen-shot.png" alt="" width="702" height="557" /></p>
<p>3. <a href="http://www.iwebtoolsonline.com/ajax-activity-indicator-generator">Ajax Activity Indicator Generator</a></p>
<p><img class="alignnone" title="AJAX loader roller" src="http://www.iwebtoolsonline.com/ajax-activity-indicator-generator/image/FFFFFF/770FFF/40/50/roller.gif" alt="" width="40" height="40" /></p>
<p>4. <a href="http://www.iwebtoolsonline.com/css-optimizer">Css Optimizer / Optimiser</a></p>
<p>5. <a href="http://www.iwebtoolsonline.com/html-and-css-rounded-corner-button-generator">HTML and CSS Rounded Corner Button Generator</a></p>
<p><img class="alignnone" title="Rounded corner buttons samples" src="http://www.iwebtoolsonline.com/images/uploads/rounded-corner-buttons-samples.png" alt="" width="420" height="300" /></p>
]]></content:encoded>
			<wfw:commentRss>http://lawrencesong.net/2008/11/iweb-tools-online/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Must have firefox add-ons for web development</title>
		<link>http://lawrencesong.net/2008/05/must-have-firefox-add-ons-for-web-development/</link>
		<comments>http://lawrencesong.net/2008/05/must-have-firefox-add-ons-for-web-development/#comments</comments>
		<pubDate>Fri, 09 May 2008 12:13:48 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Deployment]]></category>

		<guid isPermaLink="false">http://lawrencesong.net/?p=10</guid>
		<description><![CDATA[Firebug - Firebug integrates with Firefox to put a wealth of web development tools at your fingertips while you browse. You can edit, debug, and monitor CSS, HTML, and JavaScript live in any web page.
Web Developer - The Web Developer extension adds a menu and a toolbar to the browser with various web developer tools.
FireShot [...]]]></description>
			<content:encoded><![CDATA[<p><a title="web development evolved" href="http://www.getfirebug.com/" target="_blank">Firebug</a> - Firebug integrates with Firefox to put a wealth of web development tools at your fingertips while you browse. You can edit, debug, and monitor CSS, HTML, and JavaScript live in any web page.</p>
<p><a title="Web Developer" href="http://chrispederick.com/work/web-developer/" target="_blank">Web Developer</a> - The Web Developer extension adds a menu and a toolbar to the browser with various web developer tools.</p>
<p><a title="FireShot" href="http://screenshot-program.com/fireshot/" target="_self">FireShot </a>- FireShot is a Firefox extension that creates screenshots of web pages.</p>
<p><a title="ColorZilla" href="http://www.iosart.com/firefox/colorzilla/" target="_blank">ColorZilla </a>- Advanced Eyedropper, ColorPicker, Page Zoomer and other colorful goodies&#8230;</p>
<p><a title="Why slow?" href="http://developer.yahoo.com/yslow/" target="_blank">YSlow</a> - YSlow analyzes web pages and tells you why they&#8217;re slow based on the rules for high performance web sites. YSlow is a Firefox add-on integrated with the popular Firebug web development tool.</p>
]]></content:encoded>
			<wfw:commentRss>http://lawrencesong.net/2008/05/must-have-firefox-add-ons-for-web-development/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Selenium DSL II</title>
		<link>http://lawrencesong.net/2008/03/selenium-dsl-ii/</link>
		<comments>http://lawrencesong.net/2008/03/selenium-dsl-ii/#comments</comments>
		<pubDate>Tue, 11 Mar 2008 11:47:10 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Java]]></category>

		<category><![CDATA[Selenium]]></category>

		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://lawrencesong.net/?p=8</guid>
		<description><![CDATA[In this post, I will talk about creating nicer syntax for verifications.
In Ruby, we can add new methods into existing class. Rspec adds some nice assert methods such as should_equal(expected_string) into string class.  However, it is impossible to do it in Java. Right, we can&#8217;t do it in unit test. Fortunately, we are writing [...]]]></description>
			<content:encoded><![CDATA[<p>In this post, I will talk about creating nicer syntax for verifications.</p>
<p>In Ruby, we can add new methods into existing class. Rspec adds some nice assert methods such as should_equal(expected_string) into string class.  However, it is impossible to do it in Java. Right, we can&#8217;t do it in unit test. Fortunately, we are writing automated tests. we can control what to return. Hence, I write a wrap class to allow code to use rspec-like syntax.</p>
<pre class="syntax-highlight:java">

public class TextDSL extends Assert {
private String text;
private String errorMessage;

public TextDSL(String text) {
this(text, &quot;&quot;);
}

public TextDSL(String text, String errorMessage) {
this.text = text;
this.errorMessage = errorMessage;
}

public void shouldEqual(String expectedText) {
assertEquals(errorMessage, expectedText, text);
}

public void shouldNotEqual(String notExpectedText) {
assertFalse(errorMessage + &quot; not expected:&lt;&quot; + notExpectedText + &quot;&gt; but was:&lt;&quot; + text + &quot;&gt;&quot;, notExpectedText.equals(text));
}

public void shouldEqual(int expectedInteger) {
assertEquals(errorMessage, String.valueOf(expectedInteger), text);
}

public void shouldNotEqual(int notExpectedInteger) {
assertFalse(errorMessage + &quot; not expected:&lt;&quot; + notExpectedInteger + &quot;&gt; but was:&lt;&quot; + text + &quot;&gt;&quot;, String.valueOf(
notExpectedInteger).equals(text));
}

public void shouldInclude(String expectedIncludedText) {
assertTrue(errorMessage + &quot; expected included:&lt;&quot; + expectedIncludedText + &quot;&gt; but was not included in:&lt;&quot; + text + &quot;&gt;&quot;,
text.contains(expectedIncludedText));
}

public void shouldNotInclude(String expectedNotIncludedText) {
assertFalse(errorMessage + &quot; not expected included:&lt;&quot; + expectedNotIncludedText + &quot;&gt; but was included in:&lt;&quot; + text + &quot;&gt;&quot;,
text.contains(expectedNotIncludedText));
}
}
</pre>
<p>then we can get nicer syntax to express our intent for verification.</p>
<p>dropDownList.shouldDisplayLabel -&gt; dropDownList.lable().shouldEqual(expectedLabel)</p>
<p>dropDownList.shouldDisplayIndex -&gt; dropDownList.index().shouldEqual(expectedIndex)</p>
<p>and I can do something like verify css style includes a particular style:</p>
<p>dropDownList.css().shouldInclude(&#8221;errorField&#8221;)</p>
<p>We can add more methods to TextDSL class. or we can create other DSL class we want to verify the object we want.</p>
<p>Later on, I will post the source code so that you can see the whole implementation.</p>
]]></content:encoded>
			<wfw:commentRss>http://lawrencesong.net/2008/03/selenium-dsl-ii/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Selenium DSL I</title>
		<link>http://lawrencesong.net/2008/02/selenium-dsl-i/</link>
		<comments>http://lawrencesong.net/2008/02/selenium-dsl-i/#comments</comments>
		<pubDate>Wed, 27 Feb 2008 11:16:00 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Java]]></category>

		<category><![CDATA[Selenium]]></category>

		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://lawrencesong.net/?p=4</guid>
		<description><![CDATA[I was working in a project which used Selenium RC as web test tool. The functional test coverage is high. However, as the application has become more complicated and more tests have been added, the automated testing becomes a bottleneck for velocity. The problems?

Hard to understand the intent of automated tests
Duplication of Selenium test code
Hard [...]]]></description>
			<content:encoded><![CDATA[<p>I was working in a project which used Selenium RC as web test tool. The functional test coverage is high. However, as the application has become more complicated and more tests have been added, the automated testing becomes a bottleneck for velocity. The problems?</p>
<ul>
<li>Hard to understand the intent of automated tests</li>
<li>Duplication of Selenium test code</li>
<li>Hard to reuse</li>
<li><a href="http://code.google.com/p/webdriver/wiki/PageObjects" title="Page objects">Page objects</a> has all responsibilities of page operations and verifications</li>
<li>Test the wrong thing</li>
<li> Because of complexity, fewer scenarios are created</li>
<li> Overtesting cause performance problem</li>
<li> New team members find it hard to write tests</li>
<li> QAs take a long time to write automated tests</li>
</ul>
<p>Let&#8217;s see how to solve all the problems listed above.</p>
<p>In the project, developers and QAs are both writing selenium tests. Without navigator into the code, it&#8217;s very hard to understand what does the particular test do.One way to solve the problem is to name the test better. for example testShouldAllTestFieldSetMaxLengthAsWhatTheyExpected(). However, selenium tests is not unit test, sometime it&#8217;s not easy to give a name to define all the operations and verification of the tests.</p>
<p>Recently, DSL became a hot topic. Define DSL in automated tests would help develops and QAs (even BAs) understanding the intent of all tests.  Hence, I decide to define DSL for elements in the page object.</p>
<p>The advantage to use DSL as following:</p>
<ul>
<li>Easier to read</li>
<li>Precise error message, i.e.:
<ul>
<li> assertTrue(selenium.isElementPresent(&#8221;id&#8221;) will give you message&#8221;expect true, but false&#8221;,  what the heck does that mean when you see the error message?</li>
<li>element.shouldExist() will give you message &#8220;expect element ### exist, but not exist&#8221;, you can customized the error message you want.</li>
</ul>
</li>
<li> Reuse DSL</li>
<li>No more asserts in the test class</li>
<li>Quicker development</li>
<li>Precise testing</li>
</ul>
<p>Here I show some simple DSL. (two types: operations and verifications)</p>
<p>TextBox:</p>
<ul>
<li>type(String text)</li>
<li>shouldDisplayRedBorder(), shouldNotDisplayRedBoder()</li>
<li>shouldDisplayValue(String expectValue)</li>
<li>shouldBeReadOnly(), shouldNotBeReadOnly()</li>
<li>shouldBeDisabled(), shouldNotBeDisabled()</li>
<li>shouldExist(), shouldNotExist()</li>
<li>&#8230;&#8230;</li>
</ul>
<p>Radio:</p>
<ul>
<li>click()</li>
<li>shouldBeSelected(), shouldNotBeSelected()</li>
<li>&#8230;&#8230;</li>
</ul>
<p>DropDownList:</p>
<ul>
<li>selectLabel(String label)</li>
<li>sleectIndex(String index)</li>
<li>shouldDisplayLabel(String expectedLabel)</li>
<li>shouldDisplayIndex(int index)</li>
</ul>
<p>Checkbox, Label, ErrorIcon, Table&#8230;</p>
<p>Depends on the project, you can create more customized element suitable for your need.</p>
<p>In  page objects, we just need to return element object. for example:</p>
<pre class="syntax-highlight:java">

class AmazonPage

public searchInDropDownList() { return newDropDownList(&quot;url&quot;); }

public fieldKeywordTextbox() { return newTextbox(&quot;field-keyword&quot;); }

public searchButton() { return newButton(&quot;go&quot;); }

}
</pre>
<p>then the test become look like</p>
<pre class="syntax-highlight:java">

amazonPage.searchInDropDownList().selectLabel(&quot;Books&quot;);

amazonPage.fieldKeywordTextbox().type(&quot;Selenium&quot;);

amazonPage.searchButton().click()
</pre>
<p>self-documentation is better than having a lot of comment in the test.</p>
<p>In selenium DSL II, I will talk about how to define better DSL syntax.</p>
]]></content:encoded>
			<wfw:commentRss>http://lawrencesong.net/2008/02/selenium-dsl-i/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Selenium Element Locators</title>
		<link>http://lawrencesong.net/2008/01/selenium-element-locators/</link>
		<comments>http://lawrencesong.net/2008/01/selenium-element-locators/#comments</comments>
		<pubDate>Mon, 07 Jan 2008 09:37:24 +0000</pubDate>
		<dc:creator>admin</dc:creator>
		
		<category><![CDATA[Selenium]]></category>

		<category><![CDATA[Testing]]></category>

		<guid isPermaLink="false">http://lawrencesong.net/?p=7</guid>
		<description><![CDATA[When element doesn&#8217;t contain any id and name, using xpath to find the element is very important for writing selenium test. I list some sample locate for the element which doesn&#8217;t contain id or name.
1. get the link with the link text&#60;a href=&#8221;link url&#8221;&#62;Link Text&#60;/a&#62;  -&#62;  link=Link Text
2. get element with the element [...]]]></description>
			<content:encoded><![CDATA[<p>When element doesn&#8217;t contain any id and name, using xpath to find the element is very important for writing selenium test. I list some sample locate for the element which doesn&#8217;t contain id or name.</p>
<p>1. get the link with the link text&lt;a href=&#8221;link url&#8221;&gt;Link Text&lt;/a&gt;  -&gt;  link=Link Text</p>
<p>2. get element with the element text</p>
<p>&lt;a href=&#8221;link url&#8221;&gt;Link Text&lt;/a&gt;  -&gt;   //a[text()='Link Text']</p>
<p>3.   get element with part of the element text</p>
<p>&lt;a href=&#8221;link url&#8221;&gt;Link Text&lt;/a&gt;   -&gt;  //a[contains(text(), 'ink Tex')]</p>
<p>4.   get element with an attribute</p>
<p>&lt;a href=&#8221;link url&#8221;&gt;Link Text&lt;/a&gt;  -&gt; //a[@href='link url']</p>
<p>5.  get element with  two attributes</p>
<p>&lt;input type=&#8221;text&#8221; value=&#8221;value&#8221;/&gt;  -&gt;  //input[@type='text' and @value='value']</p>
<p><a href="https://addons.mozilla.org/en-US/firefox/addon/1192" title="XPather">XPather</a> is a firefox plugin help you to find the xpath.</p>
<p>There is more element locators document to be found on <a href="http://release.openqa.org/selenium-remote-control/0.9.2/doc/dotnet/Selenium.html">Selenium Doc</a></p>
]]></content:encoded>
			<wfw:commentRss>http://lawrencesong.net/2008/01/selenium-element-locators/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
