Kategorien
Angular

End-To-End-Tests mit Angular und Cypress

Um End-To-End-Tests mit Cypress und Angular zu schreiben, können Sie folgende Schritte ausführen:

  1. Stellen Sie sicher, dass Sie die neueste Version von Cypress und Angular installiert haben. Sie können Cypress mit dem Befehl npm install -D cypress installieren.
  2. Öffnen Sie Cypress mit dem Befehl npx cypress open im Hauptverzeichnis Ihres Projekts. Cypress öffnet eine Benutzeroberfläche, in der Sie Ihre Tests aufzeichnen und ausführen können.
  3. Erstellen Sie eine neue Testdatei, indem Sie auf „Add test file“ in der Cypress-Benutzeroberfläche klicken. Sie können die Testdatei auch manuell im Verzeichnis „cypress/integration“ erstellen.
  4. Fügen Sie den folgenden Code in Ihre Testdatei ein, um sicherzustellen, dass Cypress Ihre Angular-Anwendung erfolgreich geladen hat:
describe('My First Test', () => {
  it('Does not do much!', () => {
    cy.visit('http://localhost:4200');
    cy.contains('app-root h1', 'Welcome to my-app!');
  });
});
  1. Führen Sie den Test aus, indem Sie auf die Testdatei in der Cypress-Benutzeroberfläche klicken. Wenn alles erfolgreich war, sollte der Test grün markiert werden.
  2. Erstellen Sie weitere Tests, indem Sie Schritte und Assertions hinzufügen. Sie können Elemente auf der Seite auswählen und auf sie interagieren, indem Sie die Methoden von Cypress verwenden, z.B. cy.get(), cy.click() und cy.type().

Um Cypress mit einem Docker-Container zu verwenden, können Sie folgende Schritte ausführen:

  1. Erstellen Sie eine Dockerfile in Ihrem Projektverzeichnis mit den folgenden Inhalten:
FROM cypress/browsers:node18.6.0-chrome105-ff104

# Install your application's dependencies
COPY package.json yarn.lock ./
RUN yarn

# Add your application code
COPY . ./

# Run the tests
CMD ["yarn", "cy:run"]
  1. Erstellen Sie ein Docker-Image mit dem Befehl docker build -t my-app .
  2. Führen Sie einen Container auf Basis des Images mit dem Befehl docker run -it --rm -v $(pwd):/app my-app aus. Dies führt die Cypress-Tests innerhalb des Containers aus.

Durch das Hinzufügen von -v $(pwd):/app werden Ihre Projektdateien in den Container gemountet und Cypress kann auf sie zugreifen.

Kategorien
Angular

Angular Unit Testing von Komponenten mit Abhängigkeiten

Um einen Unit Test von einer Angular Komponente mit Abhängigkeiten (Dependencies) schreiben zu können, muss man die Abhängigkeiten unter Kontrolle bringen.

Wenn man dies nicht tut, schreibt man einen Integration-Test. Integration-Tests haben eine höhere Komplexität hat und gehen schneller kaputt.

Beipsiel einer Komponente „MyComponent“ mit einer Abhängikeit „MyService“:

export class MyComponent implements OnInit {

  public serviceValue;

  constructor(
    private myService: MyService,
  ) {}

  ngOnInit() {
    this.serviceValue =  this.myService.getValue();
  }
}

Um in einem Jasmine Unit Test die Abhängigkeit von MyService zu kontrollieren, kann man einen Spy einsetzen, der an die die Stelle der Methode MyService::getValue gesetzt wird und die Sachen macht, die man für den Test gern hätte.

describe('MyComponent', () => {
  let component: MyComponent;
  let fixture: ComponentFixture<MyComponent>;
  let myService:MyService;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [MyComponent,],
    }).compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(MyComponent);
    component = fixture.componentInstance;
    myService = TestBed.inject(MyService);
  });

  it('spy should set value', () => {
     spyOn(myService,'getValue').and.returnValue('foo');
    fixture.detectChanges();
    expect(component.serviceValue).toBe('foo');
  });
});

