mirror of https://github.com/abpframework/abp.git
16 changed files with 64 additions and 335 deletions
@ -1,24 +0,0 @@ |
|||
import { Config } from '../models/config'; |
|||
|
|||
/** |
|||
* @deprecated Use ConfigStateService. To be deleted in v5.0. |
|||
*/ |
|||
export class GetAppConfiguration { |
|||
static readonly type = '[Config] Get App Configuration'; |
|||
} |
|||
|
|||
/** |
|||
* @deprecated Use EnvironmentService instead. To be deleted in v5.0. |
|||
*/ |
|||
export class SetEnvironment { |
|||
static readonly type = '[Config] Set Environment'; |
|||
constructor(public environment: Config.Environment) {} |
|||
} |
|||
|
|||
/** |
|||
* @deprecated Use EnvironmentService instead. To be deleted in v5.0. |
|||
*/ |
|||
export class PatchConfigState { |
|||
static readonly type = '[Config] Set State'; |
|||
constructor(public state: Config.State) {} |
|||
} |
|||
@ -1,4 +1 @@ |
|||
export { GetAppConfiguration, SetEnvironment } from './config.actions'; |
|||
export * from './loader.actions'; |
|||
export * from './profile.actions'; |
|||
export * from './rest.actions'; |
|||
|
|||
@ -1,15 +0,0 @@ |
|||
import { Profile } from '../models'; |
|||
|
|||
export class GetProfile { |
|||
static readonly type = '[Profile] Get'; |
|||
} |
|||
|
|||
export class UpdateProfile { |
|||
static readonly type = '[Profile] Update'; |
|||
constructor(public payload: Profile.Response) {} |
|||
} |
|||
|
|||
export class ChangePassword { |
|||
static readonly type = '[Profile] Change Password'; |
|||
constructor(public payload: Profile.ChangePasswordRequest) {} |
|||
} |
|||
@ -1,28 +1,26 @@ |
|||
import { ExtensibleObject } from './dtos'; |
|||
|
|||
export namespace Profile { |
|||
export interface State { |
|||
profile: Response; |
|||
} |
|||
export interface ChangePasswordInput { |
|||
currentPassword: string; |
|||
newPassword: string; |
|||
} |
|||
|
|||
export interface Response extends Partial<ExtensibleObject> { |
|||
userName: string; |
|||
email: string; |
|||
name: string; |
|||
surname: string; |
|||
phoneNumber: string; |
|||
/** |
|||
* Following 4 fields are added as optional (for backward compatibility) on 17.08.2020 |
|||
* Also, this interface extends `ExtensibleObject` as partial for extraProperties field. |
|||
*/ |
|||
isExternal?: boolean; |
|||
hasPassword?: boolean; |
|||
emailConfirmed?: boolean; |
|||
phoneNumberConfirmed?: boolean; |
|||
} |
|||
export interface ProfileDto extends ExtensibleObject { |
|||
userName: string; |
|||
email: string; |
|||
name: string; |
|||
surname: string; |
|||
phoneNumber: string; |
|||
isExternal?: boolean; |
|||
hasPassword?: boolean; |
|||
emailConfirmed?: boolean; |
|||
phoneNumberConfirmed?: boolean; |
|||
} |
|||
|
|||
export interface ChangePasswordRequest { |
|||
currentPassword: string; |
|||
newPassword: string; |
|||
} |
|||
export interface UpdateProfileDto extends ExtensibleObject { |
|||
userName: string; |
|||
email: string; |
|||
name: string; |
|||
surname: string; |
|||
phoneNumber: string; |
|||
} |
|||
|
|||
@ -1,28 +0,0 @@ |
|||
import { Injectable } from '@angular/core'; |
|||
import { Store } from '@ngxs/store'; |
|||
import { ProfileState } from '../states'; |
|||
import { Profile } from '../models'; |
|||
import { GetProfile, UpdateProfile, ChangePassword } from '../actions'; |
|||
|
|||
@Injectable({ |
|||
providedIn: 'root', |
|||
}) |
|||
export class ProfileStateService { |
|||
constructor(private store: Store) {} |
|||
|
|||
getProfile() { |
|||
return this.store.selectSnapshot(ProfileState.getProfile); |
|||
} |
|||
|
|||
dispatchGetProfile() { |
|||
return this.store.dispatch(new GetProfile()); |
|||
} |
|||
|
|||
dispatchUpdateProfile(...args: ConstructorParameters<typeof UpdateProfile>) { |
|||
return this.store.dispatch(new UpdateProfile(...args)); |
|||
} |
|||
|
|||
dispatchChangePassword(...args: ConstructorParameters<typeof ChangePassword>) { |
|||
return this.store.dispatch(new ChangePassword(...args)); |
|||
} |
|||
} |
|||
@ -1 +0,0 @@ |
|||
export * from './profile.state'; |
|||
@ -1,47 +0,0 @@ |
|||
import { Injectable } from '@angular/core'; |
|||
import { Action, Selector, State, StateContext } from '@ngxs/store'; |
|||
import { tap } from 'rxjs/operators'; |
|||
import { ChangePassword, GetProfile, UpdateProfile } from '../actions/profile.actions'; |
|||
import { Profile } from '../models/profile'; |
|||
import { ProfileService } from '../services/profile.service'; |
|||
|
|||
@State<Profile.State>({ |
|||
name: 'ProfileState', |
|||
defaults: {} as Profile.State, |
|||
}) |
|||
@Injectable() |
|||
export class ProfileState { |
|||
@Selector() |
|||
static getProfile({ profile }: Profile.State): Profile.Response { |
|||
return profile; |
|||
} |
|||
|
|||
constructor(private profileService: ProfileService) {} |
|||
|
|||
@Action(GetProfile) |
|||
getProfile({ patchState }: StateContext<Profile.State>) { |
|||
return this.profileService.get().pipe( |
|||
tap(profile => |
|||
patchState({ |
|||
profile, |
|||
}), |
|||
), |
|||
); |
|||
} |
|||
|
|||
@Action(UpdateProfile) |
|||
updateProfile({ patchState }: StateContext<Profile.State>, { payload }: UpdateProfile) { |
|||
return this.profileService.update(payload).pipe( |
|||
tap(profile => |
|||
patchState({ |
|||
profile, |
|||
}), |
|||
), |
|||
); |
|||
} |
|||
|
|||
@Action(ChangePassword) |
|||
changePassword(_, { payload }: ChangePassword) { |
|||
return this.profileService.changePassword(payload, true); |
|||
} |
|||
} |
|||
@ -1,57 +0,0 @@ |
|||
import { createServiceFactory, SpectatorService, SpyObject } from '@ngneat/spectator/jest'; |
|||
import { ProfileStateService } from '../services/profile-state.service'; |
|||
import { ProfileState } from '../states/profile.state'; |
|||
import { Store } from '@ngxs/store'; |
|||
import * as ProfileActions from '../actions'; |
|||
|
|||
describe('ProfileStateService', () => { |
|||
let service: ProfileStateService; |
|||
let spectator: SpectatorService<ProfileStateService>; |
|||
let store: SpyObject<Store>; |
|||
|
|||
const createService = createServiceFactory({ service: ProfileStateService, mocks: [Store] }); |
|||
beforeEach(() => { |
|||
spectator = createService(); |
|||
service = spectator.service; |
|||
store = spectator.inject(Store); |
|||
}); |
|||
test('should have the all ProfileState static methods', () => { |
|||
const reg = /(?<=static )(.*)(?=\()/gm; |
|||
ProfileState.toString() |
|||
.match(reg) |
|||
.forEach(fnName => { |
|||
expect(service[fnName]).toBeTruthy(); |
|||
|
|||
const spy = jest.spyOn(store, 'selectSnapshot'); |
|||
spy.mockClear(); |
|||
|
|||
const isDynamicSelector = ProfileState[fnName].name !== 'memoized'; |
|||
|
|||
if (isDynamicSelector) { |
|||
ProfileState[fnName] = jest.fn((...args) => args); |
|||
service[fnName]('test', 0, {}); |
|||
expect(ProfileState[fnName]).toHaveBeenCalledWith('test', 0, {}); |
|||
} else { |
|||
service[fnName](); |
|||
expect(spy).toHaveBeenCalledWith(ProfileState[fnName]); |
|||
} |
|||
}); |
|||
}); |
|||
|
|||
test('should have a dispatch method for every ProfileState action', () => { |
|||
const reg = /(?<=dispatch)(\w+)(?=\()/gm; |
|||
ProfileStateService.toString() |
|||
.match(reg) |
|||
.forEach(fnName => { |
|||
expect(ProfileActions[fnName]).toBeTruthy(); |
|||
|
|||
const spy = jest.spyOn(store, 'dispatch'); |
|||
spy.mockClear(); |
|||
|
|||
const params = Array.from(new Array(ProfileActions[fnName].length)); |
|||
|
|||
service[`dispatch${fnName}`](...params); |
|||
expect(spy).toHaveBeenCalledWith(new ProfileActions[fnName](...params)); |
|||
}); |
|||
}); |
|||
}); |
|||
@ -1,74 +0,0 @@ |
|||
import { createServiceFactory, SpectatorService, SpyObject } from '@ngneat/spectator/jest'; |
|||
import { Session } from '../models/session'; |
|||
import { ProfileService } from '../services'; |
|||
import { ProfileState } from '../states'; |
|||
import { GetAppConfiguration } from '../actions/config.actions'; |
|||
import { of } from 'rxjs'; |
|||
import { Profile } from '../models/profile'; |
|||
|
|||
export class DummyClass {} |
|||
|
|||
export const PROFILE_STATE_DATA = { |
|||
profile: { userName: 'admin', email: 'info@abp.io', name: 'Admin' }, |
|||
} as Profile.State; |
|||
|
|||
describe('ProfileState', () => { |
|||
let spectator: SpectatorService<DummyClass>; |
|||
let state: ProfileState; |
|||
let profileService: SpyObject<ProfileService>; |
|||
let patchedData; |
|||
const patchState = jest.fn(data => (patchedData = data)); |
|||
|
|||
const createService = createServiceFactory({ |
|||
service: DummyClass, |
|||
mocks: [ProfileService], |
|||
}); |
|||
|
|||
beforeEach(() => { |
|||
spectator = createService(); |
|||
profileService = spectator.inject(ProfileService); |
|||
state = new ProfileState(profileService); |
|||
}); |
|||
|
|||
describe('#getProfile', () => { |
|||
it('should return the current language', () => { |
|||
expect(ProfileState.getProfile(PROFILE_STATE_DATA)).toEqual(PROFILE_STATE_DATA.profile); |
|||
}); |
|||
}); |
|||
|
|||
describe('#GetProfile', () => { |
|||
it('should call the profile service get method and update the state', () => { |
|||
const mockData = { userName: 'test', email: 'test@abp.io' }; |
|||
const spy = jest.spyOn(profileService, 'get'); |
|||
spy.mockReturnValue(of(mockData as any)); |
|||
|
|||
state.getProfile({ patchState } as any).subscribe(); |
|||
|
|||
expect(patchedData).toEqual({ profile: mockData }); |
|||
}); |
|||
}); |
|||
|
|||
describe('#UpdateProfile', () => { |
|||
it('should call the profile service update method and update the state', () => { |
|||
const mockData = { userName: 'test2', email: 'test@abp.io' }; |
|||
const spy = jest.spyOn(profileService, 'update'); |
|||
spy.mockReturnValue(of(mockData as any)); |
|||
|
|||
state.updateProfile({ patchState } as any, { payload: mockData as any }).subscribe(); |
|||
|
|||
expect(patchedData).toEqual({ profile: mockData }); |
|||
}); |
|||
}); |
|||
|
|||
describe('#ChangePassword', () => { |
|||
it('should call the profile service changePassword method', () => { |
|||
const mockData = { currentPassword: 'test123', newPassword: 'test123' }; |
|||
const spy = jest.spyOn(profileService, 'changePassword'); |
|||
spy.mockReturnValue(of(null)); |
|||
|
|||
state.changePassword(null, { payload: mockData }).subscribe(); |
|||
|
|||
expect(spy).toHaveBeenCalledWith(mockData, true); |
|||
}); |
|||
}); |
|||
}); |
|||
Loading…
Reference in new issue