angular / protractor

E2E test framework for Angular apps
http://www.protractortest.org
MIT License
8.75k stars 2.31k forks source link

provide the step by step procedure for Angular/Ionic Android App: Login Testing with Appium Inspector (Cypress or Protractor) #5569

Open SathishkumarG3 opened 5 months ago

SathishkumarG3 commented 5 months ago

This ticket outlines the creation of automated login tests for an Angular/Ionic Android application using Appium Inspector and either Cypress or Protractor.

provide the example test case for Login -> Email Address -> password for below application image

find the below ts file details

import { Component, Inject, NgZone, OnInit } from '@angular/core';
import { UntypedFormControl, UntypedFormGroup, Validators } from '@angular/forms';
import { Router } from '@angular/router';
import { AuthService } from 'src/app/services/auth.service';
import * as _ from 'lodash';
import { UserService } from 'src/app/services/user.service';
import { FingerprintAIO } from '@ionic-native/fingerprint-aio/ngx';
import { Platform } from '@ionic/angular';
import '@codetrix-studio/capacitor-google-auth';
import { Plugins } from '@capacitor/core';
import { AlertService } from 'src/app/services/alert.service';
import { AngularFireAuth } from '@angular/fire/compat/auth';
import { FacebookLogin } from '@capacitor-community/facebook-login';
import { SignInWithApple, AppleSignInResponse, AppleSignInErrorResponse, ASAuthorizationAppleIDRequest } from '@ionic-native/sign-in-with-apple/ngx';
import { FirebaseCrashlytics } from '@awesome-cordova-plugins/firebase-crashlytics/ngx';
import { debounceTime } from 'rxjs/operators';
import { ErrorService } from 'src/app/services/error.service';
import { AnalyticsService } from 'src/app/services/analytics.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.page.html',
  styleUrls: ['./login.page.scss'],
})
export class LoginPage implements OnInit {
  passHide = true;
  e_regex = '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$';
  loginForm = new UntypedFormGroup({
    username: new UntypedFormControl('', [Validators.required, Validators.pattern(this.e_regex)]),
    password: new UntypedFormControl('', Validators.required)
  });
  color: string;
  loginData: any = {};
  userData: any;
  userInfo: any;
  googleData: any;
  facebookData: any;
  appleData: any;
  isIphone = false;
  appleLogo: string;
  facebookLogo: string;
  googleLogo: string;
  headerLogo: string;

  constructor(private router: Router, private authService: AuthService,
    public firebaseCrashlytics: FirebaseCrashlytics,
    private platform: Platform, public afAuth: AngularFireAuth,
    private zone: NgZone, private faio: FingerprintAIO, private userService: UserService, private analyticsService: AnalyticsService,
    private alertService: AlertService, private signInWithApple: SignInWithApple,
    @Inject('LscLogoLocation') public LscLogoLocation: string, @Inject('LscAppleLogo') public LscAppleLogo: string,
    @Inject('LscFacebookLogo') public LscFacebookLogo: string, @Inject('LscGoogleLogo') public LscGoogleLogo: string,
    @Inject('LscHeaderLogo') public LscHeaderLogo: string,
    private errorService: ErrorService) {
    this.appleLogo = `${LscLogoLocation}` + '/' + `${LscAppleLogo}`;
    this.facebookLogo = `${LscLogoLocation}` + '/' + `${LscFacebookLogo}`;
    this.googleLogo = `${LscLogoLocation}` + '/' + `${LscGoogleLogo}`;
    this.headerLogo = `${LscLogoLocation}` + '/' + `${LscHeaderLogo}`;
    this.setRememberMe(true);
  }

  ngOnInit() {
    if (this.platform.is('ios')) {
      this.isIphone = true
    }
    try {
      const crashlytics = this.firebaseCrashlytics.initialise();
      crashlytics.logException('my caught exception');
    } catch (error) {
      console.log('error: 59', error);

    }
    this.userService.choosedColor$.subscribe((color: string) => {
      this.color = color;
    });
    this.color = localStorage.getItem('choosedColor');
    this.loginForm.get('username').valueChanges.pipe(
      debounceTime(10)
    ).subscribe((inputValue) => {
      if (inputValue) {
        //To remove whitespace from both sides of a string
        this.loginForm.get('username').setValue(inputValue.trim());
      }
    });
  }

  handleForgotPassword(): any {
    this.router.navigate(['forgot-password']);
  }

  handleMemberPage(): any {
    this.router.navigate(['memberpage']);
  }

  setRememberMeToggle(e): void {
    this.setRememberMe(e.detail.checked);
  }

  setRememberMe(flag: boolean): void {
    localStorage.setItem('rememberMeFlag', `${flag}`);
    this.afAuth.setPersistence(flag ? 'local' : 'session');
  }

  emailSignin() {
    this.authService.setLogoutFlag(false); // Update the logoutFlag in the service
    const username = this.loginForm.controls['username'].value.trim();
    if (this.notNull(username) && this.notNull(this.loginForm.controls['password'].value)) {
      localStorage.setItem('pwd',this.loginForm.controls['password'].value);     
      this.authService.signInWithEmailAndPassword(username, this.loginForm.controls['password'].value);
      this.afAuth.authState.subscribe((user) => {        
        if (user != null) {
          if (user?.providerData.length > 0) {
            this.loginForm.reset();
          }
        }
      });
      // Track Individual User for GA
      this.analyticsService.sentEvent('Login', {
        login_type: 'Username and Password',
      }); 
    }
    else {
      this.alertService.errorSnackbar('Please fill the all mandatory fields');
    }
  }

