<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic How to Unit Test Angular with ArcGIS JS API in ArcGIS JavaScript Maps SDK Questions</title>
    <link>https://community.esri.com/t5/arcgis-javascript-maps-sdk-questions/how-to-unit-test-angular-with-arcgis-js-api/m-p/1541268#M85733</link>
    <description>&lt;P&gt;Hi,&amp;nbsp;&lt;BR /&gt;I use the credential-identity Manager in an Anular 18 OAuth Project ( I log myself on into an Enterprise portal). I can't figure out how I could log my testuser in (in the Angular Jasmin and Karma Tests). I can't log my user in because I have a UI -Login Process and it looks like this:&lt;BR /&gt;&lt;BR /&gt;authService:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="c"&gt;...

  public async initializeLogin(): Promise&amp;lt;boolean&amp;gt; {
    IdentityManager.registerOAuthInfos([oauthInfo]);
    try {
      this.credential = await IdentityManager.checkSignInStatus(signInUrl);
      console.log('user successfully logged in');

      this.portal = (await new Portal({ url: oauthInfo.portalUrl }).load()) as Portal;
      this.groups = await this.portal.user?.fetchGroups();

      // Update credentials after successful login
      this._credential$.next(this.credential);

      // Initialize the ArcGIS REST API with the user's credentials
      this.initArcGisRESTAuthentication();
      environment.token = this.credential.token;
      return true;
    } catch (e) {
      console.log('user not logged in', e);
      this.login();
      return false;
    }
  }

  private initArcGisRESTAuthentication() {
    const token = Promise.resolve(this.credential.token);
    const authentication = {
      portal: signInUrl + '/rest',
      getToken(): Promise&amp;lt;string&amp;gt; {
        return token;
      },
    };
    setDefaultRequestOptions({ authentication }, true);
  }

  login() {
    void IdentityManager.getCredential(signInUrl);
  }

...&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;AppComponent:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="c"&gt;...

  async ngOnInit() {
    await this.authService.initialized;
  }

  get userName() {
    return this.authService.portal.user.username;
  }

  get displayName() {
    return this.authService.portal.user.fullName;
  }

  get initialized() {
    return this.authService.initialized;
  }

  logout() {
    return this.authService.logout();
  }

...&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The Test of the AppComponent:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="c"&gt;import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { RouterTestingModule } from '@angular/router/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { SbbIconTestingModule } from '@sbb-esta/angular/icon/testing';
import { SbbMenuItem } from '@sbb-esta/angular/menu';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
import { AuthService } from './services/oauth/auth.service';
import { ActivatedRoute } from '@angular/router';

