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: 61 68 89.7 %
Date: 2021-04-26 23:10:51 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          80 :   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          21 :   GetPathFromNameResult getPathFromName(
      70             :     String nameToMatch, {
      71             :     required Map<String, String> pathParameters,
      72             :     required GetNewParentPathResult parentPathResult,
      73             :     required Map<String, String> remainingPathParameters,
      74             :   }) {
      75          21 :     final childNameResults = <GetPathFromNameResult>[];
      76             : 
      77             :     // Check if any subroute matches the name
      78          41 :     for (var vRouteElement in _subroutes) {
      79          20 :       childNameResults.add(
      80          20 :         vRouteElement.getPathFromName(
      81             :           nameToMatch,
      82             :           pathParameters: pathParameters,
      83             :           parentPathResult: parentPathResult,
      84             :           remainingPathParameters: remainingPathParameters,
      85             :         ),
      86             :       );
      87          40 :       if (childNameResults.last is ValidNameResult) {
      88          18 :         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          16 :     final pathParamsNameErrors = PathParamsErrorsNameResult(
      96             :       name: nameToMatch,
      97          16 :       values: childNameResults.fold<List<PathParamsError>>(
      98          16 :         <PathParamsError>[],
      99          10 :         (previousValue, element) {
     100          10 :           return previousValue +
     101          25 :               ((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          32 :     if (pathParamsNameErrors.values.isNotEmpty) {
     109             :       return pathParamsNameErrors;
     110             :     }
     111             : 
     112             :     // Else try to find a NullPathError
     113             :     if (childNameResults
     114          52 :             .indexWhere((childNameResult) => childNameResult is NullPathErrorNameResult) !=
     115          16 :         -1) {
     116           2 :       return NullPathErrorNameResult(name: nameToMatch);
     117             :     }
     118             : 
     119             :     // Else return a NotFoundError
     120          16 :     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 ValidPopResult(
     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           3 :               missingPathParams: (parentPathResult as PathParamsErrorNewParentPath).pathParameters,
     148             :             ),
     149             :           ],
     150             :         );
     151             :       }
     152             :     }
     153             : 
     154          29 :     final popErrorResults = <GetPathFromPopResult>[];
     155             : 
     156             :     // Try to pop from the stackedRoutes
     157          58 :     for (var vRouteElement in _subroutes) {
     158          29 :       GetPathFromPopResult childPopResult = vRouteElement.getPathFromPop(
     159             :         elementToPop,
     160             :         pathParameters: pathParameters,
     161             :         parentPathResult: parentPathResult,
     162             :       );
     163          29 :       if (childPopResult is ValidPopResult) {
     164          46 :         if (popWithSubRoute && childPopResult.didPop) {
     165             :           // if the nestedRoute popped, we should pop too
     166          12 :           if (parentPathResult is ValidParentPathResult) {
     167          12 :             return ValidPopResult(
     168          12 :               path: parentPathResult.path,
     169             :               didPop: true,
     170             :               poppedVRouteElements:
     171          36 :                   <VRouteElement>[this] + childPopResult.poppedVRouteElements,
     172             :             );
     173             :           } else {
     174           0 :             assert(parentPathResult is PathParamsErrorNewParentPath);
     175           0 :             popErrorResults.add(
     176           0 :               PathParamsPopErrors(
     177           0 :                 values: [
     178           0 :                   MissingPathParamsError(
     179           0 :                     pathParams: pathParameters.keys.toList(),
     180             :                     missingPathParams:
     181           0 :                         (parentPathResult as PathParamsErrorNewParentPath).pathParameters,
     182             :                   ),
     183             :                 ],
     184             :               ),
     185             :             );
     186             :           }
     187             :         } else {
     188          25 :           return ValidPopResult(
     189          25 :             path: childPopResult.path,
     190             :             didPop: false,
     191          25 :             poppedVRouteElements: childPopResult.poppedVRouteElements,
     192             :           );
     193             :         }
     194             :       } else {
     195          10 :         popErrorResults.add(childPopResult);
     196             :       }
     197             :     }
     198             : 
     199             :     // If we don't have any valid result
     200             : 
     201             :     // If some stackedRoute returned PathParamsPopError, aggregate them
     202          10 :     final pathParamsPopErrors = PathParamsPopErrors(
     203          10 :       values: popErrorResults.fold<List<MissingPathParamsError>>(
     204          10 :         <MissingPathParamsError>[],
     205          10 :         (previousValue, element) {
     206          34 :           return previousValue + ((element is PathParamsPopErrors) ? element.values : []);
     207             :         },
     208             :       ),
     209             :     );
     210             : 
     211             :     // If there was any PathParamsPopError, we have some pathParamsPopErrors.values
     212             :     // and therefore should return this
     213          20 :     if (pathParamsPopErrors.values.isNotEmpty) {
     214             :       return pathParamsPopErrors;
     215             :     }
     216             : 
     217             :     // If none of the stackedRoutes popped, this did not pop, and there was no path parameters issue, return not found
     218             :     // This should never happen
     219           6 :     return ErrorNotFoundGetPathFromPopResult();
     220             :   }
     221             : }

Generated by: LCOV version 1.14