idsk_frontend_toolkit 7.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (227) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +3 -0
  3. data/.gitmodules +3 -0
  4. data/.ruby-version +1 -0
  5. data/.travis/govuk_frontend_toolkit_gem_push.enc +0 -0
  6. data/.travis/govuk_frontend_toolkit_gem_push.pub +1 -0
  7. data/.travis.yml +23 -0
  8. data/CONTRIBUTING.md +13 -0
  9. data/Gemfile +3 -0
  10. data/LICENCE +20 -0
  11. data/README.md +61 -0
  12. data/Rakefile +10 -0
  13. data/app/assets/.gitignore +5 -0
  14. data/app/assets/.ruby-version +1 -0
  15. data/app/assets/.travis/README.md +23 -0
  16. data/app/assets/.travis/govuk_frontend_toolkit_push.enc +0 -0
  17. data/app/assets/.travis/govuk_frontend_toolkit_push.pub +1 -0
  18. data/app/assets/.travis.yml +18 -0
  19. data/app/assets/CHANGELOG.md +381 -0
  20. data/app/assets/CONTRIBUTING.md +23 -0
  21. data/app/assets/Gemfile +4 -0
  22. data/app/assets/Gemfile.lock +48 -0
  23. data/app/assets/Gruntfile.js +68 -0
  24. data/app/assets/LICENCE +20 -0
  25. data/app/assets/README.md +170 -0
  26. data/app/assets/VERSION.txt +1 -0
  27. data/app/assets/create-release.sh +38 -0
  28. data/app/assets/docs/analytics.md +270 -0
  29. data/app/assets/docs/functions.md +62 -0
  30. data/app/assets/docs/javascript.md +337 -0
  31. data/app/assets/docs/mixins.md +617 -0
  32. data/app/assets/images/accordion-arrow-2x.png +0 -0
  33. data/app/assets/images/accordion-arrow.png +0 -0
  34. data/app/assets/images/arrow-sprite.png +0 -0
  35. data/app/assets/images/crests/bis_crest_13px.png +0 -0
  36. data/app/assets/images/crests/bis_crest_13px_x2.png +0 -0
  37. data/app/assets/images/crests/bis_crest_18px.png +0 -0
  38. data/app/assets/images/crests/bis_crest_18px_x2.png +0 -0
  39. data/app/assets/images/crests/bis_crest_27px.png +0 -0
  40. data/app/assets/images/crests/bis_crest_27px_x2.png +0 -0
  41. data/app/assets/images/crests/coastguard_13px.png +0 -0
  42. data/app/assets/images/crests/coastguard_13px_x2.png +0 -0
  43. data/app/assets/images/crests/coastguard_18px.png +0 -0
  44. data/app/assets/images/crests/coastguard_18px_x2.png +0 -0
  45. data/app/assets/images/crests/coastguard_27px.png +0 -0
  46. data/app/assets/images/crests/coastguard_27px_x2.png +0 -0
  47. data/app/assets/images/crests/dit_crest_13px.png +0 -0
  48. data/app/assets/images/crests/dit_crest_13px_x2.png +0 -0
  49. data/app/assets/images/crests/dit_crest_18px.png +0 -0
  50. data/app/assets/images/crests/dit_crest_18px_x2.png +0 -0
  51. data/app/assets/images/crests/dit_crest_27px.png +0 -0
  52. data/app/assets/images/crests/dit_crest_27px_x2.png +0 -0
  53. data/app/assets/images/crests/hmrc_crest_13px.png +0 -0
  54. data/app/assets/images/crests/hmrc_crest_13px_x2.png +0 -0
  55. data/app/assets/images/crests/hmrc_crest_18px.png +0 -0
  56. data/app/assets/images/crests/hmrc_crest_18px_x2.png +0 -0
  57. data/app/assets/images/crests/hmrc_crest_27px.png +0 -0
  58. data/app/assets/images/crests/hmrc_crest_27px_x2.png +0 -0
  59. data/app/assets/images/crests/ho_crest_13px.png +0 -0
  60. data/app/assets/images/crests/ho_crest_13px_x2.png +0 -0
  61. data/app/assets/images/crests/ho_crest_18px.png +0 -0
  62. data/app/assets/images/crests/ho_crest_18px_x2.png +0 -0
  63. data/app/assets/images/crests/ho_crest_27px.png +0 -0
  64. data/app/assets/images/crests/ho_crest_27px_x2.png +0 -0
  65. data/app/assets/images/crests/mod_crest_13px.png +0 -0
  66. data/app/assets/images/crests/mod_crest_13px_x2.png +0 -0
  67. data/app/assets/images/crests/mod_crest_18px.png +0 -0
  68. data/app/assets/images/crests/mod_crest_18px_x2.png +0 -0
  69. data/app/assets/images/crests/mod_crest_27px.png +0 -0
  70. data/app/assets/images/crests/mod_crest_27px_x2.png +0 -0
  71. data/app/assets/images/crests/org_crest_13px.png +0 -0
  72. data/app/assets/images/crests/org_crest_13px_x2.png +0 -0
  73. data/app/assets/images/crests/org_crest_18px.png +0 -0
  74. data/app/assets/images/crests/org_crest_18px_x2.png +0 -0
  75. data/app/assets/images/crests/org_crest_27px.png +0 -0
  76. data/app/assets/images/crests/org_crest_27px_x2.png +0 -0
  77. data/app/assets/images/crests/portcullis_13px.png +0 -0
  78. data/app/assets/images/crests/portcullis_13px_x2.png +0 -0
  79. data/app/assets/images/crests/portcullis_18px.png +0 -0
  80. data/app/assets/images/crests/portcullis_18px_x2.png +0 -0
  81. data/app/assets/images/crests/portcullis_27px.png +0 -0
  82. data/app/assets/images/crests/portcullis_27px_x2.png +0 -0
  83. data/app/assets/images/crests/so_crest_13px.png +0 -0
  84. data/app/assets/images/crests/so_crest_13px_x2.png +0 -0
  85. data/app/assets/images/crests/so_crest_18px.png +0 -0
  86. data/app/assets/images/crests/so_crest_18px_x2.png +0 -0
  87. data/app/assets/images/crests/so_crest_27px.png +0 -0
  88. data/app/assets/images/crests/so_crest_27px_x2.png +0 -0
  89. data/app/assets/images/crests/ukaea_crest_13px.png +0 -0
  90. data/app/assets/images/crests/ukaea_crest_13px_x2.png +0 -0
  91. data/app/assets/images/crests/ukaea_crest_18px.png +0 -0
  92. data/app/assets/images/crests/ukaea_crest_18px_x2.png +0 -0
  93. data/app/assets/images/crests/ukaea_crest_27px.png +0 -0
  94. data/app/assets/images/crests/ukaea_crest_27px_x2.png +0 -0
  95. data/app/assets/images/crests/ukho_13px.png +0 -0
  96. data/app/assets/images/crests/ukho_13px_x2.png +0 -0
  97. data/app/assets/images/crests/ukho_18px.png +0 -0
  98. data/app/assets/images/crests/ukho_18px_x2.png +0 -0
  99. data/app/assets/images/crests/ukho_27px.png +0 -0
  100. data/app/assets/images/crests/ukho_27px_x2.png +0 -0
  101. data/app/assets/images/crests/wales_crest_13px.png +0 -0
  102. data/app/assets/images/crests/wales_crest_13px_x2.png +0 -0
  103. data/app/assets/images/crests/wales_crest_18px.png +0 -0
  104. data/app/assets/images/crests/wales_crest_18px_x2.png +0 -0
  105. data/app/assets/images/crests/wales_crest_27px.png +0 -0
  106. data/app/assets/images/crests/wales_crest_27px_x2.png +0 -0
  107. data/app/assets/images/icon-arrow-left.png +0 -0
  108. data/app/assets/images/icon-calendar-2x.png +0 -0
  109. data/app/assets/images/icon-calendar.png +0 -0
  110. data/app/assets/images/icon-file-download-2x.png +0 -0
  111. data/app/assets/images/icon-file-download.png +0 -0
  112. data/app/assets/images/icon-important-2x.png +0 -0
  113. data/app/assets/images/icon-important.png +0 -0
  114. data/app/assets/images/icon-information-2x.png +0 -0
  115. data/app/assets/images/icon-information.png +0 -0
  116. data/app/assets/images/icon-locator-2x.png +0 -0
  117. data/app/assets/images/icon-locator.png +0 -0
  118. data/app/assets/images/icon-pointer-2x.png +0 -0
  119. data/app/assets/images/icon-pointer-black-2x.png +0 -0
  120. data/app/assets/images/icon-pointer-black.png +0 -0
  121. data/app/assets/images/icon-pointer-indexed.png +0 -0
  122. data/app/assets/images/icon-pointer.png +0 -0
  123. data/app/assets/images/icon-search-2x.png +0 -0
  124. data/app/assets/images/icon-search.png +0 -0
  125. data/app/assets/images/icon-steps/icon-step-1-2x.png +0 -0
  126. data/app/assets/images/icon-steps/icon-step-1.png +0 -0
  127. data/app/assets/images/icon-steps/icon-step-10-2x.png +0 -0
  128. data/app/assets/images/icon-steps/icon-step-10.png +0 -0
  129. data/app/assets/images/icon-steps/icon-step-11-2x.png +0 -0
  130. data/app/assets/images/icon-steps/icon-step-11.png +0 -0
  131. data/app/assets/images/icon-steps/icon-step-12-2x.png +0 -0
  132. data/app/assets/images/icon-steps/icon-step-12.png +0 -0
  133. data/app/assets/images/icon-steps/icon-step-13-2x.png +0 -0
  134. data/app/assets/images/icon-steps/icon-step-13.png +0 -0
  135. data/app/assets/images/icon-steps/icon-step-14-2x.png +0 -0
  136. data/app/assets/images/icon-steps/icon-step-14.png +0 -0
  137. data/app/assets/images/icon-steps/icon-step-2-2x.png +0 -0
  138. data/app/assets/images/icon-steps/icon-step-2.png +0 -0
  139. data/app/assets/images/icon-steps/icon-step-3-2x.png +0 -0
  140. data/app/assets/images/icon-steps/icon-step-3.png +0 -0
  141. data/app/assets/images/icon-steps/icon-step-4-2x.png +0 -0
  142. data/app/assets/images/icon-steps/icon-step-4.png +0 -0
  143. data/app/assets/images/icon-steps/icon-step-5-2x.png +0 -0
  144. data/app/assets/images/icon-steps/icon-step-5.png +0 -0
  145. data/app/assets/images/icon-steps/icon-step-6-2x.png +0 -0
  146. data/app/assets/images/icon-steps/icon-step-6.png +0 -0
  147. data/app/assets/images/icon-steps/icon-step-7-2x.png +0 -0
  148. data/app/assets/images/icon-steps/icon-step-7.png +0 -0
  149. data/app/assets/images/icon-steps/icon-step-8-2x.png +0 -0
  150. data/app/assets/images/icon-steps/icon-step-8.png +0 -0
  151. data/app/assets/images/icon-steps/icon-step-9-2x.png +0 -0
  152. data/app/assets/images/icon-steps/icon-step-9.png +0 -0
  153. data/app/assets/images/player-icon-forward.png +0 -0
  154. data/app/assets/images/player-icon-pause.png +0 -0
  155. data/app/assets/images/player-icon-play.png +0 -0
  156. data/app/assets/images/player-icon-rewind.png +0 -0
  157. data/app/assets/images/player-icon-volume.png +0 -0
  158. data/app/assets/images/separator-2x.png +0 -0
  159. data/app/assets/images/separator.png +0 -0
  160. data/app/assets/javascripts/govuk/analytics/analytics.js +143 -0
  161. data/app/assets/javascripts/govuk/analytics/download-link-tracker.js +41 -0
  162. data/app/assets/javascripts/govuk/analytics/error-tracking.js +51 -0
  163. data/app/assets/javascripts/govuk/analytics/external-link-tracker.js +56 -0
  164. data/app/assets/javascripts/govuk/analytics/google-analytics-universal-tracker.js +166 -0
  165. data/app/assets/javascripts/govuk/analytics/govuk-tracker.js +134 -0
  166. data/app/assets/javascripts/govuk/analytics/mailto-link-tracker.js +38 -0
  167. data/app/assets/javascripts/govuk/analytics/print-intent.js +39 -0
  168. data/app/assets/javascripts/govuk/details.polyfill.js +240 -0
  169. data/app/assets/javascripts/govuk/modules/auto-track-event.js +30 -0
  170. data/app/assets/javascripts/govuk/modules.js +61 -0
  171. data/app/assets/javascripts/govuk/primary-links.js +57 -0
  172. data/app/assets/javascripts/govuk/selection-buttons.js +116 -0
  173. data/app/assets/javascripts/govuk/shim-links-with-button-role.js +34 -0
  174. data/app/assets/javascripts/govuk/show-hide-content.js +172 -0
  175. data/app/assets/javascripts/govuk/stick-at-top-when-scrolling.js +128 -0
  176. data/app/assets/javascripts/govuk/stop-scrolling-at-footer.js +139 -0
  177. data/app/assets/javascripts/govuk_toolkit.js +1 -0
  178. data/app/assets/javascripts/stageprompt.js +69 -0
  179. data/app/assets/javascripts/vendor/jquery/jquery.player.min.js +25 -0
  180. data/app/assets/javascripts/vendor/polyfills/bind.js +40 -0
  181. data/app/assets/package.json +25 -0
  182. data/app/assets/spec/manifest.js +41 -0
  183. data/app/assets/spec/stylesheets/_colour_contrast_spec.scss +12 -0
  184. data/app/assets/spec/support/LocalTestRunner.html +21 -0
  185. data/app/assets/spec/support/console-runner.js +102 -0
  186. data/app/assets/spec/support/load.js +47 -0
  187. data/app/assets/spec/support/run_jasmine_test.js +62 -0
  188. data/app/assets/spec/unit/analytics/analytics.spec.js +315 -0
  189. data/app/assets/spec/unit/analytics/download-link-tracker.spec.js +72 -0
  190. data/app/assets/spec/unit/analytics/error-tracking.spec.js +65 -0
  191. data/app/assets/spec/unit/analytics/external-link-tracker.spec.js +109 -0
  192. data/app/assets/spec/unit/analytics/google-analytics-universal-tracker.spec.js +180 -0
  193. data/app/assets/spec/unit/analytics/govuk-tracker.spec.js +171 -0
  194. data/app/assets/spec/unit/analytics/mailto-link-tracker.spec.js +62 -0
  195. data/app/assets/spec/unit/details.polyfill.spec.js +91 -0
  196. data/app/assets/spec/unit/modules/auto-track-event.spec.js +54 -0
  197. data/app/assets/spec/unit/modules.spec.js +93 -0
  198. data/app/assets/spec/unit/primary-links.spec.js +55 -0
  199. data/app/assets/spec/unit/selection-button.spec.js +761 -0
  200. data/app/assets/spec/unit/shim-links-with-button-role.spec.js +41 -0
  201. data/app/assets/spec/unit/show-hide-content.spec.js +306 -0
  202. data/app/assets/spec/unit/stick-at-top-when-scrolling.spec.js +137 -0
  203. data/app/assets/stylesheets/.gitkeep +0 -0
  204. data/app/assets/stylesheets/_colours.scss +2 -0
  205. data/app/assets/stylesheets/_conditionals.scss +81 -0
  206. data/app/assets/stylesheets/_css3.scss +90 -0
  207. data/app/assets/stylesheets/_device-pixels.scss +10 -0
  208. data/app/assets/stylesheets/_font_stack.scss +25 -0
  209. data/app/assets/stylesheets/_grid_layout.scss +136 -0
  210. data/app/assets/stylesheets/_helpers.scss +16 -0
  211. data/app/assets/stylesheets/_measurements.scss +14 -0
  212. data/app/assets/stylesheets/_shims.scss +55 -0
  213. data/app/assets/stylesheets/_typography.scss +249 -0
  214. data/app/assets/stylesheets/_url-helpers.scss +16 -0
  215. data/app/assets/stylesheets/colours/_organisation.scss +104 -0
  216. data/app/assets/stylesheets/colours/_palette.scss +77 -0
  217. data/app/assets/stylesheets/design-patterns/_alpha-beta.scss +67 -0
  218. data/app/assets/stylesheets/design-patterns/_breadcrumbs.scss +53 -0
  219. data/app/assets/stylesheets/design-patterns/_buttons.scss +145 -0
  220. data/app/assets/stylesheets/design-patterns/_media-player.scss +264 -0
  221. data/app/assets/trigger.sh +24 -0
  222. data/idsk_frontend_toolkit.gemspec +49 -0
  223. data/lib/idsk_frontend_toolkit/engine.rb +4 -0
  224. data/lib/idsk_frontend_toolkit/version.rb +5 -0
  225. data/lib/idsk_frontend_toolkit.rb +4 -0
  226. data/publish.sh +30 -0
  227. metadata +314 -0
