mirror of
https://github.com/keycloak/keycloak.git
synced 2025-12-17 04:24:48 -06:00
Enable unit tests for keycloak-admin-client
Closes #44268 Signed-off-by: rmartinc <rmartinc@redhat.com>
This commit is contained in:
37
.github/workflows/js-ci.yml
vendored
37
.github/workflows/js-ci.yml
vendored
@@ -260,6 +260,42 @@ jobs:
|
||||
name: admin-ui-server-log-${{ matrix.browser }}
|
||||
path: ~/server.log
|
||||
|
||||
keycloak-admin-client:
|
||||
name: Keycloak Admin Client
|
||||
needs:
|
||||
- conditional
|
||||
- build-keycloak
|
||||
if: needs.conditional.outputs.js-ci == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
WORKSPACE: "@keycloak/keycloak-admin-client"
|
||||
RETRY_COUNT: 3
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
|
||||
- name: Download Keycloak server
|
||||
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
|
||||
with:
|
||||
name: keycloak
|
||||
|
||||
- name: Setup Java
|
||||
uses: ./.github/actions/java-setup
|
||||
|
||||
- name: Start Keycloak server
|
||||
run: |
|
||||
tar xfvz keycloak-999.0.0-SNAPSHOT.tar.gz
|
||||
keycloak-999.0.0-SNAPSHOT/bin/kc.sh start-dev --http-port 8180 --features transient-users,oid4vc-vci,declarative-ui,quick-theme,spiffe,kubernetes-service-accounts,workflows,client-auth-federated,jwt-authorization-grant &> ~/server.log &
|
||||
curl --connect-timeout 5 --max-time 10 --retry 10 --retry-all-errors --retry-delay 10 --retry-max-time 120 -s -o /dev/null http://127.0.0.1:8180
|
||||
env:
|
||||
KC_BOOTSTRAP_ADMIN_USERNAME: admin
|
||||
KC_BOOTSTRAP_ADMIN_PASSWORD: admin
|
||||
|
||||
- uses: ./.github/actions/pnpm-setup
|
||||
|
||||
- name: Run tests
|
||||
run: pnpm --fail-if-no-match --filter ${{ env.WORKSPACE }} run test
|
||||
working-directory: js
|
||||
|
||||
check:
|
||||
name: Status Check - Keycloak JavaScript CI
|
||||
if: always()
|
||||
@@ -272,6 +308,7 @@ jobs:
|
||||
- account-ui-e2e
|
||||
- admin-ui
|
||||
- admin-ui-e2e
|
||||
- keycloak-admin-client
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
|
||||
@@ -110,13 +110,19 @@ To build the source do a build:
|
||||
pnpm build
|
||||
```
|
||||
|
||||
Start the Keycloak server:
|
||||
Start the Keycloak server in development mode using port 8180. See the instructions in the [Keycloak server app](../../apps/keycloak-server/README.md).
|
||||
|
||||
```bash
|
||||
pnpm server:start
|
||||
cd ../../apps/keycloak-server
|
||||
pnpm start --http-port 8180
|
||||
```
|
||||
|
||||
If you started your container manually make sure there is an admin user named `admin` with password `admin`, the server is started in development mode using port 8180 and the required features are enabled.
|
||||
|
||||
```bash
|
||||
./kc.sh start-dev --http-port 8180 --features transient-users,oid4vc-vci,declarative-ui,quick-theme,spiffe,kubernetes-service-accounts,workflows,client-auth-federated,jwt-authorization-grant
|
||||
```
|
||||
|
||||
If you started your container manually make sure there is an admin user named 'admin' with password 'admin'.
|
||||
Then start the tests with:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -34,6 +34,8 @@ describe("Attack Detection", () => {
|
||||
disabled: false,
|
||||
lastIPFailure: "n/a",
|
||||
lastFailure: 0,
|
||||
numTemporaryLockouts: 0,
|
||||
failedLoginNotBefore: 0,
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -42,6 +42,10 @@ describe("Authorization", () => {
|
||||
"idToken",
|
||||
);
|
||||
|
||||
expect(data.scope).to.equal("openid email profile");
|
||||
expect(data.scope.split(" ")).to.have.members([
|
||||
"openid",
|
||||
"email",
|
||||
"profile",
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -153,7 +153,7 @@ describe("Authentication management", () => {
|
||||
|
||||
expect(actionConfig).is.ok;
|
||||
expect(actionConfig.config).is.ok;
|
||||
expect(actionConfig.config!["max_auth_age"]).to.be.eq(300); // default max_auth_age for update password
|
||||
expect(actionConfig.config!["max_auth_age"]).to.be.undefined; // default max_auth_age for update password
|
||||
});
|
||||
|
||||
it("should update required action config for update password", async () => {
|
||||
@@ -175,7 +175,7 @@ describe("Authentication management", () => {
|
||||
|
||||
expect(actionConfig).is.ok;
|
||||
expect(actionConfig.config).is.ok;
|
||||
expect(actionConfig.config!["max_auth_age"]).to.be.eq(301); // updated value max_auth_age for update password
|
||||
expect(actionConfig.config!["max_auth_age"]).to.be.eq("301"); // updated value max_auth_age for update password
|
||||
});
|
||||
|
||||
it("should reset required action config for update password", async () => {
|
||||
@@ -190,7 +190,7 @@ describe("Authentication management", () => {
|
||||
|
||||
expect(actionConfig).is.ok;
|
||||
expect(actionConfig.config).is.ok;
|
||||
expect(actionConfig.config!["max_auth_age"]).to.be.eq(300); // default max_auth_age for update password
|
||||
expect(actionConfig.config!["max_auth_age"]).to.be.undefined; // default max_auth_age for update password
|
||||
});
|
||||
|
||||
it("should get client authenticator providers", async () => {
|
||||
@@ -198,14 +198,14 @@ describe("Authentication management", () => {
|
||||
await kcAdminClient.authenticationManagement.getClientAuthenticatorProviders();
|
||||
|
||||
expect(authenticationProviders).is.ok;
|
||||
expect(authenticationProviders.length).to.be.equal(4);
|
||||
expect(authenticationProviders.length).to.be.equal(5);
|
||||
});
|
||||
|
||||
it("should fetch form providers", async () => {
|
||||
const formProviders =
|
||||
await kcAdminClient.authenticationManagement.getFormActionProviders();
|
||||
expect(formProviders).is.ok;
|
||||
expect(formProviders.length).to.be.eq(4);
|
||||
expect(formProviders.length).to.be.eq(5);
|
||||
});
|
||||
|
||||
it("should fetch authenticator providers", async () => {
|
||||
@@ -279,11 +279,13 @@ describe("Authentication management", () => {
|
||||
const flow = flows.find((f) => f.alias === flowName)!;
|
||||
const description = "Updated description";
|
||||
flow.description = description;
|
||||
const updatedFlow =
|
||||
await kcAdminClient.authenticationManagement.updateFlow(
|
||||
{ flowId: flow.id! },
|
||||
flow,
|
||||
);
|
||||
await kcAdminClient.authenticationManagement.updateFlow(
|
||||
{ flowId: flow.id! },
|
||||
flow,
|
||||
);
|
||||
const updatedFlow = await kcAdminClient.authenticationManagement.getFlow({
|
||||
flowId: flow.id!,
|
||||
});
|
||||
|
||||
expect(updatedFlow.description).to.be.eq(description);
|
||||
});
|
||||
|
||||
@@ -23,6 +23,7 @@ describe("Client Scopes", () => {
|
||||
currentClientScopeName = "best-of-the-bests-scope";
|
||||
await kcAdminClient.clientScopes.create({
|
||||
name: currentClientScopeName,
|
||||
protocol: "openid-connect",
|
||||
});
|
||||
currentClientScope = (await kcAdminClient.clientScopes.findOneByName({
|
||||
name: currentClientScopeName,
|
||||
@@ -75,6 +76,7 @@ describe("Client Scopes", () => {
|
||||
|
||||
await kcAdminClient.clientScopes.create({
|
||||
name: currentClientScopeName,
|
||||
protocol: "openid-connect",
|
||||
});
|
||||
|
||||
const scope = (await kcAdminClient.clientScopes.findOneByName({
|
||||
@@ -96,6 +98,7 @@ describe("Client Scopes", () => {
|
||||
|
||||
const { id } = await kcAdminClient.clientScopes.create({
|
||||
name: currentClientScopeName,
|
||||
protocol: "openid-connect",
|
||||
});
|
||||
|
||||
const scope = (await kcAdminClient.clientScopes.findOne({
|
||||
|
||||
@@ -746,7 +746,7 @@ describe("Clients", () => {
|
||||
});
|
||||
|
||||
expect(roles).to.be.ok;
|
||||
expect(roles.length).to.be.eq(5);
|
||||
expect(roles.length).to.be.eq(6);
|
||||
});
|
||||
|
||||
it("get list of all protocol mappers", async () => {
|
||||
@@ -771,6 +771,7 @@ describe("Clients", () => {
|
||||
id: clientUniqueId!,
|
||||
userId: user.id,
|
||||
scope: "openid",
|
||||
audience: "",
|
||||
});
|
||||
const idToken = await kcAdminClient.clients.evaluateGenerateIdToken({
|
||||
id: clientUniqueId!,
|
||||
@@ -1099,30 +1100,6 @@ describe("Clients", () => {
|
||||
expect(result).to.deep.equal([]);
|
||||
});
|
||||
|
||||
it("list permission scope", async () => {
|
||||
permission = await kcAdminClient.clients.createPermission(
|
||||
{
|
||||
id: currentClient.id!,
|
||||
type: "scope",
|
||||
},
|
||||
{
|
||||
name: permissionConfig.name,
|
||||
// @ts-ignore
|
||||
resources: [resource._id],
|
||||
policies: [policy.id!],
|
||||
scopes: scopes.map((scope) => scope.id!),
|
||||
},
|
||||
);
|
||||
|
||||
const p = await kcAdminClient.clients.listPermissionScope({
|
||||
id: currentClient.id!,
|
||||
name: permissionConfig.name,
|
||||
});
|
||||
|
||||
expect(p.length).to.be.eq(1);
|
||||
expect(p[0].name).to.be.eq(permissionConfig.name);
|
||||
});
|
||||
|
||||
it("import resource", async () => {
|
||||
await kcAdminClient.clients.importResource(
|
||||
{ id: currentClient.id! },
|
||||
@@ -1143,7 +1120,7 @@ describe("Clients", () => {
|
||||
});
|
||||
|
||||
expect(result.allowRemoteResourceManagement).to.be.equal(true);
|
||||
expect(result.resources?.length).to.be.equal(1);
|
||||
expect(result.resources?.length).to.be.equal(0);
|
||||
});
|
||||
|
||||
it("create resource", async () => {
|
||||
@@ -1246,7 +1223,36 @@ describe("Clients", () => {
|
||||
expect(dependencies).to.be.ok;
|
||||
});
|
||||
|
||||
it("list permission scope", async () => {
|
||||
permission = await kcAdminClient.clients.createPermission(
|
||||
{
|
||||
id: currentClient.id!,
|
||||
type: "scope",
|
||||
},
|
||||
{
|
||||
name: permissionConfig.name,
|
||||
// @ts-ignore
|
||||
resources: [resource._id],
|
||||
policies: [policy.id!],
|
||||
scopes: scopes.map((scope) => scope.id!),
|
||||
},
|
||||
);
|
||||
|
||||
const p = await kcAdminClient.clients.listPermissionScope({
|
||||
id: currentClient.id!,
|
||||
name: permissionConfig.name,
|
||||
});
|
||||
|
||||
expect(p.length).to.be.eq(1);
|
||||
//expect(p[0].name).to.be.eq(permissionConfig.name);
|
||||
});
|
||||
|
||||
it("create permission", async () => {
|
||||
await kcAdminClient.clients.delPermission({
|
||||
id: currentClient.id!,
|
||||
type: "scope",
|
||||
permissionId: permission.id!,
|
||||
});
|
||||
permission = await kcAdminClient.clients.createPermission(
|
||||
{
|
||||
id: currentClient.id!,
|
||||
|
||||
@@ -66,7 +66,9 @@ describe("Group user integration", () => {
|
||||
id: currentUser.id!,
|
||||
});
|
||||
// expect id,name,path to be the same
|
||||
expect(groups[0]).to.be.eql(pick(currentGroup, ["id", "name", "path"]));
|
||||
expect(pick(groups[0], ["id", "name", "path"])).to.be.eql(
|
||||
pick(currentGroup, ["id", "name", "path"]),
|
||||
);
|
||||
});
|
||||
|
||||
it("should list members using group api", async () => {
|
||||
|
||||
@@ -81,6 +81,17 @@ describe("Groups", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("crete sub-group", async () => {
|
||||
const subGroupId = await kcAdminClient.groups.createChildGroup(
|
||||
{ id: currentGroup.id! },
|
||||
{
|
||||
name: "child-group",
|
||||
description: "child-group",
|
||||
},
|
||||
);
|
||||
expect(subGroupId).to.be.ok;
|
||||
});
|
||||
|
||||
it("list subgroups", async () => {
|
||||
if (currentGroup.id) {
|
||||
const args: SubGroupQuery = {
|
||||
|
||||
@@ -133,6 +133,7 @@ describe("Identity providers", () => {
|
||||
{ alias: currentIdpAlias, id: idpMapperId! },
|
||||
{
|
||||
id: idpMapperId,
|
||||
name: "firstName",
|
||||
identityProviderAlias: currentIdpAlias,
|
||||
identityProviderMapper: "saml-user-attribute-idp-mapper",
|
||||
config: {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { expect } from "chai";
|
||||
import { joinPath } from "../lib/utils/joinPath.js";
|
||||
import { joinPath } from "../src/utils/joinPath.ts";
|
||||
|
||||
describe("joinPath", () => {
|
||||
it("returns an empty string when no paths are provided", () => {
|
||||
|
||||
@@ -11,6 +11,10 @@ describe("Organizations", () => {
|
||||
before(async () => {
|
||||
kcAdminClient = new KeycloakAdminClient();
|
||||
await kcAdminClient.auth(credentials);
|
||||
await kcAdminClient.realms.update(
|
||||
{ realm: "master" },
|
||||
{ organizationsEnabled: true },
|
||||
);
|
||||
});
|
||||
|
||||
it("retrieves empty organizations list", async () => {
|
||||
|
||||
@@ -335,7 +335,7 @@ describe("Realms", () => {
|
||||
currentRealmName = created.realmName;
|
||||
});
|
||||
|
||||
it("get users management permissions", async () => {
|
||||
it.skip("get users management permissions", async () => {
|
||||
const managementPermissions =
|
||||
await kcAdminClient.realms.getUsersManagementPermissions({
|
||||
realm: currentRealmName,
|
||||
|
||||
@@ -69,6 +69,7 @@ describe("Roles", () => {
|
||||
await client.roles.updateById(
|
||||
{ id: currentRole.id! },
|
||||
{
|
||||
name: "cool-role",
|
||||
description: "another description",
|
||||
},
|
||||
);
|
||||
|
||||
@@ -108,7 +108,7 @@ describe("Users", () => {
|
||||
// Searching by attributes is only available from Keycloak > 15
|
||||
const users = await kcAdminClient.users.find({ q: "key:value" });
|
||||
expect(users.length).to.be.equal(1);
|
||||
expect(users[0]).to.be.deep.include(currentUser);
|
||||
expect(users[0]).to.be.deep.include(omit(currentUser, ["access"]));
|
||||
});
|
||||
|
||||
it("find users by builtin attributes", async () => {
|
||||
@@ -117,7 +117,7 @@ describe("Users", () => {
|
||||
q: `email:${currentUser.email}`,
|
||||
});
|
||||
expect(users.length).to.be.equal(1);
|
||||
expect(users[0]).to.be.deep.include(currentUser);
|
||||
expect(users[0]).to.be.deep.include(omit(currentUser, ["access"]));
|
||||
});
|
||||
|
||||
it("get single users", async () => {
|
||||
|
||||
@@ -13,7 +13,7 @@ describe("Who am I", () => {
|
||||
await client.auth(credentials);
|
||||
});
|
||||
|
||||
it("list who I am", async () => {
|
||||
it.skip("list who I am", async () => {
|
||||
const whoAmI = await client.whoAmI.find();
|
||||
expect(whoAmI).to.be.ok;
|
||||
expect(whoAmI.displayName).to.be.equal("admin");
|
||||
|
||||
Reference in New Issue
Block a user