mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-17 15:40:22 +00:00
142 lines
5.1 KiB
Text
Executable file
142 lines
5.1 KiB
Text
Executable file
@ngdoc overview
|
|
@name Tutorial: Step 3
|
|
@description
|
|
<table id="tutorial_nav">
|
|
<tr>
|
|
<td id="previous_step">{@link tutorial.step_02 Previous}</td>
|
|
<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-3/app Live
|
|
Demo}</td>
|
|
<td id="tut_home">{@link tutorial Tutorial Home}</td>
|
|
<td id="code_diff">{@link https://github.com/angular/angular-phonecat/compare/step-2...step-3 Code
|
|
Diff}</td>
|
|
<td id="next_step">{@link tutorial.step_04 Next}</td>
|
|
</tr>
|
|
</table>
|
|
|
|
We did a lot of work in laying a foundation for the app in the last step, so now we'll do
|
|
something simple, and add full text search (yes, it will be simple!). We will also write an
|
|
end-to-end test, because a good end-to-end test is a good friend. It stays with your app, keeps an
|
|
eye on it, and quickly detects regressions.
|
|
|
|
1. Reset your workspace to Step 3 using:
|
|
|
|
git checkout --force step-3
|
|
|
|
or
|
|
|
|
./goto_step.sh 3
|
|
|
|
2. Refresh your browser or check the app out on {@link
|
|
http://angular.github.com/angular-phonecat/step-3/app our server}. The app now has a search box.
|
|
The phone list on the page changes depending on what a user types into the search box.
|
|
|
|
The most important changes are listed below. You can see the full diff on {@link
|
|
https://github.com/angular/angular-phonecat/compare/step-2...step-3
|
|
GitHub}:
|
|
|
|
|
|
## Controller
|
|
|
|
We made no changes to the controller.
|
|
|
|
|
|
## Template
|
|
|
|
__`app/index.html`:__
|
|
<pre>
|
|
...
|
|
Fulltext Search: <input name="query"/>
|
|
|
|
<ul class="phones">
|
|
<li ng:repeat="phone in phones.$filter(query)">
|
|
{{phone.name}}
|
|
<p>{{phone.snippet}}</p>
|
|
</li>
|
|
</ul>
|
|
...
|
|
</pre>
|
|
|
|
We added a standard HTML `<input>` tag and use angular's {@link angular.Array.filter $filter}
|
|
function to process the input for the `ng:repeater`.
|
|
|
|
This lets a user enter search criteria and immediately see the effects of their search on the
|
|
phone list. This new code demonstrates the following:
|
|
|
|
* Data-binding. This is one of the core features in angular. When the page loads, angular binds
|
|
the name of the input box to a variable of the same name in the data model and keeps the two in
|
|
sync.
|
|
|
|
In this code, the data that a user types into the input box (named __`query`__) is immediately
|
|
available as a filter input in the list repeater (`phone in phones.$filter(`__`query`__`)`).
|
|
When changes to the data model cause the repeater's input to change, the repeater efficiently
|
|
updates the DOM to reflect the current state of the model.
|
|
|
|
* Use of `$filter`. The `{@link angular.Array.filter $filter}` method, uses the `query` value, to
|
|
create a new array that contains only those records that match the `query`.
|
|
|
|
* `ng:repeat` automatically updates the view in response to the changing number of phones returned
|
|
by the `$filter`. The process is completely transparent to the developer.
|
|
|
|
## Test
|
|
|
|
In Step 2, we learned how to write and run unit tests. Unit tests are perfect for testing
|
|
controllers and other components of our application written in JavaScript, but they can't easily
|
|
test DOM manipulation or the wiring of our application. For these, an end-to-end test is a much
|
|
better choice.
|
|
|
|
The search feature was fully implemented via templates and data-binding, so we'll write our first
|
|
end-to-end test, to verify that the feature works.
|
|
|
|
__`test/e2e/scenarios.js`:__
|
|
<pre>
|
|
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);
|
|
});
|
|
});
|
|
});
|
|
</pre>
|
|
|
|
Even though the syntax of this test looks very much like our controller unit test written with
|
|
Jasmine, the end-to-end test uses APIs of {@link
|
|
https://docs.google.com/document/d/11L8htLKrh6c92foV71ytYpiKkeKpM4_a5-9c3HywfIc/edit?hl=en&pli=1#
|
|
angular's end-to-end test runner}.
|
|
|
|
To run the end-to-end test, open the following in a new browser tab:
|
|
|
|
* node.js users: http://localhost:8000/test/e2e/runner.html
|
|
* users with other http servers:
|
|
http://localhost:[*port-number*]/[*context-path*]/test/e2e/runner.html
|
|
* casual reader: http://angular.github.com/angular-phonecat/step-3/test/e2e/runner.html
|
|
|
|
This test verifies that the search box and the repeater are correctly wired together. Notice how
|
|
easy it is to write end-to-end tests in angular. Although this example is for a simple test, it
|
|
really is that easy to set up any functional, readable, end-to-end test.
|
|
|
|
Now that you've verified everything, go to Step 4 to learn how to add sorting capability to the
|
|
phone list app.
|
|
|
|
<table id="tutorial_nav">
|
|
<tr>
|
|
<td id="previous_step">{@link tutorial.step_02 Previous}</td>
|
|
<td id="step_result">{@link http://angular.github.com/angular-phonecat/step-3/app Live
|
|
Demo}</td>
|
|
<td id="tut_home">{@link tutorial Tutorial Home}</td>
|
|
<td id="code_diff">{@link https://github.com/angular/angular-phonecat/compare/step-2...step-3 Code
|
|
Diff}</td>
|
|
<td id="next_step">{@link tutorial.step_04 Next}</td>
|
|
</tr>
|
|
</table>
|