@@ -0,0 +1,180 @@
1
+ /* global describe it expect beforeEach spyOn jasmine */
2
+
3
+ var $ = window.jQuery
4
+
5
+ describe('GOVUK.GoogleAnalyticsUniversalTracker', function () {
6
+ 'use strict'
7
+ var GOVUK = window.GOVUK
8
+
9
+ function addGoogleAnalyticsSpy () {
10
+ window.ga = function () {}
11
+ spyOn(window, 'ga')
12
+ }
13
+
14
+ var universal
15
+ var setupArguments
16
+
17
+ beforeEach(function () {
18
+ addGoogleAnalyticsSpy()
19
+
20
+ universal = new GOVUK.GoogleAnalyticsUniversalTracker('id', {
21
+ cookieDomain: 'cookie-domain.com',
22
+ siteSpeedSampleRate: 100
23
+ })
24
+ })
25
+
26
+ it('can load the libraries needed to run universal Google Analytics', function () {
27
+ delete window.ga
28
+ $('[src="https://www.google-analytics.com/analytics.js"]').remove()
29
+ GOVUK.GoogleAnalyticsUniversalTracker.load()
30
+ expect($('script[async][src="https://www.google-analytics.com/analytics.js"]').length).toBe(1)
31
+ expect(typeof window.ga).toBe('function')
32
+
33
+ window.ga('send message')
34
+ expect(window.ga.q[0]).toEqual(jasmine.any(Object))
35
+ })
36
+
37
+ describe('when created', function () {
38
+ beforeEach(function () {
39
+ setupArguments = window.ga.calls.allArgs()
40
+ })
41
+
42
+ it('configures a Google tracker using the provided profile ID and config', function () {
43
+ expect(setupArguments[0]).toEqual(['create', 'id', {cookieDomain: 'cookie-domain.com', siteSpeedSampleRate: 100}])
44
+ })
45
+
46
+ it('anonymises the IP', function () {
47
+ expect(setupArguments[1]).toEqual(['set', 'anonymizeIp', true])
48
+ })
49
+ })
50
+
51
+ describe('when created (with legacy non-object syntax)', function () {
52
+ beforeEach(function () {
53
+ addGoogleAnalyticsSpy()
54
+
55
+ universal = new GOVUK.GoogleAnalyticsUniversalTracker('id', 'cookie-domain.com')
56
+ setupArguments = window.ga.calls.allArgs()
57
+ })
58
+
59
+ it('configures a Google tracker using the provided profile ID and cookie domain', function () {
60
+ expect(setupArguments[0]).toEqual(['create', 'id', {cookieDomain: 'cookie-domain.com'}])
61
+ })
62
+ })
63
+
64
+ describe('when pageviews are tracked', function () {
65
+ it('sends them to Google Analytics', function () {
66
+ universal.trackPageview()
67
+ expect(window.ga.calls.mostRecent().args).toEqual(['send', 'pageview'])
68
+ })
69
+
70
+ it('sends them to Google Analytics, forcing a new session', function () {
71
+ universal.trackPageview(undefined, undefined, { sessionControl: 'start' })
72
+ expect(window.ga.calls.mostRecent().args).toEqual(['send', 'pageview', {sessionControl: 'start'}])
73
+ })
74
+
75
+ it('can track a virtual pageview', function () {
76
+ universal.trackPageview('/nicholas-page')
77
+ expect(window.ga.calls.mostRecent().args).toEqual(['send', 'pageview', {page: '/nicholas-page'}])
78
+ })
79
+
80
+ it('can track a virtual pageview with a custom title', function () {
81
+ universal.trackPageview('/nicholas-page', 'Nicholas Page')
82
+ expect(window.ga.calls.mostRecent().args).toEqual(['send', 'pageview', {page: '/nicholas-page', title: 'Nicholas Page'}])
83
+ })
84
+
85
+ it('can set the transport method on a pageview', function () {
86
+ universal.trackPageview('/t', 'T', {transport: 'beacon'})
87
+ expect(window.ga.calls.mostRecent().args).toEqual(['send', 'pageview', {page: '/t', title: 'T', transport: 'beacon'}])
88
+ })
89
+ })
90
+
91
+ describe('when events are tracked', function () {
92
+ function eventObjectFromSpy () {
93
+ return window.ga.calls.mostRecent().args[1]
94
+ }
95
+
96
+ it('sends them to Google Analytics', function () {
97
+ universal.trackEvent('category', 'action', {label: 'label'})
98
+ expect(window.ga.calls.mostRecent().args).toEqual(
99
+ ['send', {hitType: 'event', eventCategory: 'category', eventAction: 'action', eventLabel: 'label'}]
100
+ )
101
+ })
102
+
103
+ it('tracks custom dimensions', function () {
104
+ universal.trackEvent('category', 'action', {dimension29: 'Home'})
105
+ expect(window.ga.calls.mostRecent().args).toEqual(
106
+ ['send', {hitType: 'event', eventCategory: 'category', eventAction: 'action', dimension29: 'Home'}]
107
+ )
108
+ })
109
+
110
+ it('the label is optional', function () {
111
+ universal.trackEvent('category', 'action')
112
+ expect(window.ga.calls.mostRecent().args).toEqual(
113
+ ['send', {hitType: 'event', eventCategory: 'category', eventAction: 'action'}]
114
+ )
115
+ })
116
+
117
+ it('only sends values if they are parseable as numbers', function () {
118
+ universal.trackEvent('category', 'action', {label: 'label', value: '10'})
119
+ expect(eventObjectFromSpy()['eventValue']).toEqual(10)
120
+
121
+ universal.trackEvent('category', 'action', {label: 'label', value: 10})
122
+ expect(eventObjectFromSpy()['eventValue']).toEqual(10)
123
+
124
+ universal.trackEvent('category', 'action', {label: 'label', value: 'not a number'})
125
+ expect(eventObjectFromSpy()['eventValue']).toEqual(undefined)
126
+ })
127
+
128
+ it('can mark an event as non interactive', function () {
129
+ universal.trackEvent('category', 'action', {label: 'label', value: 0, nonInteraction: true})
130
+ expect(window.ga.calls.mostRecent().args).toEqual(
131
+ ['send', {
132
+ hitType: 'event',
133
+ eventCategory: 'category',
134
+ eventAction: 'action',
135
+ eventLabel: 'label',
136
+ eventValue: 0,
137
+ nonInteraction: 1
138
+ }]
139
+ )
140
+ })
141
+
142
+ it('sends the page if supplied', function () {
143
+ universal.trackEvent('category', 'action', {page: '/path/to/page'})
144
+ expect(window.ga.calls.mostRecent().args).toEqual(
145
+ ['send', {hitType: 'event', eventCategory: 'category', eventAction: 'action', page: '/path/to/page'}]
146
+ )
147
+ })
148
+
149
+ it('can set the transport method on an event', function () {
150
+ universal.trackEvent('category', 'action', {transport: 'beacon'})
151
+ expect(window.ga.calls.mostRecent().args).toEqual(
152
+ ['send', {hitType: 'event', eventCategory: 'category', eventAction: 'action', transport: 'beacon'}]
153
+ )
154
+ })
155
+ })
156
+
157
+ describe('when social events are tracked', function () {
158
+ it('sends them to Google Analytics', function () {
159
+ universal.trackSocial('network', 'action', 'target')
160
+ expect(window.ga.calls.mostRecent().args).toEqual(['send', {
161
+ 'hitType': 'social',
162
+ 'socialNetwork': 'network',
163
+ 'socialAction': 'action',
164
+ 'socialTarget': 'target'
165
+ }])
166
+ })
167
+ })
168
+
169
+ describe('when setting a custom dimension', function () {
170
+ it('sends the dimension to Google Analytics with the specified index and value', function () {
171
+ universal.setDimension(1, 'value')
172
+ expect(window.ga.calls.mostRecent().args).toEqual(['set', 'dimension1', 'value'])
173
+ })
174
+
175
+ it('coerces the value to a string', function () {
176
+ universal.setDimension(1, 10)
177
+ expect(window.ga.calls.mostRecent().args).toEqual(['set', 'dimension1', '10'])
178
+ })
179
+ })
180
+ })
@@ -0,0 +1,171 @@
1
+ /* global describe it expect beforeEach spyOn jasmine */
2
+
3
+ var $ = window.jQuery
4
+
5
+ describe('GOVUK.GOVUKTracker', function () {
6
+ 'use strict'
7
+ var GOVUK = window.GOVUK
8
+
9
+ var tracker
10
+
11
+ function setupFakeGa (clientId) {
12
+ window.ga = function (cb) {
13
+ cb({
14
+ get: function () { return clientId }
15
+ })
16
+ }
17
+ }
18
+
19
+ beforeEach(function () {
20
+ tracker = new GOVUK.GOVUKTracker('http://www.example.com/a.gif')
21
+ })
22
+
23
+ describe('sendData', function () {
24
+ it('sends the data using AJAX', function () {
25
+ spyOn($, 'get')
26
+
27
+ tracker.sendData({foo: 'bar'})
28
+ expect($.get).toHaveBeenCalledWith('http://www.example.com/a.gif?foo=bar')
29
+ })
30
+ })
31
+
32
+ describe('payloadParams', function () {
33
+ it('adds the event type', function () {
34
+ var params = tracker.payloadParams('foo', {bar: 'qux'})
35
+
36
+ expect(params.eventType).toEqual('foo')
37
+ expect(params.bar).toEqual('qux')
38
+ })
39
+
40
+ it('adds the GA Client ID', function () {
41
+ tracker.gaClientId = '123456.789012'
42
+ var params = tracker.payloadParams('foo')
43
+
44
+ expect(params.gaClientId).toEqual('123456.789012')
45
+ })
46
+
47
+ it('adds the referrer', function () {
48
+ var params = tracker.payloadParams('foo')
49
+
50
+ // Can't stub window.referrer so just test that we got a string, not undefined
51
+ expect(typeof params.referrer).toEqual('string')
52
+ })
53
+
54
+ it('adds performance data', function () {
55
+ var params = tracker.payloadParams('foo')
56
+
57
+ expect(params.navigationType).toEqual('0')
58
+ expect(params.redirectCount).toEqual('0')
59
+
60
+ expect(params.timing_domComplete).toEqual(window.performance.timing.domComplete.toString())
61
+ })
62
+
63
+ it('adds custom dimensions', function () {
64
+ tracker.setDimension(1, 'foo')
65
+ tracker.setDimension(10, 'bar')
66
+ var params = tracker.payloadParams('foo')
67
+
68
+ expect(params.dimension1).toEqual('foo')
69
+ expect(params.dimension10).toEqual('bar')
70
+ })
71
+
72
+ it('adds screen and window measurements', function () {
73
+ var params = tracker.payloadParams('foo')
74
+
75
+ expect(params.screenWidth).toEqual(window.screen.width)
76
+ expect(params.screenHeight).toEqual(window.screen.height)
77
+ expect(params.windowWidth).toEqual(window.innerWidth)
78
+ expect(params.windowHeight).toEqual(window.innerHeight)
79
+ expect(params.colorDepth).toEqual(window.screen.colorDepth)
80
+ })
81
+ })
82
+
83
+ describe('sendToTracker', function () {
84
+ it('sends when the DOM is complete', function () {
85
+ setupFakeGa('123456.789012')
86
+
87
+ spyOn(tracker, 'sendData')
88
+ tracker.sendToTracker('foo')
89
+
90
+ expect(tracker.sendData).toHaveBeenCalledWith(jasmine.any(Object))
91
+ })
92
+
93
+ it('sets the ga Client ID', function () {
94
+ setupFakeGa('123456.789012')
95
+
96
+ spyOn(tracker, 'sendData')
97
+ tracker.sendToTracker('foo')
98
+
99
+ expect(tracker.gaClientId).toEqual('123456.789012')
100
+ })
101
+ })
102
+
103
+ describe('tracking', function () {
104
+ beforeEach(function () {
105
+ spyOn(tracker, 'sendToTracker')
106
+ })
107
+
108
+ describe('when pageviews are tracked', function () {
109
+ it('sends them to the tracker', function () {
110
+ tracker.trackPageview()
111
+ expect(tracker.sendToTracker.calls.mostRecent().args).toEqual(['pageview'])
112
+ })
113
+ })
114
+
115
+ describe('when events are tracked', function () {
116
+ it('sends them to the tracker', function () {
117
+ tracker.trackEvent('category', 'action', {label: 'label'})
118
+ expect(tracker.sendToTracker.calls.mostRecent().args).toEqual(
119
+ ['event', {eventCategory: 'category', eventAction: 'action', eventLabel: 'label'}]
120
+ )
121
+ })
122
+
123
+ it('tracks custom dimensions', function () {
124
+ tracker.trackEvent('category', 'action', {dimension29: 'Home'})
125
+ expect(tracker.sendToTracker.calls.mostRecent().args).toEqual(
126
+ ['event', {eventCategory: 'category', eventAction: 'action', dimension29: 'Home'}]
127
+ )
128
+ })
129
+
130
+ it('the label is optional', function () {
131
+ tracker.trackEvent('category', 'action')
132
+ expect(tracker.sendToTracker.calls.mostRecent().args).toEqual(
133
+ ['event', {eventCategory: 'category', eventAction: 'action'}]
134
+ )
135
+ })
136
+
137
+ it('sends the page if supplied', function () {
138
+ tracker.trackEvent('category', 'action', {page: '/path/to/page'})
139
+ expect(tracker.sendToTracker.calls.mostRecent().args).toEqual(
140
+ ['event', {eventCategory: 'category', eventAction: 'action', page: '/path/to/page'}]
141
+ )
142
+ })
143
+
144
+ it('tracks multiple events', function () {
145
+ tracker.trackEvent('category', 'action', {label: 'foo'})
146
+ tracker.trackEvent('category', 'action', {label: 'bar'})
147
+
148
+ expect(tracker.sendToTracker).toHaveBeenCalledWith(
149
+ 'event', {eventCategory: 'category', eventAction: 'action', eventLabel: 'foo'}
150
+ )
151
+ expect(tracker.sendToTracker).toHaveBeenCalledWith(
152
+ 'event', {eventCategory: 'category', eventAction: 'action', eventLabel: 'bar'}
153
+ )
154
+ })
155
+ })
156
+
157
+ describe('when social events are tracked', function () {
158
+ it('sends them to Google Analytics', function () {
159
+ tracker.trackSocial('network', 'action', 'target')
160
+ expect(tracker.sendToTracker.calls.mostRecent().args).toEqual([
161
+ 'social',
162
+ {
163
+ 'socialNetwork': 'network',
164
+ 'socialAction': 'action',
165
+ 'socialTarget': 'target'
166
+ }
167
+ ])
168
+ })
169
+ })
170
+ })
171
+ })
@@ -0,0 +1,62 @@
1
+ /* global describe it expect afterEach beforeEach spyOn */
2
+
3
+ var $ = window.jQuery
4
+
5
+ describe('GOVUK.analyticsPlugins.mailtoLinkTracker', function () {
6
+ 'use strict'
7
+ var GOVUK = window.GOVUK
8
+
9
+ var $links
10
+
11
+ beforeEach(function () {
12
+ $links = $(
13
+ '<div class="mailto-links">' +
14
+ '<a href="mailto:name1@email.com"></a>' +
15
+ '<a href="mailto:name2@email.com">The link for a mailto</a>' +
16
+ '<a href="mailto:name3@email.com"><img src="/img" /></a>' +
17
+ '</div>'
18
+ )
19
+
20
+ $('html').on('click', function (evt) { evt.preventDefault() })
21
+ $('body').append($links)
22
+ GOVUK.analytics = {trackEvent: function () {}}
23
+
24
+ GOVUK.analyticsPlugins.mailtoLinkTracker()
25
+ })
26
+
27
+ afterEach(function () {
28
+ $('html').off()
29
+ $('body').off()
30
+ $links.remove()
31
+ delete GOVUK.analytics
32
+ })
33
+
34
+ it('listens to click events on mailto links', function () {
35
+ spyOn(GOVUK.analytics, 'trackEvent')
36
+
37
+ $('.mailto-links a').each(function () {
38
+ $(this).trigger('click')
39
+ expect(GOVUK.analytics.trackEvent).toHaveBeenCalled()
40
+ GOVUK.analytics.trackEvent.calls.reset()
41
+ })
42
+ })
43
+
44
+ it('tracks mailto addresses and link text', function () {
45
+ spyOn(GOVUK.analytics, 'trackEvent')
46
+ $('.mailto-links a').trigger('click')
47
+
48
+ expect(GOVUK.analytics.trackEvent).toHaveBeenCalledWith(
49
+ 'Mailto Link Clicked', 'mailto:name1@email.com', {transport: 'beacon'})
50
+
51
+ expect(GOVUK.analytics.trackEvent).toHaveBeenCalledWith(
52
+ 'Mailto Link Clicked', 'mailto:name2@email.com', {transport: 'beacon', label: 'The link for a mailto'})
53
+ })
54
+
55
+ it('listens to click events on elements within mailto links', function () {
56
+ spyOn(GOVUK.analytics, 'trackEvent')
57
+
58
+ $('.mailto-links a img').trigger('click')
59
+ expect(GOVUK.analytics.trackEvent).toHaveBeenCalledWith(
60
+ 'Mailto Link Clicked', 'mailto:name3@email.com', {transport: 'beacon'})
61
+ })
62
+ })
@@ -0,0 +1,91 @@
1
+ /* global describe it expect beforeEach afterEach */
2
+
3
+ var $ = window.jQuery
4
+
5
+ describe('details-polyfill', function () {
6
+ 'use strict'
7
+ var GOVUK = window.GOVUK
8
+
9
+ beforeEach(function (done) {
10
+ // Sample markup
11
+ this.$content = $(
12
+ '<details>' +
13
+ '<summary><span class="summary">Summary</span></summary>' +
14
+ '<div><p>Hidden content</p></div>' +
15
+ '</details>'
16
+ )
17
+
18
+ // Find elements
19
+ var $summaries = this.$content.find('summary')
20
+ var $hiddenContent = this.$content.find('div')
21
+
22
+ this.$summary1 = $summaries.eq(0)
23
+ this.$hiddenContent1 = $hiddenContent.eq(0)
24
+
25
+ // Add to page
26
+ $(document.body).append(this.$content)
27
+
28
+ setTimeout(function () {
29
+ done()
30
+ }, 1)
31
+ })
32
+
33
+ afterEach(function () {
34
+ this.detailsPolyfill = null
35
+ this.$content.remove()
36
+ })
37
+
38
+ describe('When the polyfill is initialised', function () {
39
+ beforeEach(function () {
40
+ // Initialise detailsPolyfill
41
+ this.detailsPolyfill = GOVUK.details.addDetailsPolyfill()
42
+ GOVUK.details.started = false
43
+ })
44
+ it('should add to summary the button role', function () {
45
+ expect(this.$summary1.attr('role')).toBe('button')
46
+ })
47
+
48
+ it('should set the element controlled by the summary using aria-controls', function () {
49
+ expect(this.$summary1.attr('aria-controls')).toBe('details-content-0')
50
+ })
51
+
52
+ it('should set the expanded state of the summary to false using aria-expanded', function () {
53
+ expect(this.$summary1.attr('aria-expanded')).toBe('false')
54
+ })
55
+
56
+ it('should add a unique id to the hidden content in order to be controlled by the summary', function () {
57
+ expect(this.$hiddenContent1.attr('id')).toBe('details-content-0')
58
+ })
59
+
60
+ it('should present the content as hidden using aria-hidden', function () {
61
+ expect(this.$hiddenContent1.attr('aria-hidden')).toBe('true')
62
+ })
63
+
64
+ it('should visually hide the content', function () {
65
+ expect(this.$hiddenContent1.is(':visible')).toBe(false)
66
+ })
67
+
68
+ describe('and when summary is clicked', function () {
69
+ beforeEach(function () {
70
+ // Trigger click on summary
71
+ this.$summary1.click()
72
+ })
73
+
74
+ it('should indicate the expanded state of the summary using aria-expanded', function () {
75
+ expect(this.$summary1.attr('aria-expanded')).toBe('true')
76
+ })
77
+
78
+ it('should make the content visible', function () {
79
+ expect(this.$hiddenContent1.is(':visible')).toBe(true)
80
+ })
81
+
82
+ it('should indicate the visible state of the content using aria-hidden', function () {
83
+ expect(this.$hiddenContent1.attr('aria-hidden')).toBe('false')
84
+ })
85
+
86
+ it('should indicate the open state of the content', function () {
87
+ expect(this.$content.attr('open')).toBe('open')
88
+ })
89
+ })
90
+ })
91
+ })
@@ -0,0 +1,54 @@
1
+ /* global describe it expect beforeEach afterEach spyOn */
2
+
3
+ var $ = window.jQuery
4
+
5
+ describe('An auto event tracker', function () {
6
+ 'use strict'
7
+ var GOVUK = window.GOVUK
8
+
9
+ var tracker,
10
+ element
11
+
12
+ beforeEach(function () {
13
+ GOVUK.analytics = {trackEvent: function () {}}
14
+ tracker = new GOVUK.Modules.AutoTrackEvent()
15
+ })
16
+
17
+ afterEach(function () {
18
+ delete GOVUK.analytics
19
+ })
20
+
21
+ it('tracks non-interactive events on start', function () {
22
+ spyOn(GOVUK.analytics, 'trackEvent')
23
+
24
+ element = $(
25
+ '<div ' +
26
+ 'data-track-category="category"' +
27
+ 'data-track-action="action">' +
28
+ 'Some content' +
29
+ '</div>'
30
+ )
31
+
32
+ tracker.start(element)
33
+ expect(GOVUK.analytics.trackEvent).toHaveBeenCalledWith(
34
+ 'category', 'action', {nonInteraction: 1})
35
+ })
36
+
37
+ it('can track non-interactive events with optional label and value', function () {
38
+ spyOn(GOVUK.analytics, 'trackEvent')
39
+
40
+ element = $(
41
+ '<div ' +
42
+ 'data-track-category="category"' +
43
+ 'data-track-action="action"' +
44
+ 'data-track-label="label"' +
45
+ 'data-track-value="10">' +
46
+ 'Some content' +
47
+ '</div>'
48
+ )
49
+
50
+ tracker.start(element)
51
+ expect(GOVUK.analytics.trackEvent).toHaveBeenCalledWith(
52
+ 'category', 'action', {label: 'label', value: 10, nonInteraction: 1})
53
+ })
54
+ })
@@ -0,0 +1,93 @@
1
+ /* global describe it expect beforeEach afterEach jasmine */
2
+
3
+ var $ = window.jQuery
4
+
5
+ describe('GOVUK Modules', function () {
6
+ 'use strict'
7
+ var GOVUK = window.GOVUK
8
+
9
+ it('finds modules', function () {
10
+ var module = $('<div data-module="a-module"></div>')
11
+ $('body').append(module)
12
+
13
+ expect(GOVUK.modules.find().length).toBe(1)
14
+ expect(GOVUK.modules.find().eq(0).is('[data-module="a-module"]')).toBe(true)
15
+ module.remove()
16
+ })
17
+
18
+ it('finds modules in a container', function () {
19
+ var module = $('<div data-module="a-module"></div>')
20
+ var container = $('<div></div>').append(module)
21
+
22
+ expect(GOVUK.modules.find(container).length).toBe(1)
23
+ expect(GOVUK.modules.find(container).eq(0).data('module')).toBe('a-module')
24
+ })
25
+
26
+ it('finds modules that are a container', function () {
27
+ var module = $('<div data-module="a-module"></div>')
28
+ var container = $('<div data-module="container-module"></div>').append(module)
29
+
30
+ expect(GOVUK.modules.find(container).length).toBe(2)
31
+ expect(GOVUK.modules.find(container).eq(0).data('module')).toBe('container-module')
32
+ expect(GOVUK.modules.find(container).eq(1).data('module')).toBe('a-module')
33
+ })
34
+
35
+ describe('when a module exists', function () {
36
+ var callback
37
+
38
+ beforeEach(function () {
39
+ callback = jasmine.createSpy()
40
+ GOVUK.Modules.TestAlertModule = function () {
41
+ var that = this
42
+ that.start = function (element) {
43
+ callback(element)
44
+ }
45
+ }
46
+ })
47
+
48
+ afterEach(function () {
49
+ delete GOVUK.Modules.TestAlertModule
50
+ })
51
+
52
+ it('starts modules within a container', function () {
53
+ var module = $('<div data-module="test-alert-module"></div>')
54
+ var container = $('<div></div>').append(module)
55
+
56
+ GOVUK.modules.start(container)
57
+ expect(callback).toHaveBeenCalled()
58
+ })
59
+
60
+ it('does not start modules that are already started', function () {
61
+ var module = $('<div data-module="test-alert-module"></div>')
62
+ $('<div></div>').append(module)
63
+
64
+ GOVUK.modules.start(module)
65
+ GOVUK.modules.start(module)
66
+ expect(callback.calls.count()).toBe(1)
67
+ })
68
+
69
+ it('passes the HTML element to the module\'s start method', function () {
70
+ var module = $('<div data-module="test-alert-module"></div>')
71
+ var container = $('<h1></h1>').append(module)
72
+
73
+ GOVUK.modules.start(container)
74
+
75
+ var args = callback.calls.argsFor(0)
76
+ expect(args[0].is('div[data-module="test-alert-module"]')).toBe(true)
77
+ })
78
+
79
+ it('starts all modules that are on the page', function () {
80
+ var modules = $(
81
+ '<div data-module="test-alert-module"></div>' +
82
+ '<strong data-module="test-alert-module"></strong>' +
83
+ '<span data-module="test-alert-module"></span>'
84
+ )
85
+
86
+ $('body').append(modules)
87
+ GOVUK.modules.start()
88
+ expect(callback.calls.count()).toBe(3)
89
+
90
+ modules.remove()
91
+ })
92
+ })
93
+ })