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 5f6b1c63b0 Update Topology Cache Group Servers table to use AG-Grid
(#7849)
5f6b1c63b0 is described below
commit 5f6b1c63b0cd97aab655c126452a6f428d106cff
Author: The Anh Nguyen <[email protected]>
AuthorDate: Sun Nov 12 08:41:31 2023 +0100
Update Topology Cache Group Servers table to use AG-Grid (#7849)
* Update Topology Cache Group Servers table to use AG-Grid
* reformat code + add case undefined update cache group
* remove toggle test
* add open topology menu
* fix return wrong value when update cache groups
* update delete cache group success message for testable
* fix delete cg validation message
---
CHANGELOG.md | 1 +
.../traffic_ops_golang/cachegroup/cachegroups.go | 3 +-
.../cacheGroups/TableCacheGroupsController.js | 361 ++++++++++++---------
.../table/cacheGroups/table.cacheGroups.tpl.html | 60 +---
traffic_portal/test/integration/Data/cachegroup.ts | 60 +---
.../test/integration/PageObjects/CacheGroup.po.ts | 234 ++++++-------
.../test/integration/specs/CacheGroup.spec.ts | 117 ++++---
7 files changed, 399 insertions(+), 437 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ef959871ba..1098d6d003 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ The format is based on [Keep a
Changelog](http://keepachangelog.com/en/1.0.0/).
### Changed
- [#7614](https://github.com/apache/trafficcontrol/pull/7614) *Traffic Ops*
The database upgrade process no longer overwrites changes users may have made
to the initially seeded data.
- [#7832](https://github.com/apache/trafficcontrol/pull/7832) *t3c* Removed
perl dependency
+- Updated the CacheGroups Traffic Portal page to use a more performant
AG-Grid-based table.
## [8.0.0] - 2023-09-20
### Added
diff --git a/traffic_ops/traffic_ops_golang/cachegroup/cachegroups.go
b/traffic_ops/traffic_ops_golang/cachegroup/cachegroups.go
index 2a729bbbc0..f96ba19ff8 100644
--- a/traffic_ops/traffic_ops_golang/cachegroup/cachegroups.go
+++ b/traffic_ops/traffic_ops_golang/cachegroup/cachegroups.go
@@ -1405,8 +1405,7 @@ func DeleteCacheGroup(w http.ResponseWriter, r
*http.Request) {
return
}
- alertMessage := fmt.Sprintf("%s was deleted.", ID)
- alerts := tc.CreateAlerts(tc.SuccessLevel, alertMessage)
+ alerts := tc.CreateAlerts(tc.SuccessLevel, "cache group was deleted.")
api.WriteAlerts(w, r, http.StatusOK, alerts)
return
}
diff --git
a/traffic_portal/app/src/common/modules/table/cacheGroups/TableCacheGroupsController.js
b/traffic_portal/app/src/common/modules/table/cacheGroups/TableCacheGroupsController.js
index 10ccff279f..473605a093 100644
---
a/traffic_portal/app/src/common/modules/table/cacheGroups/TableCacheGroupsController.js
+++
b/traffic_portal/app/src/common/modules/table/cacheGroups/TableCacheGroupsController.js
@@ -18,206 +18,249 @@
*/
/**
- * @param {*} cacheGroups
+ * @typedef CacheGroup
+ * @property {number} id
+ * @property {string} name
+ * @property {number} shortName
+ * @property {number} latitude
+ * @property {number} longitude
+ * @property {string} parentCachegroupName
+ * @property {string} secondaryParentCachegroupName
+ * @property {string} typeName
+ * @property {string} lastUpdated
+ */
+
+/**
+ * @param {CacheGroup} cacheGroup
+ * @returns {string}
+ */
+const getHref = (cacheGroup) => `#!/cache-groups/${cacheGroup.id}`;
+
+/**
+ * @param {CacheGroup[]} cacheGroups
* @param {*} $scope
* @param {*} $state
* @param
{import("../../../service/utils/angular.ui.bootstrap").IModalService} $uibModal
- * @param {import("angular").IWindowService} $window
* @param {import("../../../service/utils/LocationUtils")} locationUtils
* @param {import("../../../api/CacheGroupService")} cacheGroupService
* @param {import("../../../models/MessageModel")} messageModel
*/
-var TableCacheGroupsController = function(cacheGroups, $scope, $state,
$uibModal, $window, locationUtils, cacheGroupService, messageModel) {
-
- let cacheGroupsTable;
+var TableCacheGroupsController = function (
+ cacheGroups,
+ $scope,
+ $state,
+ $uibModal,
+ locationUtils,
+ cacheGroupService,
+ messageModel
+) {
+ /**** Constants, scope data, etc. ****/
- var queueServerUpdates = function(cacheGroup, cdnId) {
- cacheGroupService.queueServerUpdates(cacheGroup.id, cdnId);
- };
+ /** The columns of the ag-grid table */
+ $scope.columns = [
+ {
+ headerName: "Name",
+ field: "name",
+ hide: false,
+ },
+ {
+ headerName: "Short Name",
+ field: "shortName",
+ hide: false,
+ },
+ {
+ headerName: "Type",
+ field: "typeName",
+ hide: false,
+ },
+ {
+ headerName: "1st Parent",
+ field: "parentCachegroupName",
+ hide: false,
+ },
+ {
+ headerName: "2nd Parent",
+ field: "secondaryParentCachegroupName",
+ hide: false,
+ },
+ {
+ headerName: "Latitude",
+ field: "latitude",
+ hide: false,
+ },
+ {
+ headerName: "Longitude",
+ field: "longitude",
+ hide: false,
+ },
+ {
+ headerName: "ID",
+ field: "id",
+ filter: "agNumberColumnFilter",
+ hide: true,
+ },
+ {
+ headerName: "Last Updated",
+ field: "lastUpdated",
+ hide: true,
+ filter: "agDateColumnFilter",
+ },
+ ];
- var clearServerUpdates = function(cacheGroup, cdnId) {
- cacheGroupService.clearServerUpdates(cacheGroup.id, cdnId);
- };
+ /** @type {import("../agGrid/CommonGridController").CGC.DropDownOption[]}
*/
+ $scope.dropDownOptions = [
+ {
+ name: "createCacheGroupMenuItem",
+ href: "#!/cache-groups/new",
+ text: "Create New Cache Group",
+ type: 2,
+ },
+ ];
- var deleteCacheGroup = function(cacheGroup) {
- cacheGroupService.deleteCacheGroup(cacheGroup.id)
- .then(function(result) {
- messageModel.setMessages(result.alerts, false);
- $scope.refresh();
- });
+ /** Reloads all resolved data for the view. */
+ $scope.refresh = () => {
+ $state.reload();
};
- var confirmQueueServerUpdates = function(cacheGroup) {
- var params = {
- title: 'Queue Server Updates: ' + cacheGroup.name,
- message: "Please select a CDN"
+ /**
+ * Deletes a Cache Group if confirmation is given.
+ * @param {CacheGroup} cacheGroup
+ */
+ function confirmDelete(cacheGroup) {
+ const params = {
+ title: `Delete Cache Group: ${cacheGroup.name}`,
+ key: cacheGroup.name,
};
- var modalInstance = $uibModal.open({
- templateUrl: 'common/modules/dialog/select/dialog.select.tpl.html',
- controller: 'DialogSelectController',
- size: 'md',
- resolve: {
- params: function () {
- return params;
- },
- collection: function(cdnService) {
- return cdnService.getCDNs();
- }
- }
- });
- modalInstance.result.then(function(cdn) {
- queueServerUpdates(cacheGroup, cdn.id);
- }, function () {
- // do nothing
+ const modalInstance = $uibModal.open({
+ templateUrl: "common/modules/dialog/delete/dialog.delete.tpl.html",
+ controller: "DialogDeleteController",
+ size: "md",
+ resolve: { params },
});
- };
+ modalInstance.result
+ .then(() => {
+ cacheGroupService
+ .deleteCacheGroup(cacheGroup.id)
+ .then((result) => {
+ messageModel.setMessages(result.alerts, false);
+ $scope.refresh();
+ });
+ })
+ .catch((e) => console.error("failed to delete Cache Group:", e));
+ }
- var confirmClearServerUpdates = function(cacheGroup) {
- var params = {
- title: 'Clear Server Updates: ' + cacheGroup.name,
- message: "Please select a CDN"
+ /**
+ * Queues servers updates on a Cache Group if CDN is selected
+ * @param {CacheGroup} cacheGroup
+ */
+ function confirmQueueServerUpdates(cacheGroup) {
+ const params = {
+ title: `Queue Server Updates: ${cacheGroup.name}`,
+ message: "Please select a CDN",
};
- var modalInstance = $uibModal.open({
- templateUrl: 'common/modules/dialog/select/dialog.select.tpl.html',
- controller: 'DialogSelectController',
- size: 'md',
+ const modalInstance = $uibModal.open({
+ templateUrl: "common/modules/dialog/select/dialog.select.tpl.html",
+ controller: "DialogSelectController",
+ size: "md",
resolve: {
- params: function () {
- return params;
- },
- collection: function(cdnService) {
- return cdnService.getCDNs();
- }
- }
- });
- modalInstance.result.then(function(cdn) {
- clearServerUpdates(cacheGroup, cdn.id);
- }, function () {
- // do nothing
+ params,
+ collection: (cdnService) => cdnService.getCDNs(),
+ },
});
- };
+ modalInstance.result.then((cdn) =>
+ cacheGroupService.queueServerUpdates(cacheGroup.id, cdn.id)
+ );
+ }
- var confirmDelete = function(cacheGroup) {
- var params = {
- title: 'Delete Cache Group: ' + cacheGroup.name,
- key: cacheGroup.name
+ /**
+ * Clears servers updates on a Cache Group if confirmation is given.
+ * @param {CacheGroup} cacheGroup
+ */
+ function confirmClearServerUpdates(cacheGroup) {
+ const params = {
+ title: `Clear Server Updates: ${cacheGroup.name}`,
+ message: "Please select a CDN",
};
- var modalInstance = $uibModal.open({
- templateUrl: 'common/modules/dialog/delete/dialog.delete.tpl.html',
- controller: 'DialogDeleteController',
- size: 'md',
+ const modalInstance = $uibModal.open({
+ templateUrl: "common/modules/dialog/select/dialog.select.tpl.html",
+ controller: "DialogSelectController",
+ size: "md",
resolve: {
- params: function () {
- return params;
- }
- }
+ params,
+ collection: (cdnService) => cdnService.getCDNs(),
+ },
});
- modalInstance.result.then(function() {
- deleteCacheGroup(cacheGroup);
- }, function () {
- // do nothing
+ modalInstance.result.then((cdn) => {
+ cacheGroupService.clearServerUpdates(cacheGroup.id, cdn.id);
});
- };
-
-
- $scope.cacheGroups = cacheGroups;
-
- $scope.navigateToPath = (path, unsavedChanges) =>
locationUtils.navigateToPath(path, unsavedChanges);
+ }
- $scope.columns = [
- { "name": "Name", "visible": true, "searchable": true },
- { "name": "Short Name", "visible": true, "searchable": true },
- { "name": "Type", "visible": true, "searchable": true },
- { "name": "1st Parent", "visible": true, "searchable": true },
- { "name": "2nd Parent", "visible": true, "searchable": true },
- { "name": "Latitude", "visible": true, "searchable": true },
- { "name": "Longitude", "visible": true, "searchable": true }
- ];
-
- $scope.contextMenuItems = [
+ /** @type
{import("../agGrid/CommonGridController").CGC.ContextMenuOption[]} */
+ $scope.contextMenuOptions = [
{
- text: 'Open in New Tab',
- click: function ($itemScope) {
- $window.open('/#!/cache-groups/' + $itemScope.cg.id, '_blank');
- }
+ getHref,
+ getText: (cacheGroup) => `Open ${cacheGroup.name} in a new tab`,
+ newTab: true,
+ type: 2,
},
- null, // Dividier
+ { type: 0 },
{
- text: 'Edit',
- click: function ($itemScope) {
- $scope.editCacheGroup($itemScope.cg.id);
- }
+ getHref,
+ text: "Edit",
+ type: 2,
},
{
- text: 'Delete',
- click: function ($itemScope) {
- confirmDelete($itemScope.cg);
- }
+ onClick: (cacheGroup) => confirmDelete(cacheGroup),
+ text: "Delete",
+ type: 1,
},
- null, // Dividier
+ { type: 0 },
{
- text: 'Queue Server Updates',
- click: function ($itemScope) {
- confirmQueueServerUpdates($itemScope.cg);
- }
+ onClick: (cacheGroup) => confirmQueueServerUpdates(cacheGroup),
+ text: "Queue Server Updates",
+ type: 1,
},
{
- text: 'Clear Server Updates',
- click: function ($itemScope) {
- confirmClearServerUpdates($itemScope.cg);
- }
+ onClick: (cacheGroup) => confirmClearServerUpdates(cacheGroup),
+ text: "Clear Server Updates",
+ type: 1,
},
- null, // Dividier
+ { type: 0 },
{
- text: 'Manage ASNs',
- click: function ($itemScope) {
- locationUtils.navigateToPath('/cache-groups/' +
$itemScope.cg.id + '/asns');
- }
+ getHref: (cacheGroup) => `#!/cache-groups/${cacheGroup.id}/asns`,
+ text: "Manage ASNs",
+ type: 2,
},
{
- text: 'Manage Servers',
- click: function ($itemScope) {
- locationUtils.navigateToPath('/cache-groups/' +
$itemScope.cg.id + '/servers');
- }
- }
+ getHref: (cacheGroup) =>
`#!/cache-groups/${cacheGroup.id}/servers`,
+ text: "Manage Servers",
+ type: 2,
+ },
];
- $scope.editCacheGroup = function(id) {
- locationUtils.navigateToPath('/cache-groups/' + id);
- };
-
- $scope.createCacheGroup = function() {
- locationUtils.navigateToPath('/cache-groups/new');
- };
-
- $scope.refresh = function() {
- $state.reload(); // reloads all the resolves for the view
- };
-
- $scope.toggleVisibility = function(colName) {
- const col = cacheGroupsTable.column(colName + ':name');
- col.visible(!col.visible());
- cacheGroupsTable.rows().invalidate().draw();
+ /** Options, configuration, data and callbacks for the ag-grid table. */
+ /** @type {import("../agGrid/CommonGridController").CGC.GridSettings} */
+ $scope.gridOptions = {
+ onRowClick: function (row) {
+ locationUtils.navigateToPath(`/cache-groups/${row.data.id}`);
+ },
};
- angular.element(document).ready(function () {
- cacheGroupsTable = $('#cacheGroupsTable').DataTable({
- "aLengthMenu": [[25, 50, 100, -1], [25, 50, 100, "All"]],
- "iDisplayLength": 25,
- "aaSorting": [],
- "columns": $scope.columns,
- "initComplete": function(settings, json) {
- try {
- // need to create the show/hide column checkboxes and bind
to the current visibility
- $scope.columns =
JSON.parse(localStorage.getItem('DataTables_cacheGroupsTable_/')).columns;
- } catch (e) {
- console.error("Failure to retrieve required column info
from localStorage (key=DataTables_cacheGroupsTable_/):", e);
- }
- }
- });
- });
-
+ $scope.cacheGroups = cacheGroups.map((cacheGroup) => ({
+ ...cacheGroup,
+ lastUpdated: new Date(
+ cacheGroup.lastUpdated.replace(" ", "T").replace("+00", "Z")
+ ),
+ }));
};
-TableCacheGroupsController.$inject = ['cacheGroups', '$scope', '$state',
'$uibModal', '$window', 'locationUtils', 'cacheGroupService', 'messageModel'];
+TableCacheGroupsController.$inject = [
+ "cacheGroups",
+ "$scope",
+ "$state",
+ "$uibModal",
+ "locationUtils",
+ "cacheGroupService",
+ "messageModel",
+];
module.exports = TableCacheGroupsController;
diff --git
a/traffic_portal/app/src/common/modules/table/cacheGroups/table.cacheGroups.tpl.html
b/traffic_portal/app/src/common/modules/table/cacheGroups/table.cacheGroups.tpl.html
index a2d5726824..44ef006cbb 100644
---
a/traffic_portal/app/src/common/modules/table/cacheGroups/table.cacheGroups.tpl.html
+++
b/traffic_portal/app/src/common/modules/table/cacheGroups/table.cacheGroups.tpl.html
@@ -18,54 +18,14 @@ under the License.
-->
<div class="x_panel">
- <div class="x_title">
- <ol class="breadcrumb pull-left">
- <li class="active">Cache Groups</li>
- </ol>
- <div class="pull-right" role="group" ng-if="!settings.isNew">
- <button name="createCacheGroupButton" class="btn btn-primary"
title="Create Cache Group" ng-click="createCacheGroup()"><i class="fa
fa-plus"></i></button>
- <button class="btn btn-default" title="Refresh"
ng-click="refresh()"><i class="fa fa-refresh"></i></button>
- <div id="toggleColumns" class="btn-group" role="group"
title="Select Table Columns" uib-dropdown is-open="columnSettings.isopen">
- <button type="button" class="btn btn-default dropdown-toggle"
uib-dropdown-toggle aria-haspopup="true" aria-expanded="false">
- <i class="fa fa-columns"></i>
- <span class="caret"></span>
- </button>
- <menu ng-click="$event.stopPropagation()"
class="column-settings dropdown-menu-right dropdown-menu" uib-dropdown-menu>
- <li role="menuitem" ng-repeat="c in columns |
orderBy:'name'">
- <div class="checkbox">
- <label><input type="checkbox" ng-model="c.visible"
ng-click="toggleVisibility(c.name)"> {{::c.name}}</label>
- </div>
- </li>
- </menu>
- </div>
- </div>
- <div class="clearfix"></div>
- </div>
- <div class="x_content">
- <br>
- <table id="cacheGroupsTable" class="table responsive-utilities
jambo_table">
- <thead>
- <tr class="headings">
- <th>Name</th>
- <th>Short Name</th>
- <th>Type</th>
- <th>1st Parent</th>
- <th>2nd Parent</th>
- <th>Latitude</th>
- <th>Longitude</th>
- </tr>
- </thead>
- <tbody>
- <tr ng-click="editCacheGroup(cg.id)" ng-repeat="cg in
::cacheGroups" context-menu="contextMenuItems">
- <td data-search="^{{::cg.name}}$">{{::cg.name}}</td>
- <td data-search="^{{::cg.shortName}}$">{{::cg.shortName}}</td>
- <td data-search="^{{::cg.typeName}}$">{{::cg.typeName}}</td>
- <td
data-search="^{{::cg.parentCachegroupName}}$">{{::cg.parentCachegroupName}}</td>
- <td
data-search="^{{::cg.secondaryParentCachegroupName}}$">{{::cg.secondaryParentCachegroupName}}</td>
- <td data-search="^{{::cg.latitude}}$">{{::cg.latitude}}</td>
- <td data-search="^{{::cg.longitude}}$">{{::cg.longitude}}</td>
- </tr>
- </tbody>
- </table>
- </div>
+ <common-grid-controller
+ title="Cache Groups"
+ table-name="cacheGroups"
+ options="gridOptions"
+ data="cacheGroups"
+ columns="columns"
+ drop-down-options="dropDownOptions"
+ context-menu-options="contextMenuOptions"
+ >
+ </common-grid-controller>
</div>
diff --git a/traffic_portal/test/integration/Data/cachegroup.ts
b/traffic_portal/test/integration/Data/cachegroup.ts
index 92500b97fc..4a72d7c26d 100644
--- a/traffic_portal/test/integration/Data/cachegroup.ts
+++ b/traffic_portal/test/integration/Data/cachegroup.ts
@@ -27,22 +27,6 @@ export const cachegroups = {
"password": "pa$$word"
}
],
- toggle:[
- {
- description: "hide first table column",
- Name: "1st Parent"
- },
- {
- description: "redisplay first table
column",
- Name: "1st Parent"
- }
- ],
- check: [
- {
- description: "check CSV link from
CacheGroup page",
- Name: "Export as CSV"
- }
- ],
create: [
{
Description: "create a EDGE_LOC
cachegroup with FailOver CacheGroup Field",
@@ -111,12 +95,12 @@ export const cachegroups = {
{
Description: "delete a cachegroup",
Name: "TP_Cache1",
- validationMessage: "was deleted"
+ validationMessage: "cache group was
deleted."
},
{
Description: "delete a cachegroup",
Name: "TP_Cache3",
- validationMessage: "was deleted"
+ validationMessage: "cache group was
deleted."
}
]
},
@@ -128,22 +112,6 @@ export const cachegroups = {
"password": "pa$$word"
}
],
- toggle:[
- {
- description: "hide first table column",
- Name: "1st Parent"
- },
- {
- description: "display first table
column",
- Name: "1st Parent"
- }
- ],
- check: [
- {
- description: "check CSV link from
CacheGroup page",
- Name: "Export as CSV"
- }
- ],
create: [
{
Description: "create a CacheGroup",
@@ -182,22 +150,6 @@ export const cachegroups = {
"password": "pa$$word"
}
],
- toggle:[
- {
- description: "hide first table column",
- Name: "1st Parent"
- },
- {
- description: "display first table
column",
- Name: "1st Parent"
- }
- ],
- check: [
- {
- description: "check CSV link from
CacheGroup page",
- Name: "Export as CSV"
- }
- ],
create: [
{
Description: "create a EDGE_LOC
cachegroup with FailOver CacheGroup Field",
@@ -266,22 +218,22 @@ export const cachegroups = {
{
Description: "delete a cachegroup",
Name: "TP_Cache2",
- validationMessage: "was deleted"
+ validationMessage: "cache group was
deleted."
},
{
Description: "delete a cachegroup",
Name: "TP_Cache4",
- validationMessage: "was deleted"
+ validationMessage: "cache group was
deleted."
},
{
Description: "delete a cachegroup",
Name: "TP_Cache5",
- validationMessage: "was deleted"
+ validationMessage: "cache group was
deleted."
},
{
Description: "delete a cachegroup",
Name: "TP_Cache6",
- validationMessage: "was deleted"
+ validationMessage: "cache group was
deleted."
}
]
}
diff --git a/traffic_portal/test/integration/PageObjects/CacheGroup.po.ts
b/traffic_portal/test/integration/PageObjects/CacheGroup.po.ts
index d4ebeb0e06..578e18503a 100644
--- a/traffic_portal/test/integration/PageObjects/CacheGroup.po.ts
+++ b/traffic_portal/test/integration/PageObjects/CacheGroup.po.ts
@@ -16,11 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { browser, by, element } from 'protractor';
+import { browser, by, element } from "protractor";
+import { SideNavigationPage } from "./SideNavigationPage.po";
import { randomize } from "../config";
-import { BasePage } from './BasePage.po';
-import { SideNavigationPage } from '../PageObjects/SideNavigationPage.po';
interface CreateCacheGroup {
Type: string;
@@ -37,133 +36,144 @@ interface UpdateCacheGroup {
Type: string;
FailoverCG?: string;
}
-export class CacheGroupPage extends BasePage {
- private btnCreateCacheGroups = element(by.name('createCacheGroupButton'));
- private txtName = element(by.name("name"))
- private txtShortName = element(by.name("shortName"));
- private txtType = element(by.name("type"));
- private txtLatitude = element(by.name("latitude"));
- private txtLongtitude = element(by.name("longitude"));
- private txtParentCacheGroup = element(by.name("parentCacheGroup"));
- private txtSecondaryParentCG =
element(by.name("secondaryParentCacheGroup"));
- private txtFailoverCG = element(by.name("fallbackOptions"));
- private txtSearch =
element(by.id('cacheGroupsTable_filter')).element(by.css('label input'));
- private txtConfirmCacheGroupName =
element(by.name("confirmWithNameInput"));
- private btnDelete = element(by.buttonText('Delete'));
- private randomize = randomize;
- private btnTableColumn = element(by.className("caret"))
+
+export class CacheGroupPage extends SideNavigationPage {
+ private txtName = element(by.name("name"));
+
async OpenTopologyMenu() {
- let snp = new SideNavigationPage();
- await snp.ClickTopologyMenu();
+ await this.ClickTopologyMenu();
}
+
+ /**
+ * Navigates the browser to the Cache Groups table page.
+ */
async OpenCacheGroupsPage() {
- let snp = new SideNavigationPage();
- await snp.NavigateToCacheGroupsPage();
+ await this.NavigateToCacheGroupsPage();
}
- public async CreateCacheGroups(cachegroup: CreateCacheGroup,
outputMessage: string): Promise<boolean> {
- let result = false
- let basePage = new BasePage();
- if (cachegroup.Type == "EDGE_LOC") {
- if (cachegroup.FailoverCG === undefined) {
- throw new Error(`cachegroups with Type 'EDGE_LOC' must have
FailoverCG`);
- }
- await this.btnCreateCacheGroups.click();
- await this.txtName.sendKeys(cachegroup.Name + this.randomize);
- await this.txtShortName.sendKeys(cachegroup.ShortName +
this.randomize);
- await this.txtType.sendKeys(cachegroup.Type);
- await this.txtLatitude.sendKeys(cachegroup.Latitude);
- await this.txtLongtitude.sendKeys(cachegroup.Longitude);
- await
this.txtParentCacheGroup.sendKeys(cachegroup.ParentCacheGroup);
- await
this.txtSecondaryParentCG.sendKeys(cachegroup.SecondaryParentCG);
- await this.txtFailoverCG.sendKeys(cachegroup.FailoverCG);
- } else {
- await this.btnCreateCacheGroups.click();
- await this.txtName.sendKeys(cachegroup.Name + this.randomize);
- await this.txtShortName.sendKeys(cachegroup.ShortName +
this.randomize);
- await this.txtType.sendKeys(cachegroup.Type);
- await this.txtLatitude.sendKeys(cachegroup.Latitude);
- await this.txtLongtitude.sendKeys(cachegroup.Longitude);
- await
this.txtParentCacheGroup.sendKeys(cachegroup.ParentCacheGroup);
- await
this.txtSecondaryParentCG.sendKeys(cachegroup.SecondaryParentCG);
+ /**
+ * Creates a given Cache Group.
+ *
+ * @param cachegroup The CacheGroup to create.
+ * @param outputMessage The expected output message
+ * @returns Whether or not creation succeeded, which is judged by comparing
+ * the displayed Alert message to outputMessage - they must match
+ * *exactly*!
+ */
+ public async CreateCacheGroups(
+ cachegroup: CreateCacheGroup,
+ outputMessage: string
+ ): Promise<boolean> {
+ await this.OpenCacheGroupsPage();
+ await element(by.buttonText("More")).click();
+ await element(by.linkText("Create New Cache Group")).click();
+
+ if (
+ cachegroup.Type == "EDGE_LOC" &&
+ cachegroup.FailoverCG === undefined
+ ) {
+ throw new Error(
+ `cachegroups with Type 'EDGE_LOC' must have FailoverCG`
+ );
}
- await basePage.ClickCreate();
- await basePage.GetOutputMessage().then(function (value) {
- if (outputMessage == value) {
- result = true;
- } else {
- result = false;
- }
- })
- return result;
- }
- public async SearchCacheGroups(nameCG: string): Promise<boolean> {
- let name = nameCG + this.randomize;
- await this.txtSearch.clear();
- await this.txtSearch.sendKeys(name);
- if (await
browser.isElementPresent(element(by.xpath("//td[@data-search='^" + name +
"$']"))) === true) {
- await element(by.xpath("//td[@data-search='^" + name +
"$']")).click();
- return true;
+ const actions = [
+ this.txtName.sendKeys(cachegroup.Name + randomize),
+ element(by.name("shortName")).sendKeys(cachegroup.ShortName),
+ element(by.name("type")).sendKeys(cachegroup.Type),
+ element(by.name("latitude")).sendKeys(cachegroup.Latitude),
+ element(by.name("longitude")).sendKeys(cachegroup.Longitude),
+ element(by.name("parentCacheGroup")).sendKeys(
+ cachegroup.ParentCacheGroup
+ ),
+ element(by.name("secondaryParentCacheGroup")).sendKeys(
+ cachegroup.SecondaryParentCG
+ ),
+ ];
+
+ if (cachegroup.Type == "EDGE_LOC" && cachegroup.FailoverCG) {
+ actions.push(
+ element(by.name("fallbackOptions")).sendKeys(
+ cachegroup.FailoverCG
+ )
+ );
}
- return false;
+
+ await Promise.all(actions);
+ await this.ClickCreate();
+ return this.GetOutputMessage().then((v) => outputMessage === v);
+ }
+
+ /**
+ * Searches the Cache Groups table for a specific Cache Group, and
navigates to its details
+ * page.
+ *
+ * @param nameCG The Name of the Cache Group for which to search.
+ */
+ public async SearchCacheGroups(nameCG: string): Promise<void> {
+ nameCG += randomize;
+ await this.OpenCacheGroupsPage();
+ const searchInput = element(by.id("quickSearch"));
+ await searchInput.clear();
+ await searchInput.sendKeys(nameCG);
+ await element(by.cssContainingText("span", nameCG)).click();
}
- public async UpdateCacheGroups(cachegroup: UpdateCacheGroup,
outputMessage: string | undefined): Promise<boolean | undefined> {
+ /**
+ * Updates a Cache Group's Name.
+ *
+ * @param cachegroup A definition of the CacheGroup renaming.
+ * @param outputMessage The expected output message
+ * @returns Whether or not renaming succeeded.
+ */
+ public async UpdateCacheGroups(
+ cachegroup: UpdateCacheGroup,
+ outputMessage: string | undefined
+ ): Promise<boolean | undefined> {
let result: boolean | undefined = false;
- let basePage = new BasePage();
- let snp = new SideNavigationPage();
if (cachegroup.Type == "EDGE_LOC") {
- const name = cachegroup.FailoverCG + this.randomize;
- await this.txtFailoverCG.click();
- if (await
browser.isElementPresent(element(by.css(`select[name="fallbackOptions"] >
option[label="${name}"]`)))) {
- await element(by.css(`select[name="fallbackOptions"] >
option[label="${name}"]`)).click();
+ const name = cachegroup.FailoverCG + randomize;
+ await element(by.name("fallbackOptions")).click();
+ if (
+ await browser.isElementPresent(
+ element(
+ by.css(
+ `select[name="fallbackOptions"] >
option[label="${name}"]`
+ )
+ )
+ )
+ ) {
+ await element(
+ by.css(
+ `select[name="fallbackOptions"] >
option[label="${name}"]`
+ )
+ ).click();
} else {
result = undefined;
}
}
- await this.txtType.sendKeys(cachegroup.Type);
- await snp.ClickUpdate();
+ await element(by.name("type")).sendKeys(cachegroup.Type);
+ await this.ClickUpdate();
if (result !== undefined) {
- await basePage.GetOutputMessage().then(function (value) {
- if (outputMessage === value) {
- result = true;
- } else {
- result = false;
- }
- })
+ return (await this.GetOutputMessage()) === outputMessage;
}
- return result;
}
- public async DeleteCacheGroups(nameCG: string, outputMessage: string) {
- let result = false;
- let basePage = new BasePage();
- let snp = new SideNavigationPage();
- let name = nameCG + this.randomize;
- await this.btnDelete.click();
- await this.txtConfirmCacheGroupName.sendKeys(name);
- if (await basePage.ClickDeletePermanently() == true) {
- result = await basePage.GetOutputMessage().then(function (value) {
- if (value.indexOf(outputMessage) > -1) {
- return true
- } else {
- return false;
- }
- })
- } else {
- await basePage.ClickCancel();
- }
- await snp.NavigateToCacheGroupsPage();
- return result;
- }
- public async CheckCSV(name: string): Promise<boolean> {
- return element(by.cssContainingText("span", name)).isPresent();
- }
- public async ToggleTableColumn(name: string): Promise<boolean> {
- await this.btnTableColumn.click();
- const result = await element(by.cssContainingText("th",
name)).isPresent();
- await element(by.cssContainingText("label", name)).click();
- await this.btnTableColumn.click();
- return !result;
+
+ /**
+ * Deletes a Cache Group.
+ *
+ * @param nameCG The Name of the Cache Group to be deleted.
+ * @param outputMessage The expected output message
+ * @returns Whether or not the deletion succeeded.
+ */
+ public async DeleteCacheGroups(
+ nameCG: string,
+ outputMessage: string
+ ): Promise<boolean> {
+ nameCG += randomize;
+ await element(by.buttonText("Delete")).click();
+ await element(by.name("confirmWithNameInput")).sendKeys(nameCG);
+ await this.ClickDeletePermanently();
+ return (await this.GetOutputMessage()) === outputMessage;
}
}
diff --git a/traffic_portal/test/integration/specs/CacheGroup.spec.ts
b/traffic_portal/test/integration/specs/CacheGroup.spec.ts
index b5e9ec9618..57aaddb654 100644
--- a/traffic_portal/test/integration/specs/CacheGroup.spec.ts
+++ b/traffic_portal/test/integration/specs/CacheGroup.spec.ts
@@ -16,80 +16,77 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { browser } from 'protractor';
+import { browser } from "protractor";
-import { LoginPage } from '../PageObjects/LoginPage.po'
-import { CacheGroupPage } from '../PageObjects/CacheGroup.po';
-import { TopNavigationPage } from '../PageObjects/TopNavigationPage.po';
+import { LoginPage } from "../PageObjects/LoginPage.po";
+import { CacheGroupPage } from "../PageObjects/CacheGroup.po";
+import { TopNavigationPage } from "../PageObjects/TopNavigationPage.po";
import { cachegroups } from "../Data";
-
-
let loginPage = new LoginPage();
let topNavigation = new TopNavigationPage();
let cacheGroupPage = new CacheGroupPage();
-cachegroups.tests.forEach(cacheGroupData => {
- describe(`Traffic Portal - CacheGroup - ${cacheGroupData.testName}`, () =>
{
- cacheGroupData.logins.forEach(login => {
- it('can login', async function () {
+cachegroups.tests.forEach((cacheGroupData) => {
+ for (const login of cacheGroupData.logins) {
+ describe(`Traffic Portal - CacheGroup - ${cacheGroupData.testName}`,
() => {
+ beforeAll(async () => {
browser.get(browser.params.baseUrl);
await loginPage.Login(login);
expect(await loginPage.CheckUserName(login)).toBeTruthy();
- })
- it('can open cache group page', async function () {
await cacheGroupPage.OpenTopologyMenu();
await cacheGroupPage.OpenCacheGroupsPage();
- })
- cacheGroupData.check.forEach(check => {
- it(check.description, async () => {
- expect(await
cacheGroupPage.CheckCSV(check.Name)).toBe(true);
- await cacheGroupPage.OpenCacheGroupsPage();
- });
});
- cacheGroupData.toggle.forEach(toggle => {
- it(toggle.description, async () => {
- if(toggle.description.includes('hide')){
- expect(await
cacheGroupPage.ToggleTableColumn(toggle.Name)).toBe(false);
- await cacheGroupPage.OpenCacheGroupsPage();
- }else{
- expect(await
cacheGroupPage.ToggleTableColumn(toggle.Name)).toBe(true);
- await cacheGroupPage.OpenCacheGroupsPage();
- }
-
+ afterAll(async () => {
+ expect(await topNavigation.Logout()).toBeTruthy();
+ });
+ afterEach(async () => {
+ await cacheGroupPage.OpenCacheGroupsPage();
+ });
+ for (const create of cacheGroupData.create) {
+ it(create.Description, async () => {
+ expect(
+ await cacheGroupPage.CreateCacheGroups(
+ create,
+ create.validationMessage
+ )
+ ).toBeTruthy();
});
- })
- cacheGroupData.create.forEach(create => {
- it(create.Description, async function () {
- expect(await cacheGroupPage.CreateCacheGroups(create,
create.validationMessage)).toBeTruthy();
- await cacheGroupPage.OpenCacheGroupsPage();
- })
- })
- cacheGroupData.update.forEach(update => {
+ }
+ for (const update of cacheGroupData.update) {
if (update.Description.includes("cannot")) {
- it(update.Description, async function () {
- await cacheGroupPage.SearchCacheGroups(update.Name)
- expect(await cacheGroupPage.UpdateCacheGroups(update,
update.validationMessage)).toBeUndefined();
- await cacheGroupPage.OpenCacheGroupsPage();
- })
+ it(update.Description, async () => {
+ await cacheGroupPage.SearchCacheGroups(update.Name);
+ expect(
+ await cacheGroupPage.UpdateCacheGroups(
+ update,
+ update.validationMessage
+ )
+ ).toBeUndefined();
+ });
} else {
- it(update.Description, async function () {
- await cacheGroupPage.SearchCacheGroups(update.Name)
- expect(await cacheGroupPage.UpdateCacheGroups(update,
update.validationMessage)).toBeTruthy();
- await cacheGroupPage.OpenCacheGroupsPage();
- })
+ it(update.Description, async () => {
+ await cacheGroupPage.SearchCacheGroups(update.Name);
+ expect(
+ await cacheGroupPage.UpdateCacheGroups(
+ update,
+ update.validationMessage
+ )
+ ).toBeTruthy();
+ });
}
-
- })
- cacheGroupData.remove.forEach(remove => {
- it(remove.Description, async function () {
- await cacheGroupPage.SearchCacheGroups(remove.Name)
- expect(await cacheGroupPage.DeleteCacheGroups(remove.Name,
remove.validationMessage)).toBeTruthy();
- })
- })
- it('can logout', async function () {
- expect(await topNavigation.Logout()).toBeTruthy();
- })
- })
- })
-})
+ }
+ for (const remove of cacheGroupData.remove) {
+ it(remove.Description, async () => {
+ await cacheGroupPage.SearchCacheGroups(remove.Name);
+ expect(
+ await cacheGroupPage.DeleteCacheGroups(
+ remove.Name,
+ remove.validationMessage
+ )
+ ).toBeTruthy();
+ });
+ }
+ });
+ }
+});