LCOV - code coverage report
Current view: top level - src/vroute_elements - vroute_element_single_subroute.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 63 70 90.0 %
Date: 2021-04-29 14:25:52 Functions: 0 0 -

          Line data    Source code
       1             : part of '../main.dart';
       2             : 
       3             : /// If the VRouteElement has a single [VRouteElement] as a child, it should instantiate this class
       4             : ///
       5             : /// What is does is implementing [buildRoute], [buildPathFromName] and [buildPathFromPop] methods
       6             : mixin VRouteElementSingleSubRoute on VRouteElement {
       7             :   /// The list of possible routes
       8             :   /// Only one will be chosen to be displayed
       9             :   List<VRouteElement> buildRoutes();
      10             : 
      11          78 :   late final List<VRouteElement> _subroutes = buildRoutes();
      12             : 
      13             :   /// Describes whether we should we pop this [VRouteElement]
      14             :   /// if the [VRouteElement] of the subroute pops
      15          19 :   bool get popWithSubRoute => true;
      16             : 
      17             :   /// [buildRoute] must return [VRoute] if it constitute (which its subroutes or not) a valid
      18             :   /// route given the input parameters
      19             :   /// [VRoute] should describe this valid route
      20             :   ///
      21             :   ///
      22             :   /// [vPathRequestData] contains all the information about the original request coming
      23             :   /// from [VRouter]
      24             :   /// It should not be changed and should be given as-is to its subroutes
      25             :   ///
      26             :   /// [parentRemainingPath] is the part on which to base any local path
      27             :   /// WARNING: [parentRemainingPath] is null if the parent did not match the path
      28             :   /// in which case only absolute path should be tested.
      29             :   ///
      30             :   /// [parentPathParameters] are the path parameters of every [VRouteElement] above this
      31             :   /// one in the route
      32             :   ///
      33             :   /// [buildRoute] basically just checks for a match in stackedRoutes and if any
      34             :   /// adds this [VRouteElement] to the [VRoute]
      35             :   ///
      36             :   /// For more info on buildRoute, see [VRouteElement.buildRoute]
      37          25 :   VRoute? buildRoute(
      38             :     VPathRequestData vPathRequestData, {
      39             :     required VPathMatch parentVPathMatch,
      40             :   }) {
      41             :     VRoute? childVRoute;
      42          50 :     for (var vRouteElement in _subroutes) {
      43          25 :       childVRoute = vRouteElement.buildRoute(
      44             :         vPathRequestData,
      45             :         parentVPathMatch: parentVPathMatch,
      46             :       );
      47             :       if (childVRoute != null) {
      48          25 :         return VRoute(
      49          25 :           vRouteElementNode: VRouteElementNode(
      50             :             this,
      51             :             localPath: null,
      52          25 :             stackedVRouteElementNode: childVRoute.vRouteElementNode,
      53             :           ),
      54          25 :           pages: childVRoute.pages,
      55          25 :           pathParameters: childVRoute.pathParameters,
      56          75 :           vRouteElements: <VRouteElement>[this] + childVRoute.vRouteElements,
      57             :         );
      58             :       }
      59             :     }
      60             : 
      61             :     return null;
      62             :   }
      63             : 
      64             :   /// This function takes a name and tries to find the path corresponding to
      65             :   /// the route matching this name
      66             :   ///
      67             :   /// The deeper nested the route the better
      68             :   /// The given path parameters have to include at least every path parameters of the final path
      69          14 :   GetPathFromNameResult getPathFromName(
      70             :     String nameToMatch, {
      71             :     required Map<String, String> pathParameters,
      72             :     required GetNewParentPathResult parentPathResult,
      73             :     required Map<String, String> remainingPathParameters,
      74             :   }) {
      75          14 :     final childNameResults = <GetPathFromNameResult>[];
      76             : 
      77             :     // Check if any subroute matches the name
      78          28 :     for (var vRouteElement in _subroutes) {
      79          14 :       childNameResults.add(
      80          14 :         vRouteElement.getPathFromName(
      81             :           nameToMatch,
      82             :           pathParameters: pathParameters,
      83             :           parentPathResult: parentPathResult,
      84             :           remainingPathParameters: remainingPathParameters,
      85             :         ),
      86             :       );
      87          28 :       if (childNameResults.last is ValidNameResult) {
      88          12 :         return childNameResults.last;
      89             :       }
      90             :     }
      91             : 
      92             :     // If we don't have any valid result
      93             : 
      94             :     // If some stackedRoute returned PathParamsPopError, aggregate them
      95           7 :     final pathParamsNameErrors = PathParamsErrorsNameResult(
      96             :       name: nameToMatch,
      97           7 :       values: childNameResults.fold<List<PathParamsError>>(
      98           7 :         <PathParamsError>[],
      99           7 :         (previousValue, element) {
     100           7 :           return previousValue +
     101          19 :               ((element is PathParamsErrorsNameResult) ? element.values : []);
     102             :         },
     103             :       ),
     104             :     );
     105             : 
     106             :     // If there was any PathParamsPopError, we have some pathParamsPopErrors.values
     107             :     // and therefore should return this
     108          14 :     if (pathParamsNameErrors.values.isNotEmpty) {
     109             :       return pathParamsNameErrors;
     110             :     }
     111             : 
     112             :     // Else try to find a NullPathError
     113           7 :     if (childNameResults.indexWhere(
     114          21 :             (childNameResult) => childNameResult is NullPathErrorNameResult) !=
     115           7 :         -1) {
     116           2 :       return NullPathErrorNameResult(name: nameToMatch);
     117             :     }
     118             : 
     119             :     // Else return a NotFoundError
     120           7 :     return NotFoundErrorNameResult(name: nameToMatch);
     121             :   }
     122             : 
     123             :   /// [GetPathFromPopResult.didPop] is true if this [VRouteElement] popped
     124             :   /// [GetPathFromPopResult.extendedPath] is null if this path can't be the right one according to
     125             :   ///                                                                     the path parameters
     126             :   /// [GetPathFromPopResult] is null when this [VRouteElement] does not pop AND none of
     127             :   ///                                                                     its stackedRoutes popped
     128          29 :   GetPathFromPopResult getPathFromPop(
     129             :     VRouteElement elementToPop, {
     130             :     required Map<String, String> pathParameters,
     131             :     required GetNewParentPathResult parentPathResult,
     132             :   }) {
     133             :     // If vRouteElement is this, then this is the element to pop so we return null
     134          29 :     if (elementToPop == this) {
     135           9 :       if (parentPathResult is ValidParentPathResult) {
     136           9 :         return FoundPopResult(
     137           9 :           path: parentPathResult.path,
     138             :           didPop: true,
     139           9 :           poppedVRouteElements: [this],
     140             :         );
     141             :       } else {
     142           3 :         assert(parentPathResult is PathParamsErrorNewParentPath);
     143           3 :         return PathParamsPopErrors(
     144           3 :           values: [
     145           3 :             MissingPathParamsError(
     146           6 :               pathParams: pathParameters.keys.toList(),
     147             :               missingPathParams:
     148             :                   (parentPathResult as PathParamsErrorNewParentPath)
     149           3 :                       .pathParameters,
     150             :             ),
     151             :           ],
     152             :         );
     153             :       }
     154             :     }
     155             : 
     156          29 :     final popErrorResults = <GetPathFromPopResult>[];
     157             : 
     158             :     // Try to pop from the stackedRoutes
     159          58 :     for (var vRouteElement in _subroutes) {
     160          29 :       GetPathFromPopResult childPopResult = vRouteElement.getPathFromPop(
     161             :         elementToPop,
     162             :         pathParameters: pathParameters,
     163             :         parentPathResult: parentPathResult,
     164             :       );
     165          29 :       if (childPopResult is FoundPopResult) {
     166          46 :         if (popWithSubRoute && childPopResult.didPop) {
     167             :           // if the nestedRoute popped, we should pop too
     168          12 :           if (parentPathResult is ValidParentPathResult) {
     169          12 :             return FoundPopResult(
     170          12 :               path: parentPathResult.path,
     171             :               didPop: true,
     172             :               poppedVRouteElements:
     173          36 :                   <VRouteElement>[this] + childPopResult.poppedVRouteElements,
     174             :             );
     175             :           } else {
     176           0 :             assert(parentPathResult is PathParamsErrorNewParentPath);
     177           0 :             popErrorResults.add(
     178           0 :               PathParamsPopErrors(
     179           0 :                 values: [
     180           0 :                   MissingPathParamsError(
     181           0 :                     pathParams: pathParameters.keys.toList(),
     182             :                     missingPathParams:
     183             :                         (parentPathResult as PathParamsErrorNewParentPath)
     184           0 :                             .pathParameters,
     185             :                   ),
     186             :                 ],
     187             :               ),
     188             :             );
     189             :           }
     190             :         } else {
     191          25 :           return FoundPopResult(
     192          25 :             path: childPopResult.path,
     193             :             didPop: false,
     194          25 :             poppedVRouteElements: childPopResult.poppedVRouteElements,
     195             :           );
     196             :         }
     197             :       } else {
     198          10 :         popErrorResults.add(childPopResult);
     199             :       }
     200             :     }
     201             : 
     202             :     // If we don't have any valid result
     203             : 
     204             :     // If some stackedRoute returned PathParamsPopError, aggregate them
     205          10 :     final pathParamsPopErrors = PathParamsPopErrors(
     206          10 :       values: popErrorResults.fold<List<MissingPathParamsError>>(
     207          10 :         <MissingPathParamsError>[],
     208          10 :         (previousValue, element) {
     209          10 :           return previousValue +
     210          24 :               ((element is PathParamsPopErrors) ? element.values : []);
     211             :         },
     212             :       ),
     213             :     );
     214             : 
     215             :     // If there was any PathParamsPopError, we have some pathParamsPopErrors.values
     216             :     // and therefore should return this
     217          20 :     if (pathParamsPopErrors.values.isNotEmpty) {
     218             :       return pathParamsPopErrors;
     219             :     }
     220             : 
     221             :     // If none of the stackedRoutes popped, this did not pop, and there was no path parameters issue, return not found
     222             :     // This should never happen
     223           6 :     return ErrorNotFoundGetPathFromPopResult();
     224             :   }
     225             : }

Generated by: LCOV version 1.14