From 6f92321ebf6ce5b8ab2f04f424867eb1d086db45 Mon Sep 17 00:00:00 2001 From: "jason.wall" Date: Thu, 5 Jan 2017 19:54:18 -0500 Subject: [PATCH] TEST: YAY! Got unit testing to work!... --- DynamicBibleIonic/angular-cli.json | 58 ++++++++++++++ DynamicBibleIonic/karma.conf.js | 83 ++++++++++----------- DynamicBibleIonic/package.json | 29 +++++-- DynamicBibleIonic/protractor.conf.js | 32 ++++++++ DynamicBibleIonic/src/Reference.spec.ts | 38 ++++++++++ DynamicBibleIonic/src/Reference.ts | 38 ++++++---- DynamicBibleIonic/src/bible-service.spec.ts | 69 +++++++++++++++++ DynamicBibleIonic/src/bible-service.ts | 9 ++- DynamicBibleIonic/src/mocks.ts | 66 ++++++++++++++++ DynamicBibleIonic/src/polyfills.ts | 19 +++++ DynamicBibleIonic/src/test-service.ts | 14 ++++ DynamicBibleIonic/src/test.ts | 78 +++++++++++++++++++ DynamicBibleIonic/src/tsconfig.test.json | 20 +++++ DynamicBibleIonic/tsconfig.json | 1 + 14 files changed, 485 insertions(+), 69 deletions(-) create mode 100644 DynamicBibleIonic/angular-cli.json create mode 100644 DynamicBibleIonic/protractor.conf.js create mode 100644 DynamicBibleIonic/src/Reference.spec.ts create mode 100644 DynamicBibleIonic/src/bible-service.spec.ts create mode 100644 DynamicBibleIonic/src/mocks.ts create mode 100644 DynamicBibleIonic/src/polyfills.ts create mode 100644 DynamicBibleIonic/src/test-service.ts create mode 100644 DynamicBibleIonic/src/test.ts create mode 100644 DynamicBibleIonic/src/tsconfig.test.json diff --git a/DynamicBibleIonic/angular-cli.json b/DynamicBibleIonic/angular-cli.json new file mode 100644 index 00000000..0c98060c --- /dev/null +++ b/DynamicBibleIonic/angular-cli.json @@ -0,0 +1,58 @@ +{ + "project": { + "version": "3.0.0-beta.22-1", + "name": "Dynamic Bible" + }, + "apps": [ + { + "root": "src", + "outDir": "dist", + "assets": [ + "assets" + ], + "index": "index.html", + "main": "main.ts", + "test": "test.ts", + "tsconfig": "tsconfig.test.json", + "prefix": "app", + "mobile": false, + "styles": [ + "styles.css" + ], + "scripts": [], + "environments": { + "source": "environments/environment.ts", + "dev": "environments/environment.ts", + "prod": "environments/environment.prod.ts" + } + } + ], + "addons": [], + "packages": [], + "e2e": { + "protractor": { + "config": "./protractor.conf.js" + } + }, + "test": { + "karma": { + "config": "./karma.conf.js" + } + }, + "defaults": { + "styleExt": "css", + "prefixInterfaces": false, + "inline": { + "style": false, + "template": false + }, + "spec": { + "class": false, + "component": true, + "directive": true, + "module": false, + "pipe": true, + "service": true + } + } +} \ No newline at end of file diff --git a/DynamicBibleIonic/karma.conf.js b/DynamicBibleIonic/karma.conf.js index be5a2ed0..71dfbf4d 100644 --- a/DynamicBibleIonic/karma.conf.js +++ b/DynamicBibleIonic/karma.conf.js @@ -1,42 +1,41 @@ -module.exports = function (config) -{ - config.set({ - basePath: '', - frameworks: ['jasmine', 'karma-typescript'], - - files: [ - './src/**/*.spec.ts' - ], - - exclude: [ - ], - - preprocessors: { - './src/**/*.spec.ts': ['karma-typescript'] - }, - - typescriptPreprocessor: { - options: { - sourceMap: false, - target: 'ES5', - module: 'amd', - noImplicitAny: true, - noResolve: true, - removeComments: true, - concatenateOutput: false - }, - transformPath: function (path) - { - return path.replace(/\.ts$/, '.js'); - } - }, - reporters: ['progress', 'karma-typescript'], - port: 9876, - colors: true, - logLevel: config.LOG_DEBUG, - autoWatch: true, - browsers: ['Chrome'], - singleRun: false, - concurrency: Infinity - }) -} \ No newline at end of file +module.exports = function (config) { + config.set({ + basePath: '', + proxies: { + '/data/': '/base/www/data/', + }, + frameworks: ['jasmine', 'angular-cli'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-remap-istanbul'), + require('karma-mocha-reporter'), + require('angular-cli/plugins/karma') + ], + files: [ + { pattern: './www/lib/jquery.min.js', watched: false }, + { pattern: './www/data/**/*.json', included: false, served: true }, + { pattern: './src/test.ts', watched: false }, + ], + preprocessors: { + './src/test.ts': ['angular-cli'] + }, + mime: { + 'text/x-typescript': ['ts','tsx'] + }, + + angularCli: { + config: './angular-cli.json', + environment: 'dev' + }, + reporters: config.angularCli && config.angularCli.codeCoverage + ? ['mocha', 'karma-remap-istanbul'] + : ['mocha'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: false + }); +}; \ No newline at end of file diff --git a/DynamicBibleIonic/package.json b/DynamicBibleIonic/package.json index bf4f7463..ff227ad4 100644 --- a/DynamicBibleIonic/package.json +++ b/DynamicBibleIonic/package.json @@ -12,7 +12,9 @@ "build": "ionic-app-scripts build", "ionic:build": "ionic-app-scripts build", "ionic:serve": "ionic-app-scripts serve", - "test": "karma start karma.conf.js" + "start": "ionic serve", + "test": "ng test", + "test-coverage": "ng test --code-coverage" }, "dependencies": { "@angular/common": "2.2.1", @@ -29,18 +31,29 @@ "ionic-angular": "2.0.0-rc.4", "ionic-native": "2.2.11", "ionicons": "3.0.0", - "jasmine-core": "^2.5.2", - "karma": "^1.3.0", - "karma-chrome-launcher": "^2.0.0", - "karma-jasmine": "^1.1.0", - "karma-typescript": "^2.1.5", "rxjs": "5.0.0-beta.12", "zone.js": "0.6.26" }, "devDependencies": { "@ionic/app-scripts": "0.0.47", - "karma": "^1.3.0", - "typescript": "2.0.9" + "@types/jasmine": "2.5.38", + "@types/node": "6.0.42", + "angular-cli": "1.0.0-beta.24", + "codecov": "1.0.1", + "jasmine-core": "2.5.2", + "jasmine-spec-reporter": "2.7.0", + "karma": "1.3.0", + "karma-chrome-launcher": "2.0.0", + "karma-cli": "1.0.1", + "karma-jasmine": "1.1.0", + "karma-mocha-reporter": "2.2.1", + "karma-remap-istanbul": "0.2.2", + "protractor": "4.0.13", + "protractor-jasmine2-screenshot-reporter": "0.3.2", + "ts-node": "1.7.2", + "tslint": "4.1.1", + "tslint-eslint-rules": "3.2.0", + "typescript": "2.0.10" }, "cordovaPlugins": [ "cordova-plugin-whitelist", diff --git a/DynamicBibleIonic/protractor.conf.js b/DynamicBibleIonic/protractor.conf.js new file mode 100644 index 00000000..13fb45b4 --- /dev/null +++ b/DynamicBibleIonic/protractor.conf.js @@ -0,0 +1,32 @@ +// Protractor configuration file, see link for more information +// https://github.com/angular/protractor/blob/master/docs/referenceConf.js + +/*global jasmine */ +var SpecReporter = require('jasmine-spec-reporter'); + +exports.config = { + allScriptsTimeout: 11000, + specs: [ + './e2e/**/*.e2e-spec.ts' + ], + capabilities: { + 'browserName': 'chrome' + }, + directConnect: true, + baseUrl: 'http://localhost:8100/', + framework: 'jasmine', + jasmineNodeOpts: { + showColors: true, + defaultTimeoutInterval: 30000, + print: function() {} + }, + useAllAngular2AppRoots: true, + beforeLaunch: function() { + require('ts-node').register({ + project: 'e2e' + }); + }, + onPrepare: function() { + jasmine.getEnv().addReporter(new SpecReporter()); + } +}; \ No newline at end of file diff --git a/DynamicBibleIonic/src/Reference.spec.ts b/DynamicBibleIonic/src/Reference.spec.ts new file mode 100644 index 00000000..c9945e4c --- /dev/null +++ b/DynamicBibleIonic/src/Reference.spec.ts @@ -0,0 +1,38 @@ +import { Reference } from './Reference'; + +describe('Reference', () => { + + it('Should parse the reference: Gen 1:1', () => { + let ref = new Reference("Gen 1:1").toString(); + expect(ref).toBe('Genesis 1:1'); + }); + + it('Should parse the reference: Gen 1:1-11', () => { + let ref = new Reference("Gen 1:1-11").toString(); + expect(ref).toBe('Genesis 1:1 - 11'); + }); + + it('Should parse the reference: Gen 1-2', () => { + let ref = new Reference("Gen 1-2").toString(); + expect(ref).toBe('Genesis 1:1 - 2:*'); + }); + + it('Should parse the reference: John 3:16', () => { + let ref = new Reference("John 3:16").toString(); + expect(ref).toBe('John 3:16'); + }); + + it('Should parse the reference: John 3-6', () => { + let ref = new Reference("Jn 3-6").toString(); + expect(ref).toBe('John 3:1 - 6:*'); + }); + + it('Should parse the reference: 1 Corinthians 3:5-6:5', () => { + let ref = new Reference("1 Corinthians 3:5-6:5").toString(); + expect(ref).toBe('1 Corinthians 3:5 - 6:5'); + }); + + it('Should parse the reference: 2 Samuel 5:5-6:5', () => { + expect(new Reference("II sam 5:5-6:5").toString()).toBe('2 Samuel 5:5 - 6:5'); + }); +}); \ No newline at end of file diff --git a/DynamicBibleIonic/src/Reference.ts b/DynamicBibleIonic/src/Reference.ts index 09872fd4..86a645a8 100644 --- a/DynamicBibleIonic/src/Reference.ts +++ b/DynamicBibleIonic/src/Reference.ts @@ -593,36 +593,42 @@ export class Reference { public toString() { // get the starting book, chapter, verse - let ref = this.Section.start.bookname.concat(" "). - concat(this.Section.start.chapter).concat(":"). - concat(this.Section.start.verse); + return Reference.toString(this.Section); + }; + + public static toString(section: Section) + { + // get the starting book, chapter, verse + let ref = section.start.bookname.concat(" "). + concat(section.start.chapter).concat(":"). + concat(section.start.verse); - if (this.Section.start.chapter == this.Section.end.chapter && - this.Section.start.verse == this.Section.end.verse && - this.Section.start.book == this.Section.end.book) + if (section.start.chapter == section.end.chapter && + section.start.verse == section.end.verse && + section.start.book == section.end.book) { return ref; } - if (this.Section.start.chapter == this.Section.end.chapter && - this.Section.start.verse != this.Section.end.verse && - this.Section.start.book == this.Section.end.book) + if (section.start.chapter == section.end.chapter && + section.start.verse != section.end.verse && + section.start.book == section.end.book) { - return ref.concat(" - ").concat(this.Section.end.verse); + return ref.concat(" - ").concat(section.end.verse); } - if (this.Section.start.book != this.Section.end.book) { - ref = ref.concat(" - ").concat(this.Section.end.bookname).concat(" "); + if (section.start.book != section.end.book) { + ref = ref.concat(" - ").concat(section.end.bookname).concat(" "); } else { ref = ref.concat(" - "); } - ref = ref.concat(this.Section.end.chapter).concat(":"); + ref = ref.concat(section.end.chapter).concat(":"); + + return ref.concat(section.end.verse); + } - return ref.concat(this.Section.end.verse); - }; - public static bookName(booknum: number): string { let book = new Array(); book[0] = ""; diff --git a/DynamicBibleIonic/src/bible-service.spec.ts b/DynamicBibleIonic/src/bible-service.spec.ts new file mode 100644 index 00000000..113fee7d --- /dev/null +++ b/DynamicBibleIonic/src/bible-service.spec.ts @@ -0,0 +1,69 @@ +import { getTestBed, TestBed, inject } from '@angular/core/testing'; +import { XHRBackend, BaseRequestOptions, HttpModule, Http, } from '@angular/http'; +import { MockBackend } from '@angular/http/testing'; +import { BibleService } from './bible-service'; +import { Reference } from './Reference'; + +describe('Bible Service', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [HttpModule], + providers: [ + BibleService, + { + provide: Http, + useFactory: function (backend, defaultOptions) { + return new Http(backend, defaultOptions); + }, + deps: [MockBackend, BaseRequestOptions] + }, + MockBackend, + BaseRequestOptions + ] + }); + }); + + it('Should get the verse: Gen 1:1', () => { + let svc: BibleService = getTestBed().get(BibleService); + let ref = new Reference("Gen 1:1").Section; + var r = svc.getResult(ref); + + expect(r.msg).toBe(':)'); + expect(r.ref).toBe('Genesis 1:1'); + expect(r.status).toBe(0); + expect(r.testament).toBe("old"); + + expect(r.cs.length).toBe(1); + expect(r.cs[0].vss.length).toBe(1); + expect(r.cs[0].vss[0].w.length).toBe(9); + expect(r.cs[0].vss[0].w[0].t).toBe("In the"); + }); + + it('Should get the passage: Gen 1:1-9', () => { + let svc: BibleService = getTestBed().get(BibleService); + let ref = new Reference("Gen 1:1-9").Section; + var r = svc.getResult(ref); + + expect(r.msg).toBe(':)'); + expect(r.ref).toBe('Genesis 1:1 - 9'); + expect(r.status).toBe(0); + expect(r.testament).toBe("old"); + + expect(r.cs.length).toBe(1); + expect(r.cs[0].vss.length).toBe(9); + expect(r.cs[0].vss[0].w.length).toBe(9); + expect(r.cs[0].vss[0].w[0].t).toBe("In the"); + }); + + it('Should return an error status', () => { + let svc: BibleService = getTestBed().get(BibleService); + let ref = new Reference("Gen 100:1").Section; + var r = svc.getResult(ref); + + expect(r.msg).toBe('Unable to retrieve bible passage Genesis 100:1.'); + expect(r.ref).toBe("Genesis 100:1"); + expect(r.status).toBe(-1); + expect(r.testament).toBe(''); + + }); +}); \ No newline at end of file diff --git a/DynamicBibleIonic/src/bible-service.ts b/DynamicBibleIonic/src/bible-service.ts index ff94e4fe..189228f3 100644 --- a/DynamicBibleIonic/src/bible-service.ts +++ b/DynamicBibleIonic/src/bible-service.ts @@ -2,6 +2,7 @@ /// import { Injectable } from "@angular/core"; import { Http } from "@angular/http"; +import { Reference } from "./Reference"; @Injectable() export class BibleService @@ -9,11 +10,12 @@ export class BibleService chapters: BiblePassage[]; result: BiblePassageResult; count: number = 0; + $: any; constructor(private http: Http) { } - + getResult(section: Section): BiblePassageResult { try @@ -23,7 +25,7 @@ export class BibleService this.result = { cs: [], testament: "", - ref: "", + ref: Reference.toString(section), status: 0, msg: ":)" }; @@ -32,7 +34,8 @@ export class BibleService for (let i = Number(section.start.chapter); i <= Number(section.end.chapter); i++) { const url = "data/bibles/kjv_strongs/" + section.start.book + "-" + i + ".json"; - jQuery.ajax({ + + $.ajax({ async: false, type: "GET", url: url, diff --git a/DynamicBibleIonic/src/mocks.ts b/DynamicBibleIonic/src/mocks.ts new file mode 100644 index 00000000..bd9d0ab4 --- /dev/null +++ b/DynamicBibleIonic/src/mocks.ts @@ -0,0 +1,66 @@ + +// IONIC: + +export class ConfigMock { + + public get(): any { + return ''; + } + + public getBoolean(): boolean { + return true; + } + + public getNumber(): number { + return 1; + } +} + +export class FormMock { + public register(): any { + return true; + } +} + +export class NavMock { + + public pop(): any { + return new Promise(function(resolve: Function): void { + resolve(); + }); + } + + public push(): any { + return new Promise(function(resolve: Function): void { + resolve(); + }); + } + + public getActive(): any { + return { + 'instance': { + 'model': 'something', + }, + }; + } + + public setRoot(): any { + return true; + } +} + +export class PlatformMock { + public ready(): any { + return new Promise((resolve: Function) => { + resolve(); + }); + } +} + +export class MenuMock { + public close(): any { + return new Promise((resolve: Function) => { + resolve(); + }); + } +} \ No newline at end of file diff --git a/DynamicBibleIonic/src/polyfills.ts b/DynamicBibleIonic/src/polyfills.ts new file mode 100644 index 00000000..567e660c --- /dev/null +++ b/DynamicBibleIonic/src/polyfills.ts @@ -0,0 +1,19 @@ +// This file includes polyfills needed by Angular 2 and is loaded before +// the app. You can add your own extra polyfills to this file. +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/set'; +import 'core-js/es6/reflect'; + +import 'core-js/es7/reflect'; +import 'zone.js/dist/zone'; \ No newline at end of file diff --git a/DynamicBibleIonic/src/test-service.ts b/DynamicBibleIonic/src/test-service.ts new file mode 100644 index 00000000..e9e04001 --- /dev/null +++ b/DynamicBibleIonic/src/test-service.ts @@ -0,0 +1,14 @@ +import { Injectable } from "@angular/core"; +import { Http } from "@angular/http"; + +@Injectable() +export class TestService +{ + constructor(private http: Http) + { + } + getTest() + { + return "yes"; + } +} \ No newline at end of file diff --git a/DynamicBibleIonic/src/test.ts b/DynamicBibleIonic/src/test.ts new file mode 100644 index 00000000..10860f21 --- /dev/null +++ b/DynamicBibleIonic/src/test.ts @@ -0,0 +1,78 @@ +/// +import './polyfills.ts'; + +import 'zone.js/dist/long-stack-trace-zone'; +import 'zone.js/dist/proxy.js'; +import 'zone.js/dist/sync-test'; +import 'zone.js/dist/jasmine-patch'; +import 'zone.js/dist/async-test'; +import 'zone.js/dist/fake-async-test'; + +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { getTestBed, TestBed } from '@angular/core/testing'; +import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing'; +import { App, Config, Form, IonicModule, Keyboard, DomController, MenuController, NavController, Platform } from 'ionic-angular'; +import { ConfigMock } from './mocks'; + +// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. +declare var __karma__: any; +declare var require: any; + +// Prevent Karma from running prematurely. +__karma__.loaded = function (): void { + // noop +}; + +// First, initialize the Angular testing environment. +getTestBed().initTestEnvironment( + BrowserDynamicTestingModule, + platformBrowserDynamicTesting(), +); +// Then we find all the tests. +let context: any = require.context('./', true, /\.spec\.ts/); +// And load the modules. +context.keys().map(context); +// Finally, start Karma to run the tests. +__karma__.start(); + +export class TestUtils { + + public static beforeEachCompiler(components: Array): Promise<{fixture: any, instance: any}> { + return TestUtils.configureIonicTestingModule(components) + .compileComponents().then(() => { + let fixture: any = TestBed.createComponent(components[0]); + return { + fixture: fixture, + instance: fixture.debugElement.componentInstance, + }; + }); + } + + public static configureIonicTestingModule(components: Array): typeof TestBed { + return TestBed.configureTestingModule({ + declarations: [ + ...components, + ], + providers: [ + App, Platform, Form, Keyboard, DomController, MenuController, NavController, + {provide: Config, useClass: ConfigMock}, + ], + imports: [ + FormsModule, + IonicModule, + ReactiveFormsModule, + ], + }); + } + + // http://stackoverflow.com/questions/2705583/how-to-simulate-a-click-with-javascript + public static eventFire(el: any, etype: string): void { + if (el.fireEvent) { + el.fireEvent('on' + etype); + } else { + let evObj: any = document.createEvent('Events'); + evObj.initEvent(etype, true, false); + el.dispatchEvent(evObj); + } + } +} \ No newline at end of file diff --git a/DynamicBibleIonic/src/tsconfig.test.json b/DynamicBibleIonic/src/tsconfig.test.json new file mode 100644 index 00000000..3b2f9367 --- /dev/null +++ b/DynamicBibleIonic/src/tsconfig.test.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "allowSyntheticDefaultImports": true, + "declaration": false, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "lib": [ + "dom", + "es2015" + ], + "module": "es2015", + "moduleResolution": "node", + "sourceMap": true, + "target": "es5", + "outDir": "../dist/out-tsc", + "typeRoots": [ + "../node_modules/@types" + ] + } +} \ No newline at end of file diff --git a/DynamicBibleIonic/tsconfig.json b/DynamicBibleIonic/tsconfig.json index 2e7daea7..20d82a7c 100644 --- a/DynamicBibleIonic/tsconfig.json +++ b/DynamicBibleIonic/tsconfig.json @@ -18,6 +18,7 @@ ], "exclude": [ "node_modules", + "src/**/*.spec.ts", ".tmp" ], "compileOnSave": false,