mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	Project health tests (#3028)
This commit is contained in:
		
							parent
							
								
									627958d30f
								
							
						
					
					
						commit
						ab9712812a
					
				
							
								
								
									
										203
									
								
								src/lib/domain/project-health/project-health.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								src/lib/domain/project-health/project-health.test.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,203 @@ | ||||
| import { subDays } from 'date-fns'; | ||||
| import type { IFeatureType } from 'lib/types/stores/feature-type-store'; | ||||
| import { | ||||
|     calculateProjectHealth, | ||||
|     calculateHealthRating, | ||||
| } from './project-health'; | ||||
| 
 | ||||
| const exampleFeatureTypes: IFeatureType[] = [ | ||||
|     { | ||||
|         id: 'default', | ||||
|         name: 'Default', | ||||
|         description: '', | ||||
|         lifetimeDays: 30, | ||||
|     }, | ||||
|     { | ||||
|         id: 'short-lived', | ||||
|         name: 'Short lived', | ||||
|         description: '', | ||||
|         lifetimeDays: 7, | ||||
|     }, | ||||
|     { | ||||
|         id: 'non-expiring', | ||||
|         name: 'Long lived', | ||||
|         description: '', | ||||
|         lifetimeDays: null, | ||||
|     }, | ||||
| ]; | ||||
| 
 | ||||
| describe('calculateProjectHealth', () => { | ||||
|     it('works with empty features', () => { | ||||
|         expect(calculateProjectHealth([], exampleFeatureTypes)).toEqual({ | ||||
|             activeCount: 0, | ||||
|             staleCount: 0, | ||||
|             potentiallyStaleCount: 0, | ||||
|         }); | ||||
|     }); | ||||
| 
 | ||||
|     it('counts active toggles', () => { | ||||
|         const features = [{ stale: false }, {}]; | ||||
| 
 | ||||
|         expect(calculateProjectHealth(features, exampleFeatureTypes)).toEqual({ | ||||
|             activeCount: 2, | ||||
|             staleCount: 0, | ||||
|             potentiallyStaleCount: 0, | ||||
|         }); | ||||
|     }); | ||||
| 
 | ||||
|     it('counts stale toggles', () => { | ||||
|         const features = [{ stale: true }, { stale: false }, {}]; | ||||
| 
 | ||||
|         expect(calculateProjectHealth(features, exampleFeatureTypes)).toEqual({ | ||||
|             activeCount: 2, | ||||
|             staleCount: 1, | ||||
|             potentiallyStaleCount: 0, | ||||
|         }); | ||||
|     }); | ||||
| 
 | ||||
|     it('takes feature type into account when calculating potentially stale toggles', () => { | ||||
|         expect( | ||||
|             calculateProjectHealth( | ||||
|                 [ | ||||
|                     { | ||||
|                         stale: false, | ||||
|                         createdAt: subDays(Date.now(), 15), | ||||
|                         type: 'default', | ||||
|                     }, | ||||
|                 ], | ||||
|                 exampleFeatureTypes, | ||||
|             ), | ||||
|         ).toEqual({ | ||||
|             activeCount: 1, | ||||
|             staleCount: 0, | ||||
|             potentiallyStaleCount: 0, | ||||
|         }); | ||||
| 
 | ||||
|         expect( | ||||
|             calculateProjectHealth( | ||||
|                 [ | ||||
|                     { | ||||
|                         stale: false, | ||||
|                         createdAt: subDays(Date.now(), 31), | ||||
|                         type: 'default', | ||||
|                     }, | ||||
|                 ], | ||||
|                 exampleFeatureTypes, | ||||
|             ), | ||||
|         ).toEqual({ | ||||
|             activeCount: 1, | ||||
|             staleCount: 0, | ||||
|             potentiallyStaleCount: 1, | ||||
|         }); | ||||
| 
 | ||||
|         expect( | ||||
|             calculateProjectHealth( | ||||
|                 [ | ||||
|                     { | ||||
|                         stale: false, | ||||
|                         createdAt: subDays(Date.now(), 15), | ||||
|                         type: 'short-lived', | ||||
|                     }, | ||||
|                 ], | ||||
|                 exampleFeatureTypes, | ||||
|             ), | ||||
|         ).toEqual({ | ||||
|             activeCount: 1, | ||||
|             staleCount: 0, | ||||
|             potentiallyStaleCount: 1, | ||||
|         }); | ||||
|     }); | ||||
| 
 | ||||
|     it("doesn't count stale toggles as potentially stale or stale as active", () => { | ||||
|         const features = [ | ||||
|             { | ||||
|                 stale: true, | ||||
|                 createdAt: subDays(Date.now(), 31), | ||||
|                 type: 'default', | ||||
|             }, | ||||
|             { | ||||
|                 stale: false, | ||||
|                 createdAt: subDays(Date.now(), 31), | ||||
|                 type: 'default', | ||||
|             }, | ||||
|         ]; | ||||
| 
 | ||||
|         expect(calculateProjectHealth(features, exampleFeatureTypes)).toEqual({ | ||||
|             activeCount: 1, | ||||
|             staleCount: 1, | ||||
|             potentiallyStaleCount: 1, | ||||
|         }); | ||||
|     }); | ||||
| 
 | ||||
|     it('counts non-expiring types properly', () => { | ||||
|         const features = [ | ||||
|             { | ||||
|                 createdAt: subDays(Date.now(), 366), | ||||
|                 type: 'non-expiring', | ||||
|             }, | ||||
|             { | ||||
|                 createdAt: subDays(Date.now(), 366), | ||||
|                 type: 'default', | ||||
|             }, | ||||
|         ]; | ||||
| 
 | ||||
|         expect(calculateProjectHealth(features, exampleFeatureTypes)).toEqual({ | ||||
|             activeCount: 2, | ||||
|             staleCount: 0, | ||||
|             potentiallyStaleCount: 1, | ||||
|         }); | ||||
|     }); | ||||
| }); | ||||
| 
 | ||||
| describe('calculateHealthRating', () => { | ||||
|     it('works with empty feature toggles', () => { | ||||
|         expect(calculateHealthRating([], exampleFeatureTypes)).toEqual(100); | ||||
|     }); | ||||
| 
 | ||||
|     it('works with stale and active feature toggles', () => { | ||||
|         expect( | ||||
|             calculateHealthRating( | ||||
|                 [{ stale: true }, { stale: true }], | ||||
|                 exampleFeatureTypes, | ||||
|             ), | ||||
|         ).toEqual(0); | ||||
|         expect( | ||||
|             calculateHealthRating( | ||||
|                 [{ stale: true }, { stale: false }], | ||||
|                 exampleFeatureTypes, | ||||
|             ), | ||||
|         ).toEqual(50); | ||||
|         expect( | ||||
|             calculateHealthRating( | ||||
|                 [{ stale: false }, { stale: true }, { stale: false }], | ||||
|                 exampleFeatureTypes, | ||||
|             ), | ||||
|         ).toEqual(67); | ||||
|     }); | ||||
| 
 | ||||
|     it('counts potentially stale toggles', () => { | ||||
|         expect( | ||||
|             calculateHealthRating( | ||||
|                 [ | ||||
|                     { createdAt: subDays(Date.now(), 1), type: 'default' }, | ||||
|                     { | ||||
|                         stale: true, | ||||
|                         createdAt: subDays(Date.now(), 1), | ||||
|                         type: 'default', | ||||
|                     }, | ||||
|                     { | ||||
|                         stale: true, | ||||
|                         createdAt: subDays(Date.now(), 31), | ||||
|                         type: 'default', | ||||
|                     }, | ||||
|                     { | ||||
|                         stale: false, | ||||
|                         createdAt: subDays(Date.now(), 31), | ||||
|                         type: 'default', | ||||
|                     }, | ||||
|                 ], | ||||
|                 exampleFeatureTypes, | ||||
|             ), | ||||
|         ).toEqual(25); | ||||
|     }); | ||||
| }); | ||||
| @ -2,12 +2,14 @@ import { hoursToMilliseconds } from 'date-fns'; | ||||
| import type { IProjectHealthReport } from 'lib/types'; | ||||
| import type { IFeatureType } from 'lib/types/stores/feature-type-store'; | ||||
| 
 | ||||
| const getPotentiallyStaleCount = ( | ||||
|     features: Array<{ | ||||
| type IPartialFeatures = Array<{ | ||||
|     stale?: boolean; | ||||
|     createdAt?: Date; | ||||
|     type?: string; | ||||
|     }>, | ||||
| }>; | ||||
| 
 | ||||
| const getPotentiallyStaleCount = ( | ||||
|     features: IPartialFeatures, | ||||
|     featureTypes: IFeatureType[], | ||||
| ) => { | ||||
|     const today = new Date().valueOf(); | ||||
| @ -20,17 +22,14 @@ const getPotentiallyStaleCount = ( | ||||
| 
 | ||||
|         return ( | ||||
|             !feature.stale && | ||||
|             featureTypeExpectedLifetime !== null && | ||||
|             diff >= featureTypeExpectedLifetime * hoursToMilliseconds(24) | ||||
|         ); | ||||
|     }).length; | ||||
| }; | ||||
| 
 | ||||
| export const calculateProjectHealth = ( | ||||
|     features: Array<{ | ||||
|         stale?: boolean; | ||||
|         createdAt?: Date; | ||||
|         type?: string; | ||||
|     }>, | ||||
|     features: IPartialFeatures, | ||||
|     featureTypes: IFeatureType[], | ||||
| ): Pick< | ||||
|     IProjectHealthReport, | ||||
| @ -41,12 +40,8 @@ export const calculateProjectHealth = ( | ||||
|     staleCount: features.filter((f) => f.stale).length, | ||||
| }); | ||||
| 
 | ||||
