You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by oc...@apache.org on 2021/05/20 14:54:46 UTC

[trafficcontrol] branch master updated: Migrate user tests from E2E to integration (#5870)

This is an automated email from the ASF dual-hosted git repository.

ocket8888 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git


The following commit(s) were added to refs/heads/master by this push:
     new dde7f69  Migrate user tests from E2E to integration (#5870)
dde7f69 is described below

commit dde7f69d49a056843e7c179bef44a36ba839be02
Author: Rima Shah <22...@users.noreply.github.com>
AuthorDate: Thu May 20 08:54:36 2021 -0600

    Migrate user tests from E2E to integration (#5870)
    
    * Added ts files for user and users.spec and update UserPage
    
    * Added tests for create/update user, search csv
    
    * Added toggle and register user tests
    
    * Added update registered user
    
    * Edited update register user tests
    
    * used right comparison sign
    
    * Changes made per review comments.
    
    * Changed string manipulation to template string and removed undefined return in update()
    
    * Added return type
---
 traffic_portal/test/integration/Data/users.ts      |  89 +++++++++++++
 .../test/integration/PageObjects/BasePage.po.ts    |  21 ++-
 .../test/integration/PageObjects/UsersPage.po.ts   | 148 +++++++++++++++++++--
 .../test/integration/specs/Users.spec.ts           |  91 +++++++++++++
 4 files changed, 329 insertions(+), 20 deletions(-)

diff --git a/traffic_portal/test/integration/Data/users.ts b/traffic_portal/test/integration/Data/users.ts
new file mode 100644
index 0000000..7d907de
--- /dev/null
+++ b/traffic_portal/test/integration/Data/users.ts
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import {randomize} from "../config";
+
+export const users = {
+    tests: [
+        {
+            logins: [
+                {
+                    description: "Admin Role",
+                    username: "TPAdmin",
+                    password: "pa$$word"
+                }
+            ],
+            check: [
+                {
+                    description: "check CSV link from CDN page",
+                    Name: "Export as CSV"
+                }
+            ],
+            toggle: [
+                {
+                    description: "hide first table column",
+                    Name: "Email"
+                },
+                {
+                    description: "redisplay first table column",
+                    Name: "Email"
+                }
+            ],
+            add: [
+                {
+                    description: "create a new User",
+                    FullName: "TPCreateUser1",
+                    Username: "User1",
+                    Email: "test@cdn.tc.com",
+                    Role: "admin",
+                    Tenant: "- tenantSame",
+                    Password: "qwe@123#rty",
+                    ConfirmPassword: "qwe@123#rty",
+                    PublicSSHKey: "",
+                    validationMessage: "User created"
+                },
+            ],
+            register: [
+                {
+                    description: "create a registered User",
+                    Email: "test2@cdn.tc.com",
+                    Role: "admin",
+                    Tenant: "- tenantSame",
+                    validationMessage: `Sent user registration to {{ test2@cdn.tc.com${randomize}}} with the following permissions [ role: admin | tenant: tenantSame${randomize} ]`
+                }
+            ],
+            update: [
+                {
+                    description: "update user's fullname",
+                    Username: "User1",
+                    NewFullName: "TPUpdatedUser1",
+                    validationMessage: "user was updated."
+                },
+            ],
+            updateRegisterUser: [
+                {
+                    description: "update registered user's fullname",
+                    Email: "test2@cdn.tc.com",
+                    NewFullName: "TPRegisterUser1",
+                    validationMessage: "user was updated."
+                }
+            ],
+        },
+    ]
+};
diff --git a/traffic_portal/test/integration/PageObjects/BasePage.po.ts b/traffic_portal/test/integration/PageObjects/BasePage.po.ts
index 8983a1a..17a5c0d 100644
--- a/traffic_portal/test/integration/PageObjects/BasePage.po.ts
+++ b/traffic_portal/test/integration/PageObjects/BasePage.po.ts
@@ -34,11 +34,12 @@ export class BasePage {
   private lbOutputWarning = element(by.xpath("(//div[contains(@class,'alert alert-dismissable alert-warning')]//div)[1]"));
   private lbBlankError = element(by.xpath("//small[text()='Required']"));
   private lbSyntaxError = element(by.xpath("//small[text()='Must be alphamumeric with no spaces. Dashes and underscores also allowed.']"));
-  private btnCreate= element(by.xpath("//button[text()='Create']"));
+  private btnCreate= element(by.buttonText('Create'));
   private btnDeletePermanently = element(by.buttonText('Delete Permanently'));
   private btnCancel =  element(by.className('close')).element(by.xpath("//span[text()='×']"));
-  private btnUpdate = element(by.xpath("//button[text()='Update']"))
+  private btnUpdate = element(by.buttonText('Update'));
   private btnSubmit = element(by.xpath("//button[text()='Submit']"));
+  private btnRegister = element(by.buttonText('Send Registration'));
   private btnNo = element(by.xpath("//button[text()='No']"));
   
   async ClickNo(){
@@ -53,8 +54,8 @@ export class BasePage {
     }
     
   }
-  async ClickUpdate(){
-    if(await this.btnUpdate.isEnabled() == true){
+  public async ClickUpdate(): Promise<boolean>{
+    if(await this.btnUpdate.isEnabled()){
       await this.btnUpdate.click();
       return true;
     }else{
@@ -69,14 +70,22 @@ export class BasePage {
       return false;
     }
   }
-  async ClickCreate(){
-    if(await this.btnCreate.isEnabled() == true){
+  public async ClickCreate(): Promise<boolean> {
+    if(await this.btnCreate.isEnabled()){
       await this.btnCreate.click();
       return true;
     }else{
       return false;
     }
   }
+  public async ClickRegister(): Promise<boolean> {
+    if(await this.btnRegister.isEnabled()){
+      await this.btnRegister.click();
+      return true;
+    }else{
+      return false;
+    }
+  }
   async ClickCancel(){
     await this.btnCancel.click();
   }
diff --git a/traffic_portal/test/integration/PageObjects/UsersPage.po.ts b/traffic_portal/test/integration/PageObjects/UsersPage.po.ts
index 3260a71..9788488 100644
--- a/traffic_portal/test/integration/PageObjects/UsersPage.po.ts
+++ b/traffic_portal/test/integration/PageObjects/UsersPage.po.ts
@@ -16,10 +16,10 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { by, element } from 'protractor';
 
+import { by, element } from 'protractor';
 import { BasePage } from './BasePage.po';
-import {SideNavigationPage} from '../PageObjects/SideNavigationPage.po';
+import { SideNavigationPage } from './SideNavigationPage.po';
 import { randomize } from '../config';
 
 interface User {
@@ -35,9 +35,31 @@ interface User {
   validationMessage?: string;
 }
 
-export class UsersPage extends BasePage {
+interface UpdateUser {
+    description: string;
+    Username: string;
+    NewFullName: string;
+    validationMessage?: string;
+}
+
+interface RegisterUser {
+    Email: string;
+    Role: string;
+    Tenant: string;
+    existsMessage?: string;
+    validationMessage?: string;
+}
+
+interface UpdateRegisterUser {
+    description: string;
+    Email: string;
+    NewFullName: string;
+    validationMessage?: string;
+}
 
-    private btnCreateNewUser = element(by.css('[title="Create New User"]'));
+export class UsersPage extends BasePage {
+    private btnCreateNewUser = element(by.name('createUserButton'));
+    private btnRegisterNewUser = element(by.name('createRegisterUserButton'));
     private txtFullName = element(by.name('fullName'));
     private txtUserName = element(by.name('uName'));
     private txtEmail = element(by.name('email'));
@@ -46,32 +68,58 @@ export class UsersPage extends BasePage {
     private txtPassword = element(by.name('uPass'));
     private txtConfirmPassword = element(by.name('confirmPassword'));
     private txtPublicSSHKey = element(by.name('publicSshKey'));
+    private txtSearch = element(by.id('usersTable_filter')).element(by.css('label input'));
+    private btnTableColumn = element(by.css('[title="Select Table Columns"]'));
     private randomize = randomize;
 
-    async OpenUserPage(){
-      let snp = new SideNavigationPage();
-      await snp.ClickUserAdminMenu();
-      await snp.NavigateToUsersPage();
-     }
+    public async OpenUserPage(): Promise<void> {
+        const snp = new SideNavigationPage();
+        await snp.NavigateToUsersPage();
+    }
+
+    public async OpenUserMenu(): Promise<void> {
+        const snp = new SideNavigationPage();
+        await snp.ClickUserAdminMenu();
+    }
+
+    public async CheckCSV(name: string): Promise<boolean> {
+        return element(by.cssContainingText("span", name)).isPresent();
+    }
+
+    public async CheckToggle(name: string): Promise<boolean> {
+        let result = false;
+        await this.btnTableColumn.click();
+        //if the box is already checked, uncheck it and return false
+        if (await element(by.cssContainingText("th", name)).isPresent()) {
+            await element(by.cssContainingText("label", name)).click();
+            result = false;
+        } else {
+            //if the box is unchecked, then check it and return true
+            await element(by.cssContainingText("label", name)).click();
+            result = true;
+        }
+        await this.btnTableColumn.click();
+        return result;
+    }
 
     public async CreateUser(user: User): Promise<boolean> {
       let result = false;
-      let basePage = new BasePage();
-      let snp = new SideNavigationPage();
+      const basePage = new BasePage();
+      const snp = new SideNavigationPage();
       await this.btnCreateNewUser.click();
       await this.txtFullName.sendKeys(user.FullName + this.randomize);
       await this.txtUserName.sendKeys(user.Username + this.randomize);
-      await this.txtEmail.sendKeys(user.FullName + this.randomize + user.Email);
+      await this.txtEmail.sendKeys(user.Email + this.randomize);
       await this.txtRole.sendKeys(user.Role);
       await this.txtTenant.sendKeys(user.Tenant+this.randomize);
       await this.txtPassword.sendKeys(user.Password);
       await this.txtConfirmPassword.sendKeys(user.ConfirmPassword);
       await this.txtPublicSSHKey.sendKeys(user.PublicSSHKey);
       await basePage.ClickCreate();
-      if(await basePage.GetOutputMessage() == user.existsMessage){
+      if(await basePage.GetOutputMessage() === user.existsMessage){
         await snp.NavigateToUsersPage();
         result = true;
-      }else if(await basePage.GetOutputMessage() == user.validationMessage){
+      }else if(await basePage.GetOutputMessage() === user.validationMessage){
         result = true;
       }else{
         result = false;
@@ -79,4 +127,76 @@ export class UsersPage extends BasePage {
       return result;
     }
 
+    public async SearchUser(nameUser: string): Promise<void> {
+        const snp = new SideNavigationPage();
+        const name = nameUser + this.randomize;
+        await snp.NavigateToUsersPage();
+        await this.txtSearch.clear();
+        await this.txtSearch.sendKeys(name);
+        await element.all(by.repeater('u in ::users')).filter(function (row) {
+            return row.element(by.name('username')).getText().then(function (val) {
+                return val === name;
+            });
+        }).first().click();
+    }
+
+    public async SearchEmailUser(nameEmail: string): Promise<void> {
+        const snp = new SideNavigationPage();
+        const name = nameEmail + this.randomize;
+        await snp.NavigateToUsersPage();
+        await this.txtSearch.clear();
+        await this.txtSearch.sendKeys(name);
+        await element.all(by.repeater('u in ::users')).filter(function (row) {
+            return row.element(by.name('email')).getText().then(function (val) {
+                return val === name;
+            });
+        }).first().click();
+    }
+
+    public async UpdateUser(user: UpdateUser): Promise<boolean> {
+        const basePage = new BasePage();
+        switch (user.description) {
+            case "update user's fullname":
+                await this.txtFullName.clear();
+                await this.txtFullName.sendKeys(user.NewFullName);
+                await basePage.ClickUpdate();
+                break;
+            default:
+                return false;
+        }
+        return basePage.GetOutputMessage().then(value => user.validationMessage === value);
+    }
+
+    public async RegisterUser(user: RegisterUser): Promise<boolean> {
+        let result = false;
+        const basePage = new BasePage();
+        const snp = new SideNavigationPage();
+        await this.btnRegisterNewUser.click();
+        await this.txtEmail.sendKeys(user.Email + this.randomize);
+        await this.txtRole.sendKeys(user.Role);
+        await this.txtTenant.sendKeys(user.Tenant + this.randomize);
+        await basePage.ClickRegister();
+        if (await basePage.GetOutputMessage() === user.existsMessage) {
+            await snp.NavigateToUsersPage();
+            result = true;
+        } else if (await basePage.GetOutputMessage() === user.validationMessage) {
+            result = true;
+        } else {
+            result = false;
+        }
+        return result;
+    }
+
+    public async UpdateRegisterUser(user: UpdateRegisterUser): Promise<boolean> {
+        const basePage = new BasePage();
+        switch (user.description) {
+            case "update registered user's fullname":
+                await this.txtFullName.sendKeys(user.NewFullName);
+                await basePage.ClickUpdate();
+                break;
+            default:
+                return false;
+        }
+        return basePage.GetOutputMessage().then(value => user.validationMessage === value);
+    }
   }
diff --git a/traffic_portal/test/integration/specs/Users.spec.ts b/traffic_portal/test/integration/specs/Users.spec.ts
new file mode 100644
index 0000000..b1a52a5
--- /dev/null
+++ b/traffic_portal/test/integration/specs/Users.spec.ts
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { browser } from 'protractor';
+
+import { LoginPage } from '../PageObjects/LoginPage.po';
+import { UsersPage } from '../PageObjects/UsersPage.po';
+import { TopNavigationPage } from '../PageObjects/TopNavigationPage.po';
+import { users } from "../Data/users";
+
+const loginPage = new LoginPage();
+const topNavigation = new TopNavigationPage();
+const usersPage = new UsersPage();
+
+users.tests.forEach(async usersData =>{
+    usersData.logins.forEach(login => {
+        describe('Traffic Portal - Users - ' + login.description, function(){
+            it('can login', async () => {
+                browser.get(browser.params.baseUrl);
+                await loginPage.Login(login);
+                expect(await loginPage.CheckUserName(login)).toBeTruthy();
+            });
+            it('can open users page', async () => {
+                await usersPage.OpenUserMenu()
+                await usersPage.OpenUserPage();
+            });
+            usersData.check.forEach(check => {
+                it(check.description, async () => {
+                    expect(await usersPage.CheckCSV(check.Name)).toBe(true);
+                    await usersPage.OpenUserPage();
+                });
+            });
+            usersData.toggle.forEach(toggle => {
+                it(toggle.description, async () => {
+                    if(toggle.description.includes('hide')){
+                        expect(await usersPage.CheckToggle(toggle.Name)).toBe(false);
+                        await usersPage.OpenUserPage();
+                    }else{
+                        expect(await usersPage.CheckToggle(toggle.Name)).toBe(true);
+                        await usersPage.OpenUserPage();
+                    }
+                });
+            })
+            usersData.add.forEach(add => {
+                it(add.description, async () => {
+                    expect(await usersPage.CreateUser(add)).toBeTruthy();
+                    await usersPage.OpenUserPage();
+                });
+            });
+            usersData.update.forEach(update => {
+                it(update.description, async () => {
+                    await usersPage.SearchUser(update.Username);
+                    expect(await usersPage.UpdateUser(update)).toBe(true);
+                    await usersPage.OpenUserPage();
+                });
+            });
+            usersData.register.forEach(register => {
+                it(register.description, async () => {
+                    expect(await usersPage.RegisterUser(register)).toBeTruthy();
+                    await usersPage.OpenUserPage();
+                });
+            });
+            usersData.updateRegisterUser.forEach(updateRegisterUser => {
+                it(updateRegisterUser.description, async () => {
+                    await usersPage.SearchEmailUser(updateRegisterUser.Email);
+                    expect(await usersPage.UpdateRegisterUser(updateRegisterUser)).toBe(true);
+                    await usersPage.OpenUserPage();
+                });
+            });
+            it('can logout', async () => {
+                expect(await topNavigation.Logout()).toBeTruthy();
+            });
+        });
+    });
+});