Files
cypress/packages/rewriter/test/unit/deferred-source-map-cache-spec.ts
T
Zach Bloomquist 6960f7cd78 Rewrite JS/HTML using AST-based approach (#5273)
* Add winPropAccessor to security.js, remove other replacers

* Add start of Cypress.resolveWindowReference

* Add regexes for dot and bracket access

* Some security_spec tests pass with new injection

* Add resolveWindowReference unit tests

* Old security_spec now passes with resolveWindowReference

* Inject stub resolveWindowReference so proxy still works outside of Cypress

* wip: rewrite HTML + JS with tokenizer

* Move to using esprima + hyntax to rewrite JS + HTML

* remove comment; oneLine makes the whole thing commented

* Fix tests, apple.com edge case

* wip: add getOrSet

* Revert "wip: add getOrSet"

This reverts commit a5c647c00f.

* release 3.5.0 [skip ci]

* use recast to replace window property accesses

* replace assignments to top properly

* fix yarn.lock

* bump deps

* update integration tests

* remove old security ts?

* fix integration spec

* always ignore js interception failure

* use globalThis instead of window

* add experimentalSourceRewriting flag

* restore regex-writer spec

* fix types

* update config_spec

* add source rewriting spec

* cleanup

* simplify rewriting logic, move rules into rewriter package

* create threaded rewriting tool for non-streaming use

* update @packages/rewriter to use threads for async

* use async rewriting where convenient

* add worker-shim.js

* add performance info to debug logs

* properly handle +=, -=, ...

* add proxy, rewriter to unit-tests stage

* cleanup

* use parse5 to rewrite HTML, strip SRI

* update tests

* reorganization, cleanup

* rewrite ALL parent, top identifiers except in a few cases

* handle many JS edge cases

* ensure parse5@5.1.1 is installed

* update yarn.lock

* update tests

* add debugging, add tests

* add attempted repro for .href issue

* implement source maps + extending inline source maps

* update opts passing in proxy layer

* fix sourcemap naming structure

* update tests to account for sourcemaps

* sourcemap tests

* remote source maps work

* comment

* update rewriter tests

* clean up TODOs in resolveWindowReference

* remove @types/nock

* clean up todos in deferred-source-map-cache

* fix rewriter build script

* fix concatStream import

* bump expectedresultcount

* clean up js-rules

* threading improvements, workaround for Electron segfault

* no visit_spec for now

* fix 6_visit_spec

* update MAX_WORKER_THREADS

* add repro for #3975

* cleanup

* cleanup

* make better use of namedTypes and builders

* get rid of the horrific closureDetectionTernary

ast-types keeps track of scope, so it is unneeded

* fix #3975, #3994

* add x-sourcemap, sourcemap header support

* snap-shot-it 7.9.3

* add deferred-source-map-cache-spec

* add tests

* Throw error in driver if AST rewriting fails

* Fix "location = 'relative-url'"

* fix max recursion depth

* slim down some fixtures

* fix window.location usage

* don't mess with `frames` at all

* no integration tests

* skip testing apple.com for now

* update wording: regex-based vs. ast-based

* skip real-world tests for now

* add some padding to process.exit workaround

* fix resolvers_spec

* fix html-spec

* cleanup

* Update packages/rewriter/lib/js-rules.ts

* Update packages/driver/src/cypress/resolvers.ts

* just import find by itself

* privatize typedefs for Cypress.state, remove .gitignore, remove dead code

Co-authored-by: Ben Kucera <14625260+Bkucera@users.noreply.github.com>
2020-05-11 12:54:14 -04:00

151 lines
4.3 KiB
TypeScript

import { DeferredSourceMapCache } from '../../lib/deferred-source-map-cache'
import sinon from 'sinon'
import chai, { expect } from 'chai'
import chaiAsPromised from 'chai-as-promised'
import sinonChai from 'sinon-chai'
import {
testSourceWithExternalSourceMap,
testSourceWithInlineSourceMap,
testSourceMap,
testSourceWithNoSourceMap,
} from '../fixtures'
import snapshot from 'snap-shot-it'
chai.use(chaiAsPromised)
chai.use(sinonChai)
describe('DeferredSourceMapCache', function () {
let cache: DeferredSourceMapCache
beforeEach(() => {
cache = new DeferredSourceMapCache(sinon.stub())
})
afterEach(() => {
sinon.restore()
})
context('#defer', () => {
it('adds to requests', () => {
const request = { uniqueId: 'foo', url: 'bar' }
cache.defer(request)
expect(cache.requests).to.deep.eq([request])
})
it('replaces existing requests for same URL', () => {
const request0 = { uniqueId: 'kung-fu', url: 'http://other.url/foo.js' }
const request1 = { uniqueId: 'foo', url: 'http://bar.baz/quux.js' }
const request2 = { uniqueId: 'kung-foo', url: 'http://bar.baz/quux.js' }
cache.defer(request0)
cache.defer(request1)
cache.defer(request2)
expect(cache.requests).to.deep.eq([request0, request2])
})
it('throws if uniqueId is duplicated', () => {
cache.defer({ uniqueId: 'foo', url: 'bar' })
expect(() => {
cache.defer({ uniqueId: 'foo', url: 'baz' })
}).to.throw
})
})
context('#resolve', () => {
it('rejects if unknown uniqueId', async () => {
cache.defer({
uniqueId: 'baz',
url: 'quux',
})
await expect(cache.resolve('foo', {})).to.be.rejectedWith('Missing request with ID \'foo\'')
})
it('rejects if request missing JS', async () => {
cache.defer({
uniqueId: 'foo',
url: 'bar',
})
await expect(cache.resolve('foo', {})).to.be.rejectedWith(/^Missing JS/)
})
context('sourcemap generation', () => {
it('for JS with no original sourcemap', async () => {
cache.defer({
uniqueId: 'foo',
url: 'bar',
js: 'console.log()',
resHeaders: {},
})
snapshot(await cache.resolve('foo', {}))
})
it('resolves with cached sourceMap on retry', async () => {
cache.defer({
uniqueId: 'foo',
url: 'bar',
js: 'console.log()',
resHeaders: {},
})
const result0 = await cache.resolve('foo', {})
const result1 = await cache.resolve('foo', {})
expect(result0).to.eq(result1) // same object reference
})
context('composition', () => {
const URL = 'http://somedomain.net/dir/foo.js'
const testExternalSourceMap = (js, resHeaders, expectRequest = true) => {
return async () => {
cache.defer({
uniqueId: 'foo',
url: URL,
js,
resHeaders,
})
// @ts-ignore: https://github.com/bahmutov/snap-shot-it/issues/522
snapshot('composed sourcemap', await cache.resolve('foo', {}), { allowSharedSnapshot: true })
if (!expectRequest) {
return
}
expect(cache.requestLib).to.be.calledWith({
url: 'http://somedomain.net/dir/test.js.map',
headers: {},
timeout: 5000,
})
}
}
beforeEach(() => {
cache.requestLib.resolves({ body: testSourceMap })
})
it('with inlined base64 sourceMappingURL', testExternalSourceMap(testSourceWithInlineSourceMap, {}, false))
it('with external sourceMappingURL', testExternalSourceMap(testSourceWithExternalSourceMap, {
// sourceMappingURL should override headers
'SOURCEmap': 'garbage',
'x-sourceMAP': 'garbage',
}))
it('with map referenced by sourcemap header', testExternalSourceMap(testSourceWithNoSourceMap, {
'SOURCEmap': 'test.js.map',
'x-sourceMAP': 'garbage', // SourceMap header should override x-sourcemap
}))
it('with map referenced by x-sourcemap header', testExternalSourceMap(testSourceWithNoSourceMap, {
'x-sourceMAP': 'test.js.map',
}))
})
})
})
})