Skip to content

Commit

Permalink
feat: support usage in cloudflare workers (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattcosta7 authored Nov 8, 2023
1 parent 9419819 commit a28051e
Show file tree
Hide file tree
Showing 6 changed files with 1,917 additions and 2,163 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node_version: [14, 16]
node_version: [18, 20]
steps:
- uses: actions/checkout@v3

Expand Down
24 changes: 13 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,26 @@
"lib"
],
"engines": {
"node": ">=14"
"node": ">=18"
},
"devDependencies": {
"@commitlint/cli": "^16.0.3",
"@commitlint/config-conventional": "^16.0.0",
"@ossjs/release": "^0.2.1",
"@types/jest": "^26.0.15",
"@types/set-cookie-parser": "^2.4.0",
"@types/jest": "^29.5.7",
"@types/set-cookie-parser": "^2.4.5",
"commitizen": "^4.2.4",
"cz-conventional-changelog": "^3.3.0",
"jest": "^26.6.3",
"rimraf": "^3.0.2",
"set-cookie-parser": "^2.4.6",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jest-environment-miniflare": "^2.14.1",
"rimraf": "^5.0.5",
"set-cookie-parser": "^2.6.0",
"simple-git-hooks": "^2.7.0",
"ts-jest": "^26.4.4",
"ts-node": "^9.0.0",
"ts-jest": "^29.1.1",
"ts-node": "^10.9.1",
"tsup": "^6.2.3",
"typescript": "^4.0.5",
"whatwg-fetch": "^3.5.0"
"typescript": "^5.2.2",
"whatwg-fetch": "^3.6.19"
}
}
}
29 changes: 28 additions & 1 deletion src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,26 @@ function supportsLocalStorage() {
}
}

/**
* Checks that accessing a given property on an object
* by name does not throw an error.
*
* This is generally used to avoid issues in environments
* like `miniflare` where some properties are defined as getters
* where accessing that property throws directly.
*/
function isPropertyAccessible<Obj extends Record<string, any>>(
object: Obj,
method: keyof Obj,
) {
try {
object[method]
return true
} catch {
return false
}
}

class CookieStore {
private store: Store

Expand All @@ -49,7 +69,10 @@ class CookieStore {
* Respects the `request.credentials` policy.
*/
add(request: RequestLike, response: ResponseLike): void {
if (request.credentials === 'omit') {
if (
isPropertyAccessible(request, 'credentials') &&
request.credentials === 'omit'
) {
return
}

Expand Down Expand Up @@ -89,6 +112,10 @@ class CookieStore {
const originCookies =
this.store.get(requestUrl.origin) || new Map<string, Cookie>()

if (!isPropertyAccessible(request, 'credentials')) {
return originCookies
}

switch (request.credentials) {
case 'include': {
// Support running this method in Node.js.
Expand Down
18 changes: 10 additions & 8 deletions test/invalid-store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,19 @@ afterEach(() => {
it('should reset the store if contains an invalid value', () => {
jest.spyOn(global.console, 'warn').mockImplementation(() => {})
localStorage.setItem(PERSISTENCY_KEY, 'not valid json')

const mockConsole = jest.mocked(global.console.warn)
expect(() => store.hydrate()).not.toThrow()
expect(localStorage.getItem(PERSISTENCY_KEY)).toBeNull()
expect(console.warn).toHaveBeenCalledWith(`
const errorMessage = mockConsole.mock.calls[0][0]
expect(errorMessage).toContain(`
[virtual-cookie] Failed to parse a stored cookie from the localStorage (key \"MSW_COOKIE_STORE\").
Stored value:
not valid json
Thrown exception:
SyntaxError: Unexpected token o in JSON at position 1
Invalid value has been removed from localStorage to prevent subsequent failed parsing attempts.`)
not valid json`)
// not asserting on the entire error message because it's different in different node versions
expect(errorMessage).toContain(`Thrown exception:
SyntaxError: Unexpected token`)
expect(errorMessage).toContain(
`Invalid value has been removed from localStorage to prevent subsequent failed parsing attempts.`,
)
})
91 changes: 91 additions & 0 deletions test/store.miniflare.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**
* @jest-environment miniflare
* @jest-environment-options {"scriptPath": "src/index.ts"}
*/
import { store } from '../src'

afterEach(() => {
store.clear()
})

it('stores cookies for the given request', () => {
const req = new Request('https://mswjs.io')
const res = new Response(null, {
headers: new Headers({ 'Set-Cookie': 'cookieName=abc-123' }),
})

store.add(req, res)

const allCookies = Array.from(store.getAll().entries())
expect(allCookies).toEqual([
[
'https://mswjs.io',
new Map([['cookieName', { name: 'cookieName', value: 'abc-123' }]]),
],
])
})

it('returns cookies for the requests with credentials "include"', () => {
const req = new Request('https://mswjs.io', {
credentials: 'include',
})
const res = new Response(null, {
headers: new Headers({ 'Set-Cookie': 'secret=abc-123' }),
})
store.add(req, res)

const cookies = store.get(req)
expect(cookies).toEqual(
new Map([
[
'secret',
{
name: 'secret',
value: 'abc-123',
maxAge: undefined,
expires: undefined,
},
],
]),
)
})

it('returns cookies for the requests with credentials "same-origin"', () => {
const req = new Request('https://mswjs.io', {
credentials: 'same-origin',
})
const res = new Response(null, {
headers: new Headers({ 'Set-Cookie': 'secret=abc-123' }),
})

store.add(req, res)
store.add(
{
url: 'https://test.io',
credentials: 'include',
},
new Response(null, {
headers: new Headers({ 'Set-Cookie': 'anotherCookie=yes' }),
}),
)

const cookies = store.get(req)
expect(cookies).toEqual(
new Map([['secret', { name: 'secret', value: 'abc-123' }]]),
)
})

it('returns cookies for the requests with credentials "omit"', () => {
const req = new Request('https://mswjs.io', {
credentials: 'omit',
})
const res = new Response(null, {
headers: new Headers({ 'Set-Cookie': 'secret=abc-123' }),
})
store.add(req, res)

const cookies = store.get(req)
expect(cookies).toEqual(
new Map([['secret', { name: 'secret', value: 'abc-123' }]]),
)
})
Loading

0 comments on commit a28051e

Please sign in to comment.