diff --git a/.travis.yml b/.travis.yml
index 516b0214..8f1209da 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -8,6 +8,8 @@ script:
- yarn build
- yarn test
- yarn doc
+ - yarn demobuild
+ - yarn demotest
after_success:
# upload js coverage to codecov.io
- npm run codecov
diff --git a/README.md b/README.md
index 350246d7..9c6296b6 100644
--- a/README.md
+++ b/README.md
@@ -117,3 +117,7 @@ Using yarn: `yarn add --dev ngx-speculoos`
## Issues, questions
Please, provide feedback by filing issues, or by submitting pull requests, to the [Github Project](https://github.com/Ninja-Squad/ngx-speculoos).
+
+# Complete example
+
+You can look at a minimal complete example in the [demo](https://github.com/Ninja-Squad/ngx-speculoos/tree/master/projects/demo/src/app) project.
diff --git a/angular.json b/angular.json
index f1fdc5eb..6462c0b8 100644
--- a/angular.json
+++ b/angular.json
@@ -42,6 +42,98 @@
}
}
}
+ },
+ "demo": {
+ "root": "projects/demo/",
+ "sourceRoot": "projects/demo/src",
+ "projectType": "application",
+ "prefix": "demo",
+ "schematics": {},
+ "architect": {
+ "build": {
+ "builder": "@angular-devkit/build-angular:browser",
+ "options": {
+ "outputPath": "dist/demo",
+ "index": "projects/demo/src/index.html",
+ "main": "projects/demo/src/main.ts",
+ "polyfills": "projects/demo/src/polyfills.ts",
+ "tsConfig": "projects/demo/tsconfig.app.json",
+ "assets": [
+ "projects/demo/src/favicon.ico",
+ "projects/demo/src/assets"
+ ],
+ "styles": [
+ "projects/demo/src/styles.css"
+ ],
+ "scripts": []
+ },
+ "configurations": {
+ "production": {
+ "fileReplacements": [
+ {
+ "replace": "projects/demo/src/environments/environment.ts",
+ "with": "projects/demo/src/environments/environment.prod.ts"
+ }
+ ],
+ "optimization": true,
+ "outputHashing": "all",
+ "sourceMap": false,
+ "extractCss": true,
+ "namedChunks": false,
+ "aot": true,
+ "extractLicenses": true,
+ "vendorChunk": false,
+ "buildOptimizer": true
+ }
+ }
+ },
+ "serve": {
+ "builder": "@angular-devkit/build-angular:dev-server",
+ "options": {
+ "browserTarget": "demo:build"
+ },
+ "configurations": {
+ "production": {
+ "browserTarget": "demo:build:production"
+ }
+ }
+ },
+ "extract-i18n": {
+ "builder": "@angular-devkit/build-angular:extract-i18n",
+ "options": {
+ "browserTarget": "demo:build"
+ }
+ },
+ "test": {
+ "builder": "@angular-devkit/build-angular:karma",
+ "options": {
+ "main": "projects/demo/src/test.ts",
+ "polyfills": "projects/demo/src/polyfills.ts",
+ "tsConfig": "projects/demo/tsconfig.spec.json",
+ "karmaConfig": "projects/demo/karma.conf.js",
+ "styles": [
+ "projects/demo/src/styles.css"
+ ],
+ "scripts": [],
+ "assets": [
+ "projects/demo/src/favicon.ico",
+ "projects/demo/src/assets"
+ ]
+ }
+ },
+ "lint": {
+ "builder": "@angular-devkit/build-angular:tslint",
+ "options": {
+ "tsConfig": [
+ "projects/demo/tsconfig.app.json",
+ "projects/demo/tsconfig.spec.json"
+ ],
+ "exclude": [
+ "**/node_modules/**"
+ ]
+ }
+ }
+ }
}
},
"defaultProject": "ngx-speculoos"
diff --git a/package.json b/package.json
index 7491ca71..f778cff2 100644
--- a/package.json
+++ b/package.json
@@ -4,25 +4,32 @@
"scripts": {
"ng": "ng",
"build": "ng build --prod",
- "test": "ng test --no-progress --no-watch --code-coverage",
+ "test": "ng test --no-progress --no-watch --code-coverage --project=ngx-speculoos",
+ "demobuild": "ng build --prod --no-progress --project=demo",
+ "demotest": "ng test --no-progress --no-watch --project=demo",
"lint": "ng lint",
"release": "cd projects/ngx-speculoos && standard-version --infile ../../CHANGELOG.md",
"doc": "node scripts/prepare-doc.js && cd projects/ngx-speculoos && compodoc",
"codecov": "codecov"
},
"private": true,
- "devDependencies": {
- "@angular-devkit/build-angular": "~0.6.3",
- "@angular-devkit/build-ng-packagr": "~0.6.3",
- "@angular/cli": "~6.0.3",
+ "dependencies": {
"@angular/common": "^6.0.2",
"@angular/compiler": "^6.0.2",
- "@angular/compiler-cli": "^6.0.2",
"@angular/core": "^6.0.2",
- "@angular/language-service": "^6.0.2",
+ "@angular/forms": "^6.0.2",
"@angular/platform-browser": "^6.0.2",
"@angular/platform-browser-dynamic": "^6.0.2",
"@angular/router": "^6.0.2",
+ "rxjs": "6.1.0",
+ "zone.js": "0.8.26"
+ },
+ "devDependencies": {
+ "@angular-devkit/build-angular": "~0.6.3",
+ "@angular-devkit/build-ng-packagr": "~0.6.3",
+ "@angular/cli": "~6.0.3",
+ "@angular/compiler-cli": "^6.0.2",
+ "@angular/language-service": "^6.0.2",
"@compodoc/compodoc": "1.1.3",
"@types/jasmine": "2.8.8",
"@types/jasminewd2": "2.0.3",
@@ -38,13 +45,11 @@
"karma-jasmine": "1.1.2",
"karma-jasmine-html-reporter": "0.2.2",
"ng-packagr": "3.0.1",
- "rxjs": "6.1.0",
"standard-version": "4.3.0",
"ts-node": "5.0.1",
"tsickle": "0.28.0",
"tslib": "1.9.1",
"tslint": "5.9.1",
- "typescript": "2.7.2",
- "zone.js": "0.8.26"
+ "typescript": "2.7.2"
}
}
diff --git a/projects/demo/browserslist b/projects/demo/browserslist
new file mode 100644
index 00000000..8e09ab49
--- /dev/null
+++ b/projects/demo/browserslist
@@ -0,0 +1,9 @@
+# This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
+# For additional information regarding the format and rule options, please see:
+# https://github.com/browserslist/browserslist#queries
+# For IE 9-11 support, please uncomment the last line of the file and adjust as needed
+> 0.5%
+last 2 versions
+Firefox ESR
+not dead
+# IE 9-11
\ No newline at end of file
diff --git a/projects/demo/karma.conf.js b/projects/demo/karma.conf.js
new file mode 100644
index 00000000..14f2d855
--- /dev/null
+++ b/projects/demo/karma.conf.js
@@ -0,0 +1,37 @@
+// Karma configuration file, see link for more information
+// https://karma-runner.github.io/1.0/config/configuration-file.html
+
+module.exports = function (config) {
+ config.set({
+ basePath: '',
+ frameworks: ['jasmine', '@angular-devkit/build-angular'],
+ plugins: [
+ require('karma-jasmine'),
+ require('karma-chrome-launcher'),
+ require('karma-jasmine-html-reporter'),
+ require('karma-coverage-istanbul-reporter'),
+ require('@angular-devkit/build-angular/plugins/karma')
+ ],
+ client: {
+ clearContext: false // leave Jasmine Spec Runner output visible in browser
+ },
+ coverageIstanbulReporter: {
+ dir: require('path').join(__dirname, '../../coverage'),
+ reports: ['html', 'lcovonly'],
+ fixWebpackSourcePaths: true
+ },
+ reporters: process.env.CI === 'true' ? ['dots'] : ['progress', 'kjhtml'],
+ port: 9876,
+ colors: true,
+ logLevel: config.LOG_INFO,
+ autoWatch: true,
+ browsers: process.env.CI === 'true' ? ['chrome_travis_ci'] : ['ChromeHeadless'],
+ customLaunchers: {
+ chrome_travis_ci: {
+ base: 'ChromeHeadless',
+ flags: ['--no-sandbox']
+ }
+ },
+ singleRun: false
+ });
+};
diff --git a/projects/demo/src/app/app.component.css b/projects/demo/src/app/app.component.css
new file mode 100644
index 00000000..e69de29b
diff --git a/projects/demo/src/app/app.component.html b/projects/demo/src/app/app.component.html
new file mode 100644
index 00000000..05b10efd
--- /dev/null
+++ b/projects/demo/src/app/app.component.html
@@ -0,0 +1,5 @@
+
+{{ greeting }}
diff --git a/projects/demo/src/app/app.component.spec.ts b/projects/demo/src/app/app.component.spec.ts
new file mode 100644
index 00000000..41f1be7b
--- /dev/null
+++ b/projects/demo/src/app/app.component.spec.ts
@@ -0,0 +1,66 @@
+import { TestBed, async } from '@angular/core/testing';
+import { AppComponent } from './app.component';
+import { ComponentTester } from 'ngx-speculoos';
+import { speculoosMatchers } from 'ngx-speculoos';
+import { ReactiveFormsModule } from '@angular/forms';
+
+class AppComponentTester extends ComponentTester {
+ constructor() {
+ super(AppComponent);
+ }
+
+ get firstName() {
+ return this.input('#firstName');
+ }
+
+ get submit() {
+ return this.button('button');
+ }
+
+ get greeting() {
+ return this.element('#greeting');
+ }
+}
+
+describe('AppComponent', () => {
+ let tester: AppComponentTester;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [
+ AppComponent,
+ ],
+ imports: [
+ ReactiveFormsModule
+ ]
+ }).compileComponents();
+ }));
+
+ beforeEach(() => {
+ tester = new AppComponentTester();
+
+ // a first call to detectChanges() is necessary. If the component had inputs, you would initialize them
+ // before calling detectChanges. For example:
+ // tester.someInput = 'someValue';
+ tester.detectChanges();
+
+ jasmine.addMatchers(speculoosMatchers);
+ });
+
+ it('should display an empty form, with a disabled submit button and no greeting', () => {
+ expect(tester.firstName).toHaveValue('');
+ expect(tester.submit.disabled).toBe(true);
+ expect(tester.greeting).toBeNull();
+ });
+
+ it('should enable the submit button when filling the first name', () => {
+ tester.firstName.fillWith('John');
+ expect(tester.submit.disabled).toBe(false);
+ });
+
+ it('should display the greeting when submitting the form', () => {
+ tester.firstName.fillWith('John');
+ tester.submit.click();
+ expect(tester.greeting).toContainText('Hello John');
+ });
+});
diff --git a/projects/demo/src/app/app.component.ts b/projects/demo/src/app/app.component.ts
new file mode 100644
index 00000000..996781a5
--- /dev/null
+++ b/projects/demo/src/app/app.component.ts
@@ -0,0 +1,24 @@
+import { Component, OnInit } from '@angular/core';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
+
+@Component({
+ selector: 'app-root',
+ templateUrl: './app.component.html',
+ styleUrls: ['./app.component.css']
+})
+export class AppComponent implements OnInit {
+ form: FormGroup;
+ greeting = '';
+
+ constructor(private fb: FormBuilder) { }
+
+ ngOnInit() {
+ this.form = this.fb.group({
+ firstName: ['', [Validators.required]]
+ });
+ }
+
+ sayHello() {
+ this.greeting = `Hello ${this.form.value.firstName}`;
+ }
+}
diff --git a/projects/demo/src/app/app.module.ts b/projects/demo/src/app/app.module.ts
new file mode 100644
index 00000000..56693d43
--- /dev/null
+++ b/projects/demo/src/app/app.module.ts
@@ -0,0 +1,17 @@
+import { BrowserModule } from '@angular/platform-browser';
+import { NgModule } from '@angular/core';
+
+import { AppComponent } from './app.component';
+import { ReactiveFormsModule } from '@angular/forms';
+
+@NgModule({
+ declarations: [
+ AppComponent
+ ],
+ imports: [
+ BrowserModule, ReactiveFormsModule
+ ],
+ providers: [],
+ bootstrap: [AppComponent]
+})
+export class AppModule { }
diff --git a/projects/demo/src/assets/.gitkeep b/projects/demo/src/assets/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/projects/demo/src/environments/environment.prod.ts b/projects/demo/src/environments/environment.prod.ts
new file mode 100644
index 00000000..3612073b
--- /dev/null
+++ b/projects/demo/src/environments/environment.prod.ts
@@ -0,0 +1,3 @@
+export const environment = {
+ production: true
+};
diff --git a/projects/demo/src/environments/environment.ts b/projects/demo/src/environments/environment.ts
new file mode 100644
index 00000000..012182ef
--- /dev/null
+++ b/projects/demo/src/environments/environment.ts
@@ -0,0 +1,15 @@
+// This file can be replaced during build by using the `fileReplacements` array.
+// `ng build ---prod` replaces `environment.ts` with `environment.prod.ts`.
+// The list of file replacements can be found in `angular.json`.
+
+export const environment = {
+ production: false
+};
+
+/*
+ * In development mode, to ignore zone related error stack frames such as
+ * `zone.run`, `zoneDelegate.invokeTask` for easier debugging, you can
+ * import the following file, but please comment it out in production mode
+ * because it will have performance impact when throw error
+ */
+// import 'zone.js/dist/zone-error'; // Included with Angular CLI.
diff --git a/projects/demo/src/favicon.ico b/projects/demo/src/favicon.ico
new file mode 100644
index 00000000..8081c7ce
Binary files /dev/null and b/projects/demo/src/favicon.ico differ
diff --git a/projects/demo/src/index.html b/projects/demo/src/index.html
new file mode 100644
index 00000000..77e5ff2c
--- /dev/null
+++ b/projects/demo/src/index.html
@@ -0,0 +1,14 @@
+
+
+
+
+ Demo
+
+
+
+
+
+
+
+
+
diff --git a/projects/demo/src/main.ts b/projects/demo/src/main.ts
new file mode 100644
index 00000000..91ec6da5
--- /dev/null
+++ b/projects/demo/src/main.ts
@@ -0,0 +1,12 @@
+import { enableProdMode } from '@angular/core';
+import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
+
+import { AppModule } from './app/app.module';
+import { environment } from './environments/environment';
+
+if (environment.production) {
+ enableProdMode();
+}
+
+platformBrowserDynamic().bootstrapModule(AppModule)
+ .catch(err => console.log(err));
diff --git a/projects/demo/src/polyfills.ts b/projects/demo/src/polyfills.ts
new file mode 100644
index 00000000..d310405a
--- /dev/null
+++ b/projects/demo/src/polyfills.ts
@@ -0,0 +1,80 @@
+/**
+ * This file includes polyfills needed by Angular and is loaded before the app.
+ * You can add your own extra polyfills to this file.
+ *
+ * This file is divided into 2 sections:
+ * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
+ * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
+ * file.
+ *
+ * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
+ * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
+ * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
+ *
+ * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
+ */
+
+/***************************************************************************************************
+ * BROWSER POLYFILLS
+ */
+
+/** IE9, IE10 and IE11 requires all of the following polyfills. **/
+// import 'core-js/es6/symbol';
+// import 'core-js/es6/object';
+// import 'core-js/es6/function';
+// import 'core-js/es6/parse-int';
+// import 'core-js/es6/parse-float';
+// import 'core-js/es6/number';
+// import 'core-js/es6/math';
+// import 'core-js/es6/string';
+// import 'core-js/es6/date';
+// import 'core-js/es6/array';
+// import 'core-js/es6/regexp';
+// import 'core-js/es6/map';
+// import 'core-js/es6/weak-map';
+// import 'core-js/es6/set';
+
+/** IE10 and IE11 requires the following for NgClass support on SVG elements */
+// import 'classlist.js'; // Run `npm install --save classlist.js`.
+
+/** IE10 and IE11 requires the following for the Reflect API. */
+// import 'core-js/es6/reflect';
+
+
+/** Evergreen browsers require these. **/
+// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
+import 'core-js/es7/reflect';
+
+
+/**
+ * Web Animations `@angular/platform-browser/animations`
+ * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
+ * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
+ **/
+// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
+
+/**
+ * By default, zone.js will patch all possible macroTask and DomEvents
+ * user can disable parts of macroTask/DomEvents patch by setting following flags
+ */
+
+ // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
+ // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
+ // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
+
+ /*
+ * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
+ * with the following flag, it will bypass `zone.js` patch for IE/Edge
+ */
+// (window as any).__Zone_enable_cross_context_check = true;
+
+/***************************************************************************************************
+ * Zone JS is required by default for Angular itself.
+ */
+import 'zone.js/dist/zone'; // Included with Angular CLI.
+
+
+
+/***************************************************************************************************
+ * APPLICATION IMPORTS
+ */
diff --git a/projects/demo/src/styles.css b/projects/demo/src/styles.css
new file mode 100644
index 00000000..90d4ee00
--- /dev/null
+++ b/projects/demo/src/styles.css
@@ -0,0 +1 @@
+/* You can add global styles to this file, and also import other style files */
diff --git a/projects/demo/src/test.ts b/projects/demo/src/test.ts
new file mode 100644
index 00000000..16317897
--- /dev/null
+++ b/projects/demo/src/test.ts
@@ -0,0 +1,20 @@
+// This file is required by karma.conf.js and loads recursively all the .spec and framework files
+
+import 'zone.js/dist/zone-testing';
+import { getTestBed } from '@angular/core/testing';
+import {
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting
+} from '@angular/platform-browser-dynamic/testing';
+
+declare const require: any;
+
+// First, initialize the Angular testing environment.
+getTestBed().initTestEnvironment(
+ BrowserDynamicTestingModule,
+ platformBrowserDynamicTesting()
+);
+// Then we find all the tests.
+const context = require.context('./', true, /\.spec\.ts$/);
+// And load the modules.
+context.keys().map(context);
diff --git a/projects/demo/tsconfig.app.json b/projects/demo/tsconfig.app.json
new file mode 100644
index 00000000..34b95f35
--- /dev/null
+++ b/projects/demo/tsconfig.app.json
@@ -0,0 +1,12 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../out-tsc/app",
+ "module": "es2015",
+ "types": []
+ },
+ "exclude": [
+ "src/test.ts",
+ "**/*.spec.ts"
+ ]
+}
diff --git a/projects/demo/tsconfig.spec.json b/projects/demo/tsconfig.spec.json
new file mode 100644
index 00000000..0036e072
--- /dev/null
+++ b/projects/demo/tsconfig.spec.json
@@ -0,0 +1,19 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "../../out-tsc/spec",
+ "module": "commonjs",
+ "types": [
+ "jasmine",
+ "node"
+ ]
+ },
+ "files": [
+ "src/test.ts",
+ "src/polyfills.ts"
+ ],
+ "include": [
+ "**/*.spec.ts",
+ "**/*.d.ts"
+ ]
+}
diff --git a/projects/demo/tslint.json b/projects/demo/tslint.json
new file mode 100644
index 00000000..0ad3cf4b
--- /dev/null
+++ b/projects/demo/tslint.json
@@ -0,0 +1,17 @@
+{
+ "extends": "../../tslint.json",
+ "rules": {
+ "directive-selector": [
+ true,
+ "attribute",
+ "app",
+ "camelCase"
+ ],
+ "component-selector": [
+ true,
+ "element",
+ "app",
+ "kebab-case"
+ ]
+ }
+}
diff --git a/yarn.lock b/yarn.lock
index cc9e2cf9..d96b1549 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -144,6 +144,12 @@
dependencies:
tslib "^1.9.0"
+"@angular/forms@^6.0.2":
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-6.0.2.tgz#a0647930e8b6e7fbd48f55eb69b399a41bcd091a"
+ dependencies:
+ tslib "^1.9.0"
+
"@angular/language-service@^6.0.2":
version "6.0.2"
resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-6.0.2.tgz#8f1ed45a7880f7133de88f0a1e09ae64f024c0b9"