-
Notifications
You must be signed in to change notification settings - Fork 151
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* test: add keycloak tests Signed-off-by: Paul Schultz <[email protected]> * remove mocking in config.test.ts Signed-off-by: Paul Schultz <[email protected]> * wip tests Signed-off-by: Paul Schultz <[email protected]> * finish keycloak tests Signed-off-by: Paul Schultz <[email protected]> * fix codesmells Signed-off-by: Paul Schultz <[email protected]> * resolve pr comments Signed-off-by: Paul Schultz <[email protected]> --------- Signed-off-by: Paul Schultz <[email protected]>
- Loading branch information
1 parent
e9d7ed5
commit 1872d7c
Showing
7 changed files
with
470 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
export const groups = [ | ||
{ | ||
id: '9cf51b5d-e066-4ed8-940c-dc6da77f81a5', | ||
name: 'biggroup', | ||
path: '/biggroup', | ||
subGroups: [ | ||
{ | ||
id: 'eefa5b46-0509-41d8-b8b3-7ddae9c83632', | ||
name: 'subgroup', | ||
path: '/biggroup/subgroup', | ||
subGroups: [], | ||
}, | ||
], | ||
}, | ||
{ | ||
id: '557501bd-8188-41c0-a2d5-43ff3d5b0258', | ||
name: 'emptygroup', | ||
path: '/emptygroup', | ||
subGroups: [], | ||
}, | ||
{ | ||
id: 'bb10231b-2939-4b1a-b8bb-9249ed7b76f7', | ||
name: 'testgroup', | ||
path: '/testgroup', | ||
subGroups: [], | ||
}, | ||
]; | ||
|
||
export const users = [ | ||
{ | ||
id: '59efec15-a00b-4700-8833-5f4cdecc1132', | ||
createdTimestamp: 1686170983010, | ||
username: 'jamesdoe', | ||
enabled: true, | ||
totp: false, | ||
emailVerified: false, | ||
firstName: '', | ||
lastName: '', | ||
email: '[email protected]', | ||
disableableCredentialTypes: [], | ||
requiredActions: [], | ||
notBefore: 0, | ||
access: { | ||
manageGroupMembership: false, | ||
view: true, | ||
mapRoles: false, | ||
impersonate: false, | ||
manage: false, | ||
}, | ||
}, | ||
{ | ||
id: 'c982b51a-abf6-4f68-bfdf-a1c6257214fc', | ||
createdTimestamp: 1686170953553, | ||
username: 'joedoe', | ||
enabled: true, | ||
totp: false, | ||
emailVerified: false, | ||
firstName: '', | ||
lastName: '', | ||
disableableCredentialTypes: [], | ||
requiredActions: [], | ||
notBefore: 0, | ||
access: { | ||
manageGroupMembership: false, | ||
view: true, | ||
mapRoles: false, | ||
impersonate: false, | ||
manage: false, | ||
}, | ||
}, | ||
{ | ||
id: '2bf97dbd-fd6a-47ae-986b-2632fa95e03f', | ||
createdTimestamp: 1686170890908, | ||
username: 'johndoe', | ||
enabled: true, | ||
totp: false, | ||
emailVerified: false, | ||
firstName: 'John', | ||
lastName: 'Doe', | ||
disableableCredentialTypes: [], | ||
requiredActions: [], | ||
notBefore: 0, | ||
access: { | ||
manageGroupMembership: false, | ||
view: true, | ||
mapRoles: false, | ||
impersonate: false, | ||
manage: false, | ||
}, | ||
}, | ||
]; | ||
|
||
export const groupMembers = [[], [], [], ['jamesdoe', 'joedoe', 'johndoe']]; |
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,44 @@ | ||
import { EntityProviderConnection } from '@backstage/plugin-catalog-backend'; | ||
|
||
import { groupMembers, groups, users } from './data'; | ||
|
||
export const BASIC_VALID_CONFIG = { | ||
catalog: { | ||
providers: { | ||
keycloakOrg: { | ||
default: { | ||
baseUrl: 'http://localhost:8080/auth', | ||
}, | ||
}, | ||
}, | ||
}, | ||
} as const; | ||
|
||
export class KeycloakAdminClientMock { | ||
public constructor() { | ||
return; | ||
} | ||
|
||
users = { | ||
find: jest.fn().mockResolvedValue(users), | ||
count: jest.fn().mockResolvedValue(users.length), | ||
}; | ||
|
||
groups = { | ||
find: jest.fn().mockResolvedValue(groups), | ||
count: jest.fn().mockResolvedValue(groups.length), | ||
listMembers: jest | ||
.fn() | ||
.mockResolvedValueOnce(groupMembers[0]) | ||
.mockResolvedValueOnce(groupMembers[1]) | ||
.mockResolvedValueOnce(groupMembers[2]) | ||
.mockResolvedValueOnce(groupMembers[3]), | ||
}; | ||
|
||
auth = jest.fn().mockResolvedValue({}); | ||
} | ||
|
||
export const connection = { | ||
applyMutation: jest.fn(), | ||
refresh: jest.fn(), | ||
} as unknown as EntityProviderConnection; |
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 |
---|---|---|
@@ -0,0 +1,169 @@ | ||
import { ConfigReader } from '@backstage/config'; | ||
|
||
import deepmerge from 'deepmerge'; | ||
|
||
import { BASIC_VALID_CONFIG } from '../../__fixtures__/helpers'; | ||
import { readProviderConfigs } from './config'; | ||
|
||
describe('readProviderConfigs', () => { | ||
it('should return an empty array if no providers are configured', () => { | ||
const config = new ConfigReader({}); | ||
|
||
const result = readProviderConfigs(config); | ||
|
||
expect(result).toEqual([]); | ||
}); | ||
|
||
it('should return an array of provider configs', () => { | ||
const config = new ConfigReader(BASIC_VALID_CONFIG); | ||
|
||
const result = readProviderConfigs(config); | ||
|
||
expect(result).toEqual([ | ||
{ | ||
id: 'default', | ||
baseUrl: 'http://localhost:8080/auth', | ||
loginRealm: 'master', | ||
realm: 'master', | ||
username: undefined, | ||
password: undefined, | ||
clientId: undefined, | ||
clientSecret: undefined, | ||
schedule: undefined, | ||
userQuerySize: undefined, | ||
groupQuerySize: undefined, | ||
}, | ||
]); | ||
}); | ||
|
||
it('should return an array of provider configs with optional values', () => { | ||
const config = new ConfigReader( | ||
deepmerge(BASIC_VALID_CONFIG, { | ||
catalog: { | ||
providers: { | ||
keycloakOrg: { | ||
default: { | ||
realm: 'myrealm', | ||
loginRealm: 'myloginrealm', | ||
username: 'myusername', | ||
password: 'mypassword', | ||
clientId: 'myclientid', | ||
clientSecret: 'myclientsecret', | ||
userQuerySize: 100, | ||
groupQuerySize: 200, | ||
schedule: { | ||
frequency: { hours: 1 }, | ||
timeout: { minutes: 50 }, | ||
initialDelay: { seconds: 15 }, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
}), | ||
); | ||
|
||
const result = readProviderConfigs(config); | ||
|
||
expect(result).toEqual([ | ||
{ | ||
id: 'default', | ||
baseUrl: 'http://localhost:8080/auth', | ||
loginRealm: 'myloginrealm', | ||
realm: 'myrealm', | ||
username: 'myusername', | ||
password: 'mypassword', | ||
clientId: 'myclientid', | ||
clientSecret: 'myclientsecret', | ||
userQuerySize: 100, | ||
groupQuerySize: 200, | ||
schedule: { | ||
scope: undefined, | ||
frequency: { hours: 1 }, | ||
timeout: { minutes: 50 }, | ||
initialDelay: { seconds: 15 }, | ||
}, | ||
}, | ||
]); | ||
}); | ||
|
||
it('should throw an error if clientId is provided without clientSecret', () => { | ||
const config = new ConfigReader( | ||
deepmerge(BASIC_VALID_CONFIG, { | ||
catalog: { | ||
providers: { | ||
keycloakOrg: { | ||
default: { | ||
clientId: 'myclientid', | ||
}, | ||
}, | ||
}, | ||
}, | ||
}), | ||
); | ||
|
||
expect(() => readProviderConfigs(config)).toThrow( | ||
`clientSecret must be provided when clientId is defined.`, | ||
); | ||
}); | ||
|
||
it('should throw an error if clientSecret is provided without clientId', () => { | ||
const config = new ConfigReader( | ||
deepmerge(BASIC_VALID_CONFIG, { | ||
catalog: { | ||
providers: { | ||
keycloakOrg: { | ||
default: { | ||
clientSecret: 'myclientsecret', | ||
}, | ||
}, | ||
}, | ||
}, | ||
}), | ||
); | ||
|
||
expect(() => readProviderConfigs(config)).toThrow( | ||
`clientId must be provided when clientSecret is defined.`, | ||
); | ||
}); | ||
|
||
it('should throw an error if username is provided without password', () => { | ||
const config = new ConfigReader( | ||
deepmerge(BASIC_VALID_CONFIG, { | ||
catalog: { | ||
providers: { | ||
keycloakOrg: { | ||
default: { | ||
username: 'myusername', | ||
}, | ||
}, | ||
}, | ||
}, | ||
}), | ||
); | ||
|
||
expect(() => readProviderConfigs(config)).toThrow( | ||
`password must be provided when username is defined.`, | ||
); | ||
}); | ||
|
||
it('should throw an error if password is provided without username', () => { | ||
const config = new ConfigReader( | ||
deepmerge(BASIC_VALID_CONFIG, { | ||
catalog: { | ||
providers: { | ||
keycloakOrg: { | ||
default: { | ||
password: 'mypassword', | ||
}, | ||
}, | ||
}, | ||
}, | ||
}), | ||
); | ||
|
||
expect(() => readProviderConfigs(config)).toThrow( | ||
`username must be provided when password is defined.`, | ||
); | ||
}); | ||
}); |
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,21 @@ | ||
import KcAdminClient from '@keycloak/keycloak-admin-client'; | ||
|
||
import { KeycloakAdminClientMock } from '../../__fixtures__/helpers'; | ||
import { KeycloakProviderConfig } from './config'; | ||
import { readKeycloakRealm } from './read'; | ||
|
||
const config: KeycloakProviderConfig = { | ||
realm: 'myrealm', | ||
id: 'mock_id', | ||
baseUrl: 'http://mock-url', | ||
}; | ||
|
||
describe('readKeycloakRealm', () => { | ||
it('should return the correct number of users and groups', async () => { | ||
const client = new KeycloakAdminClientMock() as unknown as KcAdminClient; | ||
const { users, groups } = await readKeycloakRealm(client, config); | ||
|
||
expect(users).toHaveLength(3); | ||
expect(groups).toHaveLength(4); | ||
}); | ||
}); |
Oops, something went wrong.