| export const getHealthRating = ( | ||||
|     features: Array<{ | ||||
|         stale?: boolean; | ||||
|         createdAt?: Date; | ||||
|         type?: string; | ||||
|     }>, | ||||
| export const calculateHealthRating = ( | ||||
|     features: IPartialFeatures, | ||||
|     featureTypes: IFeatureType[], | ||||
| ): number => { | ||||
|     const { potentiallyStaleCount, activeCount, staleCount } = | ||||
| @ -11,8 +11,8 @@ import type { IProjectStore } from '../types/stores/project-store'; | ||||
| import ProjectService from './project-service'; | ||||
| import { | ||||
|     calculateProjectHealth, | ||||
|     getHealthRating, | ||||
| } from '../domain/calculate-project-health/calculate-project-health'; | ||||
|     calculateHealthRating, | ||||
| } from '../domain/project-health/project-health'; | ||||
| 
 | ||||
| export default class ProjectHealthService { | ||||
|     private logger: Logger; | ||||
| @ -82,7 +82,7 @@ export default class ProjectHealthService { | ||||
|             archived: false, | ||||
|         }); | ||||
| 
 | ||||
|         return getHealthRating(toggles, this.featureTypes); | ||||
|         return calculateHealthRating(toggles, this.featureTypes); | ||||
|     } | ||||
| 
 | ||||
|     async setHealthRating(): Promise<void> { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user