mauriciovigolo / keycloak-angular

Easy Keycloak setup for Angular applications.
MIT License
725 stars 278 forks source link

Protractor testing #123

Open bdparrish opened 5 years ago

bdparrish commented 5 years ago

Is there current code on how to mock the keycloak flow for using e2e tests?

mauriciovigolo commented 5 years ago

Hello @bdparrish. I know that it is late but this is something to be added on v.8.0.0. Thanks for opening the issue.

ProfEibe commented 3 years ago

Is there some new information about mocking keycloak or circumventing it?

I would like to use continous integration e2e testing with protractor for my angular app but i can´t get past the keycloak login-screen. If possible without a testuser whos credentials lie open in config.

Am i missing some information i haven´t found yet?

"keycloak-angular": "^8.0.1",
"keycloak-js": "^10.0.2",
jonkoops commented 3 years ago

@ProfEibe Not at this time. When I have some spare time available we will refactor a large part of the application to fall back more to KeycloakJS. We might make a mock version for testing available of Keycloak Angular much like Angular's router but I can't make any promises at this time.

ltrocherie commented 3 years ago

Do you have some new information about mocking keycloak?

I would like to do some e2e testing with protractor on an angular app, and I tried to create my own mock using jasmine and spies, but I can't get it to work.

Without a mock in keycloak-angular and keycloak-js, how to do e2e testing ? Do you have some advice on the subject, maybe some code template or a working example?

ltrocherie commented 3 years ago

Do you have some new information about mocking keycloak?

I would like to do some e2e testing with protractor on an angular app, and I tried to create my own mock using jasmine and spies, but I can't get it to work.

Without a mock in keycloak-angular and keycloak-js, how to do e2e testing ? Do you have some advice on the subject, maybe some code template or a working example?

I forgot I asked this question on Github, and therefore I am sorry for the delay between this follow-up and the original question.

After some digging around, I found out it is not difficult at all to mock your KeycloakService in your Angular app. Because I couldn't find any template of any code close to this on the Internet, here's what I did:

First, in my app.component.ts, I have something like this:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { KeycloakService } from 'keycloak-angular';
import { KeycloakProfile } from 'keycloak-js';

import { interval, Subscription } from 'rxjs';

import { LocalStorageService } from './services/local-storage-service.service';
import { environment } from '../environments/environment';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  public isLoggedIn = false;
  public userProfile: KeycloakProfile | null = null;
  public username = '';
  subscription: Subscription;

  constructor(private router: Router, private readonly keycloak: KeycloakService, private localStorageService: LocalStorageService) {}

  public async ngOnInit() {
    this.isLoggedIn = await this.keycloak.isLoggedIn();
    if (this.isLoggedIn) {
      this.userProfile = await this.keycloak.loadUserProfile();
      this.username = this.userProfile.username;
      this.localStorageService.setToken(await this.keycloak.getToken());
    }
  }

  public login() {
    this.keycloak.login();
  }

  public logout() {
    this.keycloak.logout();
  }
}

I can then do some unit testing with protractor and spies in my app.component.spec.ts:

import { ComponentFixture, TestBed, async, fakeAsync, tick } from '@angular/core/testing';
import { KeycloakService } from 'keycloak-angular';

import { AppComponent } from './app.component';
import { LocalStorageService } from './services/local-storage-service.service';

describe('AppComponent', () => {
  let component: AppComponent;
  let fixture: ComponentFixture<AppComponent>;
  let keycloak: KeycloakService;
  let localStorageService: LocalStorageService;

  const keycloakProfile = {
    id: 'id',
    username: 'userName',
    email: 'mail',
    enabled: true,
    emailVerified: true
  };

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [RouterTestingModule],
      declarations: [AppComponent],
      providers: [KeycloakService, LocalStorageService]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
    keycloak = TestBed.get(KeycloakService);
    localStorageService = TestBed.get(LocalStorageService);
  });

  it('should simulate a user logged in', fakeAsync(() => {
      spyOn(keycloak, 'login').and.returnValue(Promise.resolve());
      spyOn(keycloak, 'isLoggedIn').and.returnValue(Promise.resolve(true));
      spyOn(keycloak, 'loadUserProfile').and.returnValue(Promise.resolve(keycloakProfile));

      fixture.detectChanges();
      tick(1000);

      expect(component.isLoggedIn).toBe(true);
      expect(component.userProfile).toBe(keycloakProfile);
      expect(component.username).toBe('userName');
    }));
});

When it came to e2e testing, the only solution I found was to create a test user in my development instance of Keycloak and fill directly the login and password forms (I was using Selenium for my tests). Not ideal but it works and it's only development so I figured it's okay.

I'd like to thank the Keycloak team for making this software beacause it is very well made, almost plug and play and it makes so many things easy. Hats off to you.