-
Notifications
You must be signed in to change notification settings - Fork 39
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' into feat/job-launcher-server/abuse
- Loading branch information
Showing
300 changed files
with
9,473 additions
and
5,386 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,4 +11,4 @@ jobs: | |
- name: "Checkout Repository" | ||
uses: actions/[email protected] | ||
- name: "Dependency Review" | ||
uses: actions/dependency-review-action@v4.4.0 | ||
uses: actions/dependency-review-action@v4.5.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -35,4 +35,7 @@ lerna-debug.log* | |
!.vscode/extensions.json | ||
|
||
# Redis Data | ||
/redis_data | ||
/redis_data | ||
|
||
.env.development | ||
.env.production |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
version: '3.8' | ||
name: 'dashboard-server' | ||
|
||
services: | ||
redis: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
module.exports = { | ||
coverageDirectory: '../coverage', | ||
collectCoverageFrom: ['**/*.(t|j)s'], | ||
moduleFileExtensions: ['js', 'json', 'ts'], | ||
rootDir: 'src', | ||
testEnvironment: 'node', | ||
testRegex: '.*\\.spec\\.ts$', | ||
transform: { | ||
'^.+\\.(t)s$': 'ts-jest', | ||
}, | ||
moduleNameMapper: { | ||
'^uuid$': require.resolve('uuid'), | ||
'^typeorm$': require.resolve('typeorm'), | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
217 changes: 217 additions & 0 deletions
217
packages/apps/dashboard/server/src/common/config/network-config.service.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
import { createMock } from '@golevelup/ts-jest'; | ||
import { Test, TestingModule } from '@nestjs/testing'; | ||
import { CACHE_MANAGER } from '@nestjs/cache-manager'; | ||
import { Cache } from 'cache-manager'; | ||
import { Logger } from '@nestjs/common'; | ||
import { StatisticsClient } from '@human-protocol/sdk'; | ||
import { EnvironmentConfigService } from '../../common/config/env-config.service'; | ||
import { ChainId, NETWORKS } from '@human-protocol/sdk'; | ||
import { MainnetsId } from '../../common/utils/constants'; | ||
import { HttpService } from '@nestjs/axios'; | ||
import { NetworkConfigService } from './network-config.service'; | ||
import { ConfigService } from '@nestjs/config'; | ||
|
||
jest.mock('@human-protocol/sdk', () => ({ | ||
...jest.requireActual('@human-protocol/sdk'), | ||
StatisticsClient: jest.fn(), | ||
})); | ||
|
||
describe('NetworkConfigService', () => { | ||
let networkConfigService: NetworkConfigService; | ||
let cacheManager: Cache; | ||
|
||
beforeEach(async () => { | ||
const module: TestingModule = await Test.createTestingModule({ | ||
providers: [ | ||
NetworkConfigService, | ||
{ provide: HttpService, useValue: createMock<HttpService>() }, | ||
{ | ||
provide: CACHE_MANAGER, | ||
useValue: { | ||
get: jest.fn(), | ||
set: jest.fn(), | ||
}, | ||
}, | ||
{ | ||
provide: EnvironmentConfigService, | ||
useValue: { | ||
networkUsageFilterMonths: 3, | ||
networkAvailableCacheTtl: 1000, | ||
}, | ||
}, | ||
ConfigService, | ||
Logger, | ||
], | ||
}).compile(); | ||
|
||
networkConfigService = | ||
module.get<NetworkConfigService>(NetworkConfigService); | ||
cacheManager = module.get<Cache>(CACHE_MANAGER); | ||
}); | ||
|
||
it('should regenerate network list when cache TTL expires', async () => { | ||
const mockNetworkList = [ | ||
ChainId.MAINNET, | ||
ChainId.BSC_MAINNET, | ||
ChainId.POLYGON, | ||
ChainId.XLAYER, | ||
ChainId.MOONBEAM, | ||
ChainId.CELO, | ||
ChainId.AVALANCHE, | ||
]; | ||
|
||
// Step 1: Initial request - populate cache | ||
jest.spyOn(cacheManager, 'get').mockResolvedValue(null); | ||
jest.spyOn(cacheManager, 'set').mockResolvedValue(undefined); | ||
|
||
const mockStatisticsClient = { | ||
getHMTDailyData: jest | ||
.fn() | ||
.mockResolvedValue([{ totalTransactionCount: 7 }]), | ||
getEscrowStatistics: jest.fn().mockResolvedValue({ totalEscrows: 1 }), | ||
}; | ||
(StatisticsClient as jest.Mock).mockImplementation( | ||
() => mockStatisticsClient, | ||
); | ||
|
||
// First call should populate cache | ||
const firstCallResult = await networkConfigService.getAvailableNetworks(); | ||
|
||
expect(firstCallResult).toEqual(mockNetworkList); | ||
expect(cacheManager.set).toHaveBeenCalledWith( | ||
'available-networks', | ||
mockNetworkList, | ||
1000, | ||
); | ||
|
||
// Step 2: Simulate TTL expiration by returning null from cache | ||
jest.spyOn(cacheManager, 'get').mockResolvedValueOnce(null); | ||
|
||
// Second call after TTL should re-generate the network list | ||
const secondCallResult = await networkConfigService.getAvailableNetworks(); | ||
expect(secondCallResult).toEqual(mockNetworkList); | ||
|
||
// Ensure the cache is set again with the regenerated network list | ||
expect(cacheManager.set).toHaveBeenCalledWith( | ||
'available-networks', | ||
mockNetworkList, | ||
1000, | ||
); | ||
}); | ||
|
||
it('should return cached networks if available', async () => { | ||
const cachedNetworks = [ChainId.MAINNET, ChainId.POLYGON]; | ||
jest.spyOn(cacheManager, 'get').mockResolvedValue(cachedNetworks); | ||
|
||
const result = await networkConfigService.getAvailableNetworks(); | ||
expect(result).toEqual(cachedNetworks); | ||
expect(cacheManager.get).toHaveBeenCalledWith('available-networks'); | ||
}); | ||
|
||
it('should fetch and filter available networks correctly', async () => { | ||
jest.spyOn(cacheManager, 'get').mockResolvedValue(null); | ||
const mockStatisticsClient = { | ||
getHMTDailyData: jest | ||
.fn() | ||
.mockResolvedValue([ | ||
{ totalTransactionCount: 4 }, | ||
{ totalTransactionCount: 3 }, | ||
]), | ||
getEscrowStatistics: jest.fn().mockResolvedValue({ totalEscrows: 1 }), | ||
}; | ||
(StatisticsClient as jest.Mock).mockImplementation( | ||
() => mockStatisticsClient, | ||
); | ||
|
||
const result = await networkConfigService.getAvailableNetworks(); | ||
expect(result).toEqual( | ||
expect.arrayContaining([ChainId.MAINNET, ChainId.POLYGON]), | ||
); | ||
|
||
expect(cacheManager.set).toHaveBeenCalledWith( | ||
'available-networks', | ||
result, | ||
1000, | ||
); | ||
}); | ||
|
||
it('should exclude networks without sufficient HMT transfers', async () => { | ||
jest.spyOn(cacheManager, 'get').mockResolvedValue(null); | ||
const mockStatisticsClient = { | ||
getHMTDailyData: jest | ||
.fn() | ||
.mockResolvedValue([{ totalTransactionCount: 2 }]), | ||
getEscrowStatistics: jest.fn().mockResolvedValue({ totalEscrows: 1 }), | ||
}; | ||
(StatisticsClient as jest.Mock).mockImplementation( | ||
() => mockStatisticsClient, | ||
); | ||
|
||
const result = await networkConfigService.getAvailableNetworks(); | ||
expect(result).toEqual([]); | ||
}); | ||
|
||
it('should handle missing network configuration gracefully', async () => { | ||
jest.spyOn(cacheManager, 'get').mockResolvedValue(null); | ||
|
||
const originalNetworkConfig = NETWORKS[MainnetsId.MAINNET]; | ||
NETWORKS[MainnetsId.MAINNET] = undefined; | ||
|
||
const mockStatisticsClient = { | ||
getHMTDailyData: jest | ||
.fn() | ||
.mockResolvedValue([ | ||
{ totalTransactionCount: 3 }, | ||
{ totalTransactionCount: 3 }, | ||
]), | ||
getEscrowStatistics: jest.fn().mockResolvedValue({ totalEscrows: 1 }), | ||
}; | ||
(StatisticsClient as jest.Mock).mockImplementation( | ||
() => mockStatisticsClient, | ||
); | ||
|
||
const result = await networkConfigService.getAvailableNetworks(); | ||
|
||
expect(result).not.toContain(MainnetsId.MAINNET); | ||
expect(result).toEqual(expect.arrayContaining([])); | ||
|
||
NETWORKS[MainnetsId.MAINNET] = originalNetworkConfig; | ||
}); | ||
|
||
it('should handle errors in getHMTDailyData gracefully', async () => { | ||
jest.spyOn(cacheManager, 'get').mockResolvedValue(null); | ||
const mockStatisticsClient = { | ||
getHMTDailyData: jest | ||
.fn() | ||
.mockRejectedValue(new Error('Failed to fetch HMT data')), | ||
getEscrowStatistics: jest.fn().mockResolvedValue({ totalEscrows: 1 }), | ||
}; | ||
(StatisticsClient as jest.Mock).mockImplementation( | ||
() => mockStatisticsClient, | ||
); | ||
|
||
const result = await networkConfigService.getAvailableNetworks(); | ||
expect(result).toEqual([]); | ||
}); | ||
|
||
it('should handle errors in getEscrowStatistics gracefully', async () => { | ||
jest.spyOn(cacheManager, 'get').mockResolvedValue(null); | ||
const mockStatisticsClient = { | ||
getHMTDailyData: jest | ||
.fn() | ||
.mockResolvedValue([ | ||
{ totalTransactionCount: 3 }, | ||
{ totalTransactionCount: 2 }, | ||
]), | ||
getEscrowStatistics: jest | ||
.fn() | ||
.mockRejectedValue(new Error('Failed to fetch escrow stats')), | ||
}; | ||
(StatisticsClient as jest.Mock).mockImplementation( | ||
() => mockStatisticsClient, | ||
); | ||
|
||
const result = await networkConfigService.getAvailableNetworks(); | ||
expect(result).toEqual([]); | ||
}); | ||
}); |
Oops, something went wrong.