Skip to content

Commit

Permalink
Configure Jest to run existing unit tests (#9)
Browse files Browse the repository at this point in the history
* refactor: Use explicit null check to get accurate return type

* Install and configure jest to support existing unit tests

* Document basic usage in README

* v0.0.2-2

* Split e2e and jest tests into separate actions

* Document basic development workflows

* Add comment explaining use of double equals

* Remove redundant ci:unit script

Co-authored-by: Andrew Hyndman <ahyndman@dropbox.com>
  • Loading branch information
ajhyndman and Andrew Hyndman authored Mar 30, 2022
1 parent 3bc7a1a commit 44fd614
Show file tree
Hide file tree
Showing 8 changed files with 1,739 additions and 47 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Install Playwright
run: npx playwright install --with-deps
- name: Run Playwright tests
run: yarn test
run: yarn ci:e2e
- uses: actions/upload-artifact@v2
if: always()
with:
Expand Down
19 changes: 19 additions & 0 deletions .github/workflows/unit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Unit Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16.x'
- name: Install dependencies
run: yarn
- name: Run Jest tests
run: yarn test:unit
107 changes: 107 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Overview

> ⚠️ **This library is an experimental early-stage project. Use at your own risk.**
`ttvc` provides an in-browser implementation of the VisuallyComplete metric suitable for field data collection (real-user monitoring).

Visually Complete measures the moment in time when users perceive that all the visual elements of a page have completely loaded. Once the page has reached visually complete, nothing else should change in the viewport without the user’s input.

# Get started

This library is available from npm. Add it to your project using the `npm` or `yarn` package managers.

```
$ npm install @dropbox-performance/ttvc
```

```
$ yarn add @dropbox-performance/ttvc
```

# Usage

## Basic usage

> ⚠️ **This API has not stabilized and is likely to change.**
```js
import {PageloadVisuallyCompleteCalculator} from '@dropbox-performance/ttvc';

// Initialize the calculator as early as possible in your page
// load so that it can observe changes.
const calculator = new PageLoadVisuallyCompleteCalculator();
calculator.start();

// Wait for the document to complete loading and compute the
// timestamp of the last visible change.
calculator.attemptMeasurement().then(timestamp => {
console.log(timestamp);
});
```

## Report metrics to a collection endpoint

TBC

## Record a PerformanceTimeline entry

TBC

# Browser Support

TBC

# Developing

This package expects node version 16 or greater, and the `yarn` package manager. Once you have these prerequisites, install project dependencies with:

```
yarn install
```

## Building

This project is developed with TypeScript. You can compile the TypeScript source files to JavaScript with:

```
$ yarn build
```

## Testing

You can run all tests together with:

```
$ yarn test
```

### Testing with Jest

To run only jest unit tests:

```
$ yarn test:unit
```


### Testing with Playwright

Before running any playwright tests, you will need to install the default set of browsers:

```
$ npx playwright install
```

Run test suite:

```
$ yarn test:e2e
```

To manually test pages, start the test server.

```
$ yarn test:server
```

Then navigate to a test case in your favorite browser. e.g. http://localhost:3000/test/ajax-mutation/
9 changes: 9 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
testMatch: ['**/*.jest.ts'],
setupFilesAfterEnv: ['./test/jest.setup.js'],
// ignore .js extensions in import statements
moduleNameMapper: {'(.+)\\.js': '$1'},
};
11 changes: 9 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dropbox-performance/ttvc",
"version": "0.0.2-1",
"version": "0.0.2-2",
"description": "Measure Visually Complete metrics in real time",
"repository": "git@github.com:dropbox/ttvc.git",
"license": "Apache-2.0",
Expand All @@ -14,22 +14,29 @@
},
"scripts": {
"build": "tsc --project tsconfig.build.json",
"test": "npm-run-all build --parallel --race test:*",
"test": "npm-run-all build jest --parallel --race test:server test:e2e",
"test:unit": "jest",
"test:server": "node test/server/server.mjs",
"test:e2e": "playwright test",
"ci:e2e": "npm-run-all build --parallel --race test:server test:e2e",
"release": "np"
},
"engines": {
"node": ">=16.0.0"
},
"devDependencies": {
"@playwright/test": "^1.20.0",
"@testing-library/dom": "^8.11.4",
"@testing-library/user-event": "^13.5.0",
"@types/express": "^4.17.13",
"@types/jest": "^27.4.1",
"@types/node": "^17.0.21",
"express": "^4.17.3",
"jest": "^27.5.1",
"np": "^7.6.1",
"npm-run-all": "^4.1.5",
"prettier": "^2.5.1",
"ts-jest": "^27.1.4",
"typescript": "^4.6.2"
}
}
4 changes: 1 addition & 3 deletions src/visually_complete_calculator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export class VisuallyCompleteCalculator {
'MutationObserver' in window &&
'IntersectionObserver' in window &&
typeof document.querySelectorAll === 'function' &&
window.performance?.timing
window.performance?.timing != null // use != to check against null AND undefined
);
}

Expand Down Expand Up @@ -83,7 +83,6 @@ export class VisuallyCompleteCalculator {
*/
async attemptMeasurement(): Promise<number | null> {
if (!this.isSupportedEnvironment) {
console.warn('Environment is not supported');
return null;
}

Expand All @@ -94,7 +93,6 @@ export class VisuallyCompleteCalculator {
this.stopObserving();

if (!this.mutations.length) {
console.warn('No mutations detected');
return null;
}

Expand Down
35 changes: 35 additions & 0 deletions test/jest.setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// TODO: Consider rewriting unit tests so that they do not require these global stubs

// stub the MutationObserver and IntersectionObserver interfaces
global.MutationObserver = class {
constructor(callback) {}
disconnect() {}
observe(element, initObject) {}
};

global.IntersectionObserver = class {
constructor(callback) {}
disconnect() {}
observe() {}
takeRecords() {}
unobserve() {}
};

// jsdom has no performance.navigation. This is an attempt to
// give it something to use instead
window.performance.navigation = {
TYPE_NAVIGATE: 0,
TYPE_RELOAD: 1,
TYPE_BACK_FORWARD: 2,
TYPE_RESERVED: 255,
redirectCount: 0,
type: 0, // TYPE_NAVIGATE
};

// some tests need this
window.performance.timing = {
// this is an arbitrary timestamp sometime in Feb 2018. We expect tests
// shouldn't care what year / day it is, but we used a fixed one for
// repeatability.
navigationStart: 1518224417028,
};
Loading

0 comments on commit 44fd614

Please sign in to comment.