From f78d4b6e5d3dd781a65b489f6295200cdb763ff7 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Fri, 18 Nov 2016 20:50:30 +0100 Subject: [PATCH] Some more services --- src/Squidex/app/app.module.ts | 4 + src/Squidex/app/shared/index.ts | 2 + .../services/app-contributors.service.spec.ts | 88 +++++++++++++++++++ .../services/app-contributors.service.ts | 53 +++++++++++ .../app/shared/services/apps.service.spec.ts | 31 +++---- .../app/shared/services/apps.service.ts | 1 - .../shared/services/languages.service.spec.ts | 60 +++++++++++++ .../app/shared/services/languages.service.ts | 43 +++++++++ 8 files changed, 264 insertions(+), 18 deletions(-) create mode 100644 src/Squidex/app/shared/services/app-contributors.service.spec.ts create mode 100644 src/Squidex/app/shared/services/app-contributors.service.ts create mode 100644 src/Squidex/app/shared/services/languages.service.spec.ts create mode 100644 src/Squidex/app/shared/services/languages.service.ts diff --git a/src/Squidex/app/app.module.ts b/src/Squidex/app/app.module.ts index d05adbf9a..9c06e2c6a 100644 --- a/src/Squidex/app/app.module.ts +++ b/src/Squidex/app/app.module.ts @@ -12,6 +12,7 @@ import { AppComponent } from './app.component'; import { ApiUrlConfig, + AppContributorsService, AppMustExistGuard, AppsStoreService, AppsService, @@ -22,6 +23,7 @@ import { DecimalSeparatorConfig, MustBeAuthenticatedGuard, MustBeNotAuthenticatedGuard, + LanguageService, SqxFrameworkModule, TitlesConfig, TitleService @@ -52,10 +54,12 @@ const baseUrl = window.location.protocol + '//' + window.location.host + '/'; AppComponent ], providers: [ + AppContributorsService, AppsStoreService, AppsService, AppMustExistGuard, AuthService, + LanguageService, MustBeAuthenticatedGuard, MustBeNotAuthenticatedGuard, TitleService, diff --git a/src/Squidex/app/shared/index.ts b/src/Squidex/app/shared/index.ts index 4d228c779..49ecaa6ef 100644 --- a/src/Squidex/app/shared/index.ts +++ b/src/Squidex/app/shared/index.ts @@ -8,8 +8,10 @@ export * from './guards/app-must-exist.guard'; export * from './guards/must-be-authenticated.guard'; export * from './guards/must-be-not-authenticated.guard'; +export * from './services/app-contributors.service'; export * from './services/apps-store.service'; export * from './services/apps.service'; export * from './services/auth.service'; +export * from './services/languages.service'; export * from 'framework'; \ No newline at end of file diff --git a/src/Squidex/app/shared/services/app-contributors.service.spec.ts b/src/Squidex/app/shared/services/app-contributors.service.spec.ts new file mode 100644 index 000000000..7a9986aee --- /dev/null +++ b/src/Squidex/app/shared/services/app-contributors.service.spec.ts @@ -0,0 +1,88 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as TypeMoq from 'typemoq'; +import * as Ng2Http from '@angular/http'; + +import { Observable } from 'rxjs'; + +import { + ApiUrlConfig, + AppContributor, + AppContributorsService, + AuthService +} from './../'; + +describe('AppContributorsService', () => { + let authService: TypeMoq.Mock; + let appContributorsService: AppContributorsService; + + beforeEach(() => { + authService = TypeMoq.Mock.ofType(AuthService); + appContributorsService = new AppContributorsService(authService.object, new ApiUrlConfig('http://service/p/')); + }); + + it('should make get request with auth service', () => { + authService.setup(x => x.authGet('http://service/p/api/apps/my-app/contributors')) + .returns(() => Observable.of( + new Ng2Http.Response( + new Ng2Http.ResponseOptions({ + body: [{ + contributorId: '123', + permission: 'Owner' + }, { + contributorId: '456', + permission: 'Editor' + }] + }) + ) + )) + .verifiable(TypeMoq.Times.once()); + + let contributors: AppContributor[] = null; + + appContributorsService.getContributors('my-app').subscribe(result => { + contributors = result; + }).unsubscribe(); + + expect(contributors).toEqual( + [ + new AppContributor('123', 'Owner'), + new AppContributor('456', 'Editor'), + ]); + + authService.verifyAll(); + }); + + it('should make post assign contributor', () => { + const contributor = new AppContributor('123', 'Owner'); + + authService.setup(x => x.authPost('http://service/p/api/apps/my-app/contributors', TypeMoq.It.is(c => c === contributor))) + .returns(() => Observable.of( + new Ng2Http.Response( + new Ng2Http.ResponseOptions() + ) + )); + + appContributorsService.postContributor('my-app', contributor); + + authService.verifyAll(); + }); + + it('should make delete request to remove contributor', () => { + authService.setup(x => x.authDelete('http://service/p/api/apps/my-app/contributors/123')) + .returns(() => Observable.of( + new Ng2Http.Response( + new Ng2Http.ResponseOptions() + ) + )); + + appContributorsService.deleteContributor('my-app', '123'); + + authService.verifyAll(); + }); +}); \ No newline at end of file diff --git a/src/Squidex/app/shared/services/app-contributors.service.ts b/src/Squidex/app/shared/services/app-contributors.service.ts new file mode 100644 index 000000000..9840d3eaf --- /dev/null +++ b/src/Squidex/app/shared/services/app-contributors.service.ts @@ -0,0 +1,53 @@ + +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2 from '@angular/core'; + +import { Observable } from 'rxjs'; + +import { ApiUrlConfig } from 'framework'; + +import { AuthService } from './auth.service'; + +export class AppContributor { + constructor( + public readonly contributorId: string, + public readonly permission: string + ) { + } +} + +@Ng2.Injectable() +export class AppContributorsService { + constructor( + private readonly authService: AuthService, + private readonly apiUrl: ApiUrlConfig + ) { + } + + public getContributors(appName: string): Observable { + return this.authService.authGet(this.apiUrl.buildUrl(`api/apps/${appName}/contributors`)) + .map(response => { + const body: any[] = response.json(); + + return body.map(item => { + return new AppContributor( + item.contributorId, + item.permission); + }); + }); + } + + public postContributor(appName: string, contributor: AppContributor): Observable { + return this.authService.authPost(this.apiUrl.buildUrl(`api/apps/${appName}/contributors`), contributor); + } + + public deleteContributor(appName: string, contributorId: string): Observable { + return this.authService.authDelete(this.apiUrl.buildUrl(`api/apps/${appName}/contributors/{contributorId}`)); + } +} \ No newline at end of file diff --git a/src/Squidex/app/shared/services/apps.service.spec.ts b/src/Squidex/app/shared/services/apps.service.spec.ts index 48f2524df..cc5150442 100644 --- a/src/Squidex/app/shared/services/apps.service.spec.ts +++ b/src/Squidex/app/shared/services/apps.service.spec.ts @@ -12,11 +12,11 @@ import { Observable } from 'rxjs'; import { ApiUrlConfig, - DateTime, AppCreateDto, AppDto, AppsService, - AuthService + AuthService, + DateTime } from './../'; describe('AppsService', () => { @@ -28,7 +28,7 @@ describe('AppsService', () => { appsService = new AppsService(authService.object, new ApiUrlConfig('http://service/p/')); }); - it('should make get request with auth service', () => { + it('should make get request with auth service to get apps', () => { authService.setup(x => x.authGet('http://service/p/api/apps')) .returns(() => Observable.of( new Ng2Http.Response( @@ -37,12 +37,12 @@ describe('AppsService', () => { id: '123', name: 'name1', created: '2016-01-01', - lastModified: '2017-01-01' + lastModified: '2016-02-02' }, { id: '456', name: 'name2', - created: '2016-01-01', - lastModified: '2017-01-01' + created: '2017-01-01', + lastModified: '2017-02-02' }] }) ) @@ -55,15 +55,15 @@ describe('AppsService', () => { apps = result; }).unsubscribe(); - expect(apps[1].id).toBe('456'); - expect(apps[1].name).toBe('name2'); - expect(apps[1].created.eq(DateTime.parseISO('2016-01-01'))).toBeTruthy(); - expect(apps[1].lastModified.eq(DateTime.parseISO('2017-01-01'))).toBeTruthy(); + expect(apps).toEqual([ + new AppDto('123', 'name1', DateTime.parseISO('2016-01-01'), DateTime.parseISO('2016-02-02')), + new AppDto('456', 'name2', DateTime.parseISO('2017-01-01'), DateTime.parseISO('2017-02-02')), + ]); authService.verifyAll(); }); - it('should make post request', () => { + it('should make post request to create app', () => { const now = DateTime.now(); authService.setup(x => x.authPost('http://service/p/api/apps', TypeMoq.It.is(y => y['name'] === 'new-app'))) @@ -83,15 +83,12 @@ describe('AppsService', () => { newApp = result; }).unsubscribe(); - expect(newApp.id).toBe('123'); - expect(newApp.name).toBe('new-app'); - expect(newApp.created.eq(now)).toBeTruthy(); - expect(newApp.lastModified.eq(now)).toBeTruthy(); + expect(newApp).toEqual(new AppDto('123', 'new-app', now, now)); authService.verifyAll(); }); - it('should throw fallback error on 500', () => { + it('should throw fallback error on 500 when creating app failed', () => { authService.setup(x => x.authPost('http://service/p/api/apps', TypeMoq.It.isAny())) .returns(() => Observable.throw( new Ng2Http.Response( @@ -112,7 +109,7 @@ describe('AppsService', () => { authService.verifyAll(); }); - it('should throw duplicate error on 400', () => { + it('should throw duplicate error on 400 when creating app failed', () => { authService.setup(x => x.authPost('http://service/p/api/apps', TypeMoq.It.isAny())) .returns(() => Observable.throw( new Ng2Http.Response( diff --git a/src/Squidex/app/shared/services/apps.service.ts b/src/Squidex/app/shared/services/apps.service.ts index 678a40560..845544dec 100644 --- a/src/Squidex/app/shared/services/apps.service.ts +++ b/src/Squidex/app/shared/services/apps.service.ts @@ -6,7 +6,6 @@ */ import * as Ng2 from '@angular/core'; - import { Observable } from 'rxjs'; import { ApiUrlConfig, DateTime } from 'framework'; diff --git a/src/Squidex/app/shared/services/languages.service.spec.ts b/src/Squidex/app/shared/services/languages.service.spec.ts new file mode 100644 index 000000000..a8ba82829 --- /dev/null +++ b/src/Squidex/app/shared/services/languages.service.spec.ts @@ -0,0 +1,60 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as TypeMoq from 'typemoq'; +import * as Ng2Http from '@angular/http'; + +import { Observable } from 'rxjs'; + +import { + ApiUrlConfig, + AuthService, + Language, + LanguageService +} from './../'; + +describe('LanguageService', () => { + let authService: TypeMoq.Mock; + let languageService: LanguageService; + + beforeEach(() => { + authService = TypeMoq.Mock.ofType(AuthService); + languageService = new LanguageService(authService.object, new ApiUrlConfig('http://service/p/')); + }); + + it('should make get request with auth service to get languages', () => { + authService.setup(x => x.authGet('http://service/p/api/languages')) + .returns(() => Observable.of( + new Ng2Http.Response( + new Ng2Http.ResponseOptions({ + body: [{ + iso2Code: 'de', + englishName: 'German' + }, { + iso2Code: 'en', + englishName: 'English' + }] + }) + ) + )) + .verifiable(TypeMoq.Times.once()); + + let languages: Language[] = null; + + languageService.getLanguages().subscribe(result => { + languages = result; + }).unsubscribe(); + + expect(languages).toEqual( + [ + new Language('de', 'German'), + new Language('en', 'English'), + ]); + + authService.verifyAll(); + }); +}); \ No newline at end of file diff --git a/src/Squidex/app/shared/services/languages.service.ts b/src/Squidex/app/shared/services/languages.service.ts new file mode 100644 index 000000000..75588eeb5 --- /dev/null +++ b/src/Squidex/app/shared/services/languages.service.ts @@ -0,0 +1,43 @@ +/* + * Squidex Headless CMS + * + * @license + * Copyright (c) Sebastian Stehle. All rights reserved + */ + +import * as Ng2 from '@angular/core'; +import { Observable } from 'rxjs'; + +import { ApiUrlConfig } from 'framework'; + +import { AuthService } from './auth.service'; + +export class Language { + constructor( + public readonly iso2Code: string, + public readonly englishName: string + ) { + } +} + +@Ng2.Injectable() +export class LanguageService { + constructor( + private readonly authService: AuthService, + private readonly apiUrl: ApiUrlConfig + ) { + } + + public getLanguages(): Observable { + return this.authService.authGet(this.apiUrl.buildUrl('api/languages')) + .map(response => { + const body: any[] = response.json(); + + return body.map(item => { + return new Language( + item.iso2Code, + item.englishName); + }); + }); + } +} \ No newline at end of file