Stryker

route-decorators.ts - Stryker report

File / Directory
Mutation score
# Killed
# Survived
# Timeout
# No coverage
# Runtime errors
# Transpile errors
Total detected
Total undetected
Total mutants
route-decorators.ts
93.33 %
93.33 68 5 2 0 0 10 70 5 85
Expand all
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 = 0false): Observable<any> 1{
    const routes = 2[];

    if (34inherit) 5{
        // Move up
        while (6parent.firstChild) 7{
            parent = parent.firstChild;
        }
    }

    while (8parent) 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 (1415value 16&& value[arg]) 17{
                        data[arg] = value[arg];
                    }
                });

                return data;
            }, {});

            return 1819args.length 20=== 1 ? values[args[0]] : values;
        }),
    );
}

function replaceNgOnInit(prototype: any): void 21{
    const ngOnInit = prototype.ngOnInit;

    prototype.ngOnInit = function xxlFake(): void 22{
        if (232425!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 (2930state.properties.hasOwnProperty(routeProperty)) 31{
                const items = state.properties[routeProperty];

                items.configs.forEach(item => 32{
                    if (3334routeProperty 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 (4041item.config.pipe) 42{
                            stream$ = stream$.pipe(...item.config.pipe);
                        }

                        if (4344item.config.observable 45=== 46false) 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[], args: 53[] } 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 = (5556typeof args[args.length 57- 1] 58=== 59'object' ? args.pop() : {}) as RouteXxlConfig;

    return (prototype: { __xxlState: XxlState, ngOnInit(): void }, key: string): void => 60{
        if (616263!args.length) 64{
            args = 65[key.replace(/\$$/, 66'')];
        }

        // `ngOnInit` should exist on the component, otherwise the decorator will not work with the AOT compiler!!
        if (676869!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,
            79route => route.queryParams.pipe(map(80params => 81[params])));
}

export function RouteTunnel(): PropertyDecorator 82{
    return routeDecoratorFactory(83'tunnel', 84[]);
}
# 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 [] [' ... ']