  notNull(data: any): boolean {
    return data !== undefined && data !== null && data !== "";
  }

  loginUser(email: string, password: string) {
    this.authService.loginUser(email.toLowerCase(), password)
      .then(response => this.afterLoginSuccess(response))
      .catch(error => this.afterLoginError(error));
  }

  handleGoogleLogin() {
    this.googleSignIn();
  }

  async googleSignIn() {
    try {
      const googleUser = await Plugins.GoogleAuth.signIn();
      this.googleData = googleUser;
      if (googleUser.authentication.idToken) {
        this.authService.googleLogin(googleUser.authentication.idToken)
          .then(response => this.afterGoogleLoginSuccess(response))
          .catch(error => this.afterLoginError(error));
      }
      // Track Individual User for GA
      this.analyticsService.sentEvent('Login', {
        login_type: 'Google',
      }); 
    } catch (error) {
      const err = 'GoogleSignIn' + ':' + error;
      this.errorService.handleFirebaseCrashlytics(err);
      this.alertService.errorSnackbar(error);
    }
  }

  afterGoogleLoginSuccess(_response) {
    this.userData = {
      firstName: this.googleData.givenName || '',
      lastName: this.googleData.familyName || '',
      email: this.googleData.email,
      name: this.googleData.displayName || '',
      imageUrl: this.googleData.imageUrl || ''
    };
    this.authService.handleLoginSuccess();
  }

  afterLoginError(error: any) {
    this.alertService.dismissLoader();
    if (error.code === 'auth/account-exists-with-different-credential') {
      this.alertService.errorSnackbar('This Account is already exist with different login method.');
    } else {
      this.alertService.errorSnackbar(error);
    }
  }

  afterLoginSuccess(_response) {
    this.authService.handleLoginSuccess();
  }

  handleFacebookLogin() {
    this.facebookLogin();
  }

  async facebookLogin() {
    try {
      const FACEBOOK_PERMISSIONS = ['public_profile', 'email'];
      const result = await FacebookLogin.login({ permissions: FACEBOOK_PERMISSIONS });
      if (result && result.accessToken) {
        const user = { token: result.accessToken.token, userId: result.accessToken.userId };
        // eslint-disable-next-line max-len
        const response = await fetch(`https://graph.facebook.com/${result.accessToken.userId}?fields=id,name,gender,link,picture&type=large&access_token=${result.accessToken.token}`);
        this.facebookData = await response.json();
        this.authService.facebookLogin(result.accessToken.token)
          .then(res => this.afterFbLoginSuccess(res))
          .catch(error => this.afterLoginError(error));
      }
      // Track Individual User for GA
      this.analyticsService.sentEvent('Login', {
        login_type: 'Facebook',
      }); 
    } catch (error) {
      const err = 'FacebookSignIn' + ':' + error;
      this.errorService.handleFirebaseCrashlytics(err);
      this.alertService.errorSnackbar(error);
    }
  }

  afterFbLoginSuccess(_response) {
    var _firstName = '';
    var _lastName = '';
    var _displayName = this.facebookData.name;
    if (_displayName) {
      const displayNameParts = _displayName.split(' ');
      _firstName = displayNameParts[0];
      _lastName = displayNameParts.length > 1 ? displayNameParts[1] : '';
    }
    this.userData = {
      firstName: _firstName,
      lastName: _lastName,
      imageUrl: this.facebookData.picture.data.url || '',
      authId: this.facebookData.id
    };
    this.alertService.dismissLoader();
    this.authService.handleLoginSuccess();
  }

  handleAppleLogin() {
    this.appleLogin();
  }

  async appleLogin() {
    try {
      this.signInWithApple.signin({
        requestedScopes: [
          ASAuthorizationAppleIDRequest.ASAuthorizationScopeFullName,
          ASAuthorizationAppleIDRequest.ASAuthorizationScopeEmail
        ]
      })
        .then((res: AppleSignInResponse) => {
          this.appleData = res;
          console.log("Apple response", res);
          this.authService.signUpWithAppleLogin(res.identityToken)
            .then(async _res => {
              await this.afterAppleLoginSuccess(_res);
            })
        })
        .catch((error: AppleSignInErrorResponse) => {
          console.log("Apple error", error);
        });
        // Track Individual User for GA
        this.analyticsService.sentEvent('Login', {
          login_type: 'Apple Login',
        }); 
    } catch (error) {
      const err = 'AppleSignIn' + ':' + error;
      this.errorService.handleFirebaseCrashlytics(err);
      this.alertService.errorSnackbar(error);
    }
  }

  async afterAppleLoginSuccess(response) {
    if (!this.notNull(response.user.email) || response.user.email.includes('privaterelay.appleid.com')) {
      await this.authService.presentAppleEmailAlert();
    } else {
      this.authService.handleLoginSuccess();
    }
  }

  signup() {
    this.zone.run(() => {
      this.router.navigate(['/signup']);
    });
  }

  forgotPassword() {
    this.zone.run(() => {
      this.router.navigate(['/forgot-password']);
    });
  }
}
SathishkumarG3 commented 5 months ago

Please prioritize this as we are still facing the same issue. If any channels are available, please provide updates