-
Notifications
You must be signed in to change notification settings - Fork 41
test(node): add unit tests to node sdk #206
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Lakshan-Chamoditha-Perera
wants to merge
1
commit into
asgardeo:main
Choose a base branch
from
Lakshan-Chamoditha-Perera:node-unit-test
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,41 @@ | ||
|
|
||
| export default { | ||
| preset: 'ts-jest/presets/default-esm', | ||
| testEnvironment: 'node', | ||
| extensionsToTreatAsEsm: ['.ts'], | ||
| moduleNameMapper: { | ||
| '^(\\.{1,2}/.*)\\.js$': '$1', | ||
| }, | ||
| transform: { | ||
| '^.+\\.tsx?$': [ | ||
| 'ts-jest', | ||
| { | ||
| useESM: true, | ||
| tsconfig: { | ||
| module: 'ESNext', | ||
| moduleResolution: 'node', | ||
| esModuleInterop: true, | ||
| }, | ||
| }, | ||
| ], | ||
| }, | ||
| testMatch: ['**/__tests__/**/*.test.ts', '**/__tests__/**/*.spec.ts'], | ||
| collectCoverageFrom: [ | ||
| 'src/**/*.ts', | ||
| '!src/**/*.test.ts', | ||
| '!src/**/*.spec.ts', | ||
| '!src/__tests__/**', | ||
| '!src/__legacy__/**', | ||
| '!src/index.ts', | ||
| ], | ||
| coverageDirectory: 'coverage', | ||
| coverageReporters: ['text', 'html', 'lcov'], | ||
| coverageThreshold: { | ||
| global: { | ||
| lines: 80, | ||
| functions: 60, | ||
| branches: 80, | ||
| statements: 80, | ||
| }, | ||
| }, | ||
| }; |
This file contains hidden or 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
53 changes: 53 additions & 0 deletions
53
packages/node/src/__tests__/constants/CookieConfig.test.ts
This file contains hidden or 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,53 @@ | ||
| import CookieConfig from '../../constants/CookieConfig'; | ||
|
|
||
| /** | ||
| * Test suite for CookieConfig constants | ||
| * Verifies that all cookie configuration constants are correctly defined | ||
| */ | ||
| describe('CookieConfig', () => { | ||
| describe('cookie name constants', () => { | ||
| it('should have correct SESSION_COOKIE_NAME', () => { | ||
| expect(CookieConfig.SESSION_COOKIE_NAME).toBeDefined(); | ||
| expect(CookieConfig.SESSION_COOKIE_NAME).toContain('session'); | ||
| expect(typeof CookieConfig.SESSION_COOKIE_NAME).toBe('string'); | ||
| }); | ||
|
|
||
| it('should have correct TEMP_SESSION_COOKIE_NAME', () => { | ||
| expect(CookieConfig.TEMP_SESSION_COOKIE_NAME).toBeDefined(); | ||
| expect(CookieConfig.TEMP_SESSION_COOKIE_NAME).toContain('temp.session'); | ||
| expect(typeof CookieConfig.TEMP_SESSION_COOKIE_NAME).toBe('string'); | ||
| }); | ||
| }); | ||
|
|
||
| describe('default configuration values', () => { | ||
| it('should have DEFAULT_MAX_AGE of 3600', () => { | ||
| expect(CookieConfig.DEFAULT_MAX_AGE).toBe(3600); | ||
| expect(typeof CookieConfig.DEFAULT_MAX_AGE).toBe('number'); | ||
| }); | ||
|
|
||
| it('should have DEFAULT_HTTP_ONLY as true', () => { | ||
| expect(CookieConfig.DEFAULT_HTTP_ONLY).toBe(true); | ||
| expect(typeof CookieConfig.DEFAULT_HTTP_ONLY).toBe('boolean'); | ||
| }); | ||
|
|
||
| it('should have DEFAULT_SAME_SITE as lax', () => { | ||
| expect(CookieConfig.DEFAULT_SAME_SITE).toBe('lax'); | ||
| expect(typeof CookieConfig.DEFAULT_SAME_SITE).toBe('string'); | ||
| }); | ||
|
|
||
| it('should have DEFAULT_SECURE as true', () => { | ||
| expect(CookieConfig.DEFAULT_SECURE).toBe(true); | ||
| expect(typeof CookieConfig.DEFAULT_SECURE).toBe('boolean'); | ||
| }); | ||
| }); | ||
|
|
||
| describe('class design', () => { | ||
| it('should not be instantiable due to private constructor', () => { | ||
| // This test documents the design intent that CookieConfig cannot be instantiated | ||
| // TypeScript prevents instantiation at compile time with: new CookieConfig() | ||
| // We verify the constructor exists and the class is properly defined | ||
| expect(CookieConfig.constructor).toBeDefined(); | ||
| expect(typeof CookieConfig).toBe('function'); | ||
| }); | ||
| }); | ||
| }); |
This file contains hidden or 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,33 @@ | ||
| import {CookieOptions} from '../../models/cookies'; | ||
|
|
||
| /** | ||
| * Default cookie options matching CookieConfig defaults | ||
| */ | ||
| export const defaultCookieOptions: CookieOptions = { | ||
| httpOnly: true, | ||
| maxAge: 3600, | ||
| sameSite: 'lax', | ||
| secure: true, | ||
| }; | ||
|
|
||
| /** | ||
| * Custom cookie options with non-default values | ||
| */ | ||
| export const customCookieOptions: CookieOptions = { | ||
| httpOnly: false, | ||
| maxAge: 7200, | ||
| sameSite: 'strict', | ||
| secure: false, | ||
| }; | ||
|
|
||
| /** | ||
| * Partial cookie options for testing merging behavior | ||
| */ | ||
| export const partialCookieOptions: Partial<CookieOptions> = { | ||
| maxAge: 1800, | ||
| }; | ||
|
|
||
| /** | ||
| * All possible sameSite variations for testing | ||
| */ | ||
| export const sameSiteVariations = ['strict' as const, 'lax' as const, 'none' as const, true, false]; |
This file contains hidden or 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,59 @@ | ||
| import {jest} from '@jest/globals'; | ||
|
|
||
| type SpyInstance = ReturnType<typeof jest.spyOn>; | ||
|
|
||
| /** | ||
| * Mocks Date constructor to return a specific timestamp | ||
| * | ||
| * @param timestamp - The timestamp value to return from new Date().getTime() | ||
| * @returns Jest spy object for the mocked Date constructor | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const spy = mockDateNow(1234567890); | ||
| * expect(new Date().getTime()).toBe(1234567890); | ||
| * spy.mockRestore(); | ||
| * ``` | ||
| */ | ||
| export const mockDateNow = (timestamp: number): SpyInstance => { | ||
| const spy = jest.spyOn(global, 'Date').mockImplementation( | ||
| () => | ||
| ({ | ||
| getTime: () => timestamp, | ||
| } as any), | ||
| ); | ||
| return spy; | ||
| }; | ||
|
|
||
| /** | ||
| * Mocks Math.random() to return a specific value | ||
| * | ||
| * @param value - The value to return from Math.random() (should be between 0 and 1) | ||
| * @returns Jest spy object for the mocked Math.random() | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * const spy = mockMathRandom(0.5); | ||
| * expect(Math.random()).toBe(0.5); | ||
| * spy.mockRestore(); | ||
| * ``` | ||
| */ | ||
| export const mockMathRandom = (value: number): SpyInstance => { | ||
| const spy = jest.spyOn(Math, 'random'); | ||
| spy.mockReturnValue(value); | ||
| return spy; | ||
| }; | ||
|
|
||
| /** | ||
| * Restores all mocks to their original implementations | ||
| * | ||
| * @example | ||
| * ```ts | ||
| * afterEach(() => { | ||
| * restoreAllMocks(); | ||
| * }); | ||
| * ``` | ||
| */ | ||
| export const restoreAllMocks = (): void => { | ||
| jest.restoreAllMocks(); | ||
| }; |
81 changes: 81 additions & 0 deletions
81
packages/node/src/__tests__/utils/generateSessionId.test.ts
This file contains hidden or 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,81 @@ | ||
| import generateSessionId from '../../utils/generateSessionId'; | ||
| import {mockDateNow, mockMathRandom, restoreAllMocks} from '../helpers/mockHelpers'; | ||
|
|
||
| /** | ||
| * Test suite for generateSessionId utility function | ||
| * Tests the generation of unique session identifiers | ||
| */ | ||
| describe('generateSessionId', () => { | ||
| afterEach(() => { | ||
| restoreAllMocks(); | ||
| }); | ||
|
|
||
| describe('basic functionality', () => { | ||
| it('should return a string', () => { | ||
| const sessionId = generateSessionId(); | ||
|
|
||
| expect(typeof sessionId).toBe('string'); | ||
| expect(sessionId.length).toBeGreaterThan(0); | ||
| }); | ||
| }); | ||
|
|
||
| describe('uniqueness', () => { | ||
| it('should generate unique IDs on multiple calls', () => { | ||
| const ids = new Set<string>(); | ||
| const iterations = 1000; | ||
|
|
||
| for (let i = 0; i < iterations; i++) { | ||
| ids.add(generateSessionId()); | ||
| } | ||
|
|
||
| expect(ids.size).toBe(iterations); | ||
| }); | ||
|
|
||
| it('should generate different IDs in rapid succession', () => { | ||
| const id1 = generateSessionId(); | ||
| const id2 = generateSessionId(); | ||
| const id3 = generateSessionId(); | ||
|
|
||
| expect(id1).not.toBe(id2); | ||
| expect(id2).not.toBe(id3); | ||
| expect(id1).not.toBe(id3); | ||
| }); | ||
| }); | ||
|
|
||
| describe('format and composition', () => { | ||
| it('should contain timestamp component', () => { | ||
| const mockTimestamp = 1234567890000; | ||
| const expectedTimestampPart = mockTimestamp.toString(36); | ||
| mockDateNow(mockTimestamp); | ||
| mockMathRandom(0.5); | ||
|
|
||
| const sessionId = generateSessionId(); | ||
|
|
||
| expect(sessionId).toContain(expectedTimestampPart); | ||
| }); | ||
|
|
||
| it('should contain random component', () => { | ||
| const mockRandomValue = 0.123456789; | ||
| const expectedRandomPart = mockRandomValue.toString(36).substring(2); | ||
| mockDateNow(1000000); | ||
| mockMathRandom(mockRandomValue); | ||
|
|
||
| const sessionId = generateSessionId(); | ||
|
|
||
| expect(sessionId).toContain(expectedRandomPart); | ||
| }); | ||
|
|
||
| it('should combine timestamp and random components', () => { | ||
| const mockTimestamp = 1609459200000; | ||
| const mockRandomValue = 0.987654321; | ||
| const expectedTimestampPart = mockTimestamp.toString(36); | ||
| const expectedRandomPart = mockRandomValue.toString(36).substring(2); | ||
| mockDateNow(mockTimestamp); | ||
| mockMathRandom(mockRandomValue); | ||
|
|
||
| const sessionId = generateSessionId(); | ||
|
|
||
| expect(sessionId).toBe(expectedTimestampPart + expectedRandomPart); | ||
| }); | ||
| }); | ||
| }); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We use
vitestinstead of Jest.Lets utilize that instead.
https://github.com/asgardeo/javascript/blob/52d5d7b987856e4896ea61f58d8d0f37115c82f8/packages/node/vitest.config.tsThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please also check the
Buildfailure and theType Check.