標籤:des http 使用 strong 資料 os
我們在上一步做了很多基礎性的訓練,所以現在我們可以來做一些簡單的事情嘍。我們要加入全文檢索索引功能(沒錯,這個真的非常簡單!)。同時,我們也會寫一個端到端測試,因為一個好的端到端測試可以幫上很大忙。它監視著你的應用,並且在發生迴歸的時候迅速報告。
請重設工作目錄:
git checkout -f step-3
我們的應用現在有了一個搜尋方塊。注意到頁面上的手機列表隨著使用者在搜尋方塊中的輸入而變化。
步驟2和步驟3之間最重要的不同在下面列出。你可以在GitHub裡看到完整的差別。
控制器
我們對控制器不做任何修改。
模板
app/index.html
<div class="container-fluid"> <div class="row-fluid"> <div class="span2"> <!--Sidebar content--> Search: <input ng-model="query"> </div> <div class="span10"> <!--Body content--> <ul class="phones"> <li ng-repeat="phone in phones | filter:query"> {{phone.name}} <p>{{phone.snippet}}</p> </li> </ul> </div> </div></div>
我們現在添加了一個<input>標籤,並且使用AngularJS的$filter函數來處理ngRepeat指令的輸入。
這樣允許使用者輸入一個搜尋條件,立刻就能看到對電話列表的搜尋結果。我們來解釋一下新的代碼:
資料繫結: 這是AngularJS的一個核心特性。當頁面載入的時候,AngularJS會根據輸入框的屬性值名字,將其與資料模型中相同名字的變數綁定在一起,以確保兩者的同步性。
在這段代碼中,使用者在輸入框中輸入的資料名字稱作query,會立刻作為列表迭代器(phone in phones | filter:query`)其過濾器的輸入。當資料模型引起迭代器輸入變化的時候,迭代器可以高效得更新DOM將資料模型最新的狀態反映出來。
測試
在步驟2,我們學習了編寫和運行一個測試的方法。單元測試用來測試我們用js編寫的控制器和其他組件都非常方便,但是不能方便的對DOM操作和應用整合進行測試。對於這些來說,端到端測試是一個更好的選擇。
搜尋特性是完全通過模板和資料繫結實現的,所以我們的第一個端到端測試就來驗證這些特性是否符合我們的預期。
test/e2e/scenarios.js:
describe(‘PhoneCat App‘, function() { describe(‘Phone list view‘, function() { beforeEach(function() { browser().navigateTo(‘../../app/index.html‘); }); it(‘should filter the phone list as user types into the search box‘, function() { expect(repeater(‘.phones li‘).count()).toBe(3); input(‘query‘).enter(‘nexus‘); expect(repeater(‘.phones li‘).count()).toBe(1); input(‘query‘).enter(‘motorola‘); expect(repeater(‘.phones li‘).count()).toBe(2); }); });});
儘管這段測試代碼的文法看起來和我們之前用Jasmine寫的單元測試非常像,但是端到端測試使用的是AngularJS端到端測試器提供的介面。
運行一個端到端測試,在瀏覽器新標籤頁中開啟下面任意一個:
- node.js使用者:http://localhost:8000/test/e2e/runner.html
- 使用其他http伺服器的使用者:
http://localhost:[port-number]/[context-path]/test/e2e/runner.html
- 訪客:http://angular.github.com/angular-phonecat/step-3/test/e2e/runner.html
這個測實驗證了搜素框和迭代器被正確地整合起來。你可以發現,在AngularJS裡寫一個端到端測試多麼的簡單。儘管這個例子僅僅是一個簡單的測試,但是用它來構建任何一個複雜、可讀的端到端測試都很容易。
練習
- 在
index.html模板中添加一個{{query}}綁定來即時顯示query模型的當前值,然後觀察他們是如何根據輸入框中的值而變化。
現在我們來看一下我們怎麼讓query模型的值出現在HTML的頁面標題上。
你或許認為像下面這樣在title標籤上加上一個綁定就行了:
<title>Google Phone Gallery: {{query}}</title>
但是,當你重載頁面的時候,你根本沒辦法得到期望的結果。這是因為query模型僅僅在body元素定義的範圍內才有效。
<body ng-controller="PhoneListCtrl">
如果你想讓<title>元素繫結上query模型,你必須把ngController聲明移動到HTML元素上,因為它是title和body元素的共同祖先。
<html ng-app ng-controller="PhoneListCtrl">
一定要注意把body元素上的ng-controller聲明給刪了。
當綁定兩個花括弧在title元素上可以實現我們的目標,但是你或許發現了,頁面正載入的時候它們已經顯示給使用者看了。一個更好的解決方案是使用ngBind或者ngBindTemplate指令,它們在頁面載入時對使用者是不可見的:
<title ng-bind-template="Google Phone Gallery: {{query}}">Google Phone Gallery</title>
在test/e2e/scenarios.js的describe塊中加入下面這些端到端測試代碼:
it(‘should display the current filter value within an element with id "status"‘, function() { expect(element(‘#status‘).text()).toMatch(/Current filter: \s*$/); input(‘query‘).enter(‘nexus‘); expect(element(‘#status‘).text()).toMatch(/Current filter: nexus\s*$/); //alternative version of the last assertion that tests just the value of the binding using(‘#status‘).expect(binding(‘query‘)).toBe(‘nexus‘);});
重新整理瀏覽器,端到端測試器會報告測試失敗。為了讓測試通過,編輯index.html,添加一個id為“status”的div或者p元素,內容是一個query綁定,再加上Current filter:首碼。例如:
<div id="status">Current filter: {{query}}</div>
在端到端測試裡面加一條pause();語句,重新跑一遍。你將發現測試器暫停了!這樣允許你有機會在測試回合過程中查看你應用的狀態。測試應用是即時的!你可以更換搜尋內容來證明。稍有經驗你就會知道,這對於在端到端測試中迅速找到問題是多麼的關鍵。
總結
我們現在添加了全文檢索搜尋功能,並且完成一個測試證明了搜尋是對的!現在讓我們繼續到步驟4來看看給我們的手機應用增加排序功能。