Skip to content
This repository has been archived by the owner on Mar 18, 2021. It is now read-only.

COM-20077-GA-event-doesnt-work #149

Merged
merged 1 commit into from
Dec 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
!var/SymfonyRequirements.php
/vendor/
/web/bundles/

/node_modules/
/package-lock.json
/web/assets/js/compiled/
.php~

# Legacy related ignores, that are generated by composer (settings not handled out of the box)
Expand Down
14 changes: 8 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Tests cannot be run from metarepo - it's a public repository, which doesn't have access to private repositories on Travis (for security reasons).
# The actual test setup is in Page Builder bundle.
language: php
php:
- '5.6'
language: node_js

node_js:
- '11'

install:
- npm install

script:
- echo 'Test suite moved to PageBuilder bundle'
- npm test
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

{% import _self as Helper %}

<div class="window">
<div class="window" data-ga-action="eZ launchpad documentation widget">
<div class="titlebar">
<div class="buttons">
<div class="close">
Expand Down
2 changes: 2 additions & 0 deletions app/Resources/views/themes/ezplatform/full/home.html.twig
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{% extends '@ezdesign/pagelayout.html.twig' %}

{% block gaCategory %}downloads{% endblock %}

{% block main %}
<main class="white-background">
{% endblock %}
Expand Down
4 changes: 3 additions & 1 deletion app/Resources/views/themes/ezplatform/pagelayout.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
{% block canonical %}
{% endblock %}
</head>
<body>
<body data-ga-category="{% block gaCategory %}{% endblock %}">
{% block main %}
<main>
{% endblock %}
Expand All @@ -59,6 +59,8 @@
'bundles/ezplatformadminuiassets/vendors/popper.js/dist/umd/popper.min.js'
'bundles/ezplatformadminuiassets/vendors/bootstrap/dist/js/bootstrap.min.js'
'assets/js/prism.js'
'assets/js/stringUtils.helper.js'
'assets/js/GoogleAnalyticsService.js'
'assets/js/app.js'
%}
<script type="text/javascript" src="{{ asset_url }}"></script>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,48 +7,47 @@
<ul class="nav nav-pills nav-justified" role="tablist">
{% if not ez_is_field_empty(content, 'composer_description') %}
<li class="nav-item">
<a href="#composer-option" class="nav-link active show" data-toggle="tab" role="tab">
<a href="#composer-option" class="nav-link active show" data-toggle="tab" data-ga-action="Composer tab" role="tab">
<img src="{{ asset('images/composer.svg', 'ezdesign') }}" alt="Download" class="download">
<div class="label">Composer</div>
<span class="label">Composer</span>
</a>
</li>
{% endif %}
<li class="nav-item">
<a href="#ezlaunchpad-option" class="nav-link" data-toggle="tab" role="tab">
<a href="#ezlaunchpad-option" class="nav-link" data-toggle="tab" data-ga-action="eZ launchpad tab" role="tab">
<img src="{{ asset('images/ez-launchpad.svg', 'ezdesign') }}" alt="eZ Launchpad" class="download">
<div class="label">eZ Launchpad</div>
<span class="label">eZ Launchpad</span>
</a>
</li>
{% if not ez_is_field_empty(content, 'platform_sh_description') %}
<li class="nav-item">
<a href="#platform-sh-option" class="nav-link" data-toggle="tab" role="tab">
<a href="#platform-sh-option" class="nav-link" data-toggle="tab" data-ga-action="platform.sh tab" role="tab">
<img src="{{ asset('images/platform-sh-logo.svg', 'ezdesign') }}" alt="Download" class="download">
<div class="label">platform.sh</div>
<span class="label">platform.sh</span>
</a>
</li>
{% endif %}
{% if not ez_is_field_empty(content, 'download_description') %}
<li class="nav-item">
<a href="#download-option" class="nav-link" data-toggle="tab" role="tab">
<a href="#download-option" class="nav-link" data-toggle="tab" data-ga-action="Download tab" role="tab">
<img src="{{ asset('images/download.svg', 'ezdesign') }}" alt="Download" class="download">
<div class="label">Download</div>
<span class="label">Download</span>
</a>
</li>
{% endif %}
</ul>

