initial codebase

This commit is contained in:
anweshknayak
2018-05-28 21:01:27 +05:30
commit 5eedfa13bd
136 changed files with 19812 additions and 0 deletions
+171
View File
@@ -0,0 +1,171 @@
# Introduction to Angular and modern design patterns
[Angular](https://angular.io) (aka Angular 2, 4, 5, 6...) is a new framework completely rewritten from the ground up,
replacing the now well-known [AngularJS](https://angularjs.org) framework (aka Angular 1.x).
More that just a framework, Angular should now be considered as a whole *platform* which comes with a complete set of
tools, like its own [CLI](https://github.com/angular/angular-cli), [debug utilities](https://augury.angular.io) or
[performance tools](https://github.com/angular/angular/tree/master/packages/benchpress).
Angular has been around for some time now, but I still get the feeling that it’s not getting the love it deserved,
probably because of other players in the field like React or VueJS. While the simplicity behind these frameworks can
definitely be attractive, they lack in my opinion what is essential when making big, enterprise-grade apps: a solid
frame to lead both experienced developers and beginners in the same direction and a rational convergence of tools,
patterns and documentation. Yes, the Angular learning curve may seems a little steep, but it’s definitely worth it.
## Getting started
#### Newcomer
If you're new to Angular you may feel overwhelmed by the quantity of new concepts to apprehend, so before digging
into this project you may want to start with [this progressive tutorial](https://angular.io/tutorial) that will guide
you step by step into building a complete Angular application.
#### AngularJS veteran
If you come from AngularJS and want to dig straight in the new version, you may want to take a look at the
[AngularJS vs 2 quick reference](https://angular.io/guide/ajs-quick-reference).
#### Cheatsheet
Until you know the full Angular API by heart, you may want to keep this
[cheatsheet](https://angular.io/guide/cheatsheet) that resumes the syntax and features on a single page at hand.
## Style guide
This project follows the standard [Angular style guide](https://angular.io/guide/styleguide).
More that just coding rules, this style guide also gives advices and best practices for a good application architecture
and is an **essential reading** for starters. Reading deeper, you can even find many explanations for some design
choices of the framework.
## Going deeper
Even though they are not mandatory, Angular was designed for the use of design patterns you may not be accustomed to,
like [reactive programming](#reactive-programming), [unidirectional data flow](#unidirectional-data-flow) and
[centralized state management](#centralized-state-management).
These concepts are difficult to resume in a few words, and despite being tightly related to each other they concern
specific parts of an application flow, each being quite deep to learn on its own.
You will essentially find here a list of good starting points to learn more on these subjects.
#### Reactive programming
You may not be aware of it, but Angular is now a *reactive system* by design.
Although you are not forced to use reactive programming patterns, they make the core of the framework and it is
definitely recommended to learn them if you want to leverage the best of Angular.
Angular uses [RxJS](http://reactivex.io/rxjs/) to implement the *Observable* pattern.
> An *Observable* is a stream of asynchronous events that can be processed with array-like operators.
##### From promises to observables
While AngularJS used to rely heavily on [*Promises*](https://docs.angularjs.org/api/ng/service/$q) to handle
asynchronous events, *Observables* are now used instead in Angular. Even though in specific cases like for HTTP
requests, an *Observable* can be converted into a *Promise*, it is recommended to embrace the new paradigm as it can a
lot more than *Promises*, with way less code. This transition is also explained in the
[Angular tutorial](https://angular.io/tutorial/toh-pt6#!%23observables).
Once you have made the switch, you will never look back again.
##### Learning references
- [What is reactive programming?](http://paulstovell.com/blog/reactive-programming), explained nicely through a simple
imaged story *(5 min)*
- [The introduction to reactive programming you've been missing](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754),
the title says it all *(30 min)*
- [Functional reactive programming for Angular 2 developers](http://blog.angular-university.io/functional-reactive-programming-for-angular-2-developers-rxjs-and-observables/),
see the functional reactive programming principles in practice with Angular *(15 min)*
- [RxMarbles](http://rxmarbles.com), a graphical representation of Rx operators that greatly help to understand their
usage
#### Unidirectional data flow
In opposition with AngularJS where one of its selling points was two-way data binding which ended up causing a lot of
major headaches for complex applications, Angular now enforces unidirectional data flow.
What does it means? Said with other words, it means that change detection cannot cause cycles, which was one of
AngularJS problematic points. It also helps to maintain simpler and more predictable data flows in applications, along
with substantial performance improvements.
**Wait, then why the Angular documentation have mention of a
[two-way binding syntax](https://angular.io/guide/template-syntax#binding-syntax-an-overview)?**
If you look closely, the new two-way binding syntax is just syntactic sugar to combine two *one-way* bindings (a
*property* and *event* binding), keeping the data flow unidirectional.
This change is really important, as it was often the cause of performance issues with AngularJS, and it one of the
pillars enabling better performance in new Angular apps.
While Angular tries to stay *pattern-agnostic* and can be used with conventional MV* patterns, it was designed with
reactive programming in mind and really shines when used with reactive data flow patterns like
[redux](http://redux.js.org/docs/basics/DataFlow.html),
[Flux](https://facebook.github.io/flux/docs/in-depth-overview.html#content) or
[MVI](http://futurice.com/blog/reactive-mvc-and-the-virtual-dom).
#### Centralized state management
As applications grow in size, keeping track of the all its individual components state and data flows can become
tedious, and tend to be difficult to manage and debug.
The main goal of using a centralized state management is to make state changes *predictable* by imposing certain
restrictions on how and when updates can happen, using *unidirectional data flow*.
This approach was first made popular with React with introduction of the
[Flux](https://facebook.github.io/flux/docs/in-depth-overview.html#content) architecture. Many libraries emerged then
trying to adapt and refine the original concept, and one of these gained massive popularity by providing a simpler,
elegant alternative: [Redux](http://redux.js.org/docs/basics/DataFlow.html).
Redux is at the same time a library (with the big *R*) and a design pattern (with the little *r*), the latter being
framework-agnostic and working very well with Angular.
The *redux* design pattern is based on these [3 principles](http://redux.js.org/docs/introduction/ThreePrinciples.html):
- The application state is a *single immutable* data structure
- A state change is triggered by an *action*, an object describing what happened
- Pure functions called *reducers* take the previous state and the next action to compute the new state
The core concepts behind these principles are nicely explained in
[this example](http://redux.js.org/docs/introduction/CoreConcepts.html) *(3 min)*.
##### Which library to use?
You can make Angular work with any state management library you like, but your best bet would be to use
[@ngrx/store](https://github.com/ngrx/store). It works the same as the popular [Redux](http://redux.js.org) library,
but with a tight integration with Angular and [RxJS](http://reactivex.io/rxjs/), with some nice additional developer
utilities.
Here are some resources to get started:
- [Build a better Angular 2 application with redux and ngrx](http://onehungrymind.com/build-better-angular-2-application-redux-ngrx/),
a nice tutorial for @ngrx/store *(30 min)*
- [Comprehensive introduction to @ngrx/store](https://gist.github.com/btroncone/a6e4347326749f938510), an in-depth
walkthrough to this library usage in Angular *(60 min)*
##### When to use it?
You may have noticed that the starter template does not include a centralized state management system out of the box.
Why is that? Well, while there is many benefits from using this pattern, the choice is ultimately up to your team and
what you want to achieve with your app.
Keep in mind that using a single centralized state for your app introduces a new layer a complexity
[that might not be needed](https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367), depending of your
goal.
## Optimizing performance
While the new Angular version resolves by design most of the performance issues that could be experienced with
AngularJS, there is always room for improvements. Just keep in mind that delivering an app with good performance is
often a matter of common sense and sane development practices.
Here is [a list of key points](https://github.com/mgechev/angular-performance-checklist) to check for in your app to
make sure you deliver the best experience to your customers.
After going through the checklist, make sure to also run an audit of your page through
[**Lighthouse**](https://developers.google.com/web/tools/lighthouse/), the latest Google tool that gives you meaningful
insight about your app performance, accessibility, mobile compatibility and more.
+90
View File
@@ -0,0 +1,90 @@
# End-to-end tests coding guide
End-to-end (E2E for short) tests are meant to test the behavior of your application, from start to finish.
While unit tests are the first choice for catching bugs and regression on individual components, it is a good idea to
complement them with test cases covering the integration between the individual components, hence the need for E2E
tests.
These tests use [Protractor](https://github.com/angular/protractor), which is a framework built for Angular on top of
[Selenium](https://github.com/SeleniumHQ/selenium) to control browsers and simulate user inputs.
[Jasmine](http://jasmine.github.io) is used as the base test framework.
## Good practices
- Avoid whenever possible inter-dependencies between your E2E tests
- Run E2E tests on your continuous integration server against different browsers
- If you use an Agile methodology, cover each user story acceptance factors with an E2E test
## Page objects
E2E tests should follow the *[Page Object](https://github.com/SeleniumHQ/selenium/wiki/PageObjects)* pattern.
#### What is a page object?
A page object:
- Models the objects on a page under test:
* *Properties* wrap page elements
* *Methods* wrap code that interacts with the page elements
- Simplifies the test scripts
- Reduces the amount of duplicated code
If the UI changes, the fix only needs to be applied in one place.
#### How to define a page object
```typescript
// login.po.ts
import { browser, element, by } from 'protractor';
export class LoginPage {
emailInput = element(by.css('input[name=^"email"]'));
passwordInput = element(by.css('input[name=^"password"]'));
loginButton = element(by.css('button[(click)^="login"]'));
registerButton = element(by.css('button[(click)^="register"]'));
navigateTo() {
return browser.get('/');
}
getGreetingText() {
return element(by.css('.greeting')).getText();
}
}
```
#### How to use a page object
```typescript
// login.e2e-spec.ts
import { LoginPage } from './login.po';
describe('Login', () => {
let page: LoginPage ;
beforeEach(() => {
page = new LoginPage();
page.navigateTo();
});
it('should navigate to the register page when the register button is clicked', () => {
page.registerButton.click();
expect(browser.getCurrentUrl()).toContain('/register');
});
it('should allow a user to log in', () => {
page.emailInput.sendKeys('test@mail.com');
page.passwordInput.sendKeys('abc123');
page.loginButton.click();
expect(page.getGreetingText()).toContain('Welcome, Test User');
});
});
```
## Credits
Parts of this guide were freely inspired by this
[presentation](https://docs.google.com/presentation/d/1B6manhG0zEXkC-H-tPo2vwU06JhL8w9-XCF9oehXzAQ).
+40
View File
@@ -0,0 +1,40 @@
# HTML coding guide
## Naming conventions
- Everything should be named in `kebab-case` (lowercase words separated with a `-`): tags, attributes, IDs, etc,
**except for everything bound to Angular** such variables, directives or events which should be in `camelCase`
- File names should always be in `kebab-case`
## Coding rules
- Use HTML5 doctype: `<!doctype html>`
- Use HTML [semantic elements](https://developer.mozilla.org/docs/Web/HTML/Sections_and_Outlines_of_an_HTML5_document)
- Use double quotes `"` around attribute values in tags
- Use a new line for every block, list, or table element, and indent every such child element
- Clearly Separate structure (HTML) from presentation (CSS) from behavior (JavaScript):
* Never use inline CSS or JavaScript
* Keep any logic out of the HTML
- `type` attribute for stylesheets and script tags should be omitted
## Common pitfalls
- **Block**-type tags cannot be nested inside **inline**-type tags: a `<div>` tag cannot be nested in a `<span>`.
This rule also applies regarding the `display` value of an element.
- HTML is **not** XML: empty tags cannot be self-closing and will result in improper results
* `<div/>` will be interpreted as a simple `<div>` without closing tag!
* The only tags that allows self-closing are the one that does not require a closing tag in first place:
these are the void elements that do not not accept content `<br>`, `<hr>`, `<img>`, `<input>`, `<meta>`, `<link>`
(and others).
## Templates
In accordance with the [Angular style guide](https://angular.io/guide/styleguide), HTML templates should be extracted in
separate files, when more than 3 lines.
Only use inline templates sparingly in very simple components with less than 3 lines of HTML.
## Enforcement
Coding rules enforcement and basic sanity checks are done in this project by [HTMLHint](http://htmlhint.com).
+95
View File
@@ -0,0 +1,95 @@
# Sass coding guide
[Sass](http://sass-lang.com) is a superset of CSS, which brings a lot of developer candy to help scaling CSS in large
projects and keeping it maintainable.
The main benefits of using Sass over plain CSS are *variables*, *nesting* and *mixins*, see the
[basics guide](http://sass-lang.com/guide) for more details.
> Note that this project use the newer, CSS-compatible **SCSS** syntax over the old
[indented syntax](http://sass-lang.com/documentation/file.INDENTED_SYNTAX.html).
## Naming conventions
- In the CSS world, everything should be named in `kebab-case` (lowercase words separated with a `-`).
- File names should always be in `kebab-case`
## Coding rules
- Use single quotes `'` for strings
- Use this general nesting hierarchy when constructing your styles:
```scss
// The base component class acts as the namespace, to avoid naming and style collisions
.my-component {
// Put here all component elements (flat)
.my-element {
// Use a third-level only for modifiers and state variations
&.active { ... }
}
}
```
Note that with
[Angular view encapsulation](https://angular.io/docs/ts/latest/guide/component-styles.html#!#view-encapsulation),
the first "namespace" level of nesting is not necessary as Angular takes care of the scoping for avoid collisions.
> As a side note, we are aware of the [BEM naming approach](https://en.bem.info/tools/bem/bem-naming/), but we found
it impractical for large projects. The nesting approach has drawbacks such as increased specificity, but it helps
keeping everything nicely organized, and more importantly, *scoped*.
Also keep in mind this general rules:
- Always use **class selectors**, never use ID selectors and avoid element selectors whenever possible
- No more than **3 levels** of nesting
- No more than **3 qualifiers**
## Best practices
- Use object-oriented CSS (OOCSS):
* Factorize common code in base class, and extend it, for example:
```scss
// Base button class
.btn { ... }
// Color variation
.btn-warning { ... }
// Size variation
.btn-small { ... }
```
* Try to name class by semantic, not style nor function for better reusability:
Use `.btn-warning`, not `btn-orange` nor `btn-cancel`
* Avoid undoing style, refactor using common base classes and extensions
- Keep your style scoped
* Clearly separate **global** (think *framework*) and **components** style
* Global style should only go in `src/theme/`, never in components
* Avoid style interactions between components, if some style may need to be shared, refactor it as a framework
component in put it in your global theme.
* Avoid using wider selectors than needed: always use classes if you can!
- Avoid rules multiplication
* The less CSS the better, factorize rules whenever it's possible
* CSS is code, and like any code frequent refactoring is healthy
- When ugly hacks cannot be avoided, create an explicit `src/hacks.scss` file and put it in:
* These ugly hacks should only be **temporary**
* Each hack should be documented with the author name, the problem and hack reason
* Limit this file to a reasonable length (~100 lines) and refactor hacks with proper solutions when the limit is
reached.
## Pitfalls
- Never use the `!important` keyword. Ever.
- Never use **inline** style in html, even *just for debugging* (because we **KNOW** it will end up in your commit)
## Browser compatibility
You should never use browser-specific prefixes in your code, as [autoprefixer](https://github.com/postcss/autoprefixer)
takes care of that part for you during the build process.
You just need to declare which browsers you target in the [`browserslist`](https://github.com/ai/browserslist) file.
## Enforcement
Coding rules are enforced in this project with [stylelint](https://stylelint.io).
This tool also checks the compatibility of the rules used against the browsers you are targeting (specified in the
[`browserslist`](https://github.com/ai/browserslist) file), via [doiuse](https://github.com/anandthakker/doiuse).
+63
View File
@@ -0,0 +1,63 @@
# TypeScript coding guide
[TypeScript](http://www.typescriptlang.org) is a superset of JavaScript that greatly helps building large web
applications.
Coding conventions and best practices comes from the
[TypeScript guidelines](https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines), and are also detailed in the
[TypeScript Deep Dive Style Guide](https://basarat.gitbooks.io/typescript/content/docs/styleguide/styleguide.html).
In addition, this project also follows the general [Angular style guide](https://angular.io/guide/styleguide).
## Naming conventions
- Use `PascalCase` for types, classes, interfaces, constants and enum values.
- Use `camelCase` for variables, properties and functions
- Avoid prefixing interfaces with a capital `I`, see [Angular style guide](https://angular.io/guide/styleguide#!#03-03)
- Do not use `_` as a prefix for private properties. An exception can be made for backing fields like this:
```typescript
private _foo: string;
get foo() { return this._foo; } // foo is read-only to consumers
```
## Ordering
- Within a file, type definitions should come first
- Within a class, these priorities should be respected:
* Properties comes before functions
* Static symbols comes before instance symbols
* Public symbols comes before private symbols
## Coding rules
- Use single quotes `'` for strings
- Always use strict equality checks: `===` and `!==` instead of `==` or `!=` to avoid comparison pitfalls (see
[JavaScript equality table](https://dorey.github.io/JavaScript-Equality-Table/)).
The only accepted usage for `==` is when you want to check a value against `null` or `undefined`.
- Use `[]` instead of `Array` constructor
- Use `{}` instead of `Object` constructor
- Always specify types for function parameters and returns (if applicable)
- Do not export types/functions unless you need to share it across multiple components
- Do not introduce new types/values to the global namespace
- Use arrow functions over anonymous function expressions
- Only surround arrow function parameters when necessary.
For example, `(x) => x + x` is wrong but the following are correct:
* `x => x + x`
* `(x, y) => x + y`
* `<T>(x: T, y: T) => x === y`
## Definitions
In order to infer types from JavaScript modules, TypeScript language supports external type definitions. They are
located in the `node_modules/@types` folder.
To manage type definitions, use standard `npm install|update|remove` commands.
## Enforcement
Coding rules are enforced in this project via [TSLint](https://github.com/palantir/tslint).
Angular-specific rules are also enforced via the [Codelyzer](https://github.com/mgechev/codelyzer) rule extensions.
## Learn more
The read of [TypeScript Deep Dive](https://basarat.gitbooks.io/typescript) is recommended, this is a very good
reference book for TypeScript (and also open-source).
+46
View File
@@ -0,0 +1,46 @@
# Unit tests coding guide
The main objective of unit tests is to detect regressions and to help you design software components. A suite of
*good* unit tests can be *immensely* valuable for your project and makes it easier to refactor and expand your code.
But keep in mind that a suite of *bad* unit tests can also be *immensely* painful, and hurt your development by
inhibiting your ability to refactor or alter your code in any way.
## What to test?
Everything! But if you need priorities, at least all business logic code must be tested: services, helpers, models...
Shared directives/components should also be covered by unit tests, if you do not have the time to test every single
component.
Keep in mind that component unit tests should not overlap with [end-to-end tests](e2e-tests.md): while unit the tests
cover the isolated behavior of the component bindings and methods, the end-to-end tests in opposition should cover the
integration and interactions with other app components based on real use cases scenarios.
## Good practices
- Name your tests cleanly and consistently
- Do not only test nominal cases, the most important tests are the one covering the edge cases
- Each test should be independent to all the others
- Avoid unnecessary assertions: it's counter-productive to assert anything covered by another test, it just increase
pointless failures and maintenance workload
- Test only one code unit at a time: if you cannot do this, it means you have an architecture problem in your app
- Mock out all external dependencies and state: if there is too much to mock, it is often a sign that maybe you
should split your tested module into several more independent modules
- Clearly separate or identify these 3 stages of each unit test (the *3A*): *arrange*, *act* and *assert*
- When you fix a bug, add a test case for it to prevent regression
## Pitfalls
- Sometimes your architecture might mean your code modify static variables during unit tests. Avoid this if you can,
but if you can't, at least make sure each test resets the relevant statics before and after your tests.
- Don’t unit-test configuration settings
- Improving test coverage is good, but having meaningful tests is better: start with the latter first, and **only after
essential features of your code unit are tested**, your can think of improving the coverage.
## Unit testing with Angular
A good starting point for learning is the official
[testing guide](https://angular.io/docs/ts/latest/guide/testing.html).
But as you will most likely want to go bit further in real world apps, these
[example test snippets](https://gist.github.com/wkwiatek/e8a4a9d92abc4739f04f5abddd3de8a7) are also very helpful to
learn how to cover most common testing use cases.