Skip to content

Commit

Permalink
Update usage in readme
Browse files Browse the repository at this point in the history
  • Loading branch information
Jack Steam committed Mar 11, 2020
1 parent 349cb59 commit b050b68
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 41 deletions.
88 changes: 61 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ on
npm i @bumble/jest-chrome -D
```

We will set `chrome` in the global scope during setup so that it
is mocked in imported modules. We need a setup file for this:
Set `chrome` in the global scope during setup so that it is
mocked in imported modules. Add a setup file to `jest.config.js`:

```javascript
// jest.config.js
Expand All @@ -30,30 +30,39 @@ module.exports = {
}
```

Then in the setup file we will assign the mocked `chrome` object
to the global object:
Use the setup file to assign the mocked `chrome` object to the
`global` object:

```javascript
// jest.setup.js

Object.assign(global, require('@bumble/jest-chrome'))
```

Now `chrome` will be mocked for all modules.
Import `chrome` from `@bumble/jest-chrome` for Intellisense and
linting. This is the same object as `chrome` in the global scope.

```javascript
import { chrome } from '@bumble/jest-chrome'
```

## Usage

> All of the following code blocks come from
> `tests/demo.test.ts`.
> [`tests/demo.test.ts`](tests/demo.test.ts).
Import `chrome` from `@bumble/jest-chrome` for Intellisense and
linting. It will be the same object any imported modules use.
### Events

```javascript
import { chrome } from '@bumble/jest-chrome'
```
Each mocked Event has all the normal methods (`addListener`,
`hasListener`, `hasListeners`, and `removeListener`) plus two
more: `callListeners` and `clearListeners`.

<!-- TODO: explain events -->
`callListeners` triggers a specific Event. Call `callListeners`
with the arguments you expect Chrome to pass to your event
listeners. Each event listener for that Event will be called with
those arguments.

`clearListeners` removes all listeners for a specific Event.

```javascript
test('chrome api events', () => {
Expand All @@ -80,7 +89,10 @@ test('chrome api events', () => {
})
```

<!-- TODO: explain simple functions -->
### Synchronous functions

Some Chrome API functions are synchronous. Use these like any
mocked function:

```javascript
test('chrome api functions', () => {
Expand All @@ -97,7 +109,13 @@ test('chrome api functions', () => {
})
```

<!-- TODO: explain functions with callback -->
### Functions with callbacks

Most Chrome API functions do something asynchronous. They use
callbacks to handle the result. The mock implementation should be
set to handle the callback.

> Mocked functions have no default mock implementation!
```javascript
test('chrome api functions with callback', () => {
Expand All @@ -121,20 +139,29 @@ test('chrome api functions with callback', () => {
})
```

<!-- TODO: explain callbacks with lastError -->
### Callbacks and `chrome.runtime.lastError`

When something goes wrong in a callback, Chrome sets
`chrome.runtime.lastError` to an object with a message property.
If you need to test this, set and clear `lastError` in the mock
implementation.

> Remember that `lastError` is always undefined outside of a
> callback!
`lastError` is an object with a
[getter function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get)
for the `message` property. If `message` is not checked, Chrome
will log the error to the console. To emulate this, simply set
`lastError` to an object with a getter that wraps a mock, as seen
below:

```javascript
test('chrome api functions with lastError', () => {
const message = { greeting: 'hello?' }
const response = { greeting: 'here I am' }

const lastErrorSpy = jest.fn()
const callbackSpy = jest.fn(() => {
if (chrome.runtime.lastError) {
lastErrorSpy(chrome.runtime.lastError.message)
}
})

// lastError setup
const lastErrorMessage = 'this is an error'
const lastErrorGetter = jest.fn(() => lastErrorMessage)
const lastError = {
Expand All @@ -143,27 +170,34 @@ test('chrome api functions with lastError', () => {
},
}

// mock implementation
chrome.runtime.sendMessage.mockImplementation(
(message, callback) => {
chrome.runtime.lastError = lastError

callback(response)

// lastError is undefined outside of a callback
delete chrome.runtime.lastError
},
)

chrome.runtime.sendMessage(message, callbackSpy)
// callback implementation
const lastErrorSpy = jest.fn()
const callbackSpy = jest.fn(() => {
if (chrome.runtime.lastError) {
lastErrorSpy(chrome.runtime.lastError.message)
}
})

expect(chrome.runtime.sendMessage).toBeCalledWith(
message,
callbackSpy,
)
// send a message
chrome.runtime.sendMessage(message, callbackSpy)

expect(callbackSpy).toBeCalledWith(response)
expect(lastErrorGetter).toBeCalled()
expect(lastErrorSpy).toBeCalledWith(lastErrorMessage)

// lastError has been cleared
expect(chrome.runtime.lastError).toBeUndefined()
})
```
27 changes: 13 additions & 14 deletions tests/demo.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,7 @@ test('chrome api functions with lastError', () => {
const message = { greeting: 'hello?' }
const response = { greeting: 'here I am' }

const lastErrorSpy = jest.fn()
const callbackSpy = jest.fn(() => {
if (chrome.runtime.lastError) {
lastErrorSpy(chrome.runtime.lastError.message)
}
})

// lastError setup
const lastErrorMessage = 'this is an error'
const lastErrorGetter = jest.fn(() => lastErrorMessage)
const lastError = {
Expand All @@ -75,28 +69,33 @@ test('chrome api functions with lastError', () => {
},
}

// mock implementation
chrome.runtime.sendMessage.mockImplementation(
(message, callback) => {
chrome.runtime.lastError = lastError

callback(response)

// lastError is undefined outside of a callback
delete chrome.runtime.lastError
},
)

chrome.runtime.sendMessage(message, callbackSpy)
// callback implementation
const lastErrorSpy = jest.fn()
const callbackSpy = jest.fn(() => {
if (chrome.runtime.lastError) {
lastErrorSpy(chrome.runtime.lastError.message)
}
})

expect(chrome.runtime.sendMessage).toBeCalledWith(
message,
callbackSpy,
)
// send a message
chrome.runtime.sendMessage(message, callbackSpy)

expect(callbackSpy).toBeCalledWith(response)
expect(lastErrorGetter).toBeCalled()
expect(lastErrorSpy).toBeCalledWith(lastErrorMessage)

// lastError has been cleared
expect(chrome.runtime.lastError).toBeUndefined()
})


0 comments on commit b050b68

Please sign in to comment.