In dem Beispiel wird die Methode getValue der Klasse MyService mit einem Spy überschrieben und dem Spy mitgeteilt, dass er den Wert ‚foo‘ zurückgeben soll.

Kategorien
Angular

Protractor Konfiguration Headless Chrome und Firefox

Um Selenium Tests in Firefox und Chrome im Headless Modus auszuführen mit Protractor, kann man folgende Konfiguraton verwenden in der protractor.conf:

exports.config = {
....
  multiCapabilities: [
    {
      browserName: 'chrome',
      chromeOptions: {
        'args': ['--headless']
      },
    },
    {
      browserName: 'firefox',
      firefoxOptions: {
        args: ['--headless']
      },
      'moz:firefoxOptions': {
        args: ['--headless']
      }
    },
  ],
...
};
Kategorien
Angular

Angular ngx-translate TranslateLoader ohne http Modul

Um eine Kompatibilität mit alten Browsern, wie dem Firefox Version <= 5 zu erreichen, kann man das angular http Modul nicht verwenden. Das ngx-translate Module bneötigt einen Loader, der die richtige Sprache lädt per Ajax Request. Dies läst sich auch mit dem XMLHttpRequest und einem Observalbe lösen:

import {Injectable} from '@angular/core';
import {TranslateLoader} from '@ngx-translate/core';
import {Observable} from 'rxjs/Observable';

@Injectable()
export class LanguageLoader implements TranslateLoader {

  getTranslation(lang: string): Observable<any> {
    return Observable.create(function (observer) {
    let url = `./assets/i18n/${lang}.json?=` + new Date().getTime();
    let xhr = new XMLHttpRequest();

      xhr.onreadystatechange = function () {
        if (xhr.readyState == XMLHttpRequest.DONE || xhr.readyState == 4) {
              let response = JSON.parse(xhr.responseText);
              observer.next(response);
              observer.complete();
        }
      }
      xhr.open('GET', url, true);
      xhr.send(null);
    });
  }
}

In der app.module.ts kann man dann den Loader wie folgt einbinden:

TranslateModule.forRoot({
  loader: {provide: TranslateLoader, useClass: LanguageLoader}
})
Kategorien
Angular

Angular 2 HTTP Request nochmals ausführen mit rxjs und retry()

Bei einem Fehlgeschlagenen Request kann man sehr komfortabel nochmals anfragen mit der Methode retry():

import 'rxjs/add/operator/retry';

...

const result = this.http.get(url)
.retry(2);

Kategorien
Angular Apache Webserver

Angular 5 URL ohne index.html

Bei einer Angular Anwendung muss man standardmäßig die index.html aufrufen, damit die Anwendung startet auf einem Apache Webserver. Damit dies auch ohne /index.html nur mit der Domain allein (www.foo.de) funktioneirt, muss man folgendes einstellen:

1. Erstellen einer .htaccess Datei in  src/.htaccess mit dem Inhalt:

DirectoryIndex index.html

2. Ändern der Base Url in der src/index.html

<base href="">

3. ggf. hinzufügen der .htaccess zum Build Prozess in der .angular-cli.json

"apps": [
  {
    "assets": [
      "assets",
      "favicon.ico",
      ".htaccess"
    ],

 

Kategorien
Angular

Angular deutsche Lokalisierung konfigurieren

Um Angular ab Version2  die deutsche Sprache für Fehlermeldugen und auch das Datums-Format zu konfigurieren, muss man in der app.modules.ts folgendes einstellen:

...
import { LOCALE_ID} from '@angular/core';
import localeDe from '@angular/common/locales/de';
import localeDeExtra from '@angular/common/locales/extra/de';
import { registerLocaleData } from '@angular/common';
registerLocaleData(localeDe, localeDeExtra);

@NgModule({
 providers: [
 { provide: LOCALE_ID, useValue: 'de' },
 ]
})