-
-
Notifications
You must be signed in to change notification settings - Fork 215
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add unit tests to the module to be able to add vue-oauth2-keycl…
…oak module at the ci pipeline
- Loading branch information
1 parent
b54516d
commit c0b0d99
Showing
6 changed files
with
318 additions
and
1 deletion.
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
99 changes: 99 additions & 0 deletions
99
...pp/test/webapp/unit/auth/infrastructure/secondary/KeycloakAuthRepository.spec.ts.mustache
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,99 @@ | ||
import { describe, it, expect, beforeEach } from 'vitest'; | ||
import { KeycloakAuthRepository } from '@/auth/infrastructure/secondary/KeycloakAuthRepository'; | ||
import type { KeycloakHttpStub } from './KeycloakHttpStub'; | ||
import { stubKeycloakHttp, fakeAuthenticatedUser } from './KeycloakHttpStub'; | ||
|
||
describe('KeycloakAuthRepository', () => { | ||
let keycloakHttpStub: KeycloakHttpStub; | ||
let authRepository: KeycloakAuthRepository; | ||
beforeEach(() => { | ||
keycloakHttpStub = stubKeycloakHttp(); | ||
authRepository = new KeycloakAuthRepository(keycloakHttpStub); | ||
}); | ||
|
||
it('should authenticate a user', async () => { | ||
const mockUser = fakeAuthenticatedUser(); | ||
keycloakHttpStub.currentUser.resolves(mockUser); | ||
const user = await authRepository.currentUser(); | ||
expect(user).toEqual(mockUser); | ||
expect(keycloakHttpStub.currentUser.calledOnce).toBe(true); | ||
}); | ||
|
||
it('should propagate error when currentUser fails', async () => { | ||
const error = new Error('Authentication failed'); | ||
keycloakHttpStub.currentUser.rejects(error); | ||
await expect(authRepository.currentUser()).rejects.toThrow('Authentication failed'); | ||
expect(keycloakHttpStub.currentUser.calledOnce).toBe(true); | ||
}); | ||
|
||
it('should login a user successfully', async () => { | ||
keycloakHttpStub.login.resolves(); | ||
await authRepository.login(); | ||
expect(keycloakHttpStub.login.calledOnce).toBe(true); | ||
}); | ||
|
||
it('should propagate error when login fails', async () => { | ||
const error = new Error('Login failed'); | ||
keycloakHttpStub.login.rejects(error); | ||
await expect(authRepository.login()).rejects.toThrow('Login failed'); | ||
expect(keycloakHttpStub.login.calledOnce).toBe(true); | ||
}); | ||
|
||
it('should logout a user', async () => { | ||
keycloakHttpStub.logout.resolves(); | ||
await authRepository.logout(); | ||
expect(keycloakHttpStub.logout.calledOnce).toBe(true); | ||
}); | ||
|
||
it('should propagate error when logout fails', async () => { | ||
const error = new Error('Logout failed'); | ||
keycloakHttpStub.logout.rejects(error); | ||
await expect(authRepository.logout()).rejects.toThrow('Logout failed'); | ||
expect(keycloakHttpStub.logout.calledOnce).toBe(true); | ||
}); | ||
|
||
it('should check if a user is authenticated', async () => { | ||
keycloakHttpStub.authenticated.resolves(true); | ||
const isAuthenticated = await authRepository.authenticated(); | ||
expect(isAuthenticated).toBe(true); | ||
expect(keycloakHttpStub.authenticated.calledOnce).toBe(true); | ||
}); | ||
|
||
it('should propagate error when authenticated check fails', async () => { | ||
const error = new Error('Authentication check failed'); | ||
keycloakHttpStub.authenticated.rejects(error); | ||
await expect(authRepository.authenticated()).rejects.toThrow('Authentication check failed'); | ||
expect(keycloakHttpStub.authenticated.calledOnce).toBe(true); | ||
}); | ||
|
||
it('should refresh the token', async () => { | ||
const newToken = 'new-test-token'; | ||
keycloakHttpStub.refreshToken.resolves(newToken); | ||
const refreshedToken = await authRepository.refreshToken(); | ||
expect(refreshedToken).toBe(newToken); | ||
expect(keycloakHttpStub.refreshToken.calledOnce).toBe(true); | ||
}); | ||
|
||
it('should propagate error when refreshToken fails', async () => { | ||
const error = new Error('Token refresh failed'); | ||
keycloakHttpStub.refreshToken.rejects(error); | ||
await expect(authRepository.refreshToken()).rejects.toThrow('Token refresh failed'); | ||
expect(keycloakHttpStub.refreshToken.calledOnce).toBe(true); | ||
}); | ||
}); |
139 changes: 139 additions & 0 deletions
139
...e/webapp/app/test/webapp/unit/auth/infrastructure/secondary/KeycloakHttp.spec.ts.mustache
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,139 @@ | ||
import { describe, it, expect } from 'vitest'; | ||
import { KeycloakHttp } from '@/auth/infrastructure/secondary/KeycloakHttp'; | ||
import { stubKeycloak } from './KeycloakStub'; | ||
import { fakeAuthenticatedUser } from './KeycloakHttpStub'; | ||
|
||
const createKeycloakHttp = () => { | ||
const keycloakStub = stubKeycloak(); | ||
const keycloakHttp = new KeycloakHttp(keycloakStub); | ||
return { keycloakStub, keycloakHttp }; | ||
}; | ||
|
||
describe('KeycloakHttp', () => { | ||
describe('Authentication', () => { | ||
it('should authenticate successfully', async () => { | ||
const { keycloakStub, keycloakHttp } = createKeycloakHttp(); | ||
const fakeUser = fakeAuthenticatedUser(); | ||
keycloakStub.init.resolves(true); | ||
keycloakStub.authenticated = true; | ||
keycloakStub.tokenParsed = { preferred_username: fakeUser.username }; | ||
keycloakStub.token = fakeUser.token; | ||
|
||
const result = await keycloakHttp.currentUser(); | ||
|
||
expect(result).toEqual(fakeUser); | ||
expect(keycloakStub.init.calledOnce).toBe(true); | ||
}); | ||
|
||
it('should handle authentication failure', async () => { | ||
const { keycloakStub, keycloakHttp } = createKeycloakHttp(); | ||
keycloakStub.init.resolves(false); | ||
|
||
const result = await keycloakHttp.currentUser(); | ||
|
||
expect(result).toEqual({ isAuthenticated: false, username: '', token: '' }); | ||
expect(keycloakStub.init.calledOnce).toBe(true); | ||
}); | ||
}); | ||
|
||
describe('Initialization', () => { | ||
it('should not reinitialize if already initialized', async () => { | ||
const { keycloakStub, keycloakHttp } = createKeycloakHttp(); | ||
keycloakStub.init.resolves(true); | ||
|
||
await keycloakHttp.currentUser(); | ||
await keycloakHttp.currentUser(); | ||
|
||
expect(keycloakStub.init.calledOnce).toBe(true); | ||
}); | ||
|
||
it('should initialize only once across different method calls', async () => { | ||
const { keycloakStub, keycloakHttp } = createKeycloakHttp(); | ||
keycloakStub.init.resolves(true); | ||
|
||
await keycloakHttp.currentUser(); | ||
await keycloakHttp.login(); | ||
await keycloakHttp.logout(); | ||
await keycloakHttp.authenticated(); | ||
await keycloakHttp.refreshToken(); | ||
|
||
expect(keycloakStub.init.calledOnce).toBe(true); | ||
}); | ||
}); | ||
|
||
it('should handle undefined preferred_username', async () => { | ||
const { keycloakStub, keycloakHttp } = createKeycloakHttp(); | ||
keycloakStub.init.resolves(true); | ||
keycloakStub.authenticated = true; | ||
keycloakStub.tokenParsed = {}; | ||
keycloakStub.token = 'test-token'; | ||
|
||
const result = await keycloakHttp.currentUser(); | ||
|
||
expect(result).toEqual({ | ||
isAuthenticated: true, | ||
username: '', | ||
token: 'test-token' | ||
}); | ||
}); | ||
|
||
it('should handle undefined token', async () => { | ||
const { keycloakStub, keycloakHttp } = createKeycloakHttp(); | ||
keycloakStub.init.resolves(true); | ||
keycloakStub.authenticated = true; | ||
keycloakStub.tokenParsed = { preferred_username: 'test' }; | ||
keycloakStub.token = undefined; | ||
|
||
const result = await keycloakHttp.currentUser(); | ||
|
||
expect(result).toEqual({ | ||
isAuthenticated: true, | ||
username: 'test', | ||
token: '' | ||
}); | ||
}); | ||
|
||
it('should logout', async () => { | ||
const { keycloakStub, keycloakHttp } = createKeycloakHttp(); | ||
keycloakStub.logout.resolves(); | ||
|
||
await keycloakHttp.logout(); | ||
|
||
expect(keycloakStub.logout.calledOnce).toBe(true); | ||
}); | ||
|
||
it('should check if authenticated', async () => { | ||
const { keycloakStub, keycloakHttp } = createKeycloakHttp(); | ||
keycloakStub.init.resolves(true); | ||
keycloakStub.authenticated = true; | ||
keycloakStub.token = 'valid-token'; | ||
|
||
const result = await keycloakHttp.authenticated(); | ||
|
||
expect(result).toBe(true); | ||
expect(keycloakStub.init.calledOnce).toBe(true); | ||
}); | ||
|
||
it('should refresh token', async () => { | ||
const { keycloakStub, keycloakHttp } = createKeycloakHttp(); | ||
const newToken = 'new-test-token'; | ||
keycloakStub.updateToken.resolves(); | ||
keycloakStub.token = newToken; | ||
|
||
const result = await keycloakHttp.refreshToken(); | ||
|
||
expect(result).toBe(newToken); | ||
expect(keycloakStub.updateToken.calledOnce).toBe(true); | ||
}); | ||
}); | ||
|
||
it('should login successfully', async () => { | ||
const { keycloakStub, keycloakHttp } = createKeycloakHttp(); | ||
keycloakStub.init.resolves(true); | ||
keycloakStub.login.resolves(); | ||
|
||
await keycloakHttp.login(); | ||
|
||
expect(keycloakStub.init.calledOnce).toBe(true); | ||
expect(keycloakStub.login.calledOnce).toBe(true); | ||
}); |
28 changes: 28 additions & 0 deletions
28
...ue/webapp/app/test/webapp/unit/auth/infrastructure/secondary/KeycloakHttpStub.ts.mustache
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,28 @@ | ||
import sinon from 'sinon'; | ||
import type { SinonStub } from 'sinon'; | ||
import type { KeycloakHttp } from '@/auth/infrastructure/secondary/KeycloakHttp'; | ||
import type { AuthenticatedUser } from '@/auth/domain/AuthenticatedUser'; | ||
|
||
export interface KeycloakHttpStub extends KeycloakHttp { | ||
currentUser: SinonStub; | ||
login: SinonStub; | ||
logout: SinonStub; | ||
authenticated: SinonStub; | ||
refreshToken: SinonStub; | ||
getKeycloakInstance: SinonStub; | ||
} | ||
|
||
export const stubKeycloakHttp = (): KeycloakHttpStub => ({ | ||
currentUser: sinon.stub(), | ||
login: sinon.stub(), | ||
logout: sinon.stub(), | ||
authenticated: sinon.stub(), | ||
refreshToken: sinon.stub(), | ||
getKeycloakInstance: sinon.stub(), | ||
}) as KeycloakHttpStub; | ||
|
||
export const fakeAuthenticatedUser = (): AuthenticatedUser => ({ | ||
isAuthenticated: true, | ||
username: 'testuser', | ||
token: 'test-token' | ||
}); |
37 changes: 37 additions & 0 deletions
37
...nt/vue/webapp/app/test/webapp/unit/auth/infrastructure/secondary/KeycloakStub.ts.mustache
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,37 @@ | ||
import Keycloak from 'keycloak-js'; | ||
import sinon from 'sinon'; | ||
import type{ SinonStub } from 'sinon'; | ||
|
||
export interface KeycloakStub extends Keycloak { | ||
init: SinonStub; | ||
login: SinonStub; | ||
logout: SinonStub; | ||
register: SinonStub; | ||
accountManagement: SinonStub; | ||
updateToken: SinonStub; | ||
clearToken: SinonStub; | ||
hasRealmRole: SinonStub; | ||
hasResourceRole: SinonStub; | ||
loadUserProfile: SinonStub; | ||
loadUserInfo: SinonStub; | ||
authenticated?: boolean; | ||
token?: string; | ||
tokenParsed?: { preferred_username?: string }; | ||
} | ||
|
||
export const stubKeycloak = (): KeycloakStub => ({ | ||
init: sinon.stub(), | ||
login: sinon.stub(), | ||
logout: sinon.stub(), | ||
register: sinon.stub(), | ||
accountManagement: sinon.stub(), | ||
updateToken: sinon.stub(), | ||
clearToken: sinon.stub(), | ||
hasRealmRole: sinon.stub(), | ||
hasResourceRole: sinon.stub(), | ||
loadUserProfile: sinon.stub(), | ||
loadUserInfo: sinon.stub(), | ||
authenticated: false, | ||
token: undefined, | ||
tokenParsed: undefined, | ||
}) as KeycloakStub; |
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