From b30870f2188c2b27a374a8211cd6660730e8c886 Mon Sep 17 00:00:00 2001 From: JDonadio Date: Mon, 25 Sep 2017 14:20:43 -0300 Subject: [PATCH 1/3] add latest release provider --- package.json | 2 +- src/app/app.module.ts | 2 + src/pages/home/home.ts | 10 ++- src/providers/latestRelease/latestRelease.ts | 66 ++++++++++++++++++++ 4 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 src/providers/latestRelease/latestRelease.ts diff --git a/package.json b/package.json index 1e348fc98..2ec3d191e 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "angular2-template-loader": "0.6.2", "codecov": "2.2.0", "html-loader": "0.4.5", - "ionic": "3.9.2", + "ionic": "3.12.0", "jasmine-core": "2.6.4", "jasmine-spec-reporter": "4.1.1", "karma": "1.7.0", diff --git a/src/app/app.module.ts b/src/app/app.module.ts index ee85dfa4f..f19c925f5 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -61,6 +61,7 @@ import { ProfileProvider } from '../providers/profile/profile'; import { RateProvider } from '../providers/rate/rate'; import { ScanProvider } from '../providers/scan/scan'; import { WalletProvider } from '../providers/wallet/wallet'; +import { LatestRelease } from '../providers/latestRelease/latestRelease'; export function createTranslateLoader(http: Http) { return new TranslatePoHttpLoader(http, 'assets/i18n', '.po'); @@ -105,6 +106,7 @@ let providers: any = [ SocialSharing, Toast, WalletProvider, + LatestRelease, { provide: ErrorHandler, useClass: IonicErrorHandler diff --git a/src/pages/home/home.ts b/src/pages/home/home.ts index 48f4faab5..cc1fad7a3 100644 --- a/src/pages/home/home.ts +++ b/src/pages/home/home.ts @@ -1,6 +1,7 @@ import { Component } from '@angular/core'; import { NavController } from 'ionic-angular'; import { ProfileProvider } from '../../providers/profile/profile'; +import { LatestRelease } from '../../providers/latestRelease/latestRelease'; @Component({ selector: 'page-home', @@ -11,13 +12,20 @@ export class HomePage { constructor( public navCtrl: NavController, - private profile: ProfileProvider + private profile: ProfileProvider, + private latestRelease: LatestRelease, ) { } ionViewDidLoad() { console.log('ionViewDidLoad HomePage'); + this.wallets = this.profile.bind(); + this.latestRelease.checkLatestRelease().then((response) => { + console.log('New release available: ', response); + }).catch((error) => { + console.log('Latest Release error: ', error); + }); console.log('[home.ts:20]', this.wallets); //TODO } } diff --git a/src/providers/latestRelease/latestRelease.ts b/src/providers/latestRelease/latestRelease.ts new file mode 100644 index 000000000..0e5147118 --- /dev/null +++ b/src/providers/latestRelease/latestRelease.ts @@ -0,0 +1,66 @@ +import { Injectable } from '@angular/core'; +import { Http } from '@angular/http'; +import 'rxjs/add/operator/map'; +import 'rxjs/add/operator/toPromise'; +import { AppProvider } from '../../providers/app/app'; + +@Injectable() +export class LatestRelease { + private LATEST_RELEASE_URL: string; + private appVersion: string; + + constructor(public http: Http, private app: AppProvider) { + console.log('Hello LatestRelease Provider'); + this.LATEST_RELEASE_URL = 'https://api.github.com/repos/bitpay/copay/releases/latest'; + this.appVersion = this.app.info.version; + } + + checkLatestRelease(): Promise { + return new Promise((resolve, reject) => { + let self = this; + + self.requestLatestRelease().then((release: any) => { + var currentVersion = this.appVersion; + var latestVersion = release.tag_name; + + if (!verifyTagFormat(currentVersion)) + reject('Cannot verify the format of version tag: ' + currentVersion); + if (!verifyTagFormat(latestVersion)) + reject('Cannot verify the format of latest release tag: ' + latestVersion); + + var current = formatTagNumber(currentVersion); + var latest = formatTagNumber(latestVersion); + + if (latest.major < current.major || (latest.major == current.major && latest.minor <= current.minor)) + resolve(false); + else + resolve(true); + + function verifyTagFormat(tag: string) { + var regex = /^v?\d+\.\d+\.\d+$/i; + return regex.exec(tag); + }; + + function formatTagNumber(tag: string) { + var formattedNumber = tag.replace(/^v/i, '').split('.'); + return { + major: +formattedNumber[0], + minor: +formattedNumber[1], + patch: +formattedNumber[2] + }; + }; + + }).catch((error) => { + console.log("Error: ", error); + reject(error); + }); + }); + } + + requestLatestRelease(): Promise { + return this.http.get(this.LATEST_RELEASE_URL) + .map((response) => response.json()) + .toPromise() + .catch((error) => console.log("Error", error)); + } +} From b74d72a4b65d6e541054b9ba16c7f6ba360c43dd Mon Sep 17 00:00:00 2001 From: JDonadio Date: Wed, 27 Sep 2017 12:31:17 -0300 Subject: [PATCH 2/3] ref provider name - add test --- src/app/app.module.ts | 4 +- src/mocks/latestRelease.ts | 36 +++++++++++++++ src/pages/home/home.ts | 4 +- .../latestRelease/latestRelease.spec.ts | 45 +++++++++++++++++++ src/providers/latestRelease/latestRelease.ts | 2 +- 5 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 src/mocks/latestRelease.ts create mode 100644 src/providers/latestRelease/latestRelease.spec.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index f19c925f5..8898a22f7 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -61,7 +61,7 @@ import { ProfileProvider } from '../providers/profile/profile'; import { RateProvider } from '../providers/rate/rate'; import { ScanProvider } from '../providers/scan/scan'; import { WalletProvider } from '../providers/wallet/wallet'; -import { LatestRelease } from '../providers/latestRelease/latestRelease'; +import { LatestReleaseProvider } from '../providers/latestRelease/latestRelease'; export function createTranslateLoader(http: Http) { return new TranslatePoHttpLoader(http, 'assets/i18n', '.po'); @@ -106,7 +106,7 @@ let providers: any = [ SocialSharing, Toast, WalletProvider, - LatestRelease, + LatestReleaseProvider, { provide: ErrorHandler, useClass: IonicErrorHandler diff --git a/src/mocks/latestRelease.ts b/src/mocks/latestRelease.ts new file mode 100644 index 000000000..51eb7ed1b --- /dev/null +++ b/src/mocks/latestRelease.ts @@ -0,0 +1,36 @@ +export let LatestReleaseProviderStub = { + checkLatestRelease(currentVersion: string, latestVersion: string) { + if (!currentVersion || !latestVersion) return this.requestLatestRelease(); + + if (!verifyTagFormat(currentVersion)) + return ('Cannot verify the format of version tag: ' + currentVersion); + if (!verifyTagFormat(latestVersion)) + return ('Cannot verify the format of latest release tag: ' + latestVersion); + + var current = formatTagNumber(currentVersion); + var latest = formatTagNumber(latestVersion); + + if (latest.major < current.major || (latest.major == current.major && latest.minor <= current.minor)) + return false; + else + return true; + + function verifyTagFormat(tag: string) { + var regex = /^v?\d+\.\d+\.\d+$/i; + return regex.exec(tag); + }; + + function formatTagNumber(tag: string) { + var formattedNumber = tag.replace(/^v/i, '').split('.'); + return { + major: +formattedNumber[0], + minor: +formattedNumber[1], + patch: +formattedNumber[2] + }; + }; + }, + + requestLatestRelease() { + return '3.3.3'; + } +} diff --git a/src/pages/home/home.ts b/src/pages/home/home.ts index cc1fad7a3..ef88c5a62 100644 --- a/src/pages/home/home.ts +++ b/src/pages/home/home.ts @@ -1,7 +1,7 @@ import { Component } from '@angular/core'; import { NavController } from 'ionic-angular'; import { ProfileProvider } from '../../providers/profile/profile'; -import { LatestRelease } from '../../providers/latestRelease/latestRelease'; +import { LatestReleaseProvider } from '../../providers/latestRelease/latestRelease'; @Component({ selector: 'page-home', @@ -13,7 +13,7 @@ export class HomePage { constructor( public navCtrl: NavController, private profile: ProfileProvider, - private latestRelease: LatestRelease, + private latestRelease: LatestReleaseProvider, ) { } diff --git a/src/providers/latestRelease/latestRelease.spec.ts b/src/providers/latestRelease/latestRelease.spec.ts new file mode 100644 index 000000000..356f7ce1f --- /dev/null +++ b/src/providers/latestRelease/latestRelease.spec.ts @@ -0,0 +1,45 @@ +import { LatestReleaseProviderStub } from '../../mocks/latestRelease' + +describe('Latest Release Provider', () => { + var currentVersion: string; + var latestVersion: string; + + beforeEach(() => { + // Using the mock => 3.3.3 + latestVersion = LatestReleaseProviderStub.checkLatestRelease(null, null); + }); + + it('should check successfully the latest release of the app', () => { + expect(latestVersion).toBeDefined(); + }); + + it('should check unsuccessfully the current release format of the app', () => { + const result = LatestReleaseProviderStub.checkLatestRelease('V.3.3.3', '3.3.3'); + expect(result).toMatch('Cannot'); + expect(result).toMatch('version tag'); + }); + + it('should check unsuccessfully the latest release format of the app', () => { + const result = LatestReleaseProviderStub.checkLatestRelease('3.3.3', 'V.3.3.3'); + expect(result).toMatch('Cannot'); + expect(result).toMatch('release tag'); + }); + + it('should compare the current and latest version of the app with the same value', () => { + currentVersion = '3.3.3'; + const result = LatestReleaseProviderStub.checkLatestRelease(currentVersion, latestVersion); + expect(result).toBeFalsy(); + }); + + it('there should be a new version available', () => { + currentVersion = '3.2.3'; + const result = LatestReleaseProviderStub.checkLatestRelease(currentVersion, latestVersion); + expect(result).toBeTruthy(); + }); + + it('there should not be a new version available', () => { + currentVersion = '3.3.2'; + const result = LatestReleaseProviderStub.checkLatestRelease(currentVersion, latestVersion); + expect(result).toBeFalsy(); + }); +}); diff --git a/src/providers/latestRelease/latestRelease.ts b/src/providers/latestRelease/latestRelease.ts index 0e5147118..bb437ca4c 100644 --- a/src/providers/latestRelease/latestRelease.ts +++ b/src/providers/latestRelease/latestRelease.ts @@ -5,7 +5,7 @@ import 'rxjs/add/operator/toPromise'; import { AppProvider } from '../../providers/app/app'; @Injectable() -export class LatestRelease { +export class LatestReleaseProvider { private LATEST_RELEASE_URL: string; private appVersion: string; From 16ff852960da69fde3594048f38affce2ab49236 Mon Sep 17 00:00:00 2001 From: JDonadio Date: Thu, 28 Sep 2017 10:44:50 -0300 Subject: [PATCH 3/3] move mock folder outside the app src --- src/providers/latestRelease/latestRelease.spec.ts | 2 +- {src => test-config}/mocks/latestRelease.ts | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename {src => test-config}/mocks/latestRelease.ts (100%) diff --git a/src/providers/latestRelease/latestRelease.spec.ts b/src/providers/latestRelease/latestRelease.spec.ts index 356f7ce1f..f47ac117a 100644 --- a/src/providers/latestRelease/latestRelease.spec.ts +++ b/src/providers/latestRelease/latestRelease.spec.ts @@ -1,4 +1,4 @@ -import { LatestReleaseProviderStub } from '../../mocks/latestRelease' +import { LatestReleaseProviderStub } from '../../../test-config/mocks/latestRelease'; describe('Latest Release Provider', () => { var currentVersion: string; diff --git a/src/mocks/latestRelease.ts b/test-config/mocks/latestRelease.ts similarity index 100% rename from src/mocks/latestRelease.ts rename to test-config/mocks/latestRelease.ts