setup testing

This commit is contained in:
Matthias Kretschmann 2020-02-15 15:21:24 +01:00
parent c0269c71e2
commit 8103a64138
Signed by: m
GPG Key ID: 606EEEF3C479A91F
11 changed files with 180 additions and 29 deletions

View File

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

View File

@ -11,6 +11,7 @@
"env": {
"browser": true,
"node": true,
"es6": true
"es6": true,
"jest": true
}
}

1
.gitignore vendored
View File

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

View File

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

View File

@ -1,5 +1,17 @@
language: node_js
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:
email: false
email: false

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)
[![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)
[![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/)
> 🥂 Gatsby plugin to add Matomo (formerly Piwik) onto a site. https://kremalicious.com/gatsby-plugin-matomo/

View File

@ -4,9 +4,10 @@
"version": "0.7.2",
"author": "Matthias Kretschmann <m@kretschmann.io>",
"scripts": {
"build": "babel src --out-dir . --ignore __tests__",
"start": "babel -w src --out-dir . --ignore __tests__",
"test": "eslint ./src/**/*.js",
"build": "babel src --out-dir . --ignore **/__tests__",
"start": "babel -w src --out-dir . --ignore **/__tests__",
"test": "npm run lint && jest --coverage",
"lint": "eslint ./src/**/*.js",
"format": "prettier --write 'src/**/*.js'",
"release": "release-it --non-interactive",
"changelog": "auto-changelog -p",
@ -16,13 +17,16 @@
"devDependencies": {
"@babel/cli": "^7.8.4",
"@babel/core": "^7.8.4",
"@babel/runtime": "^7.8.4",
"auto-changelog": "^1.16.2",
"babel-preset-gatsby-package": "^0.2.16",
"cross-env": "^7.0.0",
"eslint": "^6.8.0",
"eslint-config-prettier": "^6.10.0",
"eslint-plugin-prettier": "^3.1.2",
"jest": "^25.1.0",
"prettier": "^1.19.1",
"react": "^16.12.0",
"release-it": "^12.4.3"
},
"homepage": "https://kremalicious.com/gatsby-plugin-matomo",
@ -30,6 +34,7 @@
"gatsby",
"gatsby-plugin",
"analytics",
"tracking",
"matomo",
"piwik"
],

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

@ -13,14 +13,11 @@ function getDuration() {
}
export const onRouteUpdate = ({ location, prevLocation }) => {
if (
(process.env.NODE_ENV === 'production' && typeof _paq !== 'undefined') ||
window.dev === true
) {
const _paq = window._paq || []
const dev = window.dev || null
if (process.env.NODE_ENV === 'production' || window.dev === true) {
if (!window._paq) return
const url = location.pathname + location.search + location.hash
const { _paq, dev } = window
const url = location && location.pathname + location.search + location.hash
const prevUrl =
prevLocation &&
prevLocation.pathname + prevLocation.search + prevLocation.hash
@ -42,14 +39,9 @@ export const onRouteUpdate = ({ location, prevLocation }) => {
}
}
if ('requestAnimationFrame' in window) {
requestAnimationFrame(() => {
requestAnimationFrame(sendPageView)
})
} else {
// simulate 2 rAF calls
setTimeout(sendPageView, 32)
}
// Minimum delay for reactHelmet's requestAnimationFrame
const delay = Math.max(32, 0)
setTimeout(sendPageView, delay)
if (first) {
first = false

View File

@ -71,19 +71,21 @@ export const onRenderBody = (
{ setHeadComponents, setPostBodyComponents, pathname },
pluginOptions
) => {
const { exclude, dev } = pluginOptions
const isProduction = process.env.NODE_ENV === 'production'
let excludePaths = ['/offline-plugin-app-shell-fallback/']
if (typeof exclude !== 'undefined') {
exclude.map(exclude => {
if (pluginOptions && typeof pluginOptions.exclude !== 'undefined') {
pluginOptions.exclude.map(exclude => {
excludePaths.push(exclude)
})
}
const isPathExcluded = excludePaths.some(path => pathname === path)
if ((isProduction || dev === true) && !isPathExcluded) {
if (
(isProduction || (pluginOptions && pluginOptions.dev === true)) &&
!isPathExcluded
) {
setHeadComponents([buildHead(pluginOptions)])
setPostBodyComponents([
buildTrackingCode(pluginOptions),