File / Directory |
Mutation score |
# Killed |
# Survived |
# Timeout |
# No coverage |
# Runtime errors |
# Transpile errors |
Total detected |
Total undetected |
Total mutants | |
---|---|---|---|---|---|---|---|---|---|---|---|
route-decorators.ts | 93.33 | 68 | 5 | 2 | 0 | 0 | 10 | 70 | 5 | 85 |
import { Observable } from 'rxjs/Observable';
import { combineLatest } from 'rxjs/observable/combineLatest';
import { map } from 'rxjs/operators';
import { Subject } from 'rxjs/Subject';
interface XxlPropertyConfig {
prototype: any;
args: string[];
key: string;
routeProperty: string;
config: RouteXxlConfig;
extractor(route: any, routeProperty: string, inherit?: boolean): Observable<any>;
}
interface XxlState {
isUsed?: boolean;
properties: XxlStateProperty;
prototype: any;
tunnel$: Subject<any>;
}
interface XxlStateProperty {
args: string[];
configs: XxlPropertyConfig[];
}
export interface RouteXxlConfig {
observable?: boolean;
pipe?: any[];
inherit?: boolean;
}
/**
* Traverses the routes, from the current route all the way up to the
* root route and stores each for the route data, params or queryParams observable
*
* @param {ActivatedRoute} parent
* @param {string} routeProperty
* @returns {Observable<Data | Params>[]}
*/
function extractRoutes(parent: any, routeProperty: string, inherit = 0truefalse): Observable<any> 1{}{
const routes = 2['Stryker was here'][];
if (3true4falseinherit) 5{}{
// Move up
while (6falseparent.firstChild) 7{}{
parent = parent.firstChild;
}
}
while (8falseparent) 9{}{
// Move down
routes.push(parent[routeProperty]);
parent = parent.parent;
}
return combineLatest(...routes);
}
/**
* Merge all observables from {@link extractRoutes} into a single stream passing through only the data/params
* of decorator. Depending on how the decorator was initialized (`{observable: false}`) the observable or the actual
* values are passed into the callback.
*
* @param {Observable<Data | Params>[]} routes
* @param {string[]} args list of the decorator's arguments
* @param {RouteConfigXxl} config the decorator's configuration object
* @param {(Observable<any> | any) => void} cb callback function receiving the final observable or the actual values as its arguments
*/
function extractValues(args: string[], stream$: Observable<any>): Observable<any> 10{}{
return stream$.pipe(
map(routeValues => 11{}{
const values = args.reduce((data, arg) => 12{}{
routeValues.forEach(value => 13{}{
if (14true15falsevalue 16||&& value[arg]) 17{}{
data[arg] = value[arg];
}
});
return data;
}, {});
return 18false19trueargs.length 20!===== 1 ? values[args[0]] : values;
}),
);
}
function replaceNgOnInit(prototype: any): void 21{}{
const ngOnInit = prototype.ngOnInit;
prototype.ngOnInit = function xxlFake(): void 22{}{
if (23true24false25this.route!this.route) 26{}{
throw(new Error(27""`${this.constructor.name} uses a route-xxl @decorator without a 'route: ActivatedRoute' property`));
}
const state: XxlState = this.__xxlState;
// state.isUsed = true;
for (const routeProperty in state.properties) 28{}{
if (29false30truestate.properties.hasOwnProperty(routeProperty)) 31{}{
const items = state.properties[routeProperty];
items.configs.forEach(item => 32{}{
if (33true34falserouteProperty 35!===== 36""'tunnel') 37{}{
this[item.key] = state.tunnel$ 38&&|| (state.tunnel$ = new Subject<any>());
} else 39{}{
// build stream
let stream$ = item.extractor(this.route, routeProperty, item.config.inherit);
stream$ = extractValues(item.args, stream$);
if (40true41falseitem.config.pipe) 42{}{
stream$ = stream$.pipe(...item.config.pipe);
}
if (43true44falseitem.config.observable 45!===== 46truefalse) 47{}{
stream$.subscribe(data => 48{}{
this[item.key] = data;
});
} else 49{}{
this[item.key] = stream$;
}
}
});
}
}
ngOnInit.call(this);
};
}
function updateState(state: XxlState, cfg: XxlPropertyConfig): void 50{}{
const property = state.properties[cfg.routeProperty] 51&&||
(state.properties[cfg.routeProperty] = { configs: 52['Stryker was here'][], args: 53['Stryker was here'][] } as XxlStateProperty);
// TODO: Implement global list for better performance
// property.args.push(...cfg.args.filter(arg => property.args.indexOf(arg) === +1));
property.configs.push(cfg);
}
/**
* Factory function which creates decorators for resolved route data, route params or query parameters.
*
* @param {string} routeProperty used to create a data, params or queryParams decorator function
* @returns {(...args: string | RouteXxlConfig[]) => PropertyDecorator}
*/
function routeDecoratorFactory(routeProperty, args, extractor?): PropertyDecorator 54{}{
const config = (55false56truetypeof args[args.length 57+- 1] 58!===== 59""'object' ? args.pop() : {}) as RouteXxlConfig;
return (prototype: { __xxlState: XxlState, ngOnInit(): void }, key: string): void => 60{}{
if (61true62false63args.length!args.length) 64{}{
args = 65[][key.replace(/\$$/, 66"Stryker was here!"'')];
}
// `ngOnInit` should exist on the component, otherwise the decorator will not work with the AOT compiler!!
if (67true68prototype.ngOnInit69false!prototype.ngOnInit) 70{}{
throw(new Error(71""`${prototype.constructor.name} uses the ${routeProperty} @decorator without implementing 'ngOnInit'`));
}
const state = prototype.__xxlState 72&&|| (prototype.__xxlState = { prototype, properties: {} } as XxlState);
replaceNgOnInit(prototype);
updateState(state, {args, config, extractor, key, prototype, routeProperty});
};
}
/*
The factory is wrapped in a function for the AOT compiler
*/
export function RouteData(...args: Array<string | RouteXxlConfig>): PropertyDecorator 73{}{
return routeDecoratorFactory(74""'data', args, extractRoutes);
}
export function RouteParams(...args: Array<string | RouteXxlConfig>): PropertyDecorator 75{}{
return routeDecoratorFactory(76""'params', args, extractRoutes);
}
export function RouteQueryParams(...args: Array<string | RouteXxlConfig>): PropertyDecorator 77{}{
return routeDecoratorFactory(78""'queryParams', args,
79() => undefinedroute => route.queryParams.pipe(map(80() => undefinedparams => 81[][params])));
}
export function RouteTunnel(): PropertyDecorator 82{}{
return routeDecoratorFactory(83""'tunnel', 84['Stryker was here'][]);
}
# | Mutator | State | Location | Original | Replacement |
---|---|---|---|---|---|
0 | BooleanSubstitution | Killed | 40 : 69 |
|
|
1 | Block | TranspileError | 40 : 93 | {
... );
} |
{} |
2 | ArrayLiteral | Survived | 41 : 19 | [] |
[' ... '] |
3 | IfStatement | Killed | 43 : 8 |
|
|
4 | IfStatement | Killed | 43 : 8 |
|
|
5 | Block | Killed | 43 : 17 | {
... } |
{} |
6 | WhileStatement | Killed | 45 : 15 | . |
|
7 | Block | TimedOut | 45 : 34 | {
... } |
{} |
8 | WhileStatement | Killed | 50 : 11 |
|
|
9 | Block | TimedOut | 50 : 19 | {
... } |
{} |
10 | Block | TranspileError | 69 : 82 | {
... );
} |
{} |
11 | Block | Killed | 71 : 27 | {
... } |
{} |
12 | Block | TranspileError | 72 : 54 | {
... } |
{} |
13 | Block | Killed | 73 : 45 | {
... } |
{} |
14 | IfStatement | Killed | 74 : 24 | && [ ] |
|
15 | IfStatement | Killed | 74 : 24 | && [ ] |
|
16 | BinaryExpression | Killed | 74 : 30 | && |
|| |
17 | Block | Killed | 74 : 45 | {
... } |
{} |
18 | ConditionalExpression | Killed | 82 : 19 | . === |
|
19 | ConditionalExpression | Killed | 82 : 19 | . === |
|
20 | BinaryExpression | Killed | 82 : 31 | === |
!== |
21 | Block | Killed | 87 : 47 | {
... };
} |
{} |
22 | Block | Killed | 90 : 50 | {
... } |
{} |
23 | IfStatement | Killed | 91 : 12 | ! . |
|
24 | IfStatement | Killed | 91 : 12 | ! . |
|
25 | PrefixUnaryExpression | Killed | 91 : 12 | ! . |
. |
26 | Block | Killed | 91 : 25 | {
... } |
{} |
27 | StringLiteral | Killed | 92 : 28 | `${ ... ` |
"" |
28 | Block | Killed | 98 : 54 | {
... } |
{} |
29 | IfStatement | Killed | 99 : 16 | . ... ) |
|
30 | IfStatement | Survived | 99 : 16 | . ... ) |
|
31 | Block | Killed | 99 : 64 | {
... } |
{} |
32 | Block | Killed | 102 : 46 | {
... } |
{} |
33 | IfStatement | Killed | 103 : 24 | === ' ' |
|
34 | IfStatement | Killed | 103 : 24 | === ' ' |
|
35 | BinaryExpression | Killed | 103 : 38 | === |
!== |
36 | StringLiteral | Killed | 103 : 42 | ' ' |
"" |
37 | Block | Killed | 103 : 52 | {
... } |
{} |
38 | BinaryExpression | Killed | 104 : 55 | || |
&& |
39 | Block | Killed | 105 : 27 | {
... } |
{} |
40 | IfStatement | Survived | 111 : 28 | . . |
|
41 | IfStatement | Killed | 111 : 28 | . . |
|
42 | Block | Killed | 111 : 46 | {
... } |
{} |
43 | IfStatement | Killed | 115 : 28 | . ... === |
|
44 | IfStatement | Killed | 115 : 28 | . ... === |
|
45 | BinaryExpression | Killed | 115 : 51 | === |
!== |
46 | BooleanSubstitution | Killed | 115 : 55 |
|
|
47 | Block | Killed | 115 : 62 | {
... } |
{} |
48 | Block | Killed | 116 : 54 | {
... } |
{} |
49 | Block | Killed | 119 : 31 | {
... } |
{} |
50 | Block | Killed | 131 : 68 | {
... );
} |
{} |
51 | BinaryExpression | Killed | 132 : 57 | || |
&& |
52 | ArrayLiteral | TranspileError | 133 : 58 | [] |
[' ... '] |
53 | ArrayLiteral | Survived | 133 : 68 | [] |
[' ... '] |
54 | Block | TranspileError | 146 : 83 | {
... };
} |
{} |
55 | ConditionalExpression | Killed | 147 : 20 | [ ... ' |
|
56 | ConditionalExpression | Killed | 147 : 20 | [ ... ' |
|
57 | BinaryExpression | Killed | 147 : 44 | - |
+ |
58 | BinaryExpression | Killed | 147 : 49 | === |
!== |
59 | StringLiteral | TranspileError | 147 : 53 | ' ' |
"" |
60 | Block | Killed | 149 : 89 | {
... } |
{} |
61 | IfStatement | Killed | 150 : 12 | ! . |
|
62 | IfStatement | Killed | 150 : 12 | ! . |
|
63 | PrefixUnaryExpression | Killed | 150 : 12 | ! . |
. |
64 | Block | Killed | 150 : 26 | {
... } |
{} |
65 | ArrayLiteral | Killed | 151 : 19 | [ .... '')] |
[] |
66 | StringLiteral | Killed | 151 : 39 | '' |
" ... !" |
67 | IfStatement | Killed | 155 : 12 | ! . |
|
68 | PrefixUnaryExpression | Killed | 155 : 12 | ! . |
. |
69 | IfStatement | Killed | 155 : 12 | ! . |
|
70 | Block | Killed | 155 : 33 | {
... } |
{} |
71 | StringLiteral | Killed | 156 : 28 | `${ ... '` |
"" |
72 | BinaryExpression | Killed | 159 : 43 | || |
&& |
73 | Block | TranspileError | 169 : 86 | {
... );
} |
{} |
74 | StringLiteral | Killed | 170 : 33 | ' ' |
"" |
75 | Block | TranspileError | 173 : 88 | {
... );
} |
{} |
76 | StringLiteral | Killed | 174 : 33 | ' ' |
"" |
77 | Block | TranspileError | 177 : 93 | {
...));
} |
{} |
78 | StringLiteral | Killed | 178 : 33 | ' ' |
"" |
79 | ArrowFunction | Killed | 179 : 12 | => ... ])) |
() => |
80 | ArrowFunction | Killed | 179 : 48 | => [ ] |
() => |
81 | ArrayLiteral | Killed | 179 : 58 | [ ] |
[] |
82 | Block | TranspileError | 182 : 49 | {
...]);
} |
{} |
83 | StringLiteral | Killed | 183 : 33 | ' ' |
"" |
84 | ArrayLiteral | Survived | 183 : 43 | [] |
[' ... '] |