describe('AppComponent', () =&amp;gt; {
  let component: AppComponent;
  let fixture: ComponentFixture&amp;lt;AppComponent&amp;gt;;
  let authService: AuthService;

  beforeEach(waitForAsync(() =&amp;gt; {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule,
        NoopAnimationsModule,
        SbbIconTestingModule,
        HttpClientModule,
        AppComponent // Standalone-Komponente wird hier importiert
      ],
      providers: [
        AuthService,
        {
          provide: ActivatedRoute,
          useValue: {
            snapshot: {
              paramMap: {
                get: (key: string) =&amp;gt; (key === 'id' ? '123' : null),
              },
            },
          },
        },
      ],
    }).compileComponents();
  }));

  beforeEach(() =&amp;gt; {
    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
    authService = TestBed.inject(AuthService);
    fixture.detectChanges();
  });

  it('should create', () =&amp;gt; {
    expect(component).toBeTruthy();
  });

  it('should render title', () =&amp;gt; {
    expect(fixture.nativeElement.querySelector('.sbb-header-lean-titlebox &amp;gt; span').textContent).toContain('ESTA GIS Blueprint');
  });

  it('should render username', waitForAsync(async () =&amp;gt; {
    await authService.initializeLogin();
    fixture.detectChanges();
    expect(fixture.nativeElement.querySelector('.sbb-usermenu-user-info-display-name').textContent).toContain(authService.portal.user.fullName);
  }));

  it('should logout', waitForAsync(async () =&amp;gt; {
    await authService.initializeLogin();
    fixture.detectChanges();

    const logoutSpy = spyOn(authService, 'logout').and.callThrough();

    const usermenuOpenButton = fixture.debugElement.query(By.css('.sbb-menu-trigger-usermenu'));
    usermenuOpenButton.nativeElement.click();
    fixture.detectChanges();

    const logoutButton = fixture.debugElement.query(By.directive(SbbMenuItem));
    logoutButton.nativeElement.click();

    expect(logoutSpy).toHaveBeenCalled();
  }));

  it('should login successfully', waitForAsync(async () =&amp;gt; {
    await authService.initializeLogin();
    await component.ngOnInit();
    fixture.detectChanges();

    expect(authService.authenticated).toBeTrue();
    expect(component.initialized).toBeTrue();
  }));

  it('should fail to login and not proceed with tests', waitForAsync(async () =&amp;gt; {
    spyOn(authService, 'initializeLogin').and.throwError('Login failed');
    await component.ngOnInit();
    fixture.detectChanges();

    expect(authService.authenticated).toBeFalse();
    expect(component.initialized).toBeFalsy();
  }));
});&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I can't say my authService with which user he should log in...&lt;/P&gt;</description>
    <pubDate>Mon, 23 Sep 2024 08:21:27 GMT</pubDate>
    <dc:creator>joelwüthrich</dc:creator>
    <dc:date>2024-09-23T08:21:27Z</dc:date>
    <item>
      <title>How to Unit Test Angular with ArcGIS JS API</title>
      <link>https://community.esri.com/t5/arcgis-javascript-maps-sdk-questions/how-to-unit-test-angular-with-arcgis-js-api/m-p/1541268#M85733</link>
      <description>&lt;P&gt;Hi,&amp;nbsp;&lt;BR /&gt;I use the credential-identity Manager in an Anular 18 OAuth Project ( I log myself on into an Enterprise portal). I can't figure out how I could log my testuser in (in the Angular Jasmin and Karma Tests). I can't log my user in because I have a UI -Login Process and it looks like this:&lt;BR /&gt;&lt;BR /&gt;authService:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="c"&gt;...

  public async initializeLogin(): Promise&amp;lt;boolean&amp;gt; {
    IdentityManager.registerOAuthInfos([oauthInfo]);
    try {
      this.credential = await IdentityManager.checkSignInStatus(signInUrl);
      console.log('user successfully logged in');

      this.portal = (await new Portal({ url: oauthInfo.portalUrl }).load()) as Portal;
      this.groups = await this.portal.user?.fetchGroups();

      // Update credentials after successful login
      this._credential$.next(this.credential);

      // Initialize the ArcGIS REST API with the user's credentials
      this.initArcGisRESTAuthentication();
      environment.token = this.credential.token;
      return true;
    } catch (e) {
      console.log('user not logged in', e);
      this.login();
      return false;
    }
  }

  private initArcGisRESTAuthentication() {
    const token = Promise.resolve(this.credential.token);
    const authentication = {
      portal: signInUrl + '/rest',
      getToken(): Promise&amp;lt;string&amp;gt; {
        return token;
      },
    };
    setDefaultRequestOptions({ authentication }, true);
  }

  login() {
    void IdentityManager.getCredential(signInUrl);
  }

...&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;AppComponent:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="c"&gt;...

  async ngOnInit() {
    await this.authService.initialized;
  }

  get userName() {
    return this.authService.portal.user.username;
  }

  get displayName() {
    return this.authService.portal.user.fullName;
  }

  get initialized() {
    return this.authService.initialized;
  }

  logout() {
    return this.authService.logout();
  }

...&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;The Test of the AppComponent:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;LI-CODE lang="c"&gt;import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { RouterTestingModule } from '@angular/router/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { SbbIconTestingModule } from '@sbb-esta/angular/icon/testing';
import { SbbMenuItem } from '@sbb-esta/angular/menu';
import { HttpClientModule } from '@angular/common/http';
import { AppComponent } from './app.component';
import { AuthService } from './services/oauth/auth.service';
import { ActivatedRoute } from '@angular/router';

