1
0
mirror of https://github.com/kremalicious/gatsby-plugin-matomo.git synced 2024-12-22 17:23:23 +01:00

Merge pull request #21 from kremalicious/feature/updates

Updates, cleanup, and testing
This commit is contained in:
Matthias Kretschmann 2020-02-15 15:34:26 +01:00 committed by GitHub
commit f5a0180b98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 214 additions and 82 deletions

View File

@ -1,6 +1,3 @@
{ {
"presets": [ "presets": [["babel-preset-gatsby-package", { "browser": true }]]
["@babel/env"],
["@babel/react"]
]
} }

View File

@ -1,5 +0,0 @@
version: "2"
checks:
method-lines:
config:
threshold: 40

View File

@ -1,10 +0,0 @@
# EditorConfig is awesome: http://EditorConfig.org
[*]
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true

View File

@ -1,10 +1,6 @@
{ {
"extends": [ "extends": ["eslint:recommended", "plugin:prettier/recommended"],
"eslint:recommended", "plugins": ["prettier"],
"plugin:react/recommended",
"plugin:prettier/recommended"
],
"plugins": ["react", "prettier"],
"parserOptions": { "parserOptions": {
"sourceType": "module", "sourceType": "module",
"ecmaFeatures": { "ecmaFeatures": {
@ -15,6 +11,7 @@
"env": { "env": {
"browser": true, "browser": true,
"node": true, "node": true,
"es6": true "es6": true,
"jest": true
} }
} }

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
/*.js /*.js
node_modules node_modules
package-lock.json package-lock.json
coverage

View File

@ -4,3 +4,5 @@ src
.editorconfig .editorconfig
.eslintrc .eslintrc
.travis.yml .travis.yml
coverage
__tests__

View File

@ -1,5 +1,6 @@
{ {
"semi": false, "semi": false,
"singleQuote": true, "singleQuote": true,
"trailingComma": "none" "trailingComma": "none",
"tabWidth": 2
} }

View File

@ -1,5 +1,17 @@
language: node_js language: node_js
node_js: node node_js: node
before_script:
- curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
- chmod +x ./cc-test-reporter
- ./cc-test-reporter before-build
script:
- npm test
- npm run build
after_script:
- ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
notifications: notifications:
email: false email: false

View File

@ -1,4 +1,4 @@
Copyright (c) 2018 Matthias Kretschmann m@kretschmann.io Copyright (c) 2020 Matthias Kretschmann m@kretschmann.io
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@ -5,6 +5,7 @@
[![npm package](https://img.shields.io/npm/v/gatsby-plugin-matomo.svg)](https://www.npmjs.com/package/gatsby-plugin-matomo) [![npm package](https://img.shields.io/npm/v/gatsby-plugin-matomo.svg)](https://www.npmjs.com/package/gatsby-plugin-matomo)
[![Build Status](https://travis-ci.com/kremalicious/gatsby-plugin-matomo.svg?branch=master)](https://travis-ci.com/kremalicious/gatsby-plugin-matomo) [![Build Status](https://travis-ci.com/kremalicious/gatsby-plugin-matomo.svg?branch=master)](https://travis-ci.com/kremalicious/gatsby-plugin-matomo)
[![Maintainability](https://api.codeclimate.com/v1/badges/067339a02f2058f5ba01/maintainability)](https://codeclimate.com/github/kremalicious/gatsby-plugin-matomo/maintainability) [![Maintainability](https://api.codeclimate.com/v1/badges/067339a02f2058f5ba01/maintainability)](https://codeclimate.com/github/kremalicious/gatsby-plugin-matomo/maintainability)
[![Test Coverage](https://api.codeclimate.com/v1/badges/067339a02f2058f5ba01/test_coverage)](https://codeclimate.com/github/kremalicious/gatsby-plugin-matomo/test_coverage)
[![Greenkeeper badge](https://badges.greenkeeper.io/kremalicious/gatsby-plugin-matomo.svg)](https://greenkeeper.io/) [![Greenkeeper badge](https://badges.greenkeeper.io/kremalicious/gatsby-plugin-matomo.svg)](https://greenkeeper.io/)
> 🥂 Gatsby plugin to add Matomo (formerly Piwik) onto a site. https://kremalicious.com/gatsby-plugin-matomo/ > 🥂 Gatsby plugin to add Matomo (formerly Piwik) onto a site. https://kremalicious.com/gatsby-plugin-matomo/
@ -82,7 +83,7 @@ plugins: [
options: { options: {
siteId: 'YOUR_SITE_ID', siteId: 'YOUR_SITE_ID',
matomoUrl: 'https://YOUR_MATOMO_URL.COM', matomoUrl: 'https://YOUR_MATOMO_URL.COM',
siteUrl: 'https://YOUR_LIVE_SITE_URL.COM' siteUrl: 'https://YOUR_LIVE_SITE_URL.COM',
// All the optional settings // All the optional settings
exclude: ['/offline-plugin-app-shell-fallback/'], exclude: ['/offline-plugin-app-shell-fallback/'],
requireConsent: false, requireConsent: false,
@ -118,7 +119,7 @@ See [CHANGELOG.md](CHANGELOG.md).
The MIT License The MIT License
Copyright (c) 2018 Matthias Kretschmann Copyright (c) 2020 Matthias Kretschmann
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@ -4,42 +4,46 @@
"version": "0.7.2", "version": "0.7.2",
"author": "Matthias Kretschmann <m@kretschmann.io>", "author": "Matthias Kretschmann <m@kretschmann.io>",
"scripts": { "scripts": {
"build": "babel src --out-dir . --ignore __tests__", "build": "babel src --out-dir . --ignore **/__tests__",
"start": "babel -w src --out-dir . --ignore __tests__", "start": "babel -w src --out-dir . --ignore **/__tests__",
"test": "eslint ./src/**/*.js", "test": "npm run lint && jest --coverage",
"format": "prettier --write 'src/**/*.{js,jsx}'", "lint": "eslint ./src/**/*.js",
"format": "prettier --write 'src/**/*.js'",
"release": "release-it --non-interactive", "release": "release-it --non-interactive",
"changelog": "auto-changelog -p", "changelog": "auto-changelog -p",
"prepublishOnly": "cross-env NODE_ENV=production npm run build" "prepublishOnly": "cross-env NODE_ENV=production npm run build"
}, },
"dependencies": {}, "dependencies": {},
"devDependencies": { "devDependencies": {
"@babel/cli": "^7.4.4", "@babel/cli": "^7.8.4",
"@babel/core": "^7.4.5", "@babel/core": "^7.8.4",
"@babel/preset-env": "^7.4.5", "@babel/runtime": "^7.8.4",
"@babel/preset-react": "^7.0.0", "auto-changelog": "^1.16.2",
"auto-changelog": "^1.13.0", "babel-preset-gatsby-package": "^0.2.16",
"cross-env": "^5.2.0", "cross-env": "^7.0.0",
"eslint": "^5.16.0", "eslint": "^6.8.0",
"eslint-config-prettier": "^4.3.0", "eslint-config-prettier": "^6.10.0",
"eslint-plugin-prettier": "^3.1.0", "eslint-plugin-prettier": "^3.1.2",
"eslint-plugin-react": "^7.13.0", "jest": "^25.1.0",
"prettier": "^1.18.2", "prettier": "^1.19.1",
"react": "^16.8.6", "react": "^16.12.0",
"react-dom": "^16.8.6", "release-it": "^12.4.3"
"release-it": "^12.3.0"
}, },
"homepage": "https://github.com/kremalicious/gatsby-plugin-matomo", "homepage": "https://kremalicious.com/gatsby-plugin-matomo",
"keywords": [ "keywords": [
"gatsby", "gatsby",
"gatsby-plugin", "gatsby-plugin",
"analytics",
"tracking",
"matomo", "matomo",
"piwik" "piwik"
], ],
"license": "MIT", "license": "MIT",
"main": "index.js", "main": "index.js",
"peerDependencies": { "peerDependencies": {
"gatsby": ">=1.9.0" "gatsby": ">=2.0.0",
"react": ">=16.4.2",
"react-dom": ">=16.4.2"
}, },
"repository": "github:kremalicious/gatsby-plugin-matomo", "repository": "github:kremalicious/gatsby-plugin-matomo",
"bugs": { "bugs": {

View File

@ -0,0 +1,66 @@
import { onRouteUpdate } from '../gatsby-browser'
describe('gatsby-plugin-matomo', () => {
describe('gatsby-browser', () => {
beforeEach(() => {
jest.useFakeTimers()
window._paq = { push: jest.fn() }
})
afterEach(() => {
jest.resetAllMocks()
})
describe('onRouteUpdate', () => {
describe('in non-production env', () => {
beforeAll(() => {
window._paq = { push: jest.fn() }
})
it('does not send page view', () => {
onRouteUpdate({})
expect(window._paq.push).not.toHaveBeenCalled()
})
it('sends page view in dev mode', () => {
window.dev = true
onRouteUpdate({})
expect(window._paq.push).toHaveBeenCalledTimes(1)
})
})
describe('in production env', () => {
let env
beforeAll(() => {
env = process.env.NODE_ENV
process.env.NODE_ENV = 'production'
})
afterAll(() => {
process.env.NODE_ENV = env
})
it('does not send page view when _paq is undefined', () => {
delete window._paq
onRouteUpdate({})
jest.runAllTimers()
expect(setTimeout).not.toHaveBeenCalled()
})
it('sends page view', () => {
onRouteUpdate({})
jest.runAllTimers()
expect(window._paq.push).toHaveBeenCalledTimes(5)
})
it('uses setTimeout with a minimum delay of 32ms', () => {
onRouteUpdate({})
jest.runAllTimers()
expect(setTimeout).toHaveBeenCalledWith(expect.any(Function), 32)
expect(window._paq.push).toHaveBeenCalledTimes(5)
})
})
})
})
})

View File

@ -0,0 +1,74 @@
import { onRenderBody } from '../gatsby-ssr'
describe('gatsby-plugin-google-analytics', () => {
describe('gatsby-ssr', () => {
describe('onRenderBody', () => {
describe('in non-production env', () => {
it('does not set tracking script', () => {
const setHeadComponents = jest.fn()
onRenderBody({ setHeadComponents })
expect(setHeadComponents).not.toHaveBeenCalled()
})
})
describe('in production env', () => {
let env
beforeAll(() => {
env = process.env.NODE_ENV
process.env.NODE_ENV = 'production'
})
afterAll(() => {
process.env.NODE_ENV = env
})
const setup = options => {
const setHeadComponents = jest.fn()
const setPostBodyComponents = jest.fn()
options = Object.assign(
{
siteId: 'TEST_SITE_ID',
matomoUrl: 'TEST_MATOMO_URL',
siteUrl: 'TEST_SITE_URL'
},
options
)
onRenderBody({ setHeadComponents, setPostBodyComponents }, options)
return {
setHeadComponents,
setPostBodyComponents
}
}
it('sets tracking script', () => {
const { setHeadComponents, setPostBodyComponents } = setup()
expect(setHeadComponents).toHaveBeenCalledTimes(1)
expect(setPostBodyComponents).toHaveBeenCalledTimes(1)
})
it('sets siteId', () => {
const { setPostBodyComponents } = setup()
const result = JSON.stringify(setPostBodyComponents.mock.calls[0][0])
expect(result).toMatch(/TEST_SITE_ID/)
})
it('sets matomoUrl', () => {
const { setPostBodyComponents } = setup()
const result = JSON.stringify(setPostBodyComponents.mock.calls[0][0])
expect(result).toMatch(/TEST_MATOMO_URL/)
})
it('sets siteUrl', () => {
const { setPostBodyComponents } = setup()
const result = JSON.stringify(setPostBodyComponents.mock.calls[0][0])
expect(result).toMatch(/TEST_SITE_URL/)
})
})
})
})
})

View File

@ -1,5 +1,3 @@
/* eslint-disable no-console */
let first = true let first = true
function getDuration() { function getDuration() {
@ -14,15 +12,12 @@ function getDuration() {
return difference return difference
} }
exports.onRouteUpdate = ({ location, prevLocation }) => { export const onRouteUpdate = ({ location, prevLocation }) => {
if ( if (process.env.NODE_ENV === 'production' || window.dev === true) {
(process.env.NODE_ENV === 'production' && typeof _paq !== 'undefined') || if (!window._paq) return
window.dev === true
) {
const _paq = window._paq || []
const dev = window.dev || null
const url = location.pathname + location.search + location.hash const { _paq, dev } = window
const url = location && location.pathname + location.search + location.hash
const prevUrl = const prevUrl =
prevLocation && prevLocation &&
prevLocation.pathname + prevLocation.search + prevLocation.hash prevLocation.pathname + prevLocation.search + prevLocation.hash
@ -40,27 +35,23 @@ exports.onRouteUpdate = ({ location, prevLocation }) => {
_paq.push(['trackAllContentImpressions']) _paq.push(['trackAllContentImpressions'])
if (dev) { if (dev) {
console.log(`[Matomo] Page view for: ${url} - ${title}`) console.debug(`[Matomo] Page view for: ${url} - ${title}`)
} }
} }
if ('requestAnimationFrame' in window) { // Minimum delay for reactHelmet's requestAnimationFrame
requestAnimationFrame(() => { const delay = Math.max(32, 0)
requestAnimationFrame(sendPageView) setTimeout(sendPageView, delay)
})
} else {
// simulate 2 rAF calls
setTimeout(sendPageView, 32)
}
if (first) { if (first) {
first = false first = false
_paq.push(['trackEvent', 'javascript', 'load', 'duration', getDuration()]) _paq.push(['trackEvent', 'javascript', 'load', 'duration', getDuration()])
if (dev) { if (dev) {
console.log(`[Matomo] Tracking duration for: ${url}`) console.debug(`[Matomo] Tracking duration for: ${url}`)
} }
} }
} }
return null return null
} }

View File

@ -1,3 +1,4 @@
// eslint-disable-next-line no-unused-vars
import React from 'react' import React from 'react'
function buildTrackingCode(pluginOptions) { function buildTrackingCode(pluginOptions) {
@ -29,29 +30,28 @@ function buildTrackingCode(pluginOptions) {
})(); })();
if (window.dev === true) { if (window.dev === true) {
console.log('[Matomo] Tracking initialized') console.debug('[Matomo] Tracking initialized')
console.log('[Matomo] matomoUrl: ${matomoUrl}, siteId: ${siteId}') console.debug('[Matomo] matomoUrl: ${matomoUrl}, siteId: ${siteId}')
} }
} }
` `
return ( return (
<script <script
key={'gatsby-plugin-matomo'} key="script-gatsby-plugin-matomo"
dangerouslySetInnerHTML={{ __html: html }} dangerouslySetInnerHTML={{ __html: html }}
/> />
) )
} }
function buildTrackingCodeNoJs(pluginOptions, pathname) { function buildTrackingCodeNoJs(pluginOptions, pathname) {
const html = `<img src="${pluginOptions.matomoUrl}/piwik.php?idsite=${ const { matomoUrl, siteId, siteUrl } = pluginOptions
pluginOptions.siteId const html = `<img src="${matomoUrl}/piwik.php?idsite=${siteId}&rec=1&url=${siteUrl +
}&rec=1&url=${pluginOptions.siteUrl +
pathname}" style="border:0" alt="tracker" />` pathname}" style="border:0" alt="tracker" />`
return ( return (
<noscript <noscript
key={'gatsby-plugin-matomo'} key="noscript-gatsby-plugin-matomo"
dangerouslySetInnerHTML={{ __html: html }} dangerouslySetInnerHTML={{ __html: html }}
/> />
) )
@ -62,18 +62,19 @@ function buildHead(pluginOptions) {
<link <link
rel="preconnect" rel="preconnect"
href={pluginOptions.matomoUrl} href={pluginOptions.matomoUrl}
key={'gatsby-plugin-matomo'} key="preconnect-gatsby-plugin-matomo"
/> />
) )
} }
exports.onRenderBody = ( export const onRenderBody = (
{ setHeadComponents, setPostBodyComponents, pathname }, { setHeadComponents, setPostBodyComponents, pathname },
pluginOptions pluginOptions
) => { ) => {
const isProduction = process.env.NODE_ENV === 'production'
let excludePaths = ['/offline-plugin-app-shell-fallback/'] let excludePaths = ['/offline-plugin-app-shell-fallback/']
if (typeof pluginOptions.exclude !== 'undefined') { if (pluginOptions && typeof pluginOptions.exclude !== 'undefined') {
pluginOptions.exclude.map(exclude => { pluginOptions.exclude.map(exclude => {
excludePaths.push(exclude) excludePaths.push(exclude)
}) })
@ -82,7 +83,7 @@ exports.onRenderBody = (
const isPathExcluded = excludePaths.some(path => pathname === path) const isPathExcluded = excludePaths.some(path => pathname === path)
if ( if (
(process.env.NODE_ENV === 'production' || pluginOptions.dev === true) && (isProduction || (pluginOptions && pluginOptions.dev === true)) &&
!isPathExcluded !isPathExcluded
) { ) {
setHeadComponents([buildHead(pluginOptions)]) setHeadComponents([buildHead(pluginOptions)])