]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
mgr/dashboard: refactoring E2E dashboard test
authorPatrick Seidensal <pseidensal@suse.com>
Fri, 23 Aug 2019 15:58:12 +0000 (17:58 +0200)
committerPatrick Seidensal <pseidensal@suse.com>
Wed, 28 Aug 2019 07:38:48 +0000 (09:38 +0200)
Signed-off-by: Patrick Seidensal <pseidensal@suse.com>
src/pybind/mgr/dashboard/frontend/e2e/cluster/hosts.po.ts
src/pybind/mgr/dashboard/frontend/e2e/dashboard.e2e-spec.ts
src/pybind/mgr/dashboard/frontend/e2e/dashboard.po.ts
src/pybind/mgr/dashboard/frontend/e2e/page-helper.po.ts

index 0d0b8f1090d4f5651cdc39553d1e2025975ba04e..81037c279c735423b15dd5679218e9b630896947 100644 (file)
@@ -7,8 +7,7 @@ export class HostsPageHelper extends PageHelper {
   async check_for_host() {
     await this.navigateTo();
 
-    const hostcount = await this.getTableCount().getText();
-    expect(await hostcount.includes('0 total')).toBe(false);
+    expect(await this.getTableTotalCount()).not.toBe(0);
   }
 
   // function that checks all services links work for first
index 02e14ecbe890fd3784040b5a7f5204341a018535..df1d03abc74d2ba170f4f7a75159fb77d42c6c7a 100644 (file)
@@ -1,10 +1,11 @@
-import { $$, browser, by, element } from 'protractor';
+import { browser } from 'protractor';
 import { IscsiPageHelper } from './block/iscsi.po';
 import { HostsPageHelper } from './cluster/hosts.po';
 import { MonitorsPageHelper } from './cluster/monitors.po';
 import { OSDsPageHelper } from './cluster/osds.po';
 import { DashboardPageHelper } from './dashboard.po';
 import { Helper } from './helper.po';
+import { PageHelper } from './page-helper.po';
 import { PoolPageHelper } from './pools/pools.po';
 import { DaemonsPageHelper } from './rgw/daemons.po';
 
@@ -18,184 +19,124 @@ describe('Dashboard Main Page', () => {
   let iscsi: IscsiPageHelper;
 
   beforeAll(() => {
-    dashboard = new Helper().dashboard;
-    daemons = new Helper().daemons;
-    hosts = new Helper().hosts;
-    osds = new Helper().osds;
-    pools = new Helper().pools;
-    monitors = new Helper().monitors;
-    iscsi = new Helper().iscsi;
+    const h = new Helper();
+    dashboard = h.dashboard;
+    daemons = h.daemons;
+    hosts = h.hosts;
+    osds = h.osds;
+    pools = h.pools;
+    monitors = h.monitors;
+    iscsi = h.iscsi;
   });
 
   afterEach(async () => {
     await Helper.checkConsole();
   });
 
-  describe('Check that all hyperlinks on cells lead to the correct page and fields exist', () => {
+  describe('Check that all hyperlinks on info cards lead to the correct page and fields exist', () => {
     beforeEach(async () => {
       await dashboard.navigateTo();
     });
 
-    it('should check all linked cells lead to correct page', async () => {
-      // Grabs cell and then clicks the hyperlink, some cells require different
-      // methods as stated below
-
-      // Monitors Cell
-      expect(await browser.getCurrentUrl()).toContain('/#/dashboard');
-      await dashboard.cellLink('Monitors');
-      expect(await dashboard.getBreadcrumbText()).toEqual('Monitors');
-
-      // OSDs Cell
-      // await browser.navigate().back();
-      await dashboard.navigateBack();
-      expect(await browser.getCurrentUrl()).toContain('/#/dashboard');
-      await dashboard.cellLink('OSDs');
-      expect(await dashboard.getBreadcrumbText()).toEqual('OSDs');
-
-      // Hosts Cell
-      // await browser.navigate().back();
-      await dashboard.navigateBack();
-      expect(await browser.getCurrentUrl()).toContain('/#/dashboard');
-      await dashboard.cellLink('Hosts');
-      expect(await dashboard.getBreadcrumbText()).toEqual('Hosts');
-
-      // Object Gateways Cell
-      // await browser.navigate().back();
-      await dashboard.navigateBack();
-      expect(await browser.getCurrentUrl()).toContain('/#/dashboard');
-      await element
-        .all(by.partialLinkText('Object'))
-        .last()
-        .click(); // Since there is a space and there are 2 occurances of
-      expect(await dashboard.getBreadcrumbText()).toEqual('Daemons'); // 'Object Gateways', this method was used to grab the link
-
-      // iSCSI Gateways Cell
-      // await browser.navigate().back();
-      await dashboard.navigateBack();
-      expect(await browser.getCurrentUrl()).toContain('/#/dashboard');
-      await dashboard.partialCellLink('iSCSI'); // Since there is a space between iSCSI and Gateways this method was
-      expect(await dashboard.getBreadcrumbText()).toEqual('Overview'); // used to grab and click the link
-
-      // Pools Cell
-      // await browser.navigate().back();
-      await dashboard.navigateBack();
-      expect(await browser.getCurrentUrl()).toContain('/#/dashboard');
-      await dashboard.cellLink('Pools');
-      expect(await dashboard.getBreadcrumbText()).toEqual('Pools');
+    it('should ensure that all linked info cards lead to correct page', async () => {
+      const expectationMap = {
+        Monitors: 'Monitors',
+        OSDs: 'OSDs',
+        Hosts: 'Hosts',
+        'Object Gateways': 'Daemons',
+        'iSCSI Gateways': 'Overview',
+        Pools: 'Pools'
+      };
+
+      for (const [linkText, breadcrumbText] of Object.entries(expectationMap)) {
+        expect(await browser.getCurrentUrl()).toContain('/#/dashboard');
+        await dashboard.clickInfoCardLink(linkText);
+        expect(await dashboard.getBreadcrumbText()).toEqual(breadcrumbText);
+        await dashboard.navigateBack();
+      }
     });
 
-    it('should verify that cells exist on dashboard in proper order', async () => {
-      // Ensures that info cards are all displayed on the dashboard tab while being
-      // in the proper order, checks for card title and position via indexing into
-      // a list of all info cards
-      await dashboard.navigateTo();
-      expect(await browser.getCurrentUrl()).toContain('/#/dashboard');
-      expect(await dashboard.infoCardText(0)).toContain('Cluster Status');
-      expect(await dashboard.infoCardText(1)).toContain('Monitors');
-      expect(await dashboard.infoCardText(2)).toContain('OSDs');
-      expect(await dashboard.infoCardText(3)).toContain('Manager Daemons');
-      expect(await dashboard.infoCardText(4)).toContain('Hosts');
-      expect(await dashboard.infoCardText(5)).toContain('Object Gateways');
-      expect(await dashboard.infoCardText(6)).toContain('Metadata Servers');
-      expect(await dashboard.infoCardText(7)).toContain('iSCSI Gateways');
-      expect(await dashboard.infoCardText(8)).toContain('Client IOPS');
-      expect(await dashboard.infoCardText(9)).toContain('Client Throughput');
-      expect(await dashboard.infoCardText(10)).toContain('Client Read/Write');
-      expect(await dashboard.infoCardText(11)).toContain('Recovery Throughput');
-      expect(await dashboard.infoCardText(12)).toContain('Scrub');
-      expect(await dashboard.infoCardText(13)).toContain('Pools');
-      expect(await dashboard.infoCardText(14)).toContain('Raw Capacity');
-      expect(await dashboard.infoCardText(15)).toContain('Objects');
-      expect(await dashboard.infoCardText(16)).toContain('PGs per OSD');
-      expect(await dashboard.infoCardText(17)).toContain('PG Status');
+    it('should verify that info cards exist on dashboard in proper order', async () => {
+      // Ensures that info cards are all displayed on the dashboard tab while being in the proper
+      // order, checks for card title and position via indexing into a list of all info cards.
+      const order = [
+        'Cluster Status',
+        'Monitors',
+        'OSDs',
+        'Manager Daemons',
+        'Hosts',
+        'Object Gateways',
+        'Metadata Servers',
+        'iSCSI Gateways',
+        'Client IOPS',
+        'Client Throughput',
+        'Client Read/Write',
+        'Recovery Throughput',
+        'Scrub',
+        'Pools',
+        'Raw Capacity',
+        'Objects',
+        'PGs per OSD',
+        'PG Status'
+      ];
+
+      for (let i = 0; i < order.length; i++) {
+        expect((await dashboard.infoCard(i)).getText()).toContain(
+          order[i],
+          `Order of ${order[i]} seems to be wrong`
+        );
+      }
     });
 
     it('should verify that info card group titles are present and in the right order', async () => {
-      // Checks that the group titles on the dashboard are correct and in the right order
-      await dashboard.navigateTo();
       expect(await browser.getCurrentUrl()).toContain('/#/dashboard');
-      expect(await dashboard.checkGroupTitles(0, 'Status'));
-      expect(await dashboard.checkGroupTitles(1, 'Performance'));
-      expect(await dashboard.checkGroupTitles(2, 'Capacity'));
+      expect(await dashboard.infoGroupTitle(0)).toBe('Status');
+      expect(await dashboard.infoGroupTitle(1)).toBe('Performance');
+      expect(await dashboard.infoGroupTitle(2)).toBe('Capacity');
     });
   });
 
-  describe('Should check that dashboard cells have correct information', () => {
-    beforeAll(async () => {
-      await dashboard.navigateTo();
-    });
-
-    it('should verify that proper number of object gateway daemons on dashboard', async () => {
-      // Checks that dashboard id card for Object Gateway has the correct number of Daemons
-      // by checking the Daemons page and taking the count found at the bottom of the table
+  it('Should check that dashboard cards have correct information', async () => {
+    interface TestSpec {
+      cardName: string;
+      regexMatcher?: RegExp;
+      pageObject: PageHelper;
+    }
+
+    const testSpecs: TestSpec[] = [
+      { cardName: 'Object Gateways', regexMatcher: /(\d+)\s+total/, pageObject: daemons },
+      { cardName: 'Monitors', regexMatcher: /(\d+)\s+\(quorum/, pageObject: monitors },
+      { cardName: 'Hosts', regexMatcher: /(\d+)\s+total/, pageObject: hosts },
+      { cardName: 'OSDs', regexMatcher: /(\d+)\s+total/, pageObject: osds },
+      { cardName: 'Pools', pageObject: pools },
+      { cardName: 'iSCSI Gateways', regexMatcher: /(\d+)\s+total/, pageObject: iscsi }
+    ];
+
+    for (let i = 0; i < testSpecs.length; i++) {
+      const spec = testSpecs[i];
       await dashboard.navigateTo();
-      const dashCount = await dashboard.cardNumb(5); // Grabs number of daemons from dashboard Object Gateway card
-      await daemons.navigateTo();
-      // Grabs number of daemons from table footer
-      const tableCount = (await daemons.getTableCount().getText()).slice(13);
-      expect(dashCount).toContain(tableCount);
-    });
-
-    it('should verify that proper number of monitors on dashboard', async () => {
-      // Checks that dashboard id card for Monitors has the correct number of Monitors
-      // by checking the Monitors page and taking the count found at the bottom of the table
-      await dashboard.navigateTo();
-      // Grabs number of monitors from dashboard Monitor card
-      const dashCount = await dashboard.cardNumb(1);
-      await monitors.navigateTo();
-      // Grabs number of monitors from table footer
-      const tableCount = (await $$('.datatable-footer-inner')
-        .first()
-        .getText()).slice(0, -6);
-      expect(dashCount).toContain(tableCount);
-    });
-
-    it('should verify that proper number of hosts on dashboard', async () => {
-      // Checks that dashboard id card for Hosts has the correct number of hosts
-      // by checking the Hosts page and taking the count found at the bottom of the table
-      await dashboard.navigateTo();
-      // Grabs number of hosts from dashboard Hosts card
-      const dashCount = await dashboard.cardNumb(4);
-      await hosts.navigateTo();
-      // Grabs number of hosts from table footer
-      const tableCount = (await hosts.getTableCount().getText()).slice(13, -6);
-      expect(dashCount).toContain(tableCount);
-    });
-
-    it('should verify that proper number of osds on dashboard', async () => {
-      // Checks that dashboard id card for Hosts has the correct number of hosts
-      // by checking the Hosts page and taking the count found at the bottom of the table
-      await dashboard.navigateTo();
-      // Grabs number of hosts from dashboard Hosts card
-      const dashCount = (await dashboard.cardNumb(2)).slice(0, -17);
-      await osds.navigateTo();
-      // Grabs number of hosts from table footer
-      const tableCount = (await osds.getTableCount().getText()).slice(13, -6);
-      expect(dashCount).toContain(tableCount);
-    });
-
-    it('should verify that proper number of pools on dashboard', async () => {
-      await dashboard.navigateTo();
-      // Grabs number of hosts from dashboard Pools card
-      const dashCount = (await dashboard.cardNumb(13)).slice(4);
-      await pools.navigateTo();
-      // Grabs number of pools from table footer
-      const tableCount = (await pools.getTableCount().getText()).slice(13, -6);
-      expect(dashCount).toContain(tableCount);
-    });
-
-    it('should verify that proper number of iscsi gateways on dashboard', async () => {
-      // Checks that dashboard id card for iSCSI has the correct number of gateways
-      // by checking the iSCSI page and taking the count found at the bottom of the table (first)
-      await dashboard.navigateTo();
-      // Grabs number of gateways from dashboard iSCSI card
-      const dashCount = await dashboard.cardNumb(7);
-      await iscsi.navigateTo();
-      // Grabs number of monitors from table footer
-      const tableCount = (await $$('.datatable-footer-inner')
-        .first()
-        .getText()).slice(0, -6);
-      expect(dashCount).toContain(tableCount);
-    });
+      const infoCardBodyText = await dashboard.infoCardBodyText(spec.cardName);
+      let dashCount = 0;
+      if (spec.regexMatcher) {
+        const match = infoCardBodyText.match(new RegExp(spec.regexMatcher));
+        if (match && match.length > 1) {
+          dashCount = Number(match[1]);
+        } else {
+          return Promise.reject(
+            `Regex ${spec.regexMatcher} did not find a match for card with name ` +
+              `${spec.cardName}`
+          );
+        }
+      } else {
+        dashCount = Number(infoCardBodyText);
+      }
+      await spec.pageObject.navigateTo();
+      const tableCount = await spec.pageObject.getTableTotalCount();
+      expect(dashCount).toBe(
+        tableCount,
+        `Text of card ${spec.cardName} and regex ${spec.regexMatcher} resulted in ${dashCount} ` +
+          `but did not match table count ${tableCount}`
+      );
+    }
   });
 });
index 724608de753d53d6b3fe822c618826b9e1288d2c..a4271d931a42b772b6f9872f98a91ae999ec8b83 100644 (file)
@@ -1,4 +1,4 @@
-import { $, by, element } from 'protractor';
+import { $, $$, by, ElementFinder } from 'protractor';
 import { PageHelper } from './page-helper.po';
 
 export class DashboardPageHelper extends PageHelper {
@@ -6,45 +6,48 @@ export class DashboardPageHelper extends PageHelper {
     index: '/#/dashboard'
   };
 
-  async checkGroupTitles(index, name) {
-    // Checks that the titles of all the groups on the dashboard are correct
-    const titles = element.all(by.className('info-group-title'));
-    const text = await titles.get(index).getText();
-    expect(text).toBe(name);
+  async infoGroupTitle(index: number): Promise<string> {
+    return $$('.info-group-title')
+      .get(index)
+      .getText();
   }
 
-  cellFromGroup(cardName) {
-    // Grabs cell from dashboard page based off the title. Then returns the card
-    // element
-    return $(`cd-info-card[cardtitle=${cardName}]`);
-  }
-
-  async cellLink(cardName) {
-    // Grabs the link from the correct card using the cellFromGroup function,
-    // then clicks the hyperlinked title
-    await this.navigateTo();
-    await this.cellFromGroup(cardName)
+  async clickInfoCardLink(cardName: string): Promise<void> {
+    await $(`cd-info-card[cardtitle="${cardName}"]`)
       .element(by.linkText(cardName))
       .click();
   }
 
-  async partialCellLink(partName) {
-    // Used for cases in which there was a space inbetween two words in the hyperlink,
-    // has the same functionality as cellLink
-    await element(by.partialLinkText(partName)).click();
-  }
-
-  async infoCardText(index) {
-    // Grabs a list of all info cards, then checks by index that the title text
-    // is equal to the desired title, thus checking the presence of the card
-    const cardList = element.all(by.tagName('cd-info-card'));
-    return cardList.get(index).getText();
+  async infoCard(indexOrTitle: number | string): Promise<ElementFinder> {
+    let infoCards = $$('cd-info-card');
+    if (typeof indexOrTitle === 'number') {
+      if ((await infoCards.count()) <= indexOrTitle) {
+        return Promise.reject(
+          `No element found for index ${indexOrTitle}. Elements array has ` +
+            `only ${await infoCards.count()} elements.`
+        );
+      }
+      return infoCards.get(indexOrTitle);
+    } else if (typeof indexOrTitle === 'string') {
+      infoCards = infoCards.filter(
+        async (e) => (await e.$('.card-title').getText()) === indexOrTitle
+      );
+      if ((await infoCards.count()) === 0) {
+        return Promise.reject(`No element found for title "${indexOrTitle}"`);
+      }
+      return infoCards.first();
+    }
   }
 
-  async cardNumb(index) {
-    // Grabs a list of all info cards and returns the text on the card via
-    // the index of the card in the list
-    const cardList = element.all(by.tagName('cd-info-card'));
-    return cardList.get(index).getText();
+  async infoCardBodyText(
+    infoCard: ElementFinder | Promise<ElementFinder> | string
+  ): Promise<string> {
+    let _infoCard: ElementFinder;
+    if (typeof infoCard === 'string') {
+      _infoCard = await this.infoCard(infoCard);
+    } else {
+      _infoCard = typeof infoCard.then === 'function' ? await infoCard : infoCard;
+    }
+    return _infoCard.$('.card-text').getText();
   }
 }
index 11bc0eb79d91dabf09dfe3d1a10c5e5d1eebe817..afe73a08b112fe81cdb3b125f47a50448556f3b7 100644 (file)
@@ -89,8 +89,13 @@ export abstract class PageHelper {
       .getText();
   }
 
-  getTableCount() {
-    return $('.datatable-footer-inner.selected-count');
+  async getTableTotalCount(): Promise<number> {
+    return Number(
+      (await $$('.datatable-footer-inner .page-count span')
+        .filter(async (e) => (await e.getText()).includes('total'))
+        .first()
+        .getText()).match(/.*(\d+\s+)total.*/)[1]
+    );
   }
 
   // getTitleText() {