<div class="tab-content">
{% if not ez_is_field_empty(content, 'composer_description') %}
<div role="tabpanel" class="tab-pane active" id="composer-option">
<div class="details">
<h3>Composer</h3>
<div class="description text-center">
<div data-ga-action="Composer documentation" class="description text-center ga-link-listener">
{{ ez_render_field(content, 'composer_description') }}
</div>
</div>
<div class="launch text-center">
<img src="{{ asset('images/pulley-hero.svg', 'ezdesign') }}" alt="Platform.sh" class="hero">
<a href="//doc.ezplatform.com/en/latest/getting_started/install_using_composer/" class="btn btn-primary">Install with composer</a>
<a href="//doc.ezplatform.com/en/latest/getting_started/install_using_composer/" class="btn btn-primary" data-ga-action="Install with Composer">Install with composer</a>
</div>
</div>
{% endif %}
Expand All @@ -61,7 +60,6 @@
{{ ez_render_field(content, 'download_description') }}
</div>
</div>

<table class="table table-striped text-center download-table">
<thead>
<tr>
Expand All @@ -72,7 +70,7 @@
</thead>
<tbody>
{% if betas is not empty %}
<tr class="beta">
<tr class="beta" data-ga-action="Download" data-ga-label="{{ ez_field_value(release, 'release_version') }}">
<th scope="row">
<a href="{{ ez_field_value(betas|first, 'file') }}">{{ ez_render_field(betas|first, 'release_version') }}</a>
</th>
Expand All @@ -88,7 +86,7 @@
{% endif %}

{% for release in releases %}
<tr class="releases">
<tr class="releases" data-ga-action="Download" data-ga-label="{{ ez_field_value(release, 'release_version') }}">
<th scope="row"{% if ez_field_value(release, 'lts').bool %} class="lts"{% endif %}>
<a href="{{ ez_field_value(release, 'file') }}">{{ ez_render_field(release, 'release_version') }}</a>
</th>
Expand All @@ -107,7 +105,7 @@

<tr class="releases ezpublish">
<th colspan="3">
Looking for <a href="http://share.ez.no">eZ Publish / eZ Publish Platform</a> ?
Looking for <a href="http://share.ez.no" data-ga-action="Download eZ publish">eZ Publish / eZ Publish Platform</a> ?
</th>
</tr>
</tbody>
Expand All @@ -126,13 +124,13 @@

<div class="launch text-center">
<img src="{{ asset('images/platform-sh-rocket.svg', 'ezdesign') }}" alt="Platform.sh" class="rocket">
<a href="//accounts.platform.sh/platform/trial/ezplatform/setup?branch=demo" class="btn btn-primary">Deploy on platform.sh</a>
<a href="//accounts.platform.sh/platform/trial/ezplatform/setup?branch=demo" class="btn btn-primary" data-ga-action="platform.sh deploy">Deploy on platform.sh</a>
</div>
</div>
{% endif %}

<div role="tabpanel" class="tab-pane" id="ezlaunchpad-option">
<div class="details">
<div class="details" data-ga-action="eZ launchpad documentation">
<h3>eZ Launchpad</h3>
{% if content.fields['launchpad_description'] is defined and not ez_is_field_empty(content, 'launchpad_description') %}
<div class="description text-center">
Expand Down
23 changes: 23 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "ezplatform.com",
"version": "2.3.0",
"author": "eZ Systems",
"homepage": "ez.no",
"scripts": {
"test": "mocha ./test/*.spec.js"
},
"devDependencies": {
"chai": "^4.2.0",
"chai-dom": "^1.8.1",
"chai-subset": "^1.6.0",
"eslint": "^5.10.0",
"eslint-config-prettier": "^3.3.0",
"eslint-plugin-prettier": "^3.0.0",
"eslint-plugin-react": "^7.11.1",
"jquery": "^3.3.1",
"jsdom": "^13.0.0",
"mocha": "^5.2.0",
"prettier": "1.15.3",
"sinon": "^7.1.1"
}
}
97 changes: 97 additions & 0 deletions test/googleAnalyticsService.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
const expect = require('chai').use(require('chai-dom')).use(require('chai-subset')).expect;
const sinon = require('sinon');
const { JSDOM } = require('jsdom');
const GoogleAnalyticsService = require('../web/assets/js/GoogleAnalyticsService');

describe('GoogleAnalyticsService', () => {
let gaService;
let document;
let handleClick;

const template = '/html/gaTemplate.html';
const gaDataAttr = 'data-ga-action';
const gaCategoryAttr = 'data-ga-category';
const gaLabelAttr = 'data-ga-label';

beforeEach(() => {
gaService = new GoogleAnalyticsService();
handleClick = sinon.spy();

return JSDOM.fromFile(__dirname + template)
.then(dom => {
document = dom.window.document;
document.addEventListener('click', handleClick, false);

return document;
})
.catch(error => {
console.log(error);
});
});

it('should return instance of GoogleAnalyticsService', () => {
expect(gaService).to.be.instanceOf(GoogleAnalyticsService);
});

it('should find selectors with data attribute data-ga-action', () => {
expect(document.querySelectorAll(`[${gaDataAttr}]`)).not.to.have.lengthOf(0);
});

it('should return value for each data-ga-action attribute', () => {
const actions = document.querySelectorAll(`[${gaDataAttr}]`);

actions.forEach(action => {
expect(gaService.getGAAction(action), action.outerHTML).not.to.have.lengthOf(0);
});
});

it('should return true if body has data-ga-category attribute', () => {
expect(document.body).to.have.attribute(gaCategoryAttr);
});

it('should return value for data-ga-category attribute', () => {
expect(document.querySelector(`[${gaCategoryAttr}]`).getAttribute(gaCategoryAttr)).not.to.have.lengthOf(0);
});

it('should return Google Analytics Label if data-ga-label attribute exists', () => {
const labels = document.querySelectorAll(`[${gaLabelAttr}]`);

labels.forEach(label => {
expect(gaService.getGALabel(label), label.outerHTML).not.to.have.lengthOf(0);
});
});

it('should rewrite data attributes to child element when ga-link-listener class exists', () => {
const element = document.querySelector('.ga-link-listener');
const childElement = gaService.rewriteByChildElement(element);

expect(childElement.dataset).containSubset(element.dataset);
});

it('should create object after click on data-ga-action event', () => {
const actions = document.querySelectorAll(`[${gaDataAttr}]`);
let gaItem;

actions.forEach(action => {
action.addEventListener('click', () => {
gaItem = new Object({
hitType: 'event',
eventCategory: 'Downloads',
eventAction: 'Download',
eventLabel: 'Label',
transport: 'Transport'
});
});
action.click();
expect(gaItem).to.be.an('object').that.containSubset({
'hitType': 'event',
'eventCategory': 'Downloads',
'eventAction': 'Download',
'eventLabel': 'Label',
'transport': 'Transport',
});
});

expect(handleClick.callCount).to.equal(actions.length);
});
});
13 changes: 13 additions & 0 deletions test/html/gaTemplate.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head></head>
<body data-ga-category="category-name">
<p data-ga-action="action1">Action name</p>
<p data-ga-action="action2">Action name</p>
<p data-ga-label="label">Label</p>
<p data-ga-label="label2">Label</p>
<div class="ga-link-listener" data-ga-action="Action rewrite" data-ga-label="label">
<a href="#">Test</a>
</div>
</body>
</html>
70 changes: 70 additions & 0 deletions web/assets/js/GoogleAnalyticsService.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
class GoogleAnalyticsService {

constructor () {
this.gaDataAttr = 'data-ga-action';
this.gaCategoryAttr = 'data-ga-category';
this.gaLabelAttr = 'data-ga-label';
}

rewriteByChildElement (element) {
if (element.classList.contains('ga-link-listener')) {
const childElement = element.querySelector('a');

return this.rewriteDataAttributes(element, childElement);
}

return element;
}

getGAItemObject (element) {
return {
hitType: 'event',
eventCategory: this.getGACategory(),
eventAction: this.getGAAction(element),
eventLabel: this.getGALabel(element)
};
}

getGAAction (element) {
return element.getAttribute(this.gaDataAttr);
}

getGACategory () {
return window.eZ.helpers.stringUtils.capitalize(document.body.getAttribute(this.gaCategoryAttr));
}

getGALabel (element) {
return element.getAttribute(this.gaLabelAttr);
}

sendGARequest (gaItem) {
ga(
'send',
gaItem.hitType,
gaItem.eventCategory,
gaItem.eventAction,
gaItem.eventLabel,
gaItem.transport
);
}

rewriteDataAttributes (parentElement, childElement) {
childElement.setAttribute(this.gaDataAttr, this.getGAAction(parentElement));
childElement.setAttribute(this.gaLabelAttr, this.getGALabel(parentElement));

return childElement;
}

init () {
const actions = document.querySelectorAll(`[${this.gaDataAttr}]`);

actions.forEach(action => {
action = this.rewriteByChildElement(action);
action.addEventListener('click', (event) => {
this.sendGARequest(this.getGAItemObject(event.currentTarget));
});
});
}
}

module.exports = GoogleAnalyticsService;