describe('AppComponent', () =&amp;gt; {
  let component: AppComponent;
  let fixture: ComponentFixture&amp;lt;AppComponent&amp;gt;;
  let authService: AuthService;

  beforeEach(waitForAsync(() =&amp;gt; {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule,
        NoopAnimationsModule,
        SbbIconTestingModule,
        HttpClientModule,
        AppComponent // Standalone-Komponente wird hier importiert
      ],
      providers: [
        AuthService,
        {
          provide: ActivatedRoute,
          useValue: {
            snapshot: {
              paramMap: {
                get: (key: string) =&amp;gt; (key === 'id' ? '123' : null),
              },
            },
          },
        },
      ],
    }).compileComponents();
  }));

  beforeEach(() =&amp;gt; {
    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
    authService = TestBed.inject(AuthService);
    fixture.detectChanges();
  });

  it('should create', () =&amp;gt; {
    expect(component).toBeTruthy();
  });

  it('should render title', () =&amp;gt; {
    expect(fixture.nativeElement.querySelector('.sbb-header-lean-titlebox &amp;gt; span').textContent).toContain('ESTA GIS Blueprint');
  });

  it('should render username', waitForAsync(async () =&amp;gt; {
    await authService.initializeLogin();
    fixture.detectChanges();
    expect(fixture.nativeElement.querySelector('.sbb-usermenu-user-info-display-name').textContent).toContain(authService.portal.user.fullName);
  }));

  it('should logout', waitForAsync(async () =&amp;gt; {
    await authService.initializeLogin();
    fixture.detectChanges();

    const logoutSpy = spyOn(authService, 'logout').and.callThrough();

    const usermenuOpenButton = fixture.debugElement.query(By.css('.sbb-menu-trigger-usermenu'));
    usermenuOpenButton.nativeElement.click();
    fixture.detectChanges();

    const logoutButton = fixture.debugElement.query(By.directive(SbbMenuItem));
    logoutButton.nativeElement.click();

    expect(logoutSpy).toHaveBeenCalled();
  }));

  it('should login successfully', waitForAsync(async () =&amp;gt; {
    await authService.initializeLogin();
    await component.ngOnInit();
    fixture.detectChanges();

    expect(authService.authenticated).toBeTrue();
    expect(component.initialized).toBeTrue();
  }));

  it('should fail to login and not proceed with tests', waitForAsync(async () =&amp;gt; {
    spyOn(authService, 'initializeLogin').and.throwError('Login failed');
    await component.ngOnInit();
    fixture.detectChanges();

    expect(authService.authenticated).toBeFalse();
    expect(component.initialized).toBeFalsy();
  }));
});&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I can't say my authService with which user he should log in...&lt;/P&gt;</description>
      <pubDate>Mon, 23 Sep 2024 08:21:27 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcgis-javascript-maps-sdk-questions/how-to-unit-test-angular-with-arcgis-js-api/m-p/1541268#M85733</guid>
      <dc:creator>joelwüthrich</dc:creator>
      <dc:date>2024-09-23T08:21:27Z</dc:date>
    </item>
    <item>
      <title>Re: How to Unit Test Angular with ArcGIS JS API</title>
      <link>https://community.esri.com/t5/arcgis-javascript-maps-sdk-questions/how-to-unit-test-angular-with-arcgis-js-api/m-p/1541412#M85741</link>
      <description>&lt;P&gt;I'd recommend avoiding testing the IdentityManager itself.&amp;nbsp; I've faced a similar challenge as you.&amp;nbsp; The solution that seems to have worked best is to not import IdentityManager directly in the component you want to test.&amp;nbsp; Instead, you could create a small wrapper class that provides a static method to returns the instance of IdentityManager.&amp;nbsp; In your component, you would then refer to YourWrapperClass.IdentityManager()... Then, in your tests, you can import the wrapper class, and in `beforeEach()`, spy on the static method that provides the identity manager class, and return a simple object with whatever methods/data you want to validate with your tests mocked.&amp;nbsp; This way you will not actually be executing the IdentityMangager, but you can validate that its methods are called with expected parameters, and/or validate that your code behaves as expected when its methods return specific results.&lt;/P&gt;&lt;P&gt;I'll be interested to see if there are other ideas offered on this.&lt;/P&gt;</description>
      <pubDate>Mon, 23 Sep 2024 14:58:18 GMT</pubDate>
      <guid>https://community.esri.com/t5/arcgis-javascript-maps-sdk-questions/how-to-unit-test-angular-with-arcgis-js-api/m-p/1541412#M85741</guid>
      <dc:creator>mleahy_cl</dc:creator>
      <dc:date>2024-09-23T14:58:18Z</dc:date>
    </item>
  </channel>
</rss>

