feat: remove routes from config state

pull/4377/head
Arman Ozak 5 years ago
parent 0fb0ebad5d
commit 04ab7e56e0

@ -1,23 +1,9 @@
import { ABP } from '../models/common';
import { Config } from '../models/config';
export class PatchRouteByName {
static readonly type = '[Config] Patch Route By Name';
constructor(public name: string, public newValue: Partial<ABP.Route>) {}
}
export class GetAppConfiguration {
static readonly type = '[Config] Get App Configuration';
}
/**
* @see usage: https://github.com/abpframework/abp/pull/2425#issue-355018812
*/
export class AddRoute {
static readonly type = '[Config] Add Route';
constructor(public payload: Omit<ABP.Route, 'children'>) {}
}
export class SetEnvironment {
static readonly type = '[Config] Set Environment';
constructor(public environment: Config.Environment) {}

@ -4,11 +4,7 @@ import { ApplicationConfiguration } from './application-configuration';
import { ABP } from './common';
export namespace Config {
export type State = ApplicationConfiguration.Response &
ABP.Root & { environment: Environment } & {
routes: ABP.FullRoute[];
flattedRoutes: ABP.FullRoute[];
};
export type State = ApplicationConfiguration.Response & ABP.Root & { environment: Environment };
export interface Environment {
application: Application;

@ -1,5 +1,4 @@
import { Inject, Injectable, InjectionToken } from '@angular/core';
import { Router, Routes } from '@angular/router';
import {
actionMatcher,
InitState,
@ -8,10 +7,7 @@ import {
setValue,
UpdateState,
} from '@ngxs/store';
import clone from 'just-clone';
import snq from 'snq';
import { ABP } from '../models/common';
import { getAbpRoutes, organizeRoutes } from '../utils/route-utils';
export const NGXS_CONFIG_PLUGIN_OPTIONS = new InjectionToken('NGXS_CONFIG_PLUGIN_OPTIONS');
@ -19,27 +15,16 @@ export const NGXS_CONFIG_PLUGIN_OPTIONS = new InjectionToken('NGXS_CONFIG_PLUGIN
export class ConfigPlugin implements NgxsPlugin {
private initialized = false;
constructor(
@Inject(NGXS_CONFIG_PLUGIN_OPTIONS) private options: ABP.Root,
private router: Router,
) {}
constructor(@Inject(NGXS_CONFIG_PLUGIN_OPTIONS) private options: ABP.Root) {}
handle(state: any, event: any, next: NgxsNextPluginFn) {
const matches = actionMatcher(event);
const isInitAction = matches(InitState) || matches(UpdateState);
if (isInitAction && !this.initialized) {
const transformedRoutes = transformRoutes(this.router.config);
let { routes, wrappers } = transformedRoutes;
wrappers = reduceWrappers(wrappers);
routes = organizeRoutes(routes, wrappers);
const flattedRoutes = flatRoutes(clone(routes));
state = setValue(state, 'ConfigState', {
...(state.ConfigState && { ...state.ConfigState }),
...this.options,
routes,
flattedRoutes,
});
this.initialized = true;
@ -48,84 +33,3 @@ export class ConfigPlugin implements NgxsPlugin {
return next(state, event);
}
}
function transformRoutes(routes: Routes = [], wrappers: ABP.FullRoute[] = []): any {
const abpRoutes = [...getAbpRoutes()];
wrappers = abpRoutes.filter(ar => ar.wrapper);
const transformed = [] as ABP.FullRoute[];
routes
.filter(route => route.component || route.loadChildren)
.forEach(route => {
const abpPackage = abpRoutes.find(
abp => abp.path.toLowerCase() === route.path.toLowerCase() && !abp.wrapper,
);
const { length } = transformed;
if (abpPackage) {
transformed.push(abpPackage);
}
if (transformed.length === length && (route.data || {}).routes) {
transformed.push({
...route.data.routes,
path: route.path,
name: snq(() => route.data.routes.name, route.path),
children: route.data.routes.children || [],
} as ABP.FullRoute);
}
});
return { routes: setUrls(transformed), wrappers };
}
function setUrls(routes: ABP.FullRoute[], parentUrl?: string): ABP.FullRoute[] {
if (parentUrl) {
// recursive block
return routes.map(route => ({
...route,
url: `${parentUrl}/${route.path}`,
...(route.children &&
route.children.length && {
children: setUrls(route.children, `${parentUrl}/${route.path}`),
}),
}));
}
return routes.map(route => ({
...route,
url: `/${route.path}`,
...(route.children &&
route.children.length && {
children: setUrls(route.children, `/${route.path}`),
}),
}));
}
function flatRoutes(routes: ABP.FullRoute[]): ABP.FullRoute[] {
const flat = (r: ABP.FullRoute[]) => {
return r.reduce((acc, val) => {
let value: ABP.FullRoute[] = [val];
if (val.children) {
val.children = val.children.map(child => ({ ...child, parentName: val.name }));
value = [val, ...flat(val.children)];
}
return [...acc, ...value];
}, []);
};
return flat(routes);
}
function reduceWrappers(wrappers: ABP.FullRoute[] = []) {
const existingWrappers = new Set();
return wrappers.filter(wrapper => {
if (existingWrappers.has(wrapper.name)) return false;
existingWrappers.add(wrapper.name);
return true;
});
}

@ -1,11 +1,6 @@
import { Injectable } from '@angular/core';
import { Store } from '@ngxs/store';
import {
AddRoute,
GetAppConfiguration,
PatchRouteByName,
SetEnvironment,
} from '../actions/config.actions';
import { GetAppConfiguration, SetEnvironment } from '../actions/config.actions';
import { ConfigState } from '../states';
@Injectable({
@ -30,10 +25,6 @@ export class ConfigStateService {
return this.store.selectSnapshot(ConfigState.getDeep(...args));
}
getRoute(...args: Parameters<typeof ConfigState.getRoute>) {
return this.store.selectSnapshot(ConfigState.getRoute(...args));
}
getApiUrl(...args: Parameters<typeof ConfigState.getApiUrl>) {
return this.store.selectSnapshot(ConfigState.getApiUrl(...args));
}
@ -58,14 +49,6 @@ export class ConfigStateService {
return this.store.dispatch(new GetAppConfiguration());
}
dispatchPatchRouteByName(...args: ConstructorParameters<typeof PatchRouteByName>) {
return this.store.dispatch(new PatchRouteByName(...args));
}
dispatchAddRoute(...args: ConstructorParameters<typeof AddRoute>) {
return this.store.dispatch(new AddRoute(...args));
}
dispatchSetEnvironment(...args: ConstructorParameters<typeof SetEnvironment>) {
return this.store.dispatch(new SetEnvironment(...args));
}

@ -4,18 +4,11 @@ import { Action, createSelector, Selector, State, StateContext, Store } from '@n
import { of, throwError } from 'rxjs';
import { catchError, switchMap, tap } from 'rxjs/operators';
import snq from 'snq';
import {
AddRoute,
GetAppConfiguration,
PatchRouteByName,
SetEnvironment,
} from '../actions/config.actions';
import { GetAppConfiguration, SetEnvironment } from '../actions/config.actions';
import { RestOccurError } from '../actions/rest.actions';
import { SetLanguage } from '../actions/session.actions';
import { ApplicationConfiguration } from '../models/application-configuration';
import { ABP } from '../models/common';
import { Config } from '../models/config';
import { organizeRoutes } from '../utils/route-utils';
import { SessionState } from './session.state';
@State<Config.State>({
@ -64,23 +57,6 @@ export class ConfigState {
return selector;
}
static getRoute(path?: string, name?: string, url?: string) {
const selector = createSelector([ConfigState], (state: Config.State) => {
const { flattedRoutes } = state;
return (flattedRoutes as ABP.FullRoute[]).find(route => {
if (path && route.path === path) {
return route;
} else if (name && route.name === name) {
return route;
} else if (url && route.url === url) {
return route;
}
});
});
return selector;
}
static getApiUrl(key?: string) {
const selector = createSelector([ConfigState], (state: Config.State): string => {
return (state.environment.apis[key || 'default'] || state.environment.apis.default).url;
@ -246,84 +222,6 @@ export class ConfigState {
);
}
@Action(PatchRouteByName)
patchRoute(
{ patchState, getState }: StateContext<Config.State>,
{ name, newValue }: PatchRouteByName,
) {
let routes: ABP.FullRoute[] = getState().routes;
routes = patchRouteDeep(routes, name, newValue);
const flattedRoutes = getState().flattedRoutes;
const index = flattedRoutes.findIndex(route => route.name === name);
if (index > -1) {
flattedRoutes[index] = { ...flattedRoutes[index], ...newValue } as ABP.FullRoute;
}
return patchState({
routes,
flattedRoutes,
});
}
@Action(AddRoute)
addRoute({ patchState, getState }: StateContext<Config.State>, { payload }: AddRoute) {
let routes: ABP.FullRoute[] = getState().routes;
const flattedRoutes = getState().flattedRoutes;
const route: ABP.FullRoute = { ...payload };
if (route.parentName) {
const index = flattedRoutes.findIndex(r => r.name === route.parentName);
if (index < 0) return;
const parent = flattedRoutes[index];
if ((parent.url || '').replace('/', '')) {
route.url = `${parent.url}/${route.path}`;
} else {
route.url = `/${route.path}`;
}
route.children = route.children || [];
route.order = route.order || route.order === 0 ? route.order : (parent.children || []).length;
parent.children = [...(parent.children || []), route].sort((a, b) => a.order - b.order);
flattedRoutes[index] = parent;
flattedRoutes.push(route);
let parentName = parent.name;
const parentNameArr = [parentName];
while (parentName) {
parentName = snq(() => flattedRoutes.find(r => r.name === parentName).parentName);
if (parentName) {
parentNameArr.unshift(parentName);
}
}
routes = updateRouteDeep(routes, parentNameArr, parent);
} else {
route.url = `/${route.path}`;
if (route.order || route.order === 0) {
routes = [...routes, route].sort((a, b) => a.order - b.order);
} else {
route.order = routes.length;
routes = [...routes, route];
}
flattedRoutes.push(route);
}
return patchState({
routes,
flattedRoutes,
});
}
@Action(SetEnvironment)
setEnvironment({ patchState }: StateContext<Config.State>, { environment }: SetEnvironment) {
return patchState({
@ -331,65 +229,3 @@ export class ConfigState {
});
}
}
function patchRouteDeep(
routes: ABP.FullRoute[],
name: string,
newValue: Partial<ABP.FullRoute>,
parentUrl: string = '',
): ABP.FullRoute[] {
routes = routes.map(route => {
if (route.name === name) {
newValue.url = `${parentUrl}/${(!newValue.path || newValue.path === ''
? route.path
: newValue.path) || ''}`;
if (newValue.children && newValue.children.length) {
newValue.children = newValue.children.map(child => ({
...child,
url: `${newValue.url}/${child.path}`.replace('//', '/'),
}));
}
return { ...route, ...newValue };
} else if (route.children && route.children.length) {
route.children = patchRouteDeep(
route.children,
name,
newValue,
(parentUrl || '/') + route.path,
);
}
return route;
});
if (parentUrl) {
// recursive block
return routes;
}
return organizeRoutes(routes);
}
function updateRouteDeep(
routes: ABP.FullRoute[],
parentNameArr: string[],
newValue: ABP.FullRoute,
parentIndex = 0,
) {
const index = routes.findIndex(route => route.name === parentNameArr[parentIndex]);
if (parentIndex === parentNameArr.length - 1) {
routes[index] = newValue;
} else {
routes[index].children = updateRouteDeep(
routes[index].children,
parentNameArr,
newValue,
parentIndex + 1,
);
}
return routes;
}

@ -29,43 +29,6 @@ const CONFIG_STATE_DATA = {
requirements: {
layouts: [null, null, null],
},
routes: [
{
name: '::Menu:Home',
path: '',
children: [],
url: '/',
},
{
name: 'AbpAccount::Menu:Account',
path: 'account',
invisible: true,
layout: 'application',
children: [
{
path: 'login',
name: 'AbpAccount::Login',
order: 1,
url: '/account/login',
},
],
url: '/account',
},
],
flattedRoutes: [
{
name: '::Menu:Home',
path: '',
children: [],
url: '/',
},
{
name: '::Menu:Identity',
path: 'identity',
children: [],
url: '/identity',
},
],
localization: {
values: {
MyProjectName: {

@ -1,351 +1,34 @@
import { RouterTestingModule } from '@angular/router/testing';
import { createServiceFactory, SpectatorService } from '@ngneat/spectator/jest';
import { NgxsModule, Store } from '@ngxs/store';
import { OAuthModule } from 'angular-oauth2-oidc';
import { environment } from '../../../../../apps/dev-app/src/environments/environment';
import { RouterOutletComponent } from '../components';
import { CoreModule } from '../core.module';
import { eLayoutType } from '../enums/common';
import { InitState } from '@ngxs/store';
import { ABP } from '../models';
import { ConfigPlugin } from '../plugins';
import { ConfigState } from '../states';
import { addAbpRoutes } from '../utils';
addAbpRoutes([
{
name: 'AbpUiNavigation::Menu:Administration',
path: '',
order: 1,
wrapper: true,
const options: ABP.Root = {
environment: {
production: false,
},
{
name: 'AbpIdentity::Menu:IdentityManagement',
path: 'identity',
order: 1,
parentName: 'AbpUiNavigation::Menu:Administration',
layout: eLayoutType.application,
iconClass: 'fa fa-id-card-o',
children: [
{ path: 'roles', name: 'AbpIdentity::Roles', order: 2, requiredPolicy: 'AbpIdentity.Roles' },
{ path: 'users', name: 'AbpIdentity::Users', order: 1, requiredPolicy: 'AbpIdentity.Users' },
],
},
{
name: 'AbpAccount::Menu:Account',
path: 'account',
invisible: true,
layout: eLayoutType.application,
children: [
{ path: 'login', name: 'AbpAccount::Login', order: 1 },
{ path: 'register', name: 'AbpAccount::Register', order: 2 },
],
},
{
name: 'AbpTenantManagement::Menu:TenantManagement',
path: 'tenant-management',
parentName: 'AbpUiNavigation::Menu:Administration',
layout: eLayoutType.application,
iconClass: 'fa fa-users',
children: [
{
path: 'tenants',
name: 'AbpTenantManagement::Tenants',
order: 1,
requiredPolicy: 'AbpTenantManagement.Tenants',
},
],
},
]);
const expectedState = {
environment,
routes: [
{
name: '::Menu:Home',
path: '',
children: [],
url: '/',
order: 1,
},
{
name: 'AbpUiNavigation::Menu:Administration',
path: '',
order: 1,
wrapper: true,
children: [
{
name: 'AbpIdentity::Menu:IdentityManagement',
path: 'identity',
order: 1,
parentName: 'AbpUiNavigation::Menu:Administration',
layout: 'application',
iconClass: 'fa fa-id-card-o',
children: [
{
path: 'users',
name: 'AbpIdentity::Users',
order: 1,
requiredPolicy: 'AbpIdentity.Users',
url: '/identity/users',
},
{
path: 'roles',
name: 'AbpIdentity::Roles',
order: 2,
requiredPolicy: 'AbpIdentity.Roles',
url: '/identity/roles',
},
],
url: '/identity',
},
{
name: 'AbpTenantManagement::Menu:TenantManagement',
path: 'tenant-management',
parentName: 'AbpUiNavigation::Menu:Administration',
layout: 'application',
iconClass: 'fa fa-users',
children: [
{
path: 'tenants',
name: 'AbpTenantManagement::Tenants',
order: 1,
requiredPolicy: 'AbpTenantManagement.Tenants',
url: '/tenant-management/tenants',
},
],
url: '/tenant-management',
order: 2,
},
],
},
{
name: 'AbpAccount::Menu:Account',
path: 'account',
invisible: true,
layout: 'application',
children: [
{
path: 'login',
name: 'AbpAccount::Login',
order: 1,
url: '/account/login',
},
{
path: 'register',
name: 'AbpAccount::Register',
order: 2,
url: '/account/register',
},
],
url: '/account',
order: 2,
},
],
flattedRoutes: [
{
name: '::Menu:Home',
path: '',
children: [],
url: '/',
order: 1,
},
{
name: 'AbpUiNavigation::Menu:Administration',
path: '',
order: 1,
wrapper: true,
children: [
{
name: 'AbpIdentity::Menu:IdentityManagement',
path: 'identity',
order: 1,
parentName: 'AbpUiNavigation::Menu:Administration',
layout: 'application',
iconClass: 'fa fa-id-card-o',
children: [
{
path: 'users',
name: 'AbpIdentity::Users',
order: 1,
parentName: 'AbpIdentity::Menu:IdentityManagement',
requiredPolicy: 'AbpIdentity.Users',
url: '/identity/users',
},
{
path: 'roles',
name: 'AbpIdentity::Roles',
order: 2,
parentName: 'AbpIdentity::Menu:IdentityManagement',
requiredPolicy: 'AbpIdentity.Roles',
url: '/identity/roles',
},
],
url: '/identity',
},
{
name: 'AbpTenantManagement::Menu:TenantManagement',
path: 'tenant-management',
parentName: 'AbpUiNavigation::Menu:Administration',
layout: 'application',
iconClass: 'fa fa-users',
children: [
{
path: 'tenants',
name: 'AbpTenantManagement::Tenants',
order: 1,
parentName: 'AbpTenantManagement::Menu:TenantManagement',
requiredPolicy: 'AbpTenantManagement.Tenants',
url: '/tenant-management/tenants',
},
],
url: '/tenant-management',
order: 2,
},
],
},
{
name: 'AbpIdentity::Menu:IdentityManagement',
path: 'identity',
order: 1,
parentName: 'AbpUiNavigation::Menu:Administration',
layout: 'application',
iconClass: 'fa fa-id-card-o',
children: [
{
path: 'users',
name: 'AbpIdentity::Users',
order: 1,
parentName: 'AbpIdentity::Menu:IdentityManagement',
requiredPolicy: 'AbpIdentity.Users',
url: '/identity/users',
},
{
path: 'roles',
name: 'AbpIdentity::Roles',
order: 2,
parentName: 'AbpIdentity::Menu:IdentityManagement',
requiredPolicy: 'AbpIdentity.Roles',
url: '/identity/roles',
},
],
url: '/identity',
},
{
path: 'users',
name: 'AbpIdentity::Users',
order: 1,
parentName: 'AbpIdentity::Menu:IdentityManagement',
requiredPolicy: 'AbpIdentity.Users',
url: '/identity/users',
},
{
path: 'roles',
name: 'AbpIdentity::Roles',
order: 2,
parentName: 'AbpIdentity::Menu:IdentityManagement',
requiredPolicy: 'AbpIdentity.Roles',
url: '/identity/roles',
},
{
name: 'AbpTenantManagement::Menu:TenantManagement',
path: 'tenant-management',
parentName: 'AbpUiNavigation::Menu:Administration',
layout: 'application',
iconClass: 'fa fa-users',
children: [
{
path: 'tenants',
name: 'AbpTenantManagement::Tenants',
order: 1,
parentName: 'AbpTenantManagement::Menu:TenantManagement',
requiredPolicy: 'AbpTenantManagement.Tenants',
url: '/tenant-management/tenants',
},
],
url: '/tenant-management',
order: 2,
},
{
path: 'tenants',
name: 'AbpTenantManagement::Tenants',
order: 1,
parentName: 'AbpTenantManagement::Menu:TenantManagement',
requiredPolicy: 'AbpTenantManagement.Tenants',
url: '/tenant-management/tenants',
},
{
name: 'AbpAccount::Menu:Account',
path: 'account',
invisible: true,
layout: 'application',
children: [
{
path: 'login',
name: 'AbpAccount::Login',
order: 1,
parentName: 'AbpAccount::Menu:Account',
url: '/account/login',
},
{
path: 'register',
name: 'AbpAccount::Register',
order: 2,
parentName: 'AbpAccount::Menu:Account',
url: '/account/register',
},
],
url: '/account',
order: 2,
},
{
path: 'login',
name: 'AbpAccount::Login',
order: 1,
parentName: 'AbpAccount::Menu:Account',
url: '/account/login',
},
{
path: 'register',
name: 'AbpAccount::Register',
order: 2,
parentName: 'AbpAccount::Menu:Account',
url: '/account/register',
},
],
};
describe('ConfigPlugin', () => {
let spectator: SpectatorService<ConfigPlugin>;
const createService = createServiceFactory({
service: ConfigPlugin,
imports: [
NgxsModule.forRoot([ConfigState]),
CoreModule.forRoot({ environment }),
OAuthModule.forRoot(),
RouterTestingModule.withRoutes([
{
path: '',
component: RouterOutletComponent,
data: {
routes: {
name: '::Menu:Home',
} as ABP.Route,
},
},
{ path: 'identity', component: RouterOutletComponent },
{ path: 'account', component: RouterOutletComponent },
{ path: 'tenant-management', component: RouterOutletComponent },
]),
],
});
const event = new InitState();
beforeEach(() => {
spectator = createService();
});
const state = {
ConfigState: {
foo: 'bar',
...options,
},
};
describe('ConfigPlugin', () => {
it('should ConfigState must be create with correct datas', () => {
const store = spectator.get(Store);
const state = store.selectSnapshot(ConfigState);
expect(state).toEqual(expectedState);
const next = jest.fn();
const plugin = new ConfigPlugin(options);
plugin.handle({ ConfigState: { foo: 'bar' } }, event, next);
expect(next).toHaveBeenCalledWith(state, event);
expect(next).toHaveBeenCalledTimes(1);
next.mockClear();
delete state.ConfigState.environment;
plugin.handle(state, event, next);
expect(next).toHaveBeenCalledWith(state, event);
expect(next).toHaveBeenCalledTimes(1);
});
});

@ -1,13 +1,11 @@
import { HttpClient } from '@angular/common/http';
import { createServiceFactory, SpectatorService, SpyObject } from '@ngneat/spectator/jest';
import { Store } from '@ngxs/store';
import clone from 'just-clone';
import { of, ReplaySubject, timer } from 'rxjs';
import { AddRoute, PatchRouteByName, SetLanguage } from '../actions';
import { ABP } from '../models';
import { SetLanguage } from '../actions';
import { Config } from '../models/config';
import { ApplicationConfigurationService, ConfigStateService } from '../services';
import { ConfigState } from '../states';
import { HttpClient } from '@angular/common/http';
export const CONFIG_STATE_DATA = {
environment: {
@ -33,61 +31,6 @@ export const CONFIG_STATE_DATA = {
requirements: {
layouts: [null, null, null],
},
routes: [
{
name: '::Menu:Home',
path: '',
children: [],
url: '/',
},
{
name: 'AbpAccount::Menu:Account',
path: 'account',
invisible: true,
layout: 'application',
children: [
{
path: 'login',
name: 'AbpAccount::Login',
order: 1,
url: '/account/login',
parentName: 'AbpAccount::Menu:Account',
},
],
url: '/account',
},
],
flattedRoutes: [
{
name: '::Menu:Home',
path: '',
children: [],
url: '/',
},
{
name: 'AbpAccount::Menu:Account',
path: 'account',
invisible: true,
layout: 'application',
children: [
{
path: 'login',
name: 'AbpAccount::Login',
order: 1,
url: '/account/login',
parentName: 'AbpAccount::Menu:Account',
},
],
url: '/account',
},
{
path: 'login',
name: 'AbpAccount::Login',
order: 1,
url: '/account/login',
parentName: 'AbpAccount::Menu:Account',
},
],
localization: {
values: {
MyProjectName: {
@ -208,17 +151,6 @@ describe('ConfigState', () => {
});
});
describe('#getRoute', () => {
it('should return route', () => {
expect(ConfigState.getRoute(null, '::Menu:Home')(CONFIG_STATE_DATA)).toEqual(
CONFIG_STATE_DATA.flattedRoutes[0],
);
expect(ConfigState.getRoute('account')(CONFIG_STATE_DATA)).toEqual(
CONFIG_STATE_DATA.flattedRoutes[1],
);
});
});
describe('#getApiUrl', () => {
it('should return api url', () => {
expect(ConfigState.getApiUrl('other')(CONFIG_STATE_DATA)).toEqual(
@ -330,121 +262,4 @@ describe('ConfigState', () => {
});
});
});
describe('#PatchRouteByName', () => {
it('should patch the route', () => {
let patchStateArg;
const patchState = jest.fn(s => (patchStateArg = s));
const getState = jest.fn(() => clone(CONFIG_STATE_DATA));
state.patchRoute(
{ patchState, getState } as any,
new PatchRouteByName('::Menu:Home', {
name: 'Home',
path: 'home',
children: [{ path: 'dashboard', name: 'Dashboard' }],
}),
);
expect(patchStateArg.routes[0]).toEqual({
name: 'Home',
path: 'home',
url: '/home',
children: [{ path: 'dashboard', name: 'Dashboard', url: '/home/dashboard' }],
});
expect(patchStateArg.flattedRoutes[0]).toEqual({
name: 'Home',
path: 'home',
url: '/home',
children: [{ path: 'dashboard', name: 'Dashboard', url: '/home/dashboard' }],
});
});
it('should patch the route without path', () => {
let patchStateArg;
const patchState = jest.fn(s => (patchStateArg = s));
const getState = jest.fn(() => clone(CONFIG_STATE_DATA));
state.patchRoute(
{ patchState, getState } as any,
new PatchRouteByName('::Menu:Home', {
name: 'Main',
children: [{ path: 'dashboard', name: 'Dashboard' }],
}),
);
expect(patchStateArg.routes[0]).toEqual({
name: 'Main',
path: '',
url: '/',
children: [{ path: 'dashboard', name: 'Dashboard', url: '/dashboard' }],
});
expect(patchStateArg.flattedRoutes[0]).toEqual({
name: 'Main',
path: '',
url: '/',
children: [{ path: 'dashboard', name: 'Dashboard', url: '/dashboard' }],
});
});
});
describe('#AddRoute', () => {
const newRoute = {
name: 'My new page',
children: [],
iconClass: 'fa fa-dashboard',
path: 'page',
invisible: false,
order: 2,
requiredPolicy: 'MyProjectName::MyNewPage',
} as Omit<ABP.Route, 'children'>;
test('should add a new route', () => {
let patchStateArg;
const patchState = jest.fn(s => (patchStateArg = s));
const getState = jest.fn(() => clone(CONFIG_STATE_DATA));
state.addRoute({ patchState, getState } as any, new AddRoute(newRoute));
expect(patchStateArg.routes[CONFIG_STATE_DATA.routes.length]).toEqual({
...newRoute,
url: '/page',
});
expect(patchStateArg.flattedRoutes[CONFIG_STATE_DATA.flattedRoutes.length]).toEqual(
patchStateArg.routes[CONFIG_STATE_DATA.routes.length],
);
});
it('should add a new child route', () => {
let patchStateArg;
const patchState = jest.fn(s => (patchStateArg = s));
const getState = jest.fn(() => clone(CONFIG_STATE_DATA));
state.addRoute(
{ patchState, getState } as any,
new AddRoute({ ...newRoute, parentName: 'AbpAccount::Login' }),
);
expect(patchStateArg.routes[1].children[0].children[0]).toEqual({
...newRoute,
parentName: 'AbpAccount::Login',
url: '/account/login/page',
});
expect(patchStateArg.flattedRoutes[CONFIG_STATE_DATA.flattedRoutes.length]).toEqual(
patchStateArg.routes[1].children[0].children[0],
);
expect(
patchStateArg.flattedRoutes[
CONFIG_STATE_DATA.flattedRoutes.findIndex(route => route.name === 'AbpAccount::Login')
],
).toEqual(patchStateArg.routes[1].children[0]);
});
});
});

Loading…
Cancel
Save