Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion default/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { AUTH_PROVIDERS } from 'angular2-jwt';
import { FocusMeDirective } from './shared/focus-me.directive';
import { BackendService } from './shared/backend.service';
import { KeysPipe } from './shared/keys.pipe';

import {GoogleAnalyticsService} from './shared/google.analytics.service';

import { AppComponent } from './app.component';
import { ReportComponent } from './report/index';
Expand Down Expand Up @@ -42,6 +42,7 @@ let providers = [
HTTP_PROVIDERS,
AuthService,
BackendService,
GoogleAnalyticsService,
];

let declarations = [
Expand Down
26 changes: 25 additions & 1 deletion default/src/app/auth/auth-button.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { AuthService } from './auth.service';
import { AuthButtonComponent } from './auth-button.component';
import {BehaviorSubject} from 'rxjs/Rx';
import { User } from '../shared/user';
import { GoogleAnalyticsService } from '../shared/google.analytics.service';



Expand All @@ -35,11 +36,21 @@ class MockAuthService {

}

class MockGoogleAnalyticsService {
event(eventCategory: string, eventAction: string, eventLabel: string) {
}
setUserId(userId: string) {
}
unsetUserId() {
}
}

describe('AuthButtonComponent', () => {
beforeEach(() => {
addProviders([
AuthButtonComponent,
{provide: AuthService, useClass: MockAuthService}
{provide: AuthService, useClass: MockAuthService},
{provide: GoogleAnalyticsService, useClass: MockGoogleAnalyticsService}
]);
});

Expand All @@ -64,4 +75,17 @@ describe('AuthButtonComponent', () => {
expect(authButtonComponent.loggedIn).toBe(false);

}));

it('should record GA event for login and logout', inject(
// Note that we pass AuthService, NOT MockAuthService
[AuthButtonComponent, GoogleAnalyticsService], (authButtonComponent: AuthButtonComponent,
ga: MockGoogleAnalyticsService
) => {

spyOn(ga, 'event');
authButtonComponent.login();
expect(ga.event).toHaveBeenCalledWith('Auth', 'Login', 'click');
authButtonComponent.logout();
expect(ga.event).toHaveBeenCalledWith('Auth', 'Logout', 'click');
}));
});
6 changes: 4 additions & 2 deletions default/src/app/auth/auth-button.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/
import { Component } from '@angular/core';
import { AuthService } from './auth.service';

import { GoogleAnalyticsService } from '../shared/google.analytics.service';

@Component({
selector: 'auth-button',
Expand All @@ -13,7 +13,7 @@ import { AuthService } from './auth.service';
export class AuthButtonComponent {
public loggedIn = false;

constructor(public auth: AuthService) {
constructor(public auth: AuthService, private ga: GoogleAnalyticsService) {
this.auth.getUser().subscribe(
user => {
if (user && user.loggedIn) {
Expand All @@ -25,9 +25,11 @@ export class AuthButtonComponent {
);
}
login() {
this.ga.event('Auth', 'Login', 'click');
this.auth.login();
}
logout() {
this.ga.event('Auth', 'Logout', 'click');
this.auth.logout();
}
}
11 changes: 4 additions & 7 deletions default/src/app/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ import { Observable, BehaviorSubject } from 'rxjs/Rx';
import { User } from '../shared/user';
import { BackendService } from '../shared/backend.service';
import { Integration } from '../shared/integration';


// Declare ga function as ambient
declare var ga: Function;
import { GoogleAnalyticsService } from '../shared/google.analytics.service';

@Injectable()
export class AuthService {
Expand All @@ -28,7 +25,7 @@ export class AuthService {
}
);

constructor(private fb_auth: AngularFireAuth, private backend: BackendService) {
constructor(private fb_auth: AngularFireAuth, private backend: BackendService, private ga: GoogleAnalyticsService) {

this.fb_auth.subscribe(
// An auth event happened.
Expand Down Expand Up @@ -63,10 +60,10 @@ export class AuthService {
this.getUser().subscribe(
(user: User) => {
if (user && user.loggedIn) {
ga('set', 'userId', user.uid); // Set the user ID using signed-in user_id.
this.ga.setUserId(user.uid); // Set the user ID using signed-in user_id.
}
if (user && !user.loggedIn) {
ga('unset', 'userId', null);
this.ga.unsetUserId();
}
}
);
Expand Down
42 changes: 41 additions & 1 deletion default/src/app/report/report.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { QueryService } from '../query/index';
import { AuthService} from '../auth/auth.service';
import { Observable, BehaviorSubject, Observer } from 'rxjs';
import { User } from '../shared/user';
import { GoogleAnalyticsService } from '../shared/google.analytics.service';
// Note that this also imports moment itself.
import * as moment from 'moment-timezone';

Expand Down Expand Up @@ -38,6 +39,15 @@ class MockAuthService {

}

class MockGoogleAnalyticsService {
event(eventCategory: string, eventAction: string, eventLabel: string) {
}
setUserId(userId: string) {
}
unsetUserId() {
}
}

// TODO: This isn't actually testing the component on the webpage, but is calling the items directly.
// TODO: RC5 adds TestBed Class.. see
// TODO: We can use https://developers.livechatinc.com/blog/testing-angular-2-apps-dependency-injection-and-components/
Expand All @@ -46,7 +56,8 @@ describe('SearchComponent', () => {
addProviders([
ReportComponent,
{provide: QueryService, useClass: MockQueryService},
{provide: AuthService, useClass: MockAuthService}
{provide: AuthService, useClass: MockAuthService},
{provide: GoogleAnalyticsService, useClass: MockGoogleAnalyticsService}
]);
});
it('should not call QueryService.getQueries() when user is logged out.',
Expand Down Expand Up @@ -281,5 +292,34 @@ describe('SearchComponent', () => {
}
)
);

it('should record GA event when clicking Show more button',
inject([ReportComponent, QueryService, GoogleAnalyticsService],
(component: ReportComponent, querySrv: QueryService, ga: MockGoogleAnalyticsService) => {

spyOn(querySrv, 'getQueries').and.callFake(() => {
return Observable.create(
(observer: Observer<any>) => {
observer.next({
'cursor': 'fake',
'payload': [
{
'query': 'asdfasdf',
'tags': ['fake-tag'],
'timestamp': '2016-09-01T22:04:38.787362'
}
]
});
observer.complete();
}
);
});

spyOn(ga, 'event');
component.getMoreData('cursor_coming_through');
expect(ga.event).toHaveBeenCalledWith('Report', 'Show more', 'click');
}
)
);
});
});
4 changes: 3 additions & 1 deletion default/src/app/report/report.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import { Component } from '@angular/core';
import { QueryService } from '../query/query.service';
import { AuthService } from '../auth/index';
import { GoogleAnalyticsService } from '../shared/google.analytics.service';
// Note that this also imports moment itself.
import * as moment from 'moment-timezone';

Expand Down Expand Up @@ -46,7 +47,7 @@ export class ReportComponent {
moment.tz.setDefault(this.tz);
}

constructor(private queryService: QueryService, private auth: AuthService) {
constructor(private queryService: QueryService, private auth: AuthService, private ga: GoogleAnalyticsService) {
this.setTimezone();

this.auth.getUser().subscribe(
Expand Down Expand Up @@ -95,6 +96,7 @@ export class ReportComponent {
}

getMoreData(cursor: string) {
this.ga.event('Report', 'Show more', 'click');
this.queryService.getQueries(cursor).subscribe(
(data: any[]) => {
this.data = this.data.concat(this.processData(data['payload'], data['cursor']));
Expand Down
66 changes: 65 additions & 1 deletion default/src/app/search/search.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { QueryService } from '../query/index';
import { AuthService} from '../auth/auth.service';
import { Observable, BehaviorSubject, Observer } from 'rxjs';
import { User } from '../shared/user';
import { GoogleAnalyticsService } from '../shared/google.analytics.service';

class MockQueryService {

Expand Down Expand Up @@ -38,6 +39,15 @@ class MockAuthService {

}

class MockGoogleAnalyticsService {
event(eventCategory: string, eventAction: string, eventLabel: string) {
}
setUserId(userId: string) {
}
unsetUserId() {
}
}

// TODO: This isn't actually testing the component on the webpage, but is calling the items directly.
// TODO: RC5 adds TestBed Class.. see
// TODO: We can use https://developers.livechatinc.com/blog/testing-angular-2-apps-dependency-injection-and-components/
Expand All @@ -46,7 +56,8 @@ describe('SearchComponent', () => {
addProviders([
SearchComponent,
{provide: QueryService, useClass: MockQueryService},
{provide: AuthService, useClass: MockAuthService}
{provide: AuthService, useClass: MockAuthService},
{provide: GoogleAnalyticsService, useClass: MockGoogleAnalyticsService}
]);
});
it('submit button should NOT send a query if search field is empty',
Expand Down Expand Up @@ -106,4 +117,57 @@ describe('SearchComponent', () => {
})

);

it('should record the GA event for submit button on clicking it or pressing enter key',
inject([SearchComponent, GoogleAnalyticsService], (component: SearchComponent,
ga: MockGoogleAnalyticsService
) => {
spyOn(component, 'doSearch').and.callFake(() => {
return Observable.create(
(observer: Observer<any>) => {
observer.next({
'success': 'true',
'payload': {
'redirect': 'http://google.com/q#=whatever',
},
'cursor': null
});
observer.complete();
}
);
});
spyOn(ga, 'event');
component.submit('whatever');
expect(ga.event).toHaveBeenCalledWith('Search', 'submit', 'clicking submit button');
component.onPressEnter({'keyCode' : 13}, 'whatever');
expect(ga.event).toHaveBeenCalledWith('Search', 'submit', 'pressing enter');
})
);

it('should record the GA event for source',
inject([SearchComponent, QueryService, GoogleAnalyticsService], (component: SearchComponent,
querySrv: MockQueryService,
ga: MockGoogleAnalyticsService
) => {
spyOn(querySrv, 'doQuery').and.callFake(() => {
return Observable.create(
(observer: Observer<any>) => {
observer.next({
'success': 'true',
'payload': {
'redirect': 'http://google.com/q#=whatever',
},
'cursor': null
});
observer.complete();
}
);
});
spyOn(ga, 'event');
component.doSearch('whatever');
expect(ga.event).toHaveBeenCalledWith('Search', 'source', 'site-search');
component.recordOmniSearch('http://localhost:8080/?q=hello');
expect(ga.event).toHaveBeenCalledWith('Search', 'source', 'omnibox');
})
);
});
7 changes: 6 additions & 1 deletion default/src/app/search/search.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { Component } from '@angular/core';
import { QueryService } from '../query/index';
import {AuthService} from '../auth/auth.service';
import { GoogleAnalyticsService } from '../shared/google.analytics.service';

@Component({
selector: 'search',
Expand All @@ -12,24 +13,27 @@ import {AuthService} from '../auth/auth.service';
export class SearchComponent {

private preSearchText: any;
constructor(private queryService: QueryService, private auth: AuthService) {
constructor(private queryService: QueryService, private auth: AuthService, private ga: GoogleAnalyticsService) {
this.preSearchText = this.populateSearch(window.location.href);
this.recordOmniSearch(window.location.href);
}

submit(searchField: string) {
if (searchField !== '') {
this.doSearch(searchField) ;
this.ga.event('Search', 'submit', 'clicking submit button');
}
}

onPressEnter(e: any, searchField: any) {
if (e.keyCode === 13 && searchField !== '') {
this.doSearch(searchField);
this.ga.event('Search', 'submit', 'pressing enter');
}
}

doSearch(searchField: any) {
this.ga.event('Search', 'source', 'site-search');
this.queryService.doQuery(searchField, 'site-search').subscribe(
data => {
// If when data is returned from a query with a redirect set, do the redirect.
Expand All @@ -50,6 +54,7 @@ export class SearchComponent {
if (parameters['q'] != null) {
this.queryService.doQuery(parameters['q'], 'omnibox').subscribe(
response => {
this.ga.event('Search', 'source', 'omnibox');
return;
}, error => {
console.log('Error happened: ' + error);
Expand Down
15 changes: 15 additions & 0 deletions default/src/app/shared/google.analytics.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
declare var ga: Function;

export class GoogleAnalyticsService {

public event(eventCategory: string, eventAction: string, eventLabel: string) {
ga('send', 'event', eventCategory, eventAction, eventLabel);
}
public setUserId(userId: string) {
ga('set', 'userId', userId);
}
public unsetUserId() {
ga('unset', 'userId', null);
}

}