Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Giehl <stefan@matomo.org>2021-11-03 22:16:58 +0300
committerGitHub <noreply@github.com>2021-11-03 22:16:58 +0300
commit6b6f572693e1e4c0d0b371133bd2082e0c09525a (patch)
tree184e5036ebbf10a41518724c6d8cd3b9fa6e9f08
parent2415b8780314578ab557d29dd3a92ea4f8b40002 (diff)
Show correct metrics in row evolution triggered from goal view tables (#18228)
-rw-r--r--plugins/API/API.php6
-rw-r--r--plugins/API/RowEvolution.php154
-rw-r--r--plugins/CoreHome/javascripts/dataTable_rowactions.js30
-rw-r--r--plugins/CoreHome/templates/getRowEvolutionPopover.twig2
-rw-r--r--plugins/Goals/tests/UI/GoalsPages_spec.js110
-rw-r--r--plugins/Goals/tests/UI/GoalsTable_spec.js (renamed from tests/UI/specs/GoalsTable_spec.js)0
-rw-r--r--plugins/Goals/tests/UI/expected-screenshots/GoalsPages_ecommerce.png (renamed from tests/UI/expected-screenshots/UIIntegrationTest_goals_ecommerce.png)0
-rw-r--r--plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_goal.png (renamed from tests/UI/expected-screenshots/UIIntegrationTest_goals_individual_goal.png)0
-rw-r--r--plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_goal_updated.png (renamed from tests/UI/expected-screenshots/UIIntegrationTest_goals_individual_goal_updated.png)0
-rw-r--r--plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_row_evolution.png3
-rw-r--r--plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_row_evolution_reloaded.png3
-rw-r--r--plugins/Goals/tests/UI/expected-screenshots/GoalsPages_manage.png (renamed from tests/UI/expected-screenshots/UIIntegrationTest_goals_manage.png)0
-rw-r--r--plugins/Goals/tests/UI/expected-screenshots/GoalsPages_overview.png (renamed from tests/UI/expected-screenshots/UIIntegrationTest_goals_overview.png)0
-rw-r--r--plugins/Goals/tests/UI/expected-screenshots/GoalsPages_overview_row_evolution.png3
-rw-r--r--plugins/Goals/tests/UI/expected-screenshots/GoalsPages_overview_row_evolution_reloaded.png3
-rw-r--r--plugins/Goals/tests/UI/expected-screenshots/GoalsTable_goals_table_abandoned_carts.png (renamed from tests/UI/expected-screenshots/GoalsTable_goals_table_abandoned_carts.png)0
-rw-r--r--plugins/Goals/tests/UI/expected-screenshots/GoalsTable_goals_table_ecommerce.png (renamed from tests/UI/expected-screenshots/GoalsTable_goals_table_ecommerce.png)0
-rw-r--r--plugins/Goals/tests/UI/expected-screenshots/GoalsTable_goals_table_ecommerce_view.png (renamed from tests/UI/expected-screenshots/GoalsTable_goals_table_ecommerce_view.png)0
-rw-r--r--plugins/Goals/tests/UI/expected-screenshots/GoalsTable_goals_table_full.png (renamed from tests/UI/expected-screenshots/GoalsTable_goals_table_full.png)0
-rw-r--r--plugins/Goals/tests/UI/expected-screenshots/GoalsTable_goals_table_single.png (renamed from tests/UI/expected-screenshots/GoalsTable_goals_table_single.png)0
-rw-r--r--plugins/Goals/tests/UI/expected-screenshots/GoalsTable_initial.png (renamed from tests/UI/expected-screenshots/GoalsTable_initial.png)0
-rw-r--r--tests/UI/expected-screenshots/RowEvolution_row_evolution_goal_view.png3
-rw-r--r--tests/UI/expected-screenshots/RowEvolution_row_evolution_goal_view_reload.png3
-rw-r--r--tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png4
-rw-r--r--tests/UI/expected-screenshots/UIIntegrationTest_goals_individual_row_evolution.png3
-rw-r--r--tests/UI/specs/RowEvolution_spec.js28
-rw-r--r--tests/UI/specs/UIIntegration_spec.js60
27 files changed, 314 insertions, 101 deletions
diff --git a/plugins/API/API.php b/plugins/API/API.php
index f897145a1e..5a80d22478 100644
--- a/plugins/API/API.php
+++ b/plugins/API/API.php
@@ -413,9 +413,11 @@ class API extends \Piwik\Plugin\API
* @param bool|string $legendAppendMetric
* @param bool|string $labelUseAbsoluteUrl
* @param bool|int $idDimension
+ * @param string $labelSeries
+ * @param string|int $showGoalMetricsForGoal
* @return array
*/
- public function getRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $label = false, $segment = false, $column = false, $language = false, $idGoal = false, $legendAppendMetric = true, $labelUseAbsoluteUrl = true, $idDimension = false, $labelSeries = false)
+ public function getRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $label = false, $segment = false, $column = false, $language = false, $idGoal = false, $legendAppendMetric = true, $labelUseAbsoluteUrl = true, $idDimension = false, $labelSeries = false, $showGoalMetricsForGoal = false)
{
// check if site exists
$idSite = (int) $idSite;
@@ -443,7 +445,7 @@ class API extends \Piwik\Plugin\API
$rowEvolution = new RowEvolution();
return $rowEvolution->getRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $label, $segment, $column,
- $language, $apiParameters, $legendAppendMetric, $labelUseAbsoluteUrl, $labelSeries);
+ $language, $apiParameters, $legendAppendMetric, $labelUseAbsoluteUrl, $labelSeries, $showGoalMetricsForGoal);
}
/**
diff --git a/plugins/API/RowEvolution.php b/plugins/API/RowEvolution.php
index fe046e9ffb..1822d3e963 100644
--- a/plugins/API/RowEvolution.php
+++ b/plugins/API/RowEvolution.php
@@ -12,14 +12,20 @@ use Exception;
use Piwik\API\DataTableManipulator\LabelFilter;
use Piwik\API\DataTablePostProcessor;
use Piwik\API\Request;
+use Piwik\Cache;
use Piwik\Common;
use Piwik\DataTable;
+use Piwik\DataTable\Filter\AddColumnsProcessedMetricsGoal;
use Piwik\DataTable\Filter\CalculateEvolutionFilter;
use Piwik\DataTable\Filter\SafeDecodeLabel;
use Piwik\DataTable\Row;
use Piwik\Period;
use Piwik\Piwik;
use Piwik\Plugins\API\Filter\DataComparisonFilter;
+use Piwik\Plugins\Goals\Columns\Metrics\GoalSpecific\ConversionRate;
+use Piwik\Plugins\Goals\Columns\Metrics\GoalSpecific\Conversions;
+use Piwik\Plugins\Goals\Columns\Metrics\GoalSpecific\Revenue;
+use Piwik\Plugins\Goals\Columns\Metrics\GoalSpecific\RevenuePerVisit;
use Piwik\Site;
use Piwik\Url;
@@ -29,15 +35,15 @@ use Piwik\Url;
*/
class RowEvolution
{
- private static $actionsUrlReports = array(
+ private static $actionsUrlReports = [
'getPageUrls',
'getPageUrlsFollowingSiteSearch',
'getEntryPageUrls',
'getExitPageUrls',
'getPageUrl'
- );
+ ];
- public function getRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $label = false, $segment = false, $column = false, $language = false, $apiParameters = array(), $legendAppendMetric = true, $labelUseAbsoluteUrl = true, $labelSeries = '')
+ public function getRowEvolution($idSite, $period, $date, $apiModule, $apiAction, $label = false, $segment = false, $column = false, $language = false, $apiParameters = [], $legendAppendMetric = true, $labelUseAbsoluteUrl = true, $labelSeries = '', $showGoalMetricsForGoal = false)
{
// validation of requested $period & $date
if ($period == 'range') {
@@ -54,10 +60,64 @@ class RowEvolution
$metadata = $this->getRowEvolutionMetaData($idSite, $period, $date, $apiModule, $apiAction, $language, $apiParameters);
- $dataTable = $this->loadRowEvolutionDataFromAPI($metadata, $idSite, $period, $date, $apiModule, $apiAction, $labels, $segment, $apiParameters);
+ // if goal metrics should be shown, we replace the metrics
+ if ($showGoalMetricsForGoal !== false) {
+ $metadata['metrics'] = [
+ 'nb_visits' => $metadata['metrics']['nb_visits'],
+ ];
+
+ // Use ecommerce specific metrics / column names when only showing ecommerce metrics
+ if ($showGoalMetricsForGoal === Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER) {
+ $metadata['metrics']['goal_ecommerceOrder_nb_conversions'] = Piwik::translate('General_EcommerceOrders');
+ $metadata['metrics']['goal_ecommerceOrder_revenue'] = Piwik::translate('General_TotalRevenue');
+ $metadata['metrics']['goal_ecommerceOrder_conversion_rate'] = Piwik::translate('Goals_ConversionRate', Piwik::translate('General_EcommerceOrders'));
+ $metadata['metrics']['goal_ecommerceOrder_avg_order_revenue'] = Piwik::translate('General_AverageOrderValue');
+ $metadata['metrics']['goal_ecommerceOrder_items'] = Piwik::translate('General_PurchasedProducts');
+ $metadata['metrics']['goal_ecommerceOrder_revenue_per_visit'] = Piwik::translate('General_ColumnValuePerVisit');
+ } else {
+ $goalsToProcess = $this->getGoalsToProcess($showGoalMetricsForGoal, $idSite);
+
+ foreach ($goalsToProcess as $idGoal) {
+ if ($idGoal === Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER) {
+
+ $metadata['metrics']['goal_ecommerceOrder_conversion_rate'] = Piwik::translate('Goals_ConversionRate', Piwik::translate('General_EcommerceOrders'));
+
+ if ((int) $showGoalMetricsForGoal === AddColumnsProcessedMetricsGoal::GOALS_OVERVIEW) {
+ // only conversion rate is used for goals overview
+ continue;
+ }
+
+ $metadata['metrics']['goal_ecommerceOrder_nb_conversions'] = Piwik::translate('Goals_Conversions', Piwik::translate('General_EcommerceOrders'));
+ $metadata['metrics']['goal_ecommerceOrder_revenue'] = Piwik::translate('General_EcommerceOrders') . ' ' . Piwik::translate('General_ColumnRevenue');
+ $metadata['metrics']['goal_ecommerceOrder_revenue_per_visit'] = Piwik::translate('General_EcommerceOrders') . ' ' . Piwik::translate('General_ColumnValuePerVisit');
+ continue;
+ }
+
+ $conversionRateMetric = new ConversionRate($idSite, $idGoal);
+ $metadata['metrics'][$conversionRateMetric->getName()] = $conversionRateMetric->getTranslatedName();
+
+ if ((int) $showGoalMetricsForGoal === AddColumnsProcessedMetricsGoal::GOALS_OVERVIEW) {
+ // only conversion rate is used for goals overview
+ continue;
+ }
+
+ $conversionsMetric = new Conversions($idSite, $idGoal);
+ $revenueMetric = new Revenue($idSite, $idGoal);
+ $revenuePerVisitMetric = new RevenuePerVisit($idSite, $idGoal);
+
+ $metadata['metrics'][$conversionsMetric->getName()] = $conversionsMetric->getTranslatedName();
+ $metadata['metrics'][$revenueMetric->getName()] = $revenueMetric->getTranslatedName();
+ $metadata['metrics'][$revenuePerVisitMetric->getName()] = $revenuePerVisitMetric->getTranslatedName();
+ }
+
+ $metadata['metrics']['revenue_per_visit'] = Piwik::translate('General_ColumnValuePerVisit');
+ }
+ }
+
+ $dataTable = $this->loadRowEvolutionDataFromAPI($metadata, $idSite, $period, $date, $apiModule, $apiAction, $labels, $segment, $apiParameters, $showGoalMetricsForGoal);
if (empty($dataTable->getDataTables())) {
- return array();
+ return [];
}
if (empty($labels)) {
@@ -90,6 +150,44 @@ class RowEvolution
return $data;
}
+ protected function getGoalsToProcess($goalId, $idSite): array
+ {
+ switch ($goalId) {
+ case AddColumnsProcessedMetricsGoal::GOALS_FULL_TABLE:
+ case AddColumnsProcessedMetricsGoal::GOALS_OVERVIEW:
+ return $this->getAllGoalIds($idSite);
+ case Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER:
+ default:
+ return [$goalId];
+ }
+ }
+
+ protected function getAllGoalIds($idSite): array
+ {
+ $cache = Cache::getTransientCache();
+ $key = 'RowEvolution_allGoalIds_' . $idSite;
+
+ if ($cache->contains($key)) {
+ return $cache->fetch($key);
+ }
+
+ $goalIds = [];
+
+ if (Site::isEcommerceEnabledFor($idSite)) {
+ $goalIds[] = Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER;
+ }
+
+ $siteGoals = Request::processRequest('Goals.getGoals', ['idSite' => $idSite, 'filter_limit' => '-1'], $default = []);
+
+ foreach ($siteGoals as $goal) {
+ $goalIds[] = $goal['idgoal'];
+ }
+
+ $cache->save($key, $goalIds);
+
+ return $goalIds;
+ }
+
/**
* @param array $labels
* @param DataTable\Map $dataTable
@@ -186,11 +284,11 @@ class RowEvolution
$actualLabel = $this->formatQueryLabelForDisplay($idSite, $apiModule, $apiAction, $label);
}
- $return = array(
+ $return = [
'label' => SafeDecodeLabel::decodeLabelSafe($actualLabel),
'reportData' => $dataTable,
- 'metadata' => $metadata
- );
+ 'metadata' => $metadata,
+ ];
if (!empty($logo)) {
$return['logo'] = $logo;
}
@@ -248,20 +346,20 @@ class RowEvolution
* @param string $date
* @param string $apiModule
* @param string $apiAction
- * @param string|bool $label
+ * @param string|bool|array $label
* @param string|bool $segment
* @param array $apiParameters
* @throws Exception
* @return DataTable\Map|DataTable
*/
- private function loadRowEvolutionDataFromAPI($metadata, $idSite, $period, $date, $apiModule, $apiAction, $label, $segment, $apiParameters)
+ private function loadRowEvolutionDataFromAPI($metadata, $idSite, $period, $date, $apiModule, $apiAction, $label, $segment, $apiParameters, $showGoalMetricsForGoal)
{
if (!is_array($label)) {
- $label = array($label);
+ $label = [$label];
}
$label = array_map('rawurlencode', $label);
- $parameters = array(
+ $parameters = [
'method' => $apiModule . '.' . $apiAction,
'label' => $label,
'idSite' => $idSite,
@@ -277,7 +375,14 @@ class RowEvolution
// row corresponds with which label (since the labels can change, and rows
// can be sorted in a different order)
'labelFilterAddLabelIndex' => count($label) > 1 ? 1 : 0,
- );
+ ];
+
+ if ($showGoalMetricsForGoal !== false) {
+ $parameters['filter_show_goal_columns_process_goals'] = implode(',', $this->getGoalsToProcess($showGoalMetricsForGoal, $idSite));
+ $parameters['filter_update_columns_when_show_all_goals'] = 1;
+ $parameters['idGoal'] = $showGoalMetricsForGoal;
+ }
+
if (!empty($apiParameters) && is_array($apiParameters)) {
foreach ($apiParameters as $param => $value) {
$parameters[$param] = $value;
@@ -353,9 +458,9 @@ class RowEvolution
private function enhanceRowEvolutionMetaData(&$metadata, $dataTable)
{
// prepare result array for metrics
- $metricsResult = array();
+ $metricsResult = [];
foreach ($metadata['metrics'] as $metric => $name) {
- $metricsResult[$metric] = array('name' => $name);
+ $metricsResult[$metric] = ['name' => $name];
if (!empty($metadata['logos'][$metric])) {
$metricsResult[$metric]['logo'] = $metadata['logos'][$metric];
@@ -377,7 +482,7 @@ class RowEvolution
$lastDataTableRow = $lastDataTable->getFirstRow();
// Process min/max values
- $firstNonZeroFound = array();
+ $firstNonZeroFound = [];
foreach ($subDataTables as $subDataTable) {
// $subDataTable is the report for one period, it has only one row
$firstRow = $subDataTable->getFirstRow();
@@ -436,7 +541,7 @@ class RowEvolution
}
// get the processed label and logo (if any) for every requested label
- $actualLabels = $logos = array();
+ $actualLabels = $logos = [];
foreach ($labels as $labelIdx => $label) {
foreach ($dataTable->getDataTables() as $table) {
$labelRow = $this->getRowEvolutionRowFromLabelIdx($table, $labelIdx);
@@ -469,8 +574,8 @@ class RowEvolution
}
}
- // convert rows to be array($column.'_'.$labelIdx => $value) as opposed to
- // array('label' => $label, 'column' => $value).
+ // convert rows to be [$column.'_'.$labelIdx => $value] as opposed to
+ // ['label' => $label, 'column' => $value].
$dataTableMulti = $dataTable->getEmptyClone();
foreach ($dataTable->getDataTables() as $tableLabel => $table) {
$newRow = new Row();
@@ -505,7 +610,7 @@ class RowEvolution
// metadata / metrics should document the rows that are compared
// this way, UI code can be reused
- $metadata['metrics'] = array();
+ $metadata['metrics'] = [];
foreach ($actualLabels as $labelIndex => $label) {
if ($legendAppendMetric) {
$label .= ' (' . $metadata['columns'][$column] . ')';
@@ -520,11 +625,11 @@ class RowEvolution
$this->enhanceRowEvolutionMetaData($metadata, $dataTableMulti);
- return array(
+ return [
'column' => $column,
'reportData' => $dataTableMulti,
- 'metadata' => $metadata
- );
+ 'metadata' => $metadata,
+ ];
}
/**
@@ -551,8 +656,7 @@ class RowEvolution
private function cleanOriginalLabel($label)
{
$label = str_replace(LabelFilter::SEPARATOR_RECURSIVE_LABEL, ' - ', $label);
- $label = SafeDecodeLabel::decodeLabelSafe($label);
- return $label;
+ return SafeDecodeLabel::decodeLabelSafe($label);
}
private function checkDataTableInstance($lastDataTable)
diff --git a/plugins/CoreHome/javascripts/dataTable_rowactions.js b/plugins/CoreHome/javascripts/dataTable_rowactions.js
index 5283944e32..2c95333d29 100644
--- a/plugins/CoreHome/javascripts/dataTable_rowactions.js
+++ b/plugins/CoreHome/javascripts/dataTable_rowactions.js
@@ -76,6 +76,11 @@ DataTable_RowActions_Registry.register({
if (dataTable === null && param) {
// when row evolution is triggered from the url (not a click on the data table)
// we look for the data table instance in the dom
+ // This actually doesn't work very good, as opening a row evolution using url params
+ // directly also triggers loading the report datatable, which might not yet be finished at
+ // this state, so the datatable might not yet be available
+ // When migrating/refactoring this it might be good to use promises in some way, so it would
+ // be possible to actually trigger the row evolution popover once the origin report was loaded.
var report = param.split(':')[0];
var div = $(require('piwik/UI').DataTable.getDataTableByReport(report));
if (div.length && div.data('uiControlObject')) {
@@ -316,11 +321,25 @@ DataTable_RowActions_RowEvolution.prototype.performAction = function (label, tr,
$.each(this.dataTable.param, function (index, value) {
// we automatically add fields like idDimension, idGoal etc.
- if (index !== 'idSite' && index.indexOf('id') === 0 && $.isNumeric(value)) {
+ if (index !== 'idSite' && index.indexOf('id') === 0 && ($.isNumeric(value) || value.indexOf('ecommerce') === 0)) {
extraParams[index] = value;
}
});
+ if (this.dataTable && this.dataTable.jsViewDataTable === 'tableGoals') {
+ // When there is a idGoal parameter available, the user is currently viewing a Goal or Ecommerce page
+ // In this case we want to show the specific goal metrics in the row evolution
+ if (extraParams['idGoal']) {
+ extraParams['showGoalMetricsForGoal'] = extraParams['idGoal'];
+ delete(extraParams['idGoal']);
+ }
+ // If no idGoal is available it is a random report switched to goal visualization
+ // we then ensure the row evolution will show the goal overview metrics
+ else {
+ extraParams['showGoalMetricsForGoal'] = -1;
+ }
+ }
+
// check if abandonedCarts is in the dataTable params and if so, propagate to row evolution request
if (this.dataTable.param.abandonedCarts !== undefined) {
extraParams['abandonedCarts'] = this.dataTable.param.abandonedCarts;
@@ -437,7 +456,7 @@ DataTable_RowActions_RowEvolution.prototype.showRowEvolution = function (apiMeth
box.find('select.multirowevoltion-metric').change(function () {
var metric = $(this).val();
Piwik_Popover.onClose(false); // unbind listener that resets multiEvolutionRows
- var extraParams = {action: 'getMultiRowEvolutionPopover', column: metric};
+ extraParams.column = metric;
self.openPopover(apiMethod, extraParams, label);
return true;
});
@@ -463,13 +482,6 @@ DataTable_RowActions_RowEvolution.prototype.showRowEvolution = function (apiMeth
}
}
- if (self.dataTable && self.dataTable.jsViewDataTable === 'tableGoals') {
- // remove idGoal param, when it's set for goal visualizations
- if (extraParams['idGoal']) {
- delete(extraParams['idGoal']);
- }
- }
-
$.extend(requestParams, extraParams);
var ajaxRequest = new ajaxHelper();
diff --git a/plugins/CoreHome/templates/getRowEvolutionPopover.twig b/plugins/CoreHome/templates/getRowEvolutionPopover.twig
index 8b95dd680f..b45ce4f154 100644
--- a/plugins/CoreHome/templates/getRowEvolutionPopover.twig
+++ b/plugins/CoreHome/templates/getRowEvolutionPopover.twig
@@ -18,7 +18,7 @@
</td>
<td class="text">
<span class="evolution-graph-colors" data-name="series{{ (i % seriesColorCount) + 1 }}">
- {{- metric.label|raw -}}
+ {{- metric.label|rawSafeDecoded -}}
</span>
{% if metric.details %}:
<span class="details" title="{{ metric.minmax }}">{{ metric.details|raw }}</span>
diff --git a/plugins/Goals/tests/UI/GoalsPages_spec.js b/plugins/Goals/tests/UI/GoalsPages_spec.js
new file mode 100644
index 0000000000..a8180b5e79
--- /dev/null
+++ b/plugins/Goals/tests/UI/GoalsPages_spec.js
@@ -0,0 +1,110 @@
+/*!
+ * Matomo - free/libre analytics platform
+ *
+ * Screenshot integration tests.
+ *
+ * @link https://matomo.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ */
+
+describe("GoalsPages", function () {
+ this.timeout(0);
+
+ var generalParams = 'idSite=1&period=year&date=2012-08-09',
+ urlBaseGeneric = 'module=CoreHome&action=index&',
+ urlBase = urlBaseGeneric + generalParams;
+
+ // goals pages
+ it('should load the goals > ecommerce page correctly', async function () {
+ await page.goto("?" + urlBase + "#?" + generalParams + "&category=Goals_Ecommerce&subcategory=General_Overview")
+ await page.waitForNetworkIdle();
+
+ expect(await page.screenshotSelector('.pageWrap')).to.matchImage('ecommerce');
+ });
+
+ it('should load the goals > overview page correctly', async function () {
+ await page.goto("?" + urlBase + "#?" + generalParams + "&category=Goals_Goals&subcategory=General_Overview");
+ await page.waitForNetworkIdle();
+
+ expect(await page.screenshotSelector('.pageWrap')).to.matchImage('overview');
+ });
+
+ it('should load row evolution with goal metrics', async function() {
+ const row = await page.waitForSelector('.reportsByDimensionView tbody tr:first-child');
+ await row.hover();
+
+ const icon = await page.waitForSelector('.reportsByDimensionView tbody tr:first-child a.actionRowEvolution');
+ await icon.click();
+
+ await page.waitForSelector('.ui-dialog');
+ await page.waitForNetworkIdle();
+
+ const dialog = await page.$('.ui-dialog');
+ expect(await dialog.screenshot()).to.matchImage('overview_row_evolution');
+ });
+
+ it('should load row evolution with goal metrics again when reloading the page url', async function() {
+ // page.reload() won't work with url hashes
+ const url = await page.evaluate('location.href');
+ await page.goto('about:blank');
+ await page.goto(url);
+
+ await page.waitForSelector('.ui-dialog');
+ await page.waitForNetworkIdle();
+
+ const dialog = await page.$('.ui-dialog');
+ expect(await dialog.screenshot()).to.matchImage('overview_row_evolution_reloaded');
+ });
+
+ it('should load the goals > management page correctly', async function () {
+ await page.goto("?" + generalParams + "&module=Goals&action=manage");
+ await page.waitForNetworkIdle();
+
+ expect(await page.screenshotSelector('#content,.top_bar_sites_selector,.entityContainer')).to.matchImage('manage');
+ });
+
+ it('should load the goals > single goal page correctly', async function () {
+ await page.goto("?" + urlBase + "#?" + generalParams + "&category=Goals_Goals&subcategory=1");
+ await page.waitForNetworkIdle();
+
+ expect(await page.screenshotSelector('.pageWrap')).to.matchImage('individual_goal');
+ });
+
+ it('should update the evolution chart if a sparkline is clicked', async function () {
+ elem = await page.jQuery('.sparkline.linked:contains(%)');
+ await elem.click();
+ await page.waitForNetworkIdle();
+ await page.mouse.move(-10, -10);
+
+ expect(await page.screenshotSelector('.pageWrap')).to.matchImage('individual_goal_updated');
+ });
+
+ // should load the row evolution [see #11526]
+ it('should show rov evolution for goal tables', async function () {
+ await page.waitForNetworkIdle();
+
+ const row = await page.waitForSelector('.dataTable tbody tr:first-child');
+ await row.hover();
+
+ const icon = await page.waitForSelector('.dataTable tbody tr:first-child a.actionRowEvolution');
+ await icon.click();
+
+ await page.waitForSelector('.rowevolution');
+ await page.waitForNetworkIdle();
+
+ expect(await page.screenshotSelector('.ui-dialog')).to.matchImage('individual_row_evolution');
+ });
+
+ it('should load row evolution with goal metrics again when reloading the page url', async function() {
+ // page.reload() won't work with url hashes
+ const url = await page.evaluate('location.href');
+ await page.goto('about:blank');
+ await page.goto(url);
+
+ await page.waitForSelector('.ui-dialog');
+ await page.waitForNetworkIdle();
+
+ const dialog = await page.$('.ui-dialog');
+ expect(await dialog.screenshot()).to.matchImage('individual_row_evolution_reloaded');
+ });
+});
diff --git a/tests/UI/specs/GoalsTable_spec.js b/plugins/Goals/tests/UI/GoalsTable_spec.js
index 828a2fb67f..828a2fb67f 100644
--- a/tests/UI/specs/GoalsTable_spec.js
+++ b/plugins/Goals/tests/UI/GoalsTable_spec.js
diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_goals_ecommerce.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_ecommerce.png
index 0d2e28a482..0d2e28a482 100644
--- a/tests/UI/expected-screenshots/UIIntegrationTest_goals_ecommerce.png
+++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_ecommerce.png
diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_goals_individual_goal.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_goal.png
index a7dbc81084..a7dbc81084 100644
--- a/tests/UI/expected-screenshots/UIIntegrationTest_goals_individual_goal.png
+++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_goal.png
diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_goals_individual_goal_updated.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_goal_updated.png
index e95f6576e6..e95f6576e6 100644
--- a/tests/UI/expected-screenshots/UIIntegrationTest_goals_individual_goal_updated.png
+++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_goal_updated.png
diff --git a/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_row_evolution.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_row_evolution.png
new file mode 100644
index 0000000000..6201921ddd
--- /dev/null
+++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_row_evolution.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:40b8aa2e147e3f3d012ef827fa680e1629fffd81a7427ff6d06744f92909e13a
+size 79278
diff --git a/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_row_evolution_reloaded.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_row_evolution_reloaded.png
new file mode 100644
index 0000000000..f33eddee94
--- /dev/null
+++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_individual_row_evolution_reloaded.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a554ae7a8249dd867010724260abf32dd65351433f28c2c07ff4fac309b1f4ae
+size 59883
diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_goals_manage.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_manage.png
index 34fedec0a5..34fedec0a5 100644
--- a/tests/UI/expected-screenshots/UIIntegrationTest_goals_manage.png
+++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_manage.png
diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_goals_overview.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_overview.png
index 110323f1c6..110323f1c6 100644
--- a/tests/UI/expected-screenshots/UIIntegrationTest_goals_overview.png
+++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_overview.png
diff --git a/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_overview_row_evolution.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_overview_row_evolution.png
new file mode 100644
index 0000000000..be7b352951
--- /dev/null
+++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_overview_row_evolution.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8c424966632880c030448e4fba43643d099b2a6ae4cf8446dd5c58981f1a7e16
+size 177941
diff --git a/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_overview_row_evolution_reloaded.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_overview_row_evolution_reloaded.png
new file mode 100644
index 0000000000..57910939c1
--- /dev/null
+++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsPages_overview_row_evolution_reloaded.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:ca6c2269f463d0918fc864b094ba7cdb5791d90392749ab3a6c8aeb8b6f33a1a
+size 158599
diff --git a/tests/UI/expected-screenshots/GoalsTable_goals_table_abandoned_carts.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsTable_goals_table_abandoned_carts.png
index 885810d277..885810d277 100644
--- a/tests/UI/expected-screenshots/GoalsTable_goals_table_abandoned_carts.png
+++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsTable_goals_table_abandoned_carts.png
diff --git a/tests/UI/expected-screenshots/GoalsTable_goals_table_ecommerce.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsTable_goals_table_ecommerce.png
index 323b44e395..323b44e395 100644
--- a/tests/UI/expected-screenshots/GoalsTable_goals_table_ecommerce.png
+++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsTable_goals_table_ecommerce.png
diff --git a/tests/UI/expected-screenshots/GoalsTable_goals_table_ecommerce_view.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsTable_goals_table_ecommerce_view.png
index a693202456..a693202456 100644
--- a/tests/UI/expected-screenshots/GoalsTable_goals_table_ecommerce_view.png
+++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsTable_goals_table_ecommerce_view.png
diff --git a/tests/UI/expected-screenshots/GoalsTable_goals_table_full.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsTable_goals_table_full.png
index 07d7dedd70..07d7dedd70 100644
--- a/tests/UI/expected-screenshots/GoalsTable_goals_table_full.png
+++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsTable_goals_table_full.png
diff --git a/tests/UI/expected-screenshots/GoalsTable_goals_table_single.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsTable_goals_table_single.png
index c64083dc31..c64083dc31 100644
--- a/tests/UI/expected-screenshots/GoalsTable_goals_table_single.png
+++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsTable_goals_table_single.png
diff --git a/tests/UI/expected-screenshots/GoalsTable_initial.png b/plugins/Goals/tests/UI/expected-screenshots/GoalsTable_initial.png
index c3ca30817f..c3ca30817f 100644
--- a/tests/UI/expected-screenshots/GoalsTable_initial.png
+++ b/plugins/Goals/tests/UI/expected-screenshots/GoalsTable_initial.png
diff --git a/tests/UI/expected-screenshots/RowEvolution_row_evolution_goal_view.png b/tests/UI/expected-screenshots/RowEvolution_row_evolution_goal_view.png
new file mode 100644
index 0000000000..bea685de86
--- /dev/null
+++ b/tests/UI/expected-screenshots/RowEvolution_row_evolution_goal_view.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0ade776bd2bbf4bc2e43d0c0ace6796b21a01d4c2c2510d57085dd5cf1e7ab03
+size 91617
diff --git a/tests/UI/expected-screenshots/RowEvolution_row_evolution_goal_view_reload.png b/tests/UI/expected-screenshots/RowEvolution_row_evolution_goal_view_reload.png
new file mode 100644
index 0000000000..bea685de86
--- /dev/null
+++ b/tests/UI/expected-screenshots/RowEvolution_row_evolution_goal_view_reload.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0ade776bd2bbf4bc2e43d0c0ace6796b21a01d4c2c2510d57085dd5cf1e7ab03
+size 91617
diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png b/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png
index 72596a2cd9..7a057fa3e7 100644
--- a/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png
+++ b/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:97283bcac38de15ea354376e3554411827912136de9cd25542b0d53721729abf
-size 4994214
+oid sha256:d92406e3cf6894abda91dcf4a0e71c645a8a48c5451e649df4ccc982e8dbacd4
+size 4995440
diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_goals_individual_row_evolution.png b/tests/UI/expected-screenshots/UIIntegrationTest_goals_individual_row_evolution.png
deleted file mode 100644
index ad9461ebb1..0000000000
--- a/tests/UI/expected-screenshots/UIIntegrationTest_goals_individual_row_evolution.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:6fa8eb9fe92f45054973d474a76f2385527083a395c9c6916ec10aad81fb168a
-size 65721
diff --git a/tests/UI/specs/RowEvolution_spec.js b/tests/UI/specs/RowEvolution_spec.js
index 2ed7337f99..a503aeeb30 100644
--- a/tests/UI/specs/RowEvolution_spec.js
+++ b/tests/UI/specs/RowEvolution_spec.js
@@ -79,6 +79,34 @@ describe("RowEvolution", function () {
expect(await dialog.screenshot()).to.matchImage('multirow_evolution_other_metric');
});
+ it('should load row evolution for goals view', async function() {
+ await page.goto(viewDataTableUrl + '&forceView=1&viewDataTable=tableGoals');
+ const row = await page.waitForSelector('tbody tr:first-child');
+ await row.hover();
+
+ const icon = await page.waitForSelector('tbody tr:first-child a.actionRowEvolution');
+ await icon.click();
+
+ await page.waitForSelector('.ui-dialog');
+ await page.waitForNetworkIdle();
+
+ const dialog = await page.$('.ui-dialog');
+ expect(await dialog.screenshot()).to.matchImage('row_evolution_goal_view');
+ });
+
+ it('should load row evolution with goal metrics again when reloading the page url', async function() {
+ // page.reload() won't work with url hashes
+ const url = await page.evaluate('location.href');
+ await page.goto('about:blank');
+ await page.goto(url);
+
+ await page.waitForSelector('.ui-dialog');
+ await page.waitForNetworkIdle();
+
+ const dialog = await page.$('.ui-dialog');
+ expect(await dialog.screenshot()).to.matchImage('row_evolution_goal_view_reload');
+ });
+
it('should display row evolution for an ecommerce item report correctly', async function() {
await page.goto(ecommerceItemReportWidgetized);
const row = await page.waitForSelector('tbody tr:first-child');
diff --git a/tests/UI/specs/UIIntegration_spec.js b/tests/UI/specs/UIIntegration_spec.js
index 1cc69b0e34..a2680e5643 100644
--- a/tests/UI/specs/UIIntegration_spec.js
+++ b/tests/UI/specs/UIIntegration_spec.js
@@ -229,7 +229,7 @@ describe("UIIntegrationTest", function () { // TODO: Rename to Piwik?
testEnvironment.queryParamOverride['ignoreClearAllViewDataTableParameters'] = 1;
- // use columns query param to make sure columns works when supplied in URL fragment
+ // use columns query param to make sure columns works when supplied in URL fragment
await page.goto("?" + urlBase + "#?" + generalParams + "&category=General_Visitors&subcategory=General_Overview&columns=nb_visits,nb_actions");
await page.waitForNetworkIdle();
@@ -572,64 +572,6 @@ describe("UIIntegrationTest", function () { // TODO: Rename to Piwik?
});
});
- describe("GoalsPages", function () {
- this.title = parentSuite.title; // to make sure the screenshot prefix is the same
-
- // goals pages
- it('should load the goals > ecommerce page correctly', async function () {
- await page.goto("?" + urlBase + "#?" + generalParams + "&category=Goals_Ecommerce&subcategory=General_Overview")
- await page.waitForNetworkIdle();
-
- expect(await page.screenshotSelector('.pageWrap')).to.matchImage('goals_ecommerce');
- });
-
- it('should load the goals > overview page correctly', async function () {
- await page.goto("?" + urlBase + "#?" + generalParams + "&category=Goals_Goals&subcategory=General_Overview");
- await page.waitForNetworkIdle();
-
- expect(await page.screenshotSelector('.pageWrap')).to.matchImage('goals_overview');
- });
-
- it('should load the goals > management page correctly', async function () {
- await page.goto("?" + generalParams + "&module=Goals&action=manage");
- await page.waitForNetworkIdle();
-
- expect(await page.screenshotSelector('#content,.top_bar_sites_selector,.entityContainer')).to.matchImage('goals_manage');
- });
-
- it('should load the goals > single goal page correctly', async function () {
- await page.goto("?" + urlBase + "#?" + generalParams + "&category=Goals_Goals&subcategory=1");
- await page.waitForNetworkIdle();
-
- expect(await page.screenshotSelector('.pageWrap')).to.matchImage('goals_individual_goal');
- });
-
- it('should update the evolution chart if a sparkline is clicked', async function () {
- elem = await page.jQuery('.sparkline.linked:contains(%)');
- await elem.click();
- await page.waitForNetworkIdle();
- await page.mouse.move(-10, -10);
-
- expect(await page.screenshotSelector('.pageWrap')).to.matchImage('goals_individual_goal_updated');
- });
-
- // should load the row evolution [see #11526]
- it('should show rov evolution for goal tables', async function () {
- await page.waitForNetworkIdle();
-
- const row = await page.waitForSelector('.dataTable tbody tr:first-child');
- await row.hover();
-
- const icon = await page.waitForSelector('.dataTable tbody tr:first-child a.actionRowEvolution');
- await icon.click();
-
- await page.waitForSelector('.rowevolution');
- await page.waitForNetworkIdle();
-
- expect(await page.screenshotSelector('.ui-dialog')).to.matchImage('goals_individual_row_evolution');
- });
- });
-
describe("EventsPages", function () {
this.title = parentSuite.title; // to make sure the screenshot prefix is the same