diff --git a/application-analytics-default/pom.xml b/application-analytics-default/pom.xml
index f048b51..02ca7f7 100644
--- a/application-analytics-default/pom.xml
+++ b/application-analytics-default/pom.xml
@@ -66,6 +66,10 @@
jersey-client
2.30.1
+
+ org.apache.commons
+ commons-lang3
+
diff --git a/application-analytics-default/src/main/java/com/xwiki/analytics/internal/MostViewedJsonNormaliser.java b/application-analytics-default/src/main/java/com/xwiki/analytics/internal/MostViewedJsonNormaliser.java
index bb25faa..aba46c3 100644
--- a/application-analytics-default/src/main/java/com/xwiki/analytics/internal/MostViewedJsonNormaliser.java
+++ b/application-analytics-default/src/main/java/com/xwiki/analytics/internal/MostViewedJsonNormaliser.java
@@ -30,6 +30,7 @@
import javax.inject.Named;
import javax.inject.Singleton;
+import org.apache.commons.lang3.exception.ExceptionUtils;
import org.xwiki.component.annotation.Component;
import org.xwiki.resource.CreateResourceReferenceException;
import org.xwiki.resource.CreateResourceTypeException;
@@ -45,7 +46,6 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.xwiki.analytics.JsonNormaliser;
-import org.apache.commons.lang3.exception.ExceptionUtils;
/**
* Implementation for {@link JsonNormaliser}.
diff --git a/application-analytics-test/application-analytics-test-docker/pom.xml b/application-analytics-test/application-analytics-test-docker/pom.xml
new file mode 100644
index 0000000..60bdbfd
--- /dev/null
+++ b/application-analytics-test/application-analytics-test-docker/pom.xml
@@ -0,0 +1,148 @@
+
+
+
+
+
+ 4.0.0
+
+ com.xwiki.analytics
+ application-analytics-test
+ 1.0-SNAPSHOT
+
+ application-analytics-test-docker
+ jar
+ Functional tests for the Analytics Application (Pro)
+
+
+ true
+
+
+
+
+
+ com.xwiki.licensing
+ application-licensing-test-api
+ ${licensing.version}
+ runtime
+
+
+
+ org.xwiki.platform
+ xwiki-platform-menu-ui
+ ${platform.version}
+ xar
+
+
+ com.xwiki.analytics
+ application-analytics-ui
+ ${project.version}
+ xar
+
+
+
+ com.xwiki.licensing
+ application-licensing-licensor-api
+
+
+
+
+
+
+
+ com.xwiki.analytics
+ application-analytics-test-pageobjects
+ ${project.version}
+ test
+
+
+ org.xwiki.platform
+ xwiki-platform-model-api
+ ${platform.version}
+
+
+ org.xwiki.commons
+ xwiki-commons-extension-api
+ ${commons.version}
+
+
+ com.google.code.findbugs
+ jsr305
+ 3.0.2
+
+
+
+ org.xwiki.platform
+ xwiki-platform-test-docker
+ ${platform.version}
+ test
+
+
+ com.xwiki.licensing
+ application-licensing-test-dependencies
+ ${licensing.version}
+ pom
+ test
+
+
+
+ src/test/it
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+
+
+ clover
+
+
+
+ org.openclover
+ clover
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-failsafe-plugin
+
+
+
+
+ xwiki.test.ui.profiles
+ clover
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/application-analytics-test/application-analytics-test-docker/src/test/it/com/xwiki/analytics/test/ui/AllITs.java b/application-analytics-test/application-analytics-test-docker/src/test/it/com/xwiki/analytics/test/ui/AllITs.java
new file mode 100644
index 0000000..62c25ea
--- /dev/null
+++ b/application-analytics-test/application-analytics-test-docker/src/test/it/com/xwiki/analytics/test/ui/AllITs.java
@@ -0,0 +1,34 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package com.xwiki.analytics.test.ui;
+
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.xwiki.test.docker.junit5.UITest;
+
+@UITest
+public class AllITs
+{
+ @Nested
+ @DisplayName("Analytics UI Test")
+ class NestedAnalyticsIT extends AnalyticsIT
+ {
+ }
+}
diff --git a/application-analytics-test/application-analytics-test-docker/src/test/it/com/xwiki/analytics/test/ui/AnalyticsIT.java b/application-analytics-test/application-analytics-test-docker/src/test/it/com/xwiki/analytics/test/ui/AnalyticsIT.java
new file mode 100644
index 0000000..ed44dc7
--- /dev/null
+++ b/application-analytics-test/application-analytics-test-docker/src/test/it/com/xwiki/analytics/test/ui/AnalyticsIT.java
@@ -0,0 +1,220 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package com.xwiki.analytics.test.ui;
+
+import java.util.Collections;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.openqa.selenium.By;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.containers.MySQLContainer;
+import org.testcontainers.utility.DockerImageName;
+import org.xwiki.test.docker.internal.junit5.DockerTestUtils;
+import org.xwiki.test.docker.junit5.TestConfiguration;
+import org.xwiki.test.docker.junit5.UITest;
+import org.xwiki.test.ui.TestUtils;
+import org.xwiki.test.ui.XWikiWebDriver;
+
+import com.xwiki.analytics.test.po.AnalyticsAdministrationSectionPage;
+import com.xwiki.analytics.test.po.AnalyticsViewPage;
+import com.xwiki.analytics.test.po.MatomoTestUtils;
+import com.xwiki.analytics.test.po.MostViewedPagesElement;
+import com.xwiki.analytics.test.po.RowEvolutionModal;
+import com.xwiki.analytics.test.ui.config.Config;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@UITest
+class AnalyticsIT
+{
+ @BeforeAll
+ void setup(XWikiWebDriver driver, TestConfiguration testConfiguration, TestUtils testUtils) throws Exception
+ {
+ setupContainers(driver, testConfiguration);
+ setupUIExtension(testUtils);
+ setupUsers(testUtils);
+ }
+
+ /**
+ * Check that the Save button displays the correct messages when the configurations provided by the users are
+ * incorrect.
+ */
+ @Test
+ @Order(1)
+ void checkWrongConfigs(XWikiWebDriver driver) throws InterruptedException
+ {
+ AnalyticsViewPage.gotoPage();
+ AnalyticsAdministrationSectionPage analyticsConfigViewPage = new AnalyticsAdministrationSectionPage();
+ analyticsConfigViewPage.gotoPage();
+ analyticsConfigViewPage.setTrackingCode("").setAuthTokenId(Config.MATOMO_AUTH_TOKEN).setIdSiteId("1")
+ .setRequestAddressId(Config.ADDRESS + ":" + Config.MATOMO_BRIDGE_PORT).saveConfigs();
+
+ analyticsConfigViewPage.waitForNotificationInProgressMessage("Saving...");
+ analyticsConfigViewPage.waitForNotificationSuccessMessage("Saved");
+ analyticsConfigViewPage.waitForNotificationInProgressMessage("Checking connection to Matomo.");
+ analyticsConfigViewPage.waitForNotificationErrorMessage(
+ "Failed to connect to Matomo. Please check your configuration values.");
+ }
+
+ /**
+ * Check that the Save button displays the correct messages when the configurations provided by the users are
+ * correct.
+ */
+ @Test
+ @Order(2)
+ void checkValidConfigs(XWikiWebDriver driver) throws InterruptedException
+ {
+ AnalyticsViewPage.gotoPage();
+ AnalyticsAdministrationSectionPage analyticsConfigViewPage = new AnalyticsAdministrationSectionPage();
+ analyticsConfigViewPage.gotoPage();
+ analyticsConfigViewPage.setTrackingCode(Config.getTrackingCode()).setAuthTokenId(Config.MATOMO_AUTH_TOKEN)
+ .setIdSiteId("1").setRequestAddressId("http://" + Config.ADDRESS + ":" + Config.MATOMO_BRIDGE_PORT + "/")
+ .saveConfigs();
+ analyticsConfigViewPage.waitForNotificationInProgressMessage("Saving...");
+ analyticsConfigViewPage.waitForNotificationSuccessMessage("Saved");
+ analyticsConfigViewPage.waitForNotificationInProgressMessage("Checking connection to Matomo.");
+ analyticsConfigViewPage.waitForNotificationSuccessMessage("Test connection succeeded!");
+ }
+
+ /**
+ * Checks if the admin has edit permissions in the home page of the application.
+ */
+ @Test
+ @Order(3)
+ void checkEditPermissionsForAdmin(XWikiWebDriver driver) throws InterruptedException
+ {
+
+ AnalyticsViewPage analyticsViewPage = AnalyticsViewPage.gotoPage();
+ assertTrue(analyticsViewPage.hasEditButton());
+ }
+
+ /**
+ * Checks if a user has view permissions in the home page of the application.
+ */
+ @Test
+ @Order(4)
+ void checkEditPermisionForUser(XWikiWebDriver driver, TestUtils testUtils) throws InterruptedException
+ {
+ testUtils.createUser("test", "test", null);
+ // Logout from the admin account
+ testUtils.setSession(null);
+ testUtils.login("test", "test");
+ AnalyticsViewPage analyticsViewPage = AnalyticsViewPage.gotoPage();
+ assertEquals("You are not allowed to view this page or perform this action.",
+ driver.findElement(By.cssSelector("p.xwikimessage")).getText());
+ // Login as the admin to run the next test
+ testUtils.setSession(null);
+ testUtils.loginAsAdmin();
+ }
+
+ /**
+ * Checks that the Row Evolution modal is loaded properly.
+ */
+ @Test
+ @Order(5)
+ void checkRowEvolutionModal()
+ {
+ AnalyticsViewPage.gotoPage();
+ MostViewedPagesElement mostViewedPagesElement = new MostViewedPagesElement();
+ RowEvolutionModal rowEvolutionModal = mostViewedPagesElement.openModal();
+ assertTrue(rowEvolutionModal.isDisplayed());
+ }
+
+ /**
+ * Creates the Admin user
+ */
+ private void setupUsers(TestUtils testUtils)
+ {
+ testUtils.loginAsSuperAdmin();
+ // TODO: remove this line after upgrading the XWiki parent to a version >= 15.10, because it was added as part
+ // of the createAdminUser method
+ testUtils.setGlobalRights("XWiki.XWikiAdminGroup", "", "admin", true);
+ testUtils.createAdminUser();
+ testUtils.loginAsAdmin();
+ }
+
+ /**
+ * Start the matomo and sql containers, rename the matomo.js to a random int to force the browser to load the
+ * tracking script without explicit settings and generate a new auth token for matomo to be used in the tests.
+ */
+ private void setupContainers(XWikiWebDriver driver, TestConfiguration testConfiguration) throws Exception
+ {
+ GenericContainer> sqlContainer = startDb(testConfiguration);
+ GenericContainer> matomoContainer = startMatomo(testConfiguration, sqlContainer);
+ // Modify the name of the matomo.js to make sure that the browser doesn't block it.
+ matomoContainer.execInContainer("sh", "-c",
+ "grep -rl 'matomo.js' /var/www/html/ | xargs -d '\\n' -I {} sed -i 's/matomo.js/36011373.js/g' \"{}\"");
+ matomoContainer.execInContainer("sh", "-c", "mv /var/www/html/matomo.js /var/www/html/36011373.js");
+ Config.MATOMO_AUTH_TOKEN =
+ MatomoTestUtils.createToken("http://" + Config.ADDRESS + ":" + matomoContainer.getMappedPort(80), driver);
+ }
+
+ /**
+ * Import the platform.html.head UIExtension point to make the tracking code work in the test environment.
+ * 'org.xwiki.platform:xwiki-platform-distribution-ui-base' but we didn't add it as a test dependency because it
+ * brings too many transitive dependencies that we don't need.
+ */
+ private void setupUIExtension(TestUtils testUtils) throws Exception
+ {
+ testUtils.setWikiPreference("meta",
+ "#foreach($uix in $services.uix.getExtensions(\"org.xwiki.platform.html.head\","
+ + " {'sortByParameter' : 'order'}))\n" + " $services.rendering.render($uix.execute(), 'xhtml/1.0')\n"
+ + "#end");
+ }
+
+ /**
+ * Create and start a container with the database.
+ */
+ private MySQLContainer startDb(TestConfiguration testConfiguration) throws Exception
+ {
+ // Since the MySQL container is derived from the official MySQL image I have to mark the image as compatible
+ // with MySQLContainers.
+ DockerImageName sqlContainer =
+ DockerImageName.parse(Config.DB_CONTAINER_NAME).asCompatibleSubstituteFor("mysql");
+ MySQLContainer> mysqlContainer =
+ new MySQLContainer<>(sqlContainer).withDatabaseName(Config.DB_NAME).withUsername(Config.DB_USERNAME)
+ .withPassword(Config.DB_PASSWORD).withExposedPorts(3306);
+ mysqlContainer.setPortBindings(
+ Collections.singletonList(String.format("%d:%d", Config.DB_BRIDGE_PORT, Config.DB_CONTAINER_EXPOSED_PORT)));
+ DockerTestUtils.startContainer(mysqlContainer, testConfiguration);
+ return mysqlContainer;
+ }
+
+ /**
+ * Creates&starts the Matomo container.
+ *
+ * @param testConfiguration test configuration
+ * @param dbContainer reference to the db container
+ */
+ private GenericContainer startMatomo(TestConfiguration testConfiguration, GenericContainer dbContainer)
+ throws Exception
+ {
+ GenericContainer> matomoContainer = new GenericContainer<>(Config.MATOMO_CONTAINER_NAME).withExposedPorts(80)
+ .withEnv("MATOMO_DATABASE_HOST",
+ Config.ADDRESS + ":" + dbContainer.getMappedPort(Config.DB_CONTAINER_EXPOSED_PORT))
+ .withFileSystemBind("src/test/it/resources/config.ini.php", Config.MATOMO_CONFIG_FILE_PATH);
+ matomoContainer.setPortBindings(Collections.singletonList(String.format("%d:80", Config.MATOMO_BRIDGE_PORT)));
+ DockerTestUtils.startContainer(matomoContainer, testConfiguration);
+ return matomoContainer;
+ }
+}
diff --git a/application-analytics-test/application-analytics-test-docker/src/test/it/com/xwiki/analytics/test/ui/config/Config.java b/application-analytics-test/application-analytics-test-docker/src/test/it/com/xwiki/analytics/test/ui/config/Config.java
new file mode 100644
index 0000000..c269845
--- /dev/null
+++ b/application-analytics-test/application-analytics-test-docker/src/test/it/com/xwiki/analytics/test/ui/config/Config.java
@@ -0,0 +1,69 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package com.xwiki.analytics.test.ui.config;
+
+public class Config
+{
+ // The custom sql container is needed to skip the Matomo installation wizard.
+ public static final String DB_CONTAINER_NAME = "farcasut/custom-mysql:latest";
+
+ public static final int DB_CONTAINER_EXPOSED_PORT = 3306;
+
+ public static final int DB_BRIDGE_PORT = 9034;
+
+ public static final String DB_NAME = "matomo";
+
+ public static final String DB_USERNAME = "matomo";
+
+ public static final String DB_PASSWORD = "secret";
+
+ public static final String ADDRESS = "172.17.0.1";
+
+ public static final String MATOMO_CONTAINER_NAME = "matomo:4.15.1";
+
+ public static final String MATOMO_CONFIG_FILE_PATH = "/var/www/html/config/config.ini.php";
+
+ public static final int MATOMO_BRIDGE_PORT = 9999;
+
+ public static final String MATOMO_CREDENTIALS = "ADMIN1";
+
+ public static String MATOMO_AUTH_TOKEN = "";
+
+ public static String getTrackingCode()
+ {
+ String sb = "\n"
+ + "\n"
+ + "\n";
+ return sb;
+ }
+}
diff --git a/application-analytics-test/application-analytics-test-docker/src/test/it/resources/config.ini.php b/application-analytics-test/application-analytics-test-docker/src/test/it/resources/config.ini.php
new file mode 100644
index 0000000..bec3429
--- /dev/null
+++ b/application-analytics-test/application-analytics-test-docker/src/test/it/resources/config.ini.php
@@ -0,0 +1,84 @@
+; DO NOT REMOVE THIS LINE
+; file automatically generated or modified by Matomo; you can manually override the default values in global.ini.php by redefining them in this file.
+[database]
+host = "172.17.0.1"
+username = "matomo"
+password = "secret"
+dbname = "matomo"
+tables_prefix = "matomo_"
+port = 9034
+charset = "utf8mb4"
+
+[General]
+enable_trusted_host_check = 0
+salt = "221e020a358ad259431e9ec76ba8a941"
+trusted_hosts[] = "localhost"
+trusted_hosts[] = "localhost:9999"
+debug = 1
+
+[PluginsInstalled]
+PluginsInstalled[] = "Diagnostics"
+PluginsInstalled[] = "Login"
+PluginsInstalled[] = "CoreAdminHome"
+PluginsInstalled[] = "UsersManager"
+PluginsInstalled[] = "SitesManager"
+PluginsInstalled[] = "Installation"
+PluginsInstalled[] = "Monolog"
+PluginsInstalled[] = "Intl"
+PluginsInstalled[] = "CoreVue"
+PluginsInstalled[] = "CorePluginsAdmin"
+PluginsInstalled[] = "CoreHome"
+PluginsInstalled[] = "WebsiteMeasurable"
+PluginsInstalled[] = "IntranetMeasurable"
+PluginsInstalled[] = "CoreVisualizations"
+PluginsInstalled[] = "Proxy"
+PluginsInstalled[] = "API"
+PluginsInstalled[] = "Widgetize"
+PluginsInstalled[] = "Transitions"
+PluginsInstalled[] = "LanguagesManager"
+PluginsInstalled[] = "Actions"
+PluginsInstalled[] = "Dashboard"
+PluginsInstalled[] = "MultiSites"
+PluginsInstalled[] = "Referrers"
+PluginsInstalled[] = "UserLanguage"
+PluginsInstalled[] = "DevicesDetection"
+PluginsInstalled[] = "Goals"
+PluginsInstalled[] = "Ecommerce"
+PluginsInstalled[] = "SEO"
+PluginsInstalled[] = "Events"
+PluginsInstalled[] = "UserCountry"
+PluginsInstalled[] = "GeoIp2"
+PluginsInstalled[] = "VisitsSummary"
+PluginsInstalled[] = "VisitFrequency"
+PluginsInstalled[] = "VisitTime"
+PluginsInstalled[] = "VisitorInterest"
+PluginsInstalled[] = "RssWidget"
+PluginsInstalled[] = "Feedback"
+PluginsInstalled[] = "TwoFactorAuth"
+PluginsInstalled[] = "CoreUpdater"
+PluginsInstalled[] = "CoreConsole"
+PluginsInstalled[] = "ScheduledReports"
+PluginsInstalled[] = "UserCountryMap"
+PluginsInstalled[] = "Live"
+PluginsInstalled[] = "PrivacyManager"
+PluginsInstalled[] = "ImageGraph"
+PluginsInstalled[] = "Annotations"
+PluginsInstalled[] = "MobileMessaging"
+PluginsInstalled[] = "Overlay"
+PluginsInstalled[] = "SegmentEditor"
+PluginsInstalled[] = "Insights"
+PluginsInstalled[] = "Morpheus"
+PluginsInstalled[] = "Contents"
+PluginsInstalled[] = "BulkTracking"
+PluginsInstalled[] = "Resolution"
+PluginsInstalled[] = "DevicePlugins"
+PluginsInstalled[] = "Heartbeat"
+PluginsInstalled[] = "Marketplace"
+PluginsInstalled[] = "ProfessionalServices"
+PluginsInstalled[] = "UserId"
+PluginsInstalled[] = "CustomJsTracker"
+PluginsInstalled[] = "Tour"
+PluginsInstalled[] = "PagePerformance"
+PluginsInstalled[] = "CustomDimensions"
+PluginsInstalled[] = "JsTrackerInstallCheck"
+
diff --git a/application-analytics-test/application-analytics-test-pageobjects/pom.xml b/application-analytics-test/application-analytics-test-pageobjects/pom.xml
new file mode 100644
index 0000000..0cd40b1
--- /dev/null
+++ b/application-analytics-test/application-analytics-test-pageobjects/pom.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+ 4.0.0
+
+ com.xwiki.analytics
+ application-analytics-test
+ 1.0-SNAPSHOT
+
+ application-analytics-test-pageobjects
+ Application Analytics (Pro) - Test - Page Objects
+ jar
+ Application Analytics (Pro) - Test - Page Objects
+
+
+ org.xwiki.platform
+ xwiki-platform-test-ui
+ ${platform.version}
+
+
+ org.xwiki.platform
+ xwiki-platform-administration-test-pageobjects
+ ${platform.version}
+
+
+ org.xwiki.platform
+ xwiki-platform-ckeditor-test-pageobjects
+ ${platform.version}
+ jar
+
+
+
\ No newline at end of file
diff --git a/application-analytics-test/application-analytics-test-pageobjects/src/main/java/com/xwiki/analytics/test/po/AnalyticsAdministrationSectionPage.java b/application-analytics-test/application-analytics-test-pageobjects/src/main/java/com/xwiki/analytics/test/po/AnalyticsAdministrationSectionPage.java
new file mode 100644
index 0000000..30e6752
--- /dev/null
+++ b/application-analytics-test/application-analytics-test-pageobjects/src/main/java/com/xwiki/analytics/test/po/AnalyticsAdministrationSectionPage.java
@@ -0,0 +1,93 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package com.xwiki.analytics.test.po;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+import org.openqa.selenium.support.FindBy;
+import org.xwiki.administration.test.po.AdministrationPage;
+import org.xwiki.test.ui.po.ViewPage;
+
+/**
+ * Responsible for interacting with the configuration tab of the application.
+ */
+public class AnalyticsAdministrationSectionPage extends ViewPage
+{
+ @FindBy(id = "Analytics.Code.ConfigurationClass_0_trackingCode")
+ private WebElement tracking_code;
+
+ @FindBy(id = "Analytics.Code.ConfigurationClass_0_authToken")
+ private WebElement auth_token;
+
+ @FindBy(id = "Analytics.Code.ConfigurationClass_0_siteId")
+ private WebElement site;
+
+ @FindBy(id = "Analytics.Code.ConfigurationClass_0_requestAddress")
+ private WebElement request_address;
+
+ public AnalyticsAdministrationSectionPage()
+ {
+
+ }
+
+ public AnalyticsAdministrationSectionPage gotoPage()
+ {
+ AdministrationPage administrationPage = AdministrationPage.gotoPage();
+ administrationPage.clickSection("Other", "Analytics");
+ return new AnalyticsAdministrationSectionPage();
+ }
+
+ public AnalyticsAdministrationSectionPage setTrackingCode(String value)
+ {
+ tracking_code.clear();
+ tracking_code.sendKeys(value);
+ return this;
+ }
+
+ public AnalyticsAdministrationSectionPage setAuthTokenId(String value)
+ {
+ auth_token.clear();
+ auth_token.sendKeys(value);
+ return this;
+ }
+
+ public AnalyticsAdministrationSectionPage setIdSiteId(String value)
+ {
+ site.clear();
+ site.sendKeys(value);
+ return this;
+ }
+
+ public AnalyticsAdministrationSectionPage setRequestAddressId(String value)
+ {
+ request_address.clear();
+ request_address.sendKeys(value);
+ return this;
+ }
+
+ public AnalyticsAdministrationSectionPage saveConfigs()
+ {
+ WebElement saveButton = getUtil().getDriver().findElement(By.cssSelector(".btn.btn-primary"));
+ Actions actions = getUtil().getDriver().createActions();
+ actions.moveToElement(saveButton).click().perform();
+ return this;
+ }
+}
diff --git a/application-analytics-test/application-analytics-test-pageobjects/src/main/java/com/xwiki/analytics/test/po/AnalyticsEditPage.java b/application-analytics-test/application-analytics-test-pageobjects/src/main/java/com/xwiki/analytics/test/po/AnalyticsEditPage.java
new file mode 100644
index 0000000..160412b
--- /dev/null
+++ b/application-analytics-test/application-analytics-test-pageobjects/src/main/java/com/xwiki/analytics/test/po/AnalyticsEditPage.java
@@ -0,0 +1,86 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package com.xwiki.analytics.test.po;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.openqa.selenium.By;
+import org.xwiki.ckeditor.test.po.MacroDialogSelectModal;
+import org.xwiki.model.reference.DocumentReference;
+import org.xwiki.test.ui.po.editor.EditPage;
+
+/**
+ * Responsible for interacting with the main page of the application when the page is in edit mode.
+ */
+public class AnalyticsEditPage extends EditPage
+{
+ public AnalyticsEditPage()
+ {
+ }
+
+ /**
+ * Adds a new macro to the homepage of the application.
+ *
+ * @param macroName name of the macro
+ * @return
+ */
+ public AnalyticsEditPage addNewMacro(String macroName)
+ {
+
+ this.clickAddGadget().selectMacro(macroName);
+ return this;
+ }
+
+ public static AnalyticsEditPage gotoPage()
+ {
+ DocumentReference documentReference = new DocumentReference("xwiki", "Analytics", "WebHome");
+ Map params = new HashMap<>();
+ params.put("force", "1");
+ getUtil().gotoPage(documentReference, "edit", params);
+ return new AnalyticsEditPage();
+ }
+
+ public AnalyticsViewPage saveDashboard()
+ {
+ this.clickSaveAndView();
+ return new AnalyticsViewPage();
+ }
+
+ private AnalyticsEditPage clickAddGadget()
+ {
+ getDriver().findElement(By.cssSelector(".addgadget")).click();
+ return this;
+ }
+
+ private void selectMacro(String macroName)
+ {
+ MacroDialogSelectModal macroDialogSelectModal = new MacroDialogSelectModal();
+ // Will bring into view the macro that I want to use.
+ getDriver().findElement(By.cssSelector(".macro-textFilter")).sendKeys(macroName);
+ macroDialogSelectModal.filterByText(macroName, 1);
+ macroDialogSelectModal.getFirstMacro();
+ macroDialogSelectModal.clickSelect();
+ // Right now the MacroDialogSelectModal doesn't have a method to press submit.
+ String css = ".modal.macro-editor-modal.in .modal-footer .btn-primary";
+ getDriver().waitUntilElementIsEnabled(getUtil().getDriver().findElement(By.cssSelector(css)));
+ getDriver().findElement(By.cssSelector(css)).click();
+ }
+}
diff --git a/application-analytics-test/application-analytics-test-pageobjects/src/main/java/com/xwiki/analytics/test/po/AnalyticsViewPage.java b/application-analytics-test/application-analytics-test-pageobjects/src/main/java/com/xwiki/analytics/test/po/AnalyticsViewPage.java
new file mode 100644
index 0000000..8cb4421
--- /dev/null
+++ b/application-analytics-test/application-analytics-test-pageobjects/src/main/java/com/xwiki/analytics/test/po/AnalyticsViewPage.java
@@ -0,0 +1,54 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package com.xwiki.analytics.test.po;
+
+import org.openqa.selenium.By;
+import org.xwiki.test.ui.po.ViewPage;
+
+/**
+ * Responsible for interacting with the main page of the application when the page is in view mode.
+ */
+public class AnalyticsViewPage extends ViewPage
+{
+ public AnalyticsViewPage()
+ {
+ }
+
+ public static AnalyticsViewPage gotoPage()
+ {
+ getUtil().gotoPage("Analytics", "WebHome");
+ return new AnalyticsViewPage();
+ }
+
+ /**
+ * Calculates the number of gadgets that are present on the homepage of the application.
+ *
+ * @return number of gadgets
+ */
+ public int getGadgetCount()
+ {
+ return getUtil().getDriver().findElements(By.className("gadget")).size();
+ }
+
+ public boolean hasEditButton()
+ {
+ return !getDriver().findElementsWithoutWaiting(By.id("tmEdit")).isEmpty();
+ }
+}
diff --git a/application-analytics-test/application-analytics-test-pageobjects/src/main/java/com/xwiki/analytics/test/po/MatomoTestUtils.java b/application-analytics-test/application-analytics-test-pageobjects/src/main/java/com/xwiki/analytics/test/po/MatomoTestUtils.java
new file mode 100644
index 0000000..922c795
--- /dev/null
+++ b/application-analytics-test/application-analytics-test-pageobjects/src/main/java/com/xwiki/analytics/test/po/MatomoTestUtils.java
@@ -0,0 +1,73 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package com.xwiki.analytics.test.po;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+import org.xwiki.test.ui.XWikiWebDriver;
+
+/**
+ * Encompass the process of creating a Matomo token using the browser interface provided by Matomo.
+ */
+public class MatomoTestUtils
+{
+ private static final String CREDENTIALS = "ADMIN1";
+
+ private static final String LOGIN_FORM_LOGIN_ID = "login_form_login";
+
+ private static final String LOGIN_FORM_PASSWORD_ID = "login_form_password";
+
+ private static final String LOGIN_FORM_SUBMIT_ID = "login_form_submit";
+
+ private static final String DESCRIPTION_ID = "description";
+
+ private static final String BTN_CSS_SELECTOR = ".btn";
+
+ private static final String TAG_NAME_CODE = "code";
+
+ /**
+ * Creates a new access token by accessing the Matomo GUI.
+ *
+ * @param address The address of the Matomo container.
+ * @return the newly created token as a string
+ */
+ public static String createToken(String address, XWikiWebDriver driver)
+ {
+ driver.get(address + "/index.php?module=UsersManager&action=addNewToken&idSite=1&period=day&date=2023-09-03");
+ driver.waitUntilElementIsVisible(By.id(LOGIN_FORM_LOGIN_ID));
+ driver.findElement(By.id(LOGIN_FORM_LOGIN_ID)).sendKeys(CREDENTIALS);
+ driver.waitUntilElementIsVisible(By.id(LOGIN_FORM_PASSWORD_ID));
+ driver.findElement(By.id(LOGIN_FORM_PASSWORD_ID)).sendKeys(CREDENTIALS);
+ driver.waitUntilElementIsVisible(By.id(LOGIN_FORM_SUBMIT_ID));
+ driver.findElement(By.id(LOGIN_FORM_SUBMIT_ID)).click();
+ driver.waitUntilElementIsVisible(By.id(LOGIN_FORM_PASSWORD_ID));
+ driver.findElement(By.id(LOGIN_FORM_PASSWORD_ID)).sendKeys(CREDENTIALS);
+ driver.waitUntilElementIsVisible(By.id(LOGIN_FORM_SUBMIT_ID));
+ driver.findElement(By.id(LOGIN_FORM_SUBMIT_ID)).click();
+ // Sometimes the Matomo page loads slower and to avoid a flicker the timeout needs to be increased.
+ driver.waitUntilCondition(ExpectedConditions.visibilityOfElementLocated(By.id(DESCRIPTION_ID)), 15);
+ driver.findElement(By.id(DESCRIPTION_ID)).sendKeys("TEST TOKEN");
+ driver.waitUntilElementIsVisible(By.cssSelector(BTN_CSS_SELECTOR));
+ driver.findElement(By.cssSelector(BTN_CSS_SELECTOR)).click();
+ driver.waitUntilElementIsVisible(By.tagName(TAG_NAME_CODE));
+ return driver.findElement(By.tagName(TAG_NAME_CODE)).getText();
+ }
+}
+
diff --git a/application-analytics-test/application-analytics-test-pageobjects/src/main/java/com/xwiki/analytics/test/po/MostViewedPagesElement.java b/application-analytics-test/application-analytics-test-pageobjects/src/main/java/com/xwiki/analytics/test/po/MostViewedPagesElement.java
new file mode 100644
index 0000000..29730e8
--- /dev/null
+++ b/application-analytics-test/application-analytics-test-pageobjects/src/main/java/com/xwiki/analytics/test/po/MostViewedPagesElement.java
@@ -0,0 +1,63 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+
+package com.xwiki.analytics.test.po;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+import org.xwiki.test.ui.po.BaseElement;
+
+/**
+ * View for the MostViewedPages macro that lets us interact with the macro.
+ */
+public class MostViewedPagesElement extends BaseElement
+{
+ static final private String MODAL_CSS = ".modal-dialog.modal-lg";
+
+ private WebElement container;
+
+ public MostViewedPagesElement()
+ {
+ }
+
+ /***
+ * This method first waits for the visibility of an information button, identified by a specific CSS selector.
+ * Once the information button is visible it selects the tile attribute and returns it.
+ * @return the description of a macro.
+ */
+ public String getMacroDescription()
+ {
+ return container.findElement(By.cssSelector(".analyticsDescription")).getAttribute("title");
+ }
+
+ public RowEvolutionModal openModal()
+ {
+ RowEvolutionModal modal = new RowEvolutionModal(By.cssSelector(MODAL_CSS));
+ modal.openModal();
+ return modal;
+ }
+
+ public void waitUntilReady(String id)
+ {
+ getDriver().waitUntilElementIsVisible(By.id(id));
+ container = getDriver().findElement(By.id(id));
+ }
+}
diff --git a/application-analytics-test/application-analytics-test-pageobjects/src/main/java/com/xwiki/analytics/test/po/RowEvolutionModal.java b/application-analytics-test/application-analytics-test-pageobjects/src/main/java/com/xwiki/analytics/test/po/RowEvolutionModal.java
new file mode 100644
index 0000000..897b39f
--- /dev/null
+++ b/application-analytics-test/application-analytics-test-pageobjects/src/main/java/com/xwiki/analytics/test/po/RowEvolutionModal.java
@@ -0,0 +1,40 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package com.xwiki.analytics.test.po;
+
+import org.openqa.selenium.By;
+import org.xwiki.test.ui.po.BaseModal;
+
+public class RowEvolutionModal extends BaseModal
+{
+ private static final String ROW_EVOLUTION_BUTTON_SELECTOR = ".analyticsRowEvolution";
+
+ public RowEvolutionModal(By selector)
+ {
+ super(selector);
+ }
+
+ public RowEvolutionModal openModal()
+ {
+ getDriver().waitUntilElementIsVisible(By.cssSelector(ROW_EVOLUTION_BUTTON_SELECTOR));
+ getDriver().findElement(By.cssSelector(ROW_EVOLUTION_BUTTON_SELECTOR)).click();
+ return this;
+ }
+}
diff --git a/application-analytics-test/pom.xml b/application-analytics-test/pom.xml
new file mode 100644
index 0000000..4f5b478
--- /dev/null
+++ b/application-analytics-test/pom.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+ 4.0.0
+
+ com.xwiki.analytics
+ application-analytics
+ 1.0-SNAPSHOT
+
+ application-analytics-test
+ Application Analytics (Pro)- Tests - Parent POM
+ pom
+ Application Analytics (Pro) - Tests - Parent POM
+
+
+ true
+ true
+
+ true
+
+
+ application-analytics-test-pageobjects
+
+
+
+ docker
+
+ application-analytics-test-docker
+
+
+
+
\ No newline at end of file
diff --git a/application-analytics-ui/pom.xml b/application-analytics-ui/pom.xml
index ef8c845..3fefb9c 100644
--- a/application-analytics-ui/pom.xml
+++ b/application-analytics-ui/pom.xml
@@ -20,7 +20,8 @@
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
-->
-
+
4.0.0
com.xwiki.analytics
@@ -63,6 +64,50 @@
application-analytics-default
${project.version}
+
+ org.xwiki.platform
+ xwiki-platform-localization-webjar
+ ${platform.version}
+ runtime
+
+
+ org.xwiki.platform
+ xwiki-platform-localization-script
+ ${platform.version}
+
+
+ org.xwiki.platform
+ xwiki-platform-localization-rest-default
+ ${platform.version}
+ runtime
+
+
+ org.xwiki.platform
+ xwiki-platform-dashboard-ui
+ runtime
+ ${platform.version}
+ xar
+
+
+ org.xwiki.platform
+ xwiki-platform-icon-ui
+ ${platform.version}
+ runtime
+ xar
+
+
+ org.xwiki.platform
+ xwiki-platform-uiextension-ui
+ ${platform.version}
+ xar
+
+
+ org.xwiki.platform
+ xwiki-platform-icon-rest-api
+ ${platform.version}
+ runtime
+ jar
+
org.xwiki.contrib
application-chartjs-webjar
diff --git a/application-analytics-ui/src/main/resources/Analytics/Code/AnalyticsJS.xml b/application-analytics-ui/src/main/resources/Analytics/Code/AnalyticsJS.xml
index 1e8de36..9a265f5 100644
--- a/application-analytics-ui/src/main/resources/Analytics/Code/AnalyticsJS.xml
+++ b/application-analytics-ui/src/main/resources/Analytics/Code/AnalyticsJS.xml
@@ -132,7 +132,7 @@
$('[id^="gadget_"]').each(function () {
let hiddenElement = $(this).find('.gadget-content .analytics-description');
if (hiddenElement.length > 0) {
- let dataElement = $(`<a class="${icon.cssClass} analyticsTitleMargin"></a>`);
+ let dataElement = $(`<a class="${icon.cssClass} analyticsDescription analyticsTitleMargin"></a>`);
dataElement.attr('title', hiddenElement.data('description'));
dataElement.attr('href', hiddenElement.data('url'));
$(this).find('.gadget-title').append(dataElement);
diff --git a/application-analytics-ui/src/main/resources/Analytics/Code/Macros/RowEvolutionJSON.xml b/application-analytics-ui/src/main/resources/Analytics/Code/Macros/RowEvolutionJSON.xml
index a108502..aee77e4 100644
--- a/application-analytics-ui/src/main/resources/Analytics/Code/Macros/RowEvolutionJSON.xml
+++ b/application-analytics-ui/src/main/resources/Analytics/Code/Macros/RowEvolutionJSON.xml
@@ -37,60 +37,62 @@
xwiki/2.1
true
{{velocity}}
-#set ($parameters = {
- 'period' : $request.period,
- 'date' : $request.date,
- 'module' : 'API',
- 'format' : 'json'
-})
-#set ($filters = {})
-#if ($request.macroName == 'MostViewedPages')
- #set ($discard = $parameters.put('pageUrl', $request.rowIdentifier))
- #set ($discard = $parameters.put('method', 'Actions.getPageUrl'))
-#elseif ($request.macroName == 'PagesFollowingASiteSearch')
- #set ($discard = $parameters.put('method', 'Actions.getPageUrlsFollowingSiteSearch'))
- #set ($discard = $parameters.put('expanded', '1'))
- #set ($discard = $parameters.put('flat', '1'))
- #set ($discard = $filters.put('url',$request.rowIdentifier))
-#elseif ($request.macroName == 'SearchCategories')
- #set ($discard = $parameters.put('segment', $request.rowIdentifier))
- #set ($discard = $parameters.put('method', 'Actions.getSiteSearchCategories'))
-#elseif ($request.macroName == 'SiteSearchKeyword')
- #set ($discard = $parameters.put('segment', $request.rowIdentifier))
- #set ($discard = $parameters.put('method', 'Actions.getSiteSearchKeywords'))
-#elseif ($request.macroName == 'BrowserEngines')
- #set ($discard = $parameters.put('method', 'DevicesDetection.getBrowserEngines'))
- #set ($discard = $parameters.put('segment', $request.rowIdentifier))
-#elseif ($request.macroName == 'Browsers')
- #set ($discard = $parameters.put('method', 'DevicesDetection.getBrowsers'))
- #set ($discard = $parameters.put('segment', $request.rowIdentifier))
-#elseif($request.macroName == 'Configurations')
- #set ($discard = $parameters.put('method', 'Resolution.getConfiguration'))
- #set ($discard = $parameters.put('segment', $request.rowIdentifier))
-#elseif($request.macroName == 'DeviceBrand')
- #set ($discard = $parameters.put('method', 'DevicesDetection.getBrand'))
- #set ($discard = $parameters.put('segment', $request.rowIdentifier))
-#elseif($request.macroName == 'DeviceModel')
- #set ($discard = $parameters.put('method', 'DevicesDetection.getModel'))
- #set ($discard = $parameters.put('segment', $request.rowIdentifier))
-#elseif($request.macroName == 'DeviceType')
- #set ($discard = $parameters.put('method', 'DevicesDetection.getType'))
- #set ($discard = $parameters.put('segment', $request.rowIdentifier))
-#elseif($request.macroName == 'ScreenResolution')
- #set ($discard = $parameters.put('method', 'Resolution.getResolution'))
- #set ($discard = $parameters.put('segment', $request.rowIdentifier))
-#elseif($request.macroName == 'OperatingSystemVersions')
- #set ($discard = $parameters.put('method', 'DevicesDetection.getOsVersions'))
- #set ($discard = $parameters.put('segment', $request.rowIdentifier))
+#if ($xcontext.action == 'get')
+ #set ($parameters = {
+ 'period' : $request.period,
+ 'date' : $request.date,
+ 'module' : 'API',
+ 'format' : 'json'
+ })
+ #set ($filters = {})
+ #if ($request.macroName == 'MostViewedPages')
+ #set ($discard = $parameters.put('pageUrl', $request.rowIdentifier))
+ #set ($discard = $parameters.put('method', 'Actions.getPageUrl'))
+ #elseif ($request.macroName == 'PagesFollowingASiteSearch')
+ #set ($discard = $parameters.put('method', 'Actions.getPageUrlsFollowingSiteSearch'))
+ #set ($discard = $parameters.put('expanded', '1'))
+ #set ($discard = $parameters.put('flat', '1'))
+ #set ($discard = $filters.put('url',$request.rowIdentifier))
+ #elseif ($request.macroName == 'SearchCategories')
+ #set ($discard = $parameters.put('segment', $request.rowIdentifier))
+ #set ($discard = $parameters.put('method', 'Actions.getSiteSearchCategories'))
+ #elseif ($request.macroName == 'SiteSearchKeyword')
+ #set ($discard = $parameters.put('segment', $request.rowIdentifier))
+ #set ($discard = $parameters.put('method', 'Actions.getSiteSearchKeywords'))
+ #elseif ($request.macroName == 'BrowserEngines')
+ #set ($discard = $parameters.put('method', 'DevicesDetection.getBrowserEngines'))
+ #set ($discard = $parameters.put('segment', $request.rowIdentifier))
+ #elseif ($request.macroName == 'Browsers')
+ #set ($discard = $parameters.put('method', 'DevicesDetection.getBrowsers'))
+ #set ($discard = $parameters.put('segment', $request.rowIdentifier))
+ #elseif($request.macroName == 'Configurations')
+ #set ($discard = $parameters.put('method', 'Resolution.getConfiguration'))
+ #set ($discard = $parameters.put('segment', $request.rowIdentifier))
+ #elseif($request.macroName == 'DeviceBrand')
+ #set ($discard = $parameters.put('method', 'DevicesDetection.getBrand'))
+ #set ($discard = $parameters.put('segment', $request.rowIdentifier))
+ #elseif($request.macroName == 'DeviceModel')
+ #set ($discard = $parameters.put('method', 'DevicesDetection.getModel'))
+ #set ($discard = $parameters.put('segment', $request.rowIdentifier))
+ #elseif($request.macroName == 'DeviceType')
+ #set ($discard = $parameters.put('method', 'DevicesDetection.getType'))
+ #set ($discard = $parameters.put('segment', $request.rowIdentifier))
+ #elseif($request.macroName == 'ScreenResolution')
+ #set ($discard = $parameters.put('method', 'Resolution.getResolution'))
+ #set ($discard = $parameters.put('segment', $request.rowIdentifier))
+ #elseif($request.macroName == 'OperatingSystemVersions')
+ #set ($discard = $parameters.put('method', 'DevicesDetection.getOsVersions'))
+ #set ($discard = $parameters.put('segment', $request.rowIdentifier))
#elseif($request.macroName == 'ExitPages')
#set ($discard = $parameters.put('pageUrl', $request.rowIdentifier))
#set ($discard = $parameters.put('method', 'Actions.getPageUrl'))
#elseif ($request.macroName == 'EntryPages')
#set ($discard = $parameters.put('pageUrl', $request.rowIdentifier))
#set ($discard = $parameters.put('method', 'Actions.getPageUrl'))
+ #end
+ #set ($analyticsResult = $services.analytics.makeRequest($parameters, $filters, 'RowEvolution'))
+ #jsonResponse($analyticsResult)
#end
-#set ($analyticsResult = $services.analytics.makeRequest($parameters, $filters, 'RowEvolution'))
-#jsonResponse($analyticsResult)
{{/velocity}}
diff --git a/application-analytics-ui/src/main/resources/Analytics/Code/Macros/VelocityMacros.xml b/application-analytics-ui/src/main/resources/Analytics/Code/Macros/VelocityMacros.xml
index 3375f84..611cd92 100644
--- a/application-analytics-ui/src/main/resources/Analytics/Code/Macros/VelocityMacros.xml
+++ b/application-analytics-ui/src/main/resources/Analytics/Code/Macros/VelocityMacros.xml
@@ -119,7 +119,7 @@
#end
#macro(analytics_modalRowEvolution $matomoFields $macroName $id)
- #set ($requestPageURL = $xwiki.getURL('Analytics.Code.Macros.RowEvolutionJSON'))
+ #set ($requestPageURL = $xwiki.getURL('Analytics.Code.Macros.RowEvolutionJSON', 'get'))
{{html clean=false}}
<div class="modal fade analyticsRowEvolutionModal" tabindex="-1" role="dialog" aria-label="chartModalLabel"
aria-hidden="true">
@@ -203,7 +203,7 @@
#set ($discard = $xwiki.jsx.use('Analytics.Code.AnalyticsJS'))
#else
{{html clean="false"}}
- <h2><div><span>$escapetool.xml($services.localization.render($nameTranslationKey))</span> <a title="$description" href=$url>$services.icon.renderHTML('info')</a><div></h2>
+ <h2><div><span>$escapetool.xml($services.localization.render($nameTranslationKey))</span> <a class="analyticsDescription" title="$description" href=$url>$services.icon.renderHTML('info')</a><div></h2>
{{/html}}
#end
#end
diff --git a/pom.xml b/pom.xml
index 0a60f42..2454622 100644
--- a/pom.xml
+++ b/pom.xml
@@ -53,4 +53,12 @@
application-analytics-default
application-analytics-ui
-
\ No newline at end of file
+
+
+ integration-tests
+
+ application-analytics-test
+
+
+
+