@revoloo/cypress6
Version:
Cypress.io end to end testing tool
373 lines (329 loc) • 11.4 kB
text/typescript
import _ from 'lodash'
import { concatStream } from '@packages/network'
import { expect } from 'chai'
import fs from 'fs'
import Promise from 'bluebird'
import rp from '@cypress/request-promise'
import * as regexRewriter from '../../../../lib/http/util/regex-rewriter'
const original = `\
<html>
<body>
top1
settop
settopbox
parent1
grandparent
grandparents
myself
mywindow
selfVar
fooparent
windowFile
topFoo
topFoo.window
topFoo.window != topFoo
parentFoo
parentFoo.window
parentFoo.window != parentFoo
<div style="left: 1500px; top: 0px;"></div>
<div style="left: 1500px; top : 0px;"></div>
<div style="left: 1500px; top : 0px;"></div>
parent()
foo.parent()
top()
foo.top()
foo("parent")
foo("top")
const parent = () => { bar: 'bar', framesStyle: 'foo' }
const loadStop = { locationExists = true }
parent.bar
<script type="text/javascript">
if (top != self) run()
if (top!=self) run()
if (self !== top) run()
if (self!==top) run()
if (self === top) return
if (myself !== top) runs()
if (mywindow !== top) runs()
if (top.location!=self.location&&(top.location.href=self.location.href)) run()
if (top.location != self.location) run()
if (top.location != location) run()
if (self.location != top.location) run()
if (loadStop.locationExists) run()
if (!top.locationExists) run()
if (parent.frames.length > 0) run()
if (parent.framesStyle) run()
if (window != top) run()
if (window.top !== window.self) run()
if (window.top!==window.self) run()
if (window.self != window.top) run()
if (window.top != window.self) run()
if (window["top"] != window["parent"]) run()
if (window['top'] != window['parent']) run()
if (window["top"] != self['parent']) run()
if (parent && parent != window) run()
if (parent && parent != self) run()
if (parent && window != parent) run()
if (parent && self != parent) run()
if (myself != parent) run()
if (parent && parent.frames && parent.frames.length > 0) run()
if ((self.parent && !(self.parent === self)) && (self.parent.frames.length != 0)) run()
if (parent !== null && parent.tag !== 'HostComponent' && parent.tag !== 'HostRoot') { }
if (null !== parent && parent.tag !== 'HostComponent' && parent.tag !== 'HostRoot') { }
if (top===self) return
if (top==self) return
if (loadStop===selfVar) return
if (fooparent===selfVar) return
if (loadStop===windowFile) return
if (fooparent===windowFile) return
</script>
</body>
</html>\
`
const expected = `\
<html>
<body>
top1
settop
settopbox
parent1
grandparent
grandparents
myself
mywindow
selfVar
fooparent
windowFile
topFoo
topFoo.window
topFoo.window != topFoo
parentFoo
parentFoo.window
parentFoo.window != parentFoo
<div style="left: 1500px; top: 0px;"></div>
<div style="left: 1500px; top : 0px;"></div>
<div style="left: 1500px; top : 0px;"></div>
parent()
foo.parent()
top()
foo.top()
foo("parent")
foo("top")
const parent = () => { bar: 'bar', framesStyle: 'foo' }
const loadStop = { locationExists = true }
parent.bar
<script type="text/javascript">
if (self != self) run()
if (self!=self) run()
if (self !== self) run()
if (self!==self) run()
if (self === self) return
if (myself !== top) runs()
if (mywindow !== top) runs()
if (self.location!=self.location&&(self.location.href=self.location.href)) run()
if (self.location != self.location) run()
if (self.location != location) run()
if (self.location != self.location) run()
if (loadStop.locationExists) run()
if (!top.locationExists) run()
if (self.frames.length > 0) run()
if (parent.framesStyle) run()
if (window != self) run()
if (window.self !== window.self) run()
if (window.self!==window.self) run()
if (window.self != window.self) run()
if (window.self != window.self) run()
if (window["self"] != window["self"]) run()
if (window['self'] != window['self']) run()
if (window["self"] != self['self']) run()
if (parent && self != window) run()
if (parent && self != self) run()
if (parent && window != self) run()
if (parent && self != self) run()
if (myself != parent) run()
if (parent && self.frames && self.frames.length > 0) run()
if ((self.parent && !(self.self === self)) && (self.self.frames.length != 0)) run()
if (parent !== null && parent.tag !== 'HostComponent' && parent.tag !== 'HostRoot') { }
if (null !== parent && parent.tag !== 'HostComponent' && parent.tag !== 'HostRoot') { }
if (self===self) return
if (self==self) return
if (loadStop===selfVar) return
if (fooparent===selfVar) return
if (loadStop===windowFile) return
if (fooparent===windowFile) return
</script>
</body>
</html>\
`
describe('http/util/regex-rewriter', () => {
context('.strip', () => {
it('replaces obstructive code', () => {
expect(regexRewriter.strip(original)).to.eq(expected)
})
it('replaces jira window getter', () => {
const jira = `\
for (; !function (n) {
return n === n.parent
}(n)\
`
const jira2 = `\
function(n){for(;!function(l){return l===l.parent}(l)&&function(l){try{if(void 0==l.location.href)return!1}catch(l){return!1}return!0}(l.parent);)l=l.parent;return l}\
`
const jira3 = `\
function satisfiesSameOrigin(w) {
try {
// Accessing location.href from a window on another origin will throw an exception.
if ( w.location.href == undefined) {
return false;
}
} catch (e) {
return false;
}
return true;
}
function isTopMostWindow(w) {
return w === w.parent;
}
while (!isTopMostWindow(parentOf) && satisfiesSameOrigin(parentOf.parent)) {
parentOf = parentOf.parent;
}\
`
expect(regexRewriter.strip(jira)).to.eq(`\
for (; !function (n) {
return n === n.parent || n.parent.__Cypress__
}(n)\
`)
expect(regexRewriter.strip(jira2)).to.eq(`\
function(n){for(;!function(l){return l===l.parent || l.parent.__Cypress__}(l)&&function(l){try{if(void 0==l.location.href)return!1}catch(l){return!1}return!0}(l.parent);)l=l.parent;return l}\
`)
expect(regexRewriter.strip(jira3)).to.eq(`\
function satisfiesSameOrigin(w) {
try {
// Accessing location.href from a window on another origin will throw an exception.
if ( w.location.href == undefined) {
return false;
}
} catch (e) {
return false;
}
return true;
}
function isTopMostWindow(w) {
return w === w.parent || w.parent.__Cypress__;
}
while (!isTopMostWindow(parentOf) && satisfiesSameOrigin(parentOf.parent)) {
parentOf = parentOf.parent;
}\
`)
})
describe('libs', () => {
// go out and download all of these libs and ensure
// that we can run them through the security strip
// and that they are not modified!
const cdnUrl = 'https://cdnjs.cloudflare.com/ajax/libs'
const needsDash = ['backbone', 'underscore']
let libs = {
jquery: `${cdnUrl}/jquery/3.3.1/jquery.js`,
jqueryui: `${cdnUrl}/jqueryui/1.12.1/jquery-ui.js`,
angular: `${cdnUrl}/angular.js/1.6.5/angular.js`,
bootstrap: `${cdnUrl}/twitter-bootstrap/4.0.0/js/bootstrap.js`,
fontawesome: `${cdnUrl}/font-awesome/4.7.0/css/font-awesome.css`,
moment: `${cdnUrl}/moment.js/2.20.1/moment.js`,
lodash: `${cdnUrl}/lodash.js/4.17.5/lodash.js`,
vue: `${cdnUrl}/vue/2.5.13/vue.js`,
backbone: `${cdnUrl}/backbone.js/1.3.3/backbone.js`,
cycle: `${cdnUrl}/cyclejs-core/7.0.0/cycle.js`,
d3: `${cdnUrl}/d3/4.13.0/d3.js`,
normalize: `${cdnUrl}/normalize/8.0.0/normalize.css`,
underscore: `${cdnUrl}/underscore.js/1.8.3/underscore.js`,
foundation: `${cdnUrl}/foundation/6.4.3/js/foundation.js`,
require: `${cdnUrl}/require.js/2.3.5/require.js`,
rxjs: `${cdnUrl}/rxjs/5.5.6/Rx.js`,
bluebird: `${cdnUrl}/bluebird/3.5.1/bluebird.js`,
}
libs = _
.chain(libs)
.clone()
.reduce((memo, url, lib) => {
memo[lib] = url
memo[`${lib}Min`] = url
.replace(/js$/, 'min.js')
.replace(/css$/, 'min.css')
if (needsDash.includes(lib)) {
memo[`${lib}Min`] = url.replace('min', '-min')
}
return memo
}
, {})
.extend({
knockoutDebug: `${cdnUrl}/knockout/3.4.2/knockout-debug.js`,
knockoutMin: `${cdnUrl}/knockout/3.4.2/knockout-min.js`,
emberMin: `${cdnUrl}/ember.js/2.18.2/ember.min.js`,
emberProd: `${cdnUrl}/ember.js/2.18.2/ember.prod.js`,
reactDev: `${cdnUrl}/react/16.2.0/umd/react.development.js`,
reactProd: `${cdnUrl}/react/16.2.0/umd/react.production.min.js`,
vendorBundle: 'https://s3.amazonaws.com/internal-test-runner-assets.cypress.io/vendor.bundle.js',
hugeApp: 'https://s3.amazonaws.com/internal-test-runner-assets.cypress.io/huge_app.js',
})
.value() as unknown as typeof libs
_.each(libs, (url, lib) => {
it(`does not alter code from: '${lib}'`, function () {
this.timeout(10000)
const pathToLib = `/tmp/${lib}`
const downloadFile = () => {
return rp(url)
.then((resp) => {
return Promise.fromCallback((cb) => {
fs.writeFile(pathToLib, resp, cb)
})
.return(resp)
})
}
return Promise.fromCallback((cb) => {
fs.readFile(pathToLib, 'utf8', cb)
})
.catch(downloadFile)
.then((libCode: string) => {
let stripped = regexRewriter.strip(libCode)
// nothing should have changed!
// TODO: this is currently failing but we're
// going to accept this for now and make this
// test pass, but need to refactor to using
// inline expressions and change the strategy
// for removing obstructive code
if (lib === 'hugeApp') {
stripped = stripped.replace(
'window.self !== window.self',
'window.self !== window.top',
)
}
try {
expect(stripped).to.eq(libCode)
} catch (err) {
throw new Error(`code from '${lib}' was different`)
}
})
})
})
})
})
context('.stripStream', () => {
it('replaces obstructive code', (done) => {
const haystacks = original.split('\n')
const replacer = regexRewriter.stripStream()
replacer.pipe(concatStream({ encoding: 'string' }, (str) => {
const string = str.toString().trim()
try {
expect(string).to.eq(expected)
done()
} catch (err) {
done(err)
}
}))
haystacks.forEach((haystack) => {
replacer.write(`${haystack}\n`)
})
replacer.end()
})
})
})