|
3 | 3 | ## Table of Contents |
4 | 4 | 1. [High-level Goals](#high-level-goals) |
5 | 5 | 2. [Third-party Dependencies](#third-party-dependencies) |
6 | | -2. [Directory and File Structure](#directory-and-file-structure) |
7 | | -3. [Parts of Angular](#parts-of-angular) |
8 | | -4. [General Patterns and Anti-patterns](#general-patterns-and-anti-patterns) |
| 6 | +3. [Directory and File Structure](#directory-and-file-structure) |
| 7 | +4. [Parts of Angular](#parts-of-angular) |
| 8 | +5. [Testing](#testing) |
| 9 | +6. [General Patterns and Anti-patterns](#general-patterns-and-anti-patterns) |
9 | 10 |
|
10 | 11 | ## High-level Goals |
11 | 12 |
|
@@ -746,6 +747,80 @@ _Why_: Avoids unnecessary expensive `$watch`ers. |
746 | 747 | - Don’t use `ngInit` – use controllers instead. |
747 | 748 | - Don’t use `<div ng-controller="Controller">` syntax. Use directives instead. |
748 | 749 |
|
| 750 | +## Testing |
| 751 | + |
| 752 | +Our applications are covered by two different types of test: |
| 753 | +- unit tests, which test individual components by asserting that they behave as expected. |
| 754 | +- End to End, or E2E, tests, which load up the application in a browser and interact with it as if a user would, asserting the application behaves expectedly. |
| 755 | + |
| 756 | +To write our tests we use [Jasmine BDD](http://jasmine.github.io/2.0/introduction.html) and [ngMock](https://docs.angularjs.org/api/ngMock). |
| 757 | + |
| 758 | +### Unit Testing |
| 759 | + |
| 760 | +Every component should have a comprehensive set of unit tests. |
| 761 | + |
| 762 | +#### Structure of Unit Tests |
| 763 | + |
| 764 | +Tests should be grouped into logical blocks using Jasmine's `describe` function. Tests for a function should all be contained within a `describe` block, and `describe` blocks should also be used to describe different scenarios, or _contexts_: |
| 765 | + |
| 766 | +```js |
| 767 | +describe('#update', function() { |
| 768 | + describe('when the data is valid', function() { |
| 769 | + it('shows the success message', function() {…}); |
| 770 | + }); |
| 771 | + |
| 772 | + describe('when the data is invalid', function() { |
| 773 | + it('shows errors', function() {…}); |
| 774 | + }); |
| 775 | +}); |
| 776 | +``` |
| 777 | + |
| 778 | +#### Dependencies |
| 779 | + |
| 780 | +Each component should have its dependencies stubbed in each test. |
| 781 | + |
| 782 | +Inject the dependencies and the components being tested in a `beforeEach` function. This encapsulates each test's state, ensuring that they are independent, making them easier to reason about. Tests should never depend on being run in a specific order. |
| 783 | + |
| 784 | +```js |
| 785 | +var SomeService; |
| 786 | + |
| 787 | +beforeEach(inject(function($injector) { |
| 788 | + SomeService = $injector.get('SomeService'); |
| 789 | +})); |
| 790 | +``` |
| 791 | + |
| 792 | +#### Controllers |
| 793 | + |
| 794 | +When injecting controllers for a test, use the `controller as` syntax: |
| 795 | + |
| 796 | +```js |
| 797 | +beforeEach(inject(function($injector, $controller) { |
| 798 | + $controller('OrganisationController as ctrl', {…}); |
| 799 | +})); |
| 800 | +``` |
| 801 | + |
| 802 | +Always create a new scope to pass into the controller: |
| 803 | + |
| 804 | +```js |
| 805 | +var scope; |
| 806 | +beforeEach(inject(function($injector, $controller) { |
| 807 | + scope = $injector.get('$rootScope').$new(); |
| 808 | + $controller('OrganisationController as ctrl', { |
| 809 | + $scope: scope, |
| 810 | + … |
| 811 | + }); |
| 812 | +})); |
| 813 | +``` |
| 814 | + |
| 815 | +#### Fixtures |
| 816 | + |
| 817 | +When stubbing an API request using `$httpBackend`, always respond with a correctly formatted object. These responses should be saved individually as `.json` files and imported using the SystemJS JSON plugin: |
| 818 | + |
| 819 | +```js |
| 820 | +import updateFixture from 'app/services/roles/update.fixture.json!json |
| 821 | +
|
| 822 | +$httpBackend.expectPUT('someurl.com').respond(201, updateFixture); |
| 823 | +``` |
749 | 824 |
|
750 | 825 | ## General Patterns and Anti-Patterns |
751 | 826 |
|
@@ -838,80 +913,6 @@ _Why_: Using DI makes testing and refactoring easier. |
838 | 913 |
|
839 | 914 | _Why_: You should `$scope.$apply()` as close to the asynchronous event binding as possible. |
840 | 915 |
|
841 | | -### Testing |
842 | | - |
843 | | -Our applications are covered by two different types of test: |
844 | | -- unit tests, which test individual components by asserting that they behave as expected. |
845 | | -- End to End, or E2E, tests, which load up the application in a browser and interact with it as if a user would, asserting the application behaves expectedly. |
846 | | - |
847 | | -To write our tests we use [Jasmine BDD](http://jasmine.github.io/2.0/introduction.html) and [ngMock](https://docs.angularjs.org/api/ngMock). |
848 | | - |
849 | | -#### Unit Testing |
850 | | - |
851 | | -Every component should have a comprehensive set of unit tests. |
852 | | - |
853 | | -##### Structure of Unit Tests |
854 | | - |
855 | | -Tests should be grouped into logical blocks using Jasmine's `describe` function. Tests for a function should all be contained within a `describe` block, and `describe` blocks should also be used to describe different scenarios, or _contexts_: |
856 | | - |
857 | | -```js |
858 | | -describe('#update', function() { |
859 | | - describe('when the data is valid', function() { |
860 | | - it('shows the success message', function() {…}); |
861 | | - }); |
862 | | - |
863 | | - describe('when the data is invalid', function() { |
864 | | - it('shows errors', function() {…}); |
865 | | - }); |
866 | | -}); |
867 | | -``` |
868 | | - |
869 | | -##### Dependencies |
870 | | - |
871 | | -Each component should have its dependencies stubbed in each test. |
872 | | - |
873 | | -Inject the dependencies and the components being tested in a `beforeEach` function. This encapsulates each test's state, ensuring that they are independent, making them easier to reason about. Tests should never depend on being run in a specific order. |
874 | | - |
875 | | -```js |
876 | | -var SomeService; |
877 | | - |
878 | | -beforeEach(inject(function($injector) { |
879 | | - SomeService = $injector.get('SomeService'); |
880 | | -})); |
881 | | -``` |
882 | | - |
883 | | -##### Controllers |
884 | | - |
885 | | -When injecting controllers for a test, use the `controller as` syntax: |
886 | | - |
887 | | -```js |
888 | | -beforeEach(inject(function($injector, $controller) { |
889 | | - $controller('OrganisationController as ctrl', {…}); |
890 | | -})); |
891 | | -``` |
892 | | - |
893 | | -Always create a new scope to pass into the controller: |
894 | | - |
895 | | -```js |
896 | | -var scope; |
897 | | -beforeEach(inject(function($injector, $controller) { |
898 | | - scope = $injector.get('$rootScope').$new(); |
899 | | - $controller('OrganisationController as ctrl', { |
900 | | - $scope: scope, |
901 | | - … |
902 | | - }); |
903 | | -})); |
904 | | -``` |
905 | | - |
906 | | -##### Fixtures |
907 | | - |
908 | | -When stubbing an API request using `$httpBackend`, always respond with a correctly formatted object. These responses should be saved individually as `.json` files and imported using the SystemJS JSON plugin: |
909 | | - |
910 | | -```js |
911 | | -import updateFixture from 'app/services/roles/update.fixture.json!json |
912 | | -
|
913 | | -$httpBackend.expectPUT('someurl.com').respond(201, updateFixture); |
914 | | -``` |
915 | 916 |
|
916 | 917 | ## Credits |
917 | 918 |
|
|
0 commit comments