Merge branch 'master' into pln/docs-index

# Conflicts:
#	docs/package.json
#	docs/source/_data/menu.yml
#	docs/themes/cypress/languages/en.yml
This commit is contained in:
Loren Norman
2017-05-17 16:36:08 -04:00
71 changed files with 11201 additions and 550 deletions
-22
View File
@@ -1,22 +0,0 @@
# There are multiple packages and for each package we might have
# unit, integration and e2e tests
#
# If we can control only a single variable, and it should be our command
env:
- CMD="test -- --package packages/coffee/"
- CMD="test -- --package packages/desktop-gui/"
# TODO fix driver tests
- CMD="test -- --package packages/electron/"
# TODO clarify unit vs E2E tests in example project
- CMD="test -- --package packages/extension/"
- CMD="test -- --package packages/https-proxy/"
- CMD="test -- --package packages/launcher/"
- CMD="test -- --package packages/reporter/"
- CMD="test -- --package packages/runner/"
# TODO fix server tests
- CMD="test -- --package packages/socket/"
- CMD="test -- --package packages/static/"
command:
- echo "Running $CMD"
- npm run all $CMD
-2
View File
@@ -46,8 +46,6 @@ Each package is responsible for building itself and testing itself and can do so
**clean-deps**: Remove any dependencies installed (usually by npm or bower)
**clean-all**: Run *clean* and *clean-deps* scripts
**test-all**: Run all tests in watch mode
**test-all-once**: Run all tests
+64 -7
View File
@@ -5,14 +5,10 @@ machine:
dependencies:
# CircleCI caching
# https://circleci.com/docs/1.0/how-cache-works/
pre:
# for "simple" parallel builds on CircleCI
# https://github.com/michaelcontento/circleci-matrix
# also see file .circleci-matrix.yml
- curl -fsSL https://git.io/v2Ifn | bash
cache_directories:
# downloaded Electron binary
- "~/.electron"
- docs/node_modules
# could not use wildcard format, so list every subfolder
- packages/coffee/node_modules
- packages/desktop-gui/node_modules
@@ -41,6 +37,67 @@ test:
## runner (5)
## server (5, 6)
override:
- circleci-matrix :
#
# things to run in the 1st CI container
#
# build docs site (fast)
- if [ $CIRCLE_NODE_INDEX == 0 ]; then cd docs && npm install; fi:
parallel: true
# TODO E2E tests
# run linter (fast)
- if [ $CIRCLE_NODE_INDEX == 0 ]; then npm run all lint; fi:
parallel: true
# run unit tests (fast)
# separate commands for better GUI view
- if [ $CIRCLE_NODE_INDEX == 0 ]; then npm run all test -- --package coffee; fi:
parallel: true
- if [ $CIRCLE_NODE_INDEX == 0 ]; then npm run all test -- --package desktop-gui; fi:
parallel: true
- if [ $CIRCLE_NODE_INDEX == 0 ]; then npm run all test -- --package electron; fi:
parallel: true
- if [ $CIRCLE_NODE_INDEX == 0 ]; then npm run all test -- --package extension; fi:
parallel: true
- if [ $CIRCLE_NODE_INDEX == 0 ]; then npm run all test -- --package https-proxy; fi:
parallel: true
- if [ $CIRCLE_NODE_INDEX == 0 ]; then npm run all test -- --package launcher; fi:
parallel: true
- if [ $CIRCLE_NODE_INDEX == 0 ]; then npm run all test -- --package reporter; fi:
parallel: true
- if [ $CIRCLE_NODE_INDEX == 0 ]; then npm run all test -- --package runner; fi:
parallel: true
- if [ $CIRCLE_NODE_INDEX == 0 ]; then npm run all test -- --package server; fi:
parallel: true
- if [ $CIRCLE_NODE_INDEX == 0 ]; then npm run all test -- --package socket; fi:
parallel: true
- if [ $CIRCLE_NODE_INDEX == 0 ]; then npm run all test -- --package static; fi:
parallel: true
- if [ $CIRCLE_NODE_INDEX == 0 ]; then npm run all test-integration-once -- --package server; fi:
parallel: true
#
# things to run in the 2nd CI container
#
- if [ $CIRCLE_NODE_INDEX == 1 ]; then npm run all test -- --package driver; fi:
parallel: true
#
# things to run in the 3rd CI container
#
- if [ $CIRCLE_NODE_INDEX == 2 ]; then npm run all test-e2e-once -- --package server; fi:
parallel: true
# Example project E2E tests
# Hanging now, so commented out
# - if [ $CIRCLE_NODE_INDEX == 0 ]; then npm start -- --project ../example/; fi:
# parallel: true
+1 -2
View File
@@ -11,8 +11,7 @@ switch (args.exec) {
require('dev/run')(args)
break
case 'install':
//// TODO: do this through lib/cli.js?
require('packages/core-download').install()
require('./lib/download').install()
break
case undefined:
throw new Error('Must pass --exec option')
-3
View File
@@ -17,11 +17,8 @@ const packageNameFromPath = (fullPath) => {
.replace('packages/', '')
}
const nonPackageDirs = ['docs/']
const getDirs = () => {
return globAsync('packages/*/')
.then((dirs) => dirs.concat(nonPackageDirs))
.map((dir) => path.join(process.cwd(), dir).replace(/\/$/, ''))
}
+3 -3
View File
@@ -98,10 +98,9 @@ node_sass:
precision: 5
sourceComments: false
## https://github.com/hexojs/hexo-generator-sitemap
## https://github.com/ludoviclefevre/hexo-generator-seo-friendly-sitemap
sitemap:
path: sitemap.xml
template: ./sitemap_template.xml
## https://github.com/mamboer/hexo-filter-cleanup
hfc_useref:
@@ -144,5 +143,6 @@ hfc_favicons:
## Docs: https://hexo.io/docs/deployment.html
deploy:
type: git
repo: https://github.com/cypress-io/cypress-documentation
repo: git@github.com:cypress-io/cypress-monorepo
branch: gh-pages
message: '[skip ci] deploying docs'
+1 -1
View File
@@ -27,7 +27,7 @@ describe "Documentation", ->
cy
.contains(".main-nav-link", "Guides")
.should("have.attr", "href")
.and("include", "/guides/welcome/guides.html")
.and("include", "/guides/index.html")
cy
.contains(".main-nav-link", "API")
.should("have.attr", "href")
+34 -4
View File
@@ -4,7 +4,7 @@ const clean = require('gulp-clean')
const runSequence = require('run-sequence')
const revisionOpts = {
dontGlobal: ['.ico', 'sitemap.xml', 'logo.png'],
dontGlobal: ['.ico', 'sitemap.xml', 'sitemap.xsl', 'logo.png'],
dontRenameFile: ['.html', 'CNAME'],
dontUpdateReference: ['.html'],
dontSearchFile: ['.js'],
@@ -17,6 +17,34 @@ function remove (folder) {
.pipe(clean())
}
function moveJSNodeModule (path) {
return gulp
.src(`./node_modules/${path}`)
.pipe(gulp.dest('./themes/cypress/source/js'))
}
function moveCSSNodeModule (path) {
return gulp
.src(`./node_modules/${path}`)
.pipe(gulp.dest('./themes/cypress/source/css'))
}
gulp.task('move:menu:spy:js', function () {
return moveJSNodeModule('menuspy/dist/menuspy.js')
})
gulp.task('move:scrolling:element:js', function () {
return moveJSNodeModule('scrollingelement/scrollingelement.js')
})
gulp.task('move:doc:search:js', function () {
return moveJSNodeModule('docsearch.js/dist/cdn/docsearch.js')
})
gulp.task('move:doc:search:css', function () {
return moveCSSNodeModule('docsearch.js/dist/cdn/docsearch.css')
})
gulp.task('revision', () => {
return gulp
.src('public/**')
@@ -24,7 +52,7 @@ gulp.task('revision', () => {
.pipe(gulp.dest('tmp'))
})
gulp.task('copyTmpToPublic', () => {
gulp.task('copy:tmp:to:public', () => {
return gulp
.src('tmp/**')
.pipe(gulp.dest('public'))
@@ -46,6 +74,8 @@ gulp.task('cname', () => {
return gulp.src('CNAME').pipe(gulp.dest('public'))
})
gulp.task('prep', (cb) => {
runSequence('clean:js', 'revision', 'clean:public', 'copyTmpToPublic', 'clean:tmp', 'cname', cb)
gulp.task('post:build', (cb) => {
runSequence('copy:static:assets', 'clean:js', 'revision', 'clean:public', 'copy:tmp:to:public', 'clean:tmp', 'cname', cb)
})
gulp.task('copy:static:assets', ['move:menu:spy:js', 'move:scrolling:element:js', 'move:doc:search:js', 'move:doc:search:css'])
+8 -3
View File
@@ -6,9 +6,12 @@
"version": "3.3.1"
},
"scripts": {
"postinstall": "npm run build",
"prebuild": "npm run clean",
"build": "hexo generate",
"postbuild": "gulp post:build",
"clean": "hexo clean",
"clean-deps": "rm -rf node_modules",
"clean-all": "npm run clean && npm run clean-deps",
"convert": "node ./cy_scripts/convert.js",
"deploy": "npm run build && hexo deploy",
"build-prod": "hexo clean && hexo generate && gulp prep",
@@ -28,18 +31,20 @@
},
"dependencies": {
"bluebird": "^3.5.0",
"docsearch.js": "^2.3.3",
"hexo": "3.3.1",
"hexo-algoliasearch": "^0.2.1",
"hexo-deployer-git": "^0.2.0",
"hexo-generator-archive": "^0.1.4",
"hexo-generator-category": "^0.1.3",
"hexo-generator-index": "^0.2.0",
"hexo-generator-sitemap": "^1.1.2",
"hexo-generator-seo-friendly-sitemap": "0.0.20",
"hexo-renderer-marked": "^0.2.10",
"hexo-renderer-scss": "^1.0.2",
"hexo-server": "^0.2.0",
"lodash": "^4.17.4",
"lunr": "^2.0.1",
"menuspy": "^1.0.1"
"menuspy": "1.0.1",
"scrollingelement": "1.5.2"
}
}
+3 -3
View File
@@ -1,4 +1,4 @@
guides: /guides/welcome/guides.html
guides: /guides/index.html
api: /api/welcome/api.html
faq: /faq.html
ecosystem: /ecosystem.html
ecosystem: /ecosystem/index.html
faq: /faq/index.html
-71
View File
@@ -1,71 +0,0 @@
title: Frequently Asked Questions
---
# General Questions
### What is Cypress?
Cypress is this thing that does this stuff.
### Why is this different?
This stuff has never been done before!
### Does Cypress use Selenium / Webdriver?
No way!
### What operating systems do you support?
All the really great ones.
### Will Cypress work in my CI provider?
Indubitably!
### What are good use cases for Cypress?
Testing the untestable.
### What are bad use cases for Cypress?
Testing the way you've always done it.
### How can I parallelize my runs?
Cloudy cloud clouder
### Is there code coverage?
Don't chase the dragon.
### What kind of tests do I write in Cypress?
The BEST kind!
### Are there driver bindings in my language?
I didn't understand the questions I heard.
### Does Cypress have an equivalent to Selenium IDE?
WIZARD MODE COMING SOON
# Using Cypress (potentially split this into Beginner / Advanced sections)
### How do I wait for an element not to exist?
### How do I do different things depending on whats currently in the dom/url/cookies/localstore?
### Can I run a single test or group of tests?
### Can I test file uploading?
### How do I test drag-n-drop?
### How do I seed / reset my database?
### How do I test anchor links that open in a new tab?
### Should I start my webserver from within Cypress?
### Can I make an assertion on my applications console.logs?
### How do I make conditional based assertions / control flow?
# Dashboard
### What is the Dashboard?
### How much does it cost?
### What does Cypress record?
# Company
### Whos behind Cypress?
### Are you hiring?
+230
View File
@@ -0,0 +1,230 @@
---
layout: plain
title: FAQ
comments: false
containerClass: faq
---
# General Questions
## What is Cypress?
## Hasnt this been done before?
## Is Cypress free?
## What operating systems do you support?
## Do you support native mobile apps?
## Do you support X language or X framework?
## Will Cypress work in my CI provider?
## What are good use cases for Cypress?
## What are bad use cases for Cypress?
## Is there code coverage?
[#346](https://github.com/cypress-io/cypress/issues/346)
## What kind of tests do I write in Cypress?
## Does Cypress use Selenium / Webdriver?
## Are there driver bindings in my language?
## Does Cypress have an equivalent to Selenium IDE?
## Is Cypress open source?
## How can I contribute to Cypress?
## I found a bug! What do I do?
# Using Cypress (potentially split this into Beginner / Advanced sections)
## How do I wait for an element not to exist?
## How do I do different things depending on whats currently in the dom/url/cookies/localstore?
## How can I parallelize my runs?
[#64](https://github.com/cypress-io/cypress/issues/64)
## Can I run a single test or group of tests?
[#236](https://github.com/cypress-io/cypress/issues/263)
## How do I test uploading a file?
[#170](https://github.com/cypress-io/cypress/issues/170)
## What is the projectId for?
## How do I get the native DOM reference of an element found using Cypress?
## How do I make Cypress wait for an XHR request?
## How do I wait for multiple XHR requests to the same url?
## How do I test drag-n-drop?
## How do I seed / reset my database?
## How do I pass data to my webserver from Cypress?
## How do I content inside an iframe?
[#136](https://github.com/cypress-io/cypress/issues/136)
## How do I preserve cookies/localstorage in between my tests?
[#461](https://github.com/cypress-io/cypress/issues/461)
## Some of my elements animate in, how do I work around that?
## Can I test anchor links that open in a new tab?
## Should I start my webserver from within Cypress?
## Can I make an assertion on my applications console.logs?
## How do I run my tests in another browser?
## Where do I get the key to run my tests in CI?
## Can I create more than one key for CI?
## I have an app that needs to be tested across multiple user sessions, like a chat app across 2 browsers. How do I test that?
## I want to test clicking a link that navigates, how do I wait and check the resulting location url?
## Is there a way to watch for an xhr request and assert that the response code came back a certain way?
## Im running a lot of tests that appear to slow down as they run, is there a way to fix this?
## How do I make conditional based assertions / control flow?
# Dashboard
## What is the Dashboard?
## How much does it cost?
## What does Cypress record?
## How many recordings can I store?
## Can't I just record my app running, without the Cypress runner?
## Can I see the mouse movements in my recorded video?
## Is there a way to see console logs or application errors in a recorded run?
## Is it possible to transfer a project to an organization I'm not a member of?
## Why are my tests displaying a “still running”?
## Is there any way to remove a run and the data from the Dashboard?
## How secure is storing my test runs (videos and screenshots) on your servers?
# Company
## Whos behind Cypress?
## Are you hiring?
+4 -21
View File
@@ -5,26 +5,9 @@
{{ js('js/menuspy') }}
{{ js('js/toc') }}
{{ js('js/mobile_nav') }}
<!-- endbuild -->
<script src="https://cdn.jsdelivr.net/retinajs/1.3.0/retina.min.js" async></script>
<!-- Algolia -->
{% if config.algolia[page.lang] %}
<script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.js"></script>
<script type="text/javascript">
document.getElementById('search-input-wrap').classList.add('on');
docsearch({
apiKey: '{{ config.algolia[page.lang].api_key }}',
indexName: '{{ config.algolia[page.lang].index_name }}',
inputSelector: '#search-input',
algoliaOptions: {
// See https://www.algolia.com/doc/api-client/javascript/parameters/#overview
// For full list of options
},
autocompleteOptions: {
// See https://github.com/algolia/autocomplete.js#options
// For full list of options
}
});
</script>
<!-- Algolia -->
{{ js('js/docsearch') }}
{{ js('js/docsearch-config') }}
{% endif %}
<!-- endbuild -->
+1 -2
View File
@@ -21,10 +21,9 @@
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/1/docsearch.min.css">
<!-- CSS -->
<!-- build:css build/css/cypress.css -->
{{ css('css/docsearch') }}
{{ css('css/cypress') }}
<!-- endbuild -->
+31
View File
@@ -0,0 +1,31 @@
.faq {
width: 750px;
margin: 0 auto 50px;
h1, h2, p {
font-family: $font-title;
}
h1 {
font-size: 2.5em;
line-height: 1em;
font-weight: 800;
margin: 2em 0 1em;
&:first-of-type {
margin-top: 1em;
}
}
h2 {
font-size: 1.4em;
line-height: 1.6em;
margin: 1.5em 0 0.5em;
font-weight: 500;
}
p {
font-size: 1em;
}
}
+1
View File
@@ -4,6 +4,7 @@
@import "_partial/header";
@import "_partial/search";
@import "_partial/index";
@import "_partial/faq";
@import "_partial/sidebar";
@import "_partial/toc";
@import "_partial/page";
File diff suppressed because one or more lines are too long
+14
View File
@@ -0,0 +1,14 @@
document.getElementById('search-input-wrap').classList.add('on');
docsearch({
apiKey: '{{ config.algolia[page.lang].api_key }}',
indexName: '{{ config.algolia[page.lang].index_name }}',
inputSelector: '#search-input',
algoliaOptions: {
// See https://www.algolia.com/doc/api-client/javascript/parameters/#overview
// For full list of options
},
autocompleteOptions: {
// See https://github.com/algolia/autocomplete.js#options
// For full list of options
}
});
File diff suppressed because it is too large Load Diff
+173 -173
View File
@@ -1,173 +1,173 @@
/*! MenuSpy v1.0.0 (Nov 29 2016) - http://leocs.me/menuspy/ - Copyright (c) 2016 Leonardo Santos; MIT License */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.MenuSpy = factory());
}(this, (function () { 'use strict';
var utils = {
extend: function extend(a, b) {
for (var key in b) {
if (b.hasOwnProperty(key)) {
a[key] = b[key];
}
}
return a;
},
offset: function offset(el) {
var rect = el.getBoundingClientRect();
return {
top: rect.top + document.body.scrollTop,
left: rect.left + document.body.scrollLeft
};
},
scrollTop: function scrollTop() {
return window.pageYOffset || document.documentElement.scrollTop;
},
addClass: function addClass(el, className) {
if (el.classList) {
el.classList.add(className);
} else {
var classes = el.className.split(' ');
var existingIndex = classes.indexOf(className);
if (existingIndex === -1) {
classes.push(className);
}
el.className = classes.join(' ');
}
},
removeClass: function removeClass(el, className) {
if (el.classList) {
el.classList.remove(className);
} else {
el.className = el.className.replace(new RegExp(("(^|\\b)" + (className.split(' ').join('|')) + "(\\b|$)"), 'gi'), ' ');
}
},
debounce: function debounce(fn, delay) {
var timeout = null;
return function() {
var args = arguments;
var context = this;
if (!timeout) {
timeout = setTimeout(function () {
timeout = 0;
return fn.apply(context, args);
}, delay);
}
};
}
};
var MenuSpy = function MenuSpy(element, options) {
var this$1 = this;
if (!element) {
return;
}
var defaults = {
menuItemSelector: 'a[href^="#"]',
activeClass : 'active',
threshold : 15,
hashTimeout : 600,
callback : null
};
this.element = element;
this.options = utils.extend(defaults, options);
this.assignValues();
window.addEventListener('resize', utils.debounce(function () { return this$1.assignValues(); }));
this.debouncedHashFn = utils.debounce(function () {
if (history.replaceState) {
history.replaceState(null, null, ("#" + (this$1.lastId)));
} else {
var st = utils.scrollTop();
window.location.hash = this$1.lastId;
window.scrollTo(0, st);
}
}, this.options.hashTimeout);
this.cacheItems();
this.scrollFn();
};
MenuSpy.prototype.assignValues = function assignValues () {
this.currScrollTop = 0;
this.lastId = '';
this.menuHeight = this.element.offsetHeight + this.options.threshold;
this.menuItems = [].slice.call(this.element.querySelectorAll(this.options.menuItemSelector));
};
MenuSpy.prototype.cacheItems = function cacheItems () {
this.scrollItems = this.menuItems.map(function (a) {
var elm = document.querySelector(a.getAttribute('href'));
if (elm) {
var offset = utils.offset(elm).top;
return { elm: elm, offset: offset };
} else {
console.warn('MenuSpy warning: %s not found on page.', a.href);
}
});
this.scrollItems = this.scrollItems.filter( Boolean );
};
MenuSpy.prototype.tick = function tick () {
var fromTop = this.currScrollTop + this.menuHeight;
var inViewElms = this.scrollItems
.filter(function (item) { return item.offset < fromTop; })
.map(function (item) { return item.elm; });
this.activateItem(inViewElms.pop());
};
MenuSpy.prototype.activateItem = function activateItem (inViewElm) {
var this$1 = this;
var id = inViewElm ? inViewElm.id : '';
var activeClass = this.options.activeClass;
var callback = this.options.callback;
if (this.lastId !== id) {
this.lastId = id;
this.menuItems.forEach(function (item) {
utils.removeClass(item.parentNode, activeClass);
if (item.getAttribute('href') === ("#" + id)) {
utils.addClass(item.parentNode, activeClass);
if (typeof callback === 'function') {
callback.call(this$1, item, inViewElm);
}
this$1.debouncedHashFn();
}
});
}
};
MenuSpy.prototype.scrollFn = function scrollFn () {
var st = utils.scrollTop();
if (this.currScrollTop !== st) {
this.currScrollTop = st;
this.tick();
}
window.requestAnimationFrame(this.scrollFn.bind(this));
};
return MenuSpy;
})));
/*! MenuSpy v1.0.0 (Nov 29 2016) - http://leocs.me/menuspy/ - Copyright (c) 2016 Leonardo Santos; MIT License */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.MenuSpy = factory());
}(this, (function () { 'use strict';
var utils = {
extend: function extend(a, b) {
for (var key in b) {
if (b.hasOwnProperty(key)) {
a[key] = b[key];
}
}
return a;
},
offset: function offset(el) {
var rect = el.getBoundingClientRect();
return {
top: rect.top + document.body.scrollTop,
left: rect.left + document.body.scrollLeft
};
},
scrollTop: function scrollTop() {
return window.pageYOffset || document.documentElement.scrollTop;
},
addClass: function addClass(el, className) {
if (el.classList) {
el.classList.add(className);
} else {
var classes = el.className.split(' ');
var existingIndex = classes.indexOf(className);
if (existingIndex === -1) {
classes.push(className);
}
el.className = classes.join(' ');
}
},
removeClass: function removeClass(el, className) {
if (el.classList) {
el.classList.remove(className);
} else {
el.className = el.className.replace(new RegExp(("(^|\\b)" + (className.split(' ').join('|')) + "(\\b|$)"), 'gi'), ' ');
}
},
debounce: function debounce(fn, delay) {
var timeout = null;
return function() {
var args = arguments;
var context = this;
if (!timeout) {
timeout = setTimeout(function () {
timeout = 0;
return fn.apply(context, args);
}, delay);
}
};
}
};
var MenuSpy = function MenuSpy(element, options) {
var this$1 = this;
if (!element) {
return;
}
var defaults = {
menuItemSelector: 'a[href^="#"]',
activeClass : 'active',
threshold : 15,
hashTimeout : 600,
callback : null
};
this.element = element;
this.options = utils.extend(defaults, options);
this.assignValues();
window.addEventListener('resize', utils.debounce(function () { return this$1.assignValues(); }));
this.debouncedHashFn = utils.debounce(function () {
if (history.replaceState) {
history.replaceState(null, null, ("#" + (this$1.lastId)));
} else {
var st = utils.scrollTop();
window.location.hash = this$1.lastId;
window.scrollTo(0, st);
}
}, this.options.hashTimeout);
this.cacheItems();
this.scrollFn();
};
MenuSpy.prototype.assignValues = function assignValues () {
this.currScrollTop = 0;
this.lastId = '';
this.menuHeight = this.element.offsetHeight + this.options.threshold;
this.menuItems = [].slice.call(this.element.querySelectorAll(this.options.menuItemSelector));
};
MenuSpy.prototype.cacheItems = function cacheItems () {
this.scrollItems = this.menuItems.map(function (a) {
var elm = document.querySelector(a.getAttribute('href'));
if (elm) {
var offset = utils.offset(elm).top;
return { elm: elm, offset: offset };
} else {
console.warn('MenuSpy warning: %s not found on page.', a.href);
}
});
this.scrollItems = this.scrollItems.filter( Boolean );
};
MenuSpy.prototype.tick = function tick () {
var fromTop = this.currScrollTop + this.menuHeight;
var inViewElms = this.scrollItems
.filter(function (item) { return item.offset < fromTop; })
.map(function (item) { return item.elm; });
this.activateItem(inViewElms.pop());
};
MenuSpy.prototype.activateItem = function activateItem (inViewElm) {
var this$1 = this;
var id = inViewElm ? inViewElm.id : '';
var activeClass = this.options.activeClass;
var callback = this.options.callback;
if (this.lastId !== id) {
this.lastId = id;
this.menuItems.forEach(function (item) {
utils.removeClass(item.parentNode, activeClass);
if (item.getAttribute('href') === ("#" + id)) {
utils.addClass(item.parentNode, activeClass);
if (typeof callback === 'function') {
callback.call(this$1, item, inViewElm);
}
this$1.debouncedHashFn();
}
});
}
};
MenuSpy.prototype.scrollFn = function scrollFn () {
var st = utils.scrollTop();
if (this.currScrollTop !== st) {
this.currScrollTop = st;
this.tick();
}
window.requestAnimationFrame(this.scrollFn.bind(this));
};
return MenuSpy;
})));
+7 -12
View File
@@ -6,19 +6,14 @@
"cypress": "bin/cypress"
},
"scripts": {
"install-app": "node cli.js --exec install",
"postinstall": "npm run all install && npm run all build-dev",
"deploy:docs": "npm run all deploy -- --package docs",
"start": "node start.js",
"watch-dev": "npm run all watch-dev",
"test": "mocha --watch",
"test-once": "mocha",
"test-all": "npm run all test -- --serial",
"test-all-once": "npm run all test-once -- --serial",
"test-all-unit-once": "npm run all test-unit-once -- --serial",
"test-all-integration-once": "npm run all test-integration-once -- --serial",
"test-all-e2e-once": "npm run all test-e2e-once -- --serial",
"all": "node cli.js --exec run"
"watch": "npm run all watch",
"build": "npm run all build",
"all": "node cli.js --exec run",
"test": "echo 'This runs just the CLI tests' && mocha",
"test-watch": "mocha --watch",
"test-e2e": "blah",
"postinstall": "npm run all install && npm run build"
},
"author": "",
"license": "MIT",
+3 -4
View File
@@ -4,16 +4,15 @@
"description": "Desktop GUI for managing Cypress projects.",
"main": "lib/gui.js",
"scripts": {
"build-dev": "zunder build-dev",
"build": "zunder build-dev",
"build-prod": "node ./scripts/build-prod.js",
"run-prod": "npm run build-prod && npm run server",
"watch": "zunder watch",
"server": "zunder serve-prod --port 8000",
"watch-dev": "zunder watch",
"clean": "zunder clean",
"clean-deps": "rm -rf node_modules",
"clean-all": "npm run clean && npm run clean-deps",
"lint": "eslint --fix lib/*.js src/*.js* src/**/*.js*",
"test": "npm run build-dev",
"test": "npm run build",
"pretest": "npm run lint"
},
"repository": {
+2 -2
View File
@@ -155,7 +155,7 @@ gulp.task "server", -> require("./server/server.coffee")
gulp.task "ensure:dist:dir", ->
fs.ensureDirAsync(path.resolve("./dist-test"))
gulp.task "test", ["ensure:dist:dir"], ->
gulp.task "test:watch", ["ensure:dist:dir"], ->
watchSpecHelper = bundleJs(specHelperOptions)
watchIndex = bundleJs(specIndexOptions)
watchRunner = bundleJs(specRunnerOptions)
@@ -167,7 +167,7 @@ gulp.task "test", ["ensure:dist:dir"], ->
return watchSpecHelper.process
gulp.task "test:once", ["ensure:dist:dir"], ->
gulp.task "test", ["ensure:dist:dir"], ->
buildSpecHelper = bundleJs(specHelperOptions, false)
buildIndex = bundleJs(specIndexOptions, false)
buildRunner = bundleJs(specRunnerOptions, false)
+4 -4
View File
@@ -3,11 +3,11 @@
"version": "1.0.0",
"description": "",
"scripts": {
"build-dev": "gulp build",
"build": "gulp build",
"watch": "gulp watch",
"clean-deps": "rm -rf node_modules",
"test": "gulp test:once",
"test-watch": "gulp test",
"watch-dev": "gulp watch"
"test": "gulp test",
"test-watch": "gulp test:watch"
},
"devDependencies": {
"@cypress/bower-kendo-ui": "0.0.2",
@@ -29,9 +29,6 @@ args = [
"--disable-new-avatar-menu"
"--allow-insecure-localhost"
"--reduce-security-for-testing"
## FIXME: theme doesn't seem to work
"--load-extension=#{themeDir}"
"--user-data-dir=#{profileDir}"
## the following come frome chromedriver
## https://code.google.com/p/chromium/codesearch#chromium/src/chrome/test/chromedriver/chrome_launcher.cc&sq=package:chromium&l=70
@@ -46,6 +43,9 @@ args = [
"--disable-client-side-phishing-detection"
"--disable-component-update"
"--disable-default-apps"
"--load-extension=#{themeDir}"
"--user-data-dir=#{profileDir}"
]
module.exports = {
@@ -57,8 +57,9 @@ module.exports = {
launch.launch(browser, url, args)
.then (spawnedBrowser) ->
{
stop: (cb) ->
spawnedBrowser.on("close", cb)
spawnedBrowser.kill()
stop: ->
new Promise (resolve) ->
spawnedBrowser.once("exit", resolve)
spawnedBrowser.kill()
}
}
@@ -62,6 +62,7 @@ module.exports = class Runner
@_errors = []
@_localBus = new EventEmitter()
@_runnerBus = new EventEmitter()
@_browserInstance = { stop: -> Promise.resolve() }
process.on "SIGINT", =>
@_stopBrowser().then ->
@@ -82,14 +83,19 @@ module.exports = class Runner
@_runnerBus.emit(event, info, err)
runAllSpecsOnce: (specPaths) ->
@_start().then =>
@_start()
.then =>
new Promise (resolve, reject) =>
current = 0
timeouts = []
next = =>
current++
@run(specPaths[current])
@_stopBrowser()
.then =>
@_launchBrowser()
.then =>
@run(specPaths[current])
finish = (event, info, err) =>
@_runnerBus.emit(event, info, err)
@@ -100,9 +106,6 @@ module.exports = class Runner
@_reporter = new @_Reporter(@_runnerBus)
@_runnerBus.emit("start")
@_localBus.once "client:connected", =>
@run(specPaths[current])
@_localBus.on "test:event", (event, info, err) =>
if event is "end"
if current is (specPaths.length - 1)
@@ -113,10 +116,18 @@ module.exports = class Runner
else if event isnt "start"
@_runnerBus.emit(event, info, err)
@_localBus.on "timeout", ->
timeouts.push(specPaths[current])
@_localBus.on "timeout", (test) ->
timeouts.push({ path: specPaths[current], test })
next()
@run(specPaths[current])
.tap ({ timeouts }) =>
if timeouts.length
logWarning("The following spec(s) timed out:")
console.log()
for spec in timeouts
@_logTest(spec.test, spec.path)
run: (specPath) ->
specPath = specPath
.replace(path.join(__dirname, "../.."), "specs/")
@@ -148,13 +159,16 @@ module.exports = class Runner
theBrowser = getArg("browser") or "chrome"
url = "http://localhost:#{@_config.port}?reporter=socket"
browser.launch(theBrowser, url)
.then (instance) =>
@_browserInstance = instance
.catch (err) =>
logError("Error attempting to launch browser:")
logError(err)
throw err
new Promise (resolve, reject) =>
@_localBus.once "client:connected", resolve
browser.launch(theBrowser, url)
.then (instance) =>
@_browserInstance = instance
.catch (err) =>
logError("Error attempting to launch browser:")
logError(err)
reject(err)
_onReport: ({ tests }) ->
for test in tests
@@ -173,27 +187,33 @@ module.exports = class Runner
"#{info.parentTitle} #{info.title}"
else
info.title
if event is "test"
@_lastTest = { event, info, err }
@_localBus.emit("test:event", event, info, err)
_logTest: ({ info, err }, path) ->
logWarning("Spec:", path) if path
logWarning("Test: #{info.fullTitle()}")
logWarning("Error: #{err}") if err
_onTimeout: ->
console.log()
logError("Tests timed out")
logError("Test timed out")
console.log()
if @_lastTest
@_logTest(@_lastTest)
if @_errors.length
logWarning("The following errors were captured:")
else
logError("No errors were captured")
console.log()
logWarning("The following other errors were captured:")
for error in @_errors
console.log()
logError(error.stack or error)
@_localBus.emit("timeout")
@_localBus.emit("timeout", @_lastTest)
_stopBrowser: ->
if not @_browserInstance
return Promise.resolve()
new Promise (resolve) =>
@_browserInstance.stop(resolve)
@_browserInstance.stop()
.timeout(10000)
.catch Promise.TimeoutError, ->
logWarning("Timed out trying to stop browser")
@@ -44,6 +44,12 @@ getAllSpecs = (allSpecs = true) ->
_.map specs, (spec) ->
removeExtension(spec.replace("../..", "specs"))
## specify which files to run
# [
# "specs/unit/cy/commands/agents_spec"
# "specs/unit/cy/commands/assertions_spec"
# ]
getSpec = (spec) ->
spec = "#{removeExtension(spec)}.coffee"
file = fs.readFileSync(path.join(__dirname, "../..", spec), "utf8")
@@ -69,6 +75,9 @@ app.get "/specs/*", (req, res) ->
else
res.render(path.join(__dirname, "views/spec.html"), {
specs: getSpecPath(req.path)
env: JSON.stringify({
isCi: !!process.env.CI
})
})
app.get "/timeout", (req, res) ->
@@ -169,9 +178,5 @@ module.exports = {
.runAllSpecsOnce(getAllSpecs(false))
.then ({ stats, timeouts }) ->
code = if stats.failures or timeouts.length then 1 else 0
if timeouts.length
console.error("The following spec(s) timed out:")
console.log()
console.error(spec) for spec in timeouts
process.exit(code)
}
@@ -0,0 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<title>Blank</title>
</head>
<body>
</body>
</html>
@@ -14,6 +14,9 @@
<a id="terminal-reporter" href="?reporter=socket">Terminal Reporter</a>
</p>
<div id="mocha"></div>
<script>
window.env = {{{env}}}
</script>
<script src="/dist-test/spec_helper.js"></script>
{{#each specs}}
<script src="/{{this}}.js"></script>
@@ -30,6 +30,18 @@ before ->
c = Cypress ? @Cypress
c.off("fail")
@assertWindowIsInFocus = (cb) ->
return cb() if document.hasFocus()
ct = @test or @currentTest
if window.env.isCi
ct.callback(
new Error("Test requires the browser window be in focus, but it was not")
)
else
ct.skip()
# sinon.format = -> ""
@sandbox = s = sinon.sandbox.create()
@sandbox.useFakeTimers = ->
@@ -211,6 +223,9 @@ window.enterCommandTestingMode = (fixture = "dom", options = {}) ->
## since we bypass our Runner instance
@Cypress.on "fail", (err) ->
console.error(err.stack)
## bubble error up to mocha
if ct
ct.callback(err)
## if we've changed the src by navigating
## away (aka cy.visit(...)) then we need
@@ -440,7 +440,8 @@ describe "$Cypress.Cy Miscellaneous Commands", ->
@cy.get("button:first").ttrigger("mouseover", "foo")
it "throws when element animation exceeds timeout", (done) ->
## FIXME: needs focus
it.skip "throws when element animation exceeds timeout", (done) ->
@cy._timeout(100)
mouseovers = 0
@@ -540,7 +540,7 @@ describe "$Cypress.Cy Scrolling Commands", ->
@cy.get("button").scrollIntoView()
describe "argument errors", ->
context "argument errors", ->
it "throws if arg passed as non-object", (done) ->
@cy.on "fail", (err) =>
expect(err.message).to.include "cy.scrollIntoView() can only be called with an options object. Your argument was: foo"
@@ -87,22 +87,24 @@ describe "$Cypress.Cy Text Commands", ->
@cy.get(":text:first").type("foo{enter}")
it "waits until element stops animating", (done) ->
retries = []
input = $("<input class='slidein' />")
input.css("animation-duration", ".3s")
## FIXME: flakiness due to animation events
it.skip "waits until element stops animating", (done) ->
@assertWindowIsInFocus =>
retries = []
input = $("<input class='slidein' />")
input.css("animation-duration", ".3s")
@cy.on "retry", (obj) ->
## this verifies the input has not been typed into
expect(input).to.have.value("")
retries.push(obj)
@cy.on "retry", (obj) ->
## this verifies the input has not been typed into
expect(input).to.have.value("")
retries.push(obj)
input.on "animationstart", =>
@cy.get(".slidein").type("foo").then ->
expect(retries.length).to.be.gt(10)
done()
input.on "animationstart", =>
@cy.get(".slidein").type("foo").then ->
expect(retries.length).to.be.gt(10)
done()
@cy.$$("#animation-container").append(input)
@cy.$$("#animation-container").append(input)
it "does not throw when waiting for animations is disabled", ->
@sandbox.stub(@Cypress, "config").withArgs("waitForAnimations").returns(false)
@@ -428,7 +430,8 @@ describe "$Cypress.Cy Text Commands", ->
@cy.get(":text:first").invoke("val", "foo").type(" bar").then ($text) ->
expect($text).to.have.value("foo bar")
it "inserts text after existing text on input[type=number]", ->
## FIXME: legitimate bug
it.skip "inserts text after existing text on input[type=number]", ->
@cy.get("#input-types [type=number]").invoke("val", "12").type("34").then ($text) ->
expect($text).to.have.value("1234")
@@ -441,7 +444,8 @@ describe "$Cypress.Cy Text Commands", ->
@cy.get(":text:first").type("50").then ($input) ->
expect($input).to.have.value("50")
it "overwrites text on input[type=number] when input has existing text", ->
## FIXME: legitimate bug
it.skip "overwrites text on input[type=number] when input has existing text", ->
## when the text is clicked we want to
## select everything in it
@cy.$$("#input-types [type=number]").val("0").click ->
@@ -454,7 +458,8 @@ describe "$Cypress.Cy Text Commands", ->
@cy.get("#input-types [type=email]").type("brian@foo.com").then ($text) ->
expect($text).to.have.value("brian@foo.com")
it "inserts text after existing text on input[type=email]", ->
## FIXME: legitimate bug
it.skip "inserts text after existing text on input[type=email]", ->
@cy.get("#input-types [type=email]").invoke("val", "brian@foo.c").type("om").then ($text) ->
expect($text).to.have.value("brian@foo.com")
@@ -1776,7 +1781,7 @@ describe "$Cypress.Cy Text Commands", ->
@cy.get(":text:first").type("foo")
it "snapshots before typing", (done) ->
@cy.$$(":text:first").keydown =>
@cy.$$(":text:first").one "keydown", =>
expect(@log.get("snapshots").length).to.eq(1)
expect(@log.get("snapshots")[0].name).to.eq("before")
expect(@log.get("snapshots")[0].body).to.be.an("object")
@@ -40,9 +40,9 @@ describe "$Cypress.Cy Fixtures Commands", ->
@cy.fixture("foo", "ascii", {timeout: 1000}).then (obj) ->
expect(obj).to.deep.eq {foo: "bar"}
## FIXME
describe.skip "cancellation", ->
it "cancels promise", (done) ->
describe "cancellation", ->
## FIXME: fails when running all tests in this file
it.skip "cancels promise", (done) ->
## respond after 50 ms
@respondWith({}, 50)
@@ -204,8 +204,7 @@ describe "$Cypress.Cy Navigation Commands", ->
.visit("/fixtures/sinon.html")
.go("back", {timeout: 1})
## FIXME: flaky!
it.skip "only logs once on error", (done) ->
it "only logs once on error", (done) ->
logs = []
@Cypress.on "log", (attrs, log) =>
@@ -297,9 +296,9 @@ describe "$Cypress.Cy Navigation Commands", ->
it "can visit pages on the same originPolicy", ->
@cy
.visit("http://localhost:3500")
.visit("http://localhost:3500")
.visit("http://localhost:3500")
.visit("http://localhost:3500/blank.html")
.visit("http://localhost:3500/blank.html")
.visit("http://localhost:3500/blank.html")
it "can visit pages on different subdomain but same originPolicy", ->
$remoteIframe = @cy.privateState("$remoteIframe")
@@ -312,8 +311,8 @@ describe "$Cypress.Cy Navigation Commands", ->
@sandbox.stub(@cy, "_src", load)
## make it seem like we're already on www.foobar.com:3500
one = @Cypress.Location.create("http://www.foobar.com:3500")
two = @Cypress.Location.create("http://help.foobar.com:3500")
one = @Cypress.Location.create("http://www.foobar.com:3500/blank.html")
two = @Cypress.Location.create("http://help.foobar.com:3500/blank.html")
@sandbox.stub(@cy, "_existing")
.onCall(0).returns(one)
@@ -322,8 +321,8 @@ describe "$Cypress.Cy Navigation Commands", ->
trigger = @sandbox.spy(@Cypress, "trigger")
@cy
.visit("http://www.foobar.com:3500")
.visit("http://help.foobar.com:3500")
.visit("http://www.foobar.com:3500/blank.html")
.visit("http://help.foobar.com:3500/blank.html")
.then ->
## we should never have to go across domains even though
## we're visiting a subdomain
@@ -357,22 +356,22 @@ describe "$Cypress.Cy Navigation Commands", ->
.visit("/hash.html?foo#bar") ## yes (2)
.visit("/hash.html?foo#foo") ## no (2)
.visit("/hash.html?bar#bar") ## yes (3)
.visit("/index.html?bar#bar") ## yes (4)
.visit("/index.html?baz#bar") ## yes (5)
.visit("/index.html#bar") ## yes (6)
.visit("/index.html") ## yes (7)
.visit("/index.html#baz") ## no (7)
.visit("/index.html#") ## no (7)
.visit("/blank.html?bar#bar") ## yes (4)
.visit("/blank.html?baz#bar") ## yes (5)
.visit("/blank.html#bar") ## yes (6)
.visit("/blank.html") ## yes (7)
.visit("/blank.html#baz") ## no (7)
.visit("/blank.html#") ## no (7)
.then ->
expect(count).to.eq(7)
expect(urls).to.deep.eq([
"about:blank"
"http://localhost:3500/hash.html?foo#bar"
"http://localhost:3500/hash.html?bar#bar"
"http://localhost:3500/index.html?bar#bar"
"http://localhost:3500/index.html?baz#bar"
"http://localhost:3500/index.html#bar"
"http://localhost:3500/index.html"
"http://localhost:3500/blank.html?bar#bar"
"http://localhost:3500/blank.html?baz#bar"
"http://localhost:3500/blank.html#bar"
"http://localhost:3500/blank.html"
])
describe "when origins don't match", ->
@@ -500,6 +499,7 @@ describe "$Cypress.Cy Navigation Commands", ->
describe ".log", ->
beforeEach ->
@sandbox.stub(@Cypress, "getEmissions").returns([])
@Cypress.on "log", (attrs, @log) =>
it "preserves url on subsequent visits", ->
@@ -510,27 +510,27 @@ describe "$Cypress.Cy Navigation Commands", ->
@Cypress.on "log", (attrs, log) ->
expect(log.pick("name", "message")).to.deep.eq {
name: "visit"
message: "localhost:4200/app/foo#/hash"
message: "localhost:3500/app/foo#/hash"
}
done()
@cy.visit("localhost:4200/app/foo#/hash")
@cy.visit("localhost:3500/app/foo#/hash")
it "logs obj once complete", ->
@cy.visit("http://localhost:3500/index.html").then ->
@cy.visit("http://localhost:3500/blank.html").then ->
obj = {
state: "passed"
name: "visit"
message: "http://localhost:3500/index.html"
url: "http://localhost:3500/index.html"
message: "http://localhost:3500/blank.html"
url: "http://localhost:3500/blank.html"
}
_.each obj, (value, key) =>
expect(@log.get(key)).deep.eq(value, "expected key: #{key} to eq value: #{value}")
it "snapshots once", ->
@cy.visit("/index.html").then ->
@cy.visit("/blank.html").then ->
expect(@log.get("snapshots").length).to.eq(1)
expect(@log.get("snapshots")[0]).to.be.an("object")
@@ -632,7 +632,7 @@ describe "$Cypress.Cy Navigation Commands", ->
expect(@log.get("error")).to.eq err
done()
@cy.visit("/index.html")
@cy.visit("/blank.html")
it "logs once on error", (done) ->
@sandbox.stub(@cy, "_resolveUrl").rejects(new Error)
@@ -646,7 +646,7 @@ describe "$Cypress.Cy Navigation Commands", ->
expect(logs).to.have.length(1)
done()
@cy.visit("/index.html")
@cy.visit("/blank.html")
it "logs once on timeout error", (done) ->
logs = []
@@ -708,8 +708,8 @@ describe "$Cypress.Cy Navigation Commands", ->
done()
@cy
.visit("")
.visit("http://localhost:3501")
.visit("http://localhost:3500/blank.html")
.visit("http://localhost:3501/blank.html")
it "throws when attempting to visit a 2nd domain on different protocol", (done) ->
logs = []
@@ -724,8 +724,8 @@ describe "$Cypress.Cy Navigation Commands", ->
done()
@cy
.visit("")
.visit("https://localhost:3500")
.visit("http://localhost:3500/blank.html")
.visit("https://localhost:3500/blank.html")
it "throws when attempting to visit a 2nd domain on different host", (done) ->
logs = []
@@ -740,8 +740,8 @@ describe "$Cypress.Cy Navigation Commands", ->
done()
@cy
.visit("")
.visit("http://google.com:3500")
.visit("http://localhost:3500/blank.html")
.visit("http://google.com:3500/blank.html")
it "throws attemping to visit 2 unique ip addresses", (done) ->
$remoteIframe = @cy.privateState("$remoteIframe")
@@ -756,7 +756,7 @@ describe "$Cypress.Cy Navigation Commands", ->
logs = []
## make it seem like we're already on http://127.0.0.1:3500
one = @Cypress.Location.create("http://127.0.0.1:3500")
one = @Cypress.Location.create("http://127.0.0.1:3500/blank.html")
@sandbox.stub(@cy, "_existing")
.returns(one)
@@ -770,20 +770,20 @@ describe "$Cypress.Cy Navigation Commands", ->
done()
@cy
.visit("http://127.0.0.1:3500")
.visit("http://126.0.0.1:3500")
.visit("http://127.0.0.1:3500/blank.html")
.visit("http://126.0.0.1:3500/blank.html")
it "does not call resolve:url when throws attemping to visit a 2nd domain", (done) ->
trigger = @sandbox.spy(@Cypress, "trigger")
@cy.on "fail", (err) =>
expect(trigger).to.be.calledWithMatch("resolve:url", "http://localhost:3500")
expect(trigger).not.to.be.calledWithMatch("resolve:url", "http://google.com:3500")
expect(trigger).to.be.calledWithMatch("resolve:url", "http://localhost:3500/blank.html")
expect(trigger).not.to.be.calledWithMatch("resolve:url", "http://google.com:3500/blank.html")
done()
@cy
.visit("http://localhost:3500")
.visit("http://google.com:3500")
.visit("http://localhost:3500/blank.html")
.visit("http://google.com:3500/blank.html")
it "displays loading_network_failed when _resolveUrl throws", (done) ->
err1 = new Error("connect ECONNREFUSED 127.0.0.1:64646")
@@ -60,14 +60,12 @@ describe "$Cypress.Cy Listeners Extensions", ->
@cy.get("a#change-page").click().then ->
expect(@isReady).not.to.be.calledWith false
## FIXME: the following 2 fail when running all test files
it.skip "sets initial cookies", ->
it "sets initial cookies", ->
setInitial = @sandbox.stub @Cypress.Cookies, "setInitial"
@cy.get("a#change-page").click().then ->
expect(setInitial).to.be.called
it.skip "calls cy#loading", ->
it "calls cy#loading", ->
loading = @sandbox.stub @cy, "loading"
@cy.get("a#change-page").click().then ->
expect(loading).to.be.called
@@ -849,6 +849,7 @@ describe "$Cypress.Log API", ->
@cy.get("button").contains("asdfasdfasdfasdf")
## FIXME: timed out once on full run
it "#consoleProps for nested children commands", (done) ->
@Cypress.on "log", (attrs, @log) =>
+1 -2
View File
@@ -8,8 +8,7 @@
"start": "./bin/cypress-electron",
"test": "mocha --compilers coffee:../coffee/register",
"postinstall": "./bin/cypress-electron --install",
"clean-deps": "rm -rf node_modules",
"clean-all": "npm run clean-deps"
"clean-deps": "rm -rf node_modules"
},
"bin": {
"cypress-electron": "./bin/cypress-electron"
+2 -2
View File
@@ -5,8 +5,8 @@
"main": "index.js",
"scripts": {
"clean-deps": "rm -rf node_modules",
"test-lib": "NODE_ENV=test mocha",
"test": "cypress run",
"test": "NODE_ENV=test mocha",
"test-e2e": "cypress run",
"build": "./bin/build.sh && gulp build",
"predeploy": "npm run build",
"deploy": "gulp deploy",
+5 -7
View File
@@ -4,15 +4,13 @@
"description": "Cypress Chrome Extension",
"main": "index.js",
"scripts": {
"watch-dev": "gulp watch",
"build-dev": "gulp build",
"watch": "gulp watch",
"build": "gulp build",
"build-prod": "gulp build",
"test": "npm run test-unit-once",
"test-once": "npm run test-unit-once",
"test-unit-once": "NODE_ENV=test mocha --require test-setup.js",
"test": "NODE_ENV=test mocha --require test-setup.js",
"test-watch": "npm run test -- --watch",
"clean": "gulp clean",
"clean-deps": "rm -rf node_modules",
"clean-all": "npm run clean && npm run clean-deps"
"clean-deps": "rm -rf node_modules"
},
"files": [
"app",
-46
View File
@@ -1,46 +0,0 @@
// all common type definition for this module
type NotInstalledError = Error & {notInstalled: boolean}
type BrowserNotFoundError = Error & {specificBrowserNotFound: boolean}
interface ExtraLauncherMethods {
update: Function,
detect: Function
}
type LauncherLaunch = (browsers?: any[]) => Promise<any>
type LauncherApi = LauncherLaunch & ExtraLauncherMethods
type Browser = {
name: string,
re: RegExp,
profile: boolean,
binary: string,
executable: string,
version?: string,
majorVersion?: string,
page?: string
}
// missing type definitions for 3rd party libraries
// https://glebbahmutov.com/blog/trying-typescript/#manual-types-for-3rd-party-libraries
declare module 'execa' {
type ExecaResult = {
stdout: string
}
interface Execa {
shell: (cmd:string) => Promise<ExecaResult>
}
const execa: Execa
export = execa
}
declare module 'plist' {
interface Plist {
parse: (s:string) => any
}
const plist: Plist
export = plist
}
+13 -1
View File
@@ -1,2 +1,14 @@
// @ts-check
module.exports = require("./lib/launcher")
// compile TypeScript files on the fly using
// Node require hook project
require('../ts/register')
const launcher = require("./lib/launcher")
module.exports = launcher
if (!module.parent) {
// quick way to check if TS is working
console.log('Launcher project exports')
console.log(launcher)
console.log('please use it as a module, not from CLI')
}
@@ -1,6 +1,7 @@
import {log} from './log'
import {find, map} from 'lodash'
import cp = require('child_process')
import {BrowserNotFoundError} from './types'
type FoundBrowser = {
name: string,
@@ -31,7 +32,7 @@ export function launch (browsers:FoundBrowser[],
}
if (url) {
args.unshift(url)
args = [url].concat(args)
}
return cp.spawn(browser.path, args, {stdio: 'ignore'})
@@ -1,4 +1,5 @@
import {log} from '../log'
import {NotInstalledError} from '../types'
import execa = require('execa')
import fs = require('fs-extra')
@@ -1,10 +1,12 @@
import {linuxBrowser} from './linux'
import darwin from './darwin'
import {log} from './log'
import {Browser, NotInstalledError} from './types'
import * as Bluebird from 'bluebird'
import _ = require('lodash')
import os = require('os')
import Promise = require('bluebird')
// import Promise = require('bluebird')
const browsers:Browser[] = [
{
@@ -39,21 +41,21 @@ const setMajorVersion = (obj:Browser) => {
type MacBrowserName = 'chrome' | 'chromium' | 'canary'
function lookup (platform:string, obj:Browser) {
function lookup (platform:string, obj:Browser):Promise<Object> {
log('looking up %s on %s platform', obj.name, platform)
switch (platform) {
case 'darwin':
const browserName:MacBrowserName = obj.name as MacBrowserName
const fn = darwin[browserName]
if (fn) {
return fn.get(obj.executable)
return fn.get(obj.executable) as any as Promise<Object>
}
const err: NotInstalledError =
new Error(`Browser not installed: ${obj.name}`) as NotInstalledError
err.notInstalled = true
return Promise.reject(err)
throw err
case 'linux':
return linuxBrowser.get(obj.binary, obj.re)
return linuxBrowser.get(obj.binary, obj.re) as any as Promise<Object>
default:
throw new Error(`Cannot lookup browser ${obj.name} on ${platform}`)
}
@@ -62,7 +64,7 @@ function lookup (platform:string, obj:Browser) {
function checkOneBrowser(browser:Browser) {
const platform = os.platform()
return lookup(platform, browser)
.then(props => {
.then((props:object) => {
return _.chain({})
.extend(browser, props)
.pick('name', 'type', 'version', 'path')
@@ -79,9 +81,9 @@ function checkOneBrowser(browser:Browser) {
}
/** returns list of detected browsers */
function detectBrowsers (): Promise<Browser[]> {
return Promise.map(browsers, checkOneBrowser)
.then(_.compact) as Promise<Browser[]>
function detectBrowsers (): Bluebird<Browser[]> {
return Bluebird.map(browsers, checkOneBrowser)
.then(_.compact) as Bluebird<Browser[]>
}
export default detectBrowsers
@@ -1,6 +1,7 @@
import {writeJson} from 'fs-extra'
import {launch} from './browsers'
import detect from './detect'
import {Browser, LauncherApi} from './types'
const Promise = require('bluebird')
@@ -1,5 +1,6 @@
import cp = require('child_process')
import Promise = require('bluebird')
import {NotInstalledError} from '../types'
const execAsync = Promise.promisify(cp.exec)
+25
View File
@@ -0,0 +1,25 @@
export type Browser = {
name: string,
re: RegExp,
profile: boolean,
binary: string,
executable: string,
version?: string,
majorVersion?: string,
page?: string
}
interface ExtraLauncherMethods {
update: Function,
detect: Function
}
type LauncherLaunch = (browsers?: any[]) => Promise<any>
export type LauncherApi = LauncherLaunch & ExtraLauncherMethods
// all common type definition for this module
export type NotInstalledError = Error & {notInstalled: boolean}
export type BrowserNotFoundError = Error & {specificBrowserNotFound: boolean}
+5 -8
View File
@@ -3,16 +3,13 @@
"version": "0.1.1",
"description": "Internal lib for spawning browser processes",
"main": "index.js",
"types": "./index.d.ts",
"types": "../ts/index.d.ts",
"scripts": {
"clean-deps": "rm -rf node_modules",
"clean-all": "npm run clean-deps",
"lint": "tslint --type-check --project . --fix --format stylish src/**/*.ts",
"build": "tsc",
"build-dev": "npm run build",
"prebuild": "npm run lint",
"build": "npm run lint",
"pretest": "npm run lint",
"test": "mocha",
"build-and-test": "npm run build && npm test"
"clean-deps": "rm -rf node_modules",
"lint": "tslint --type-check --project .. --fix --format stylish launcher/lib/*.ts launcher/lib/**/*.ts"
},
"repository": {
"type": "git",
+1 -1
View File
@@ -1,3 +1,3 @@
test/unit
--compilers coffee:../coffee/register
--compilers coffee:../coffee/register,ts:../ts/register
--recursive
+3 -6
View File
@@ -4,15 +4,12 @@
"main": "lib/reporter",
"browser": "src/main",
"scripts": {
"build-dev": "node ./scripts/build-dev.js",
"build": "node ./scripts/build-dev.js",
"build-prod": "node ./scripts/build-prod.js",
"watch": "node ./scripts/watch.js",
"clean": "zunder clean",
"clean-deps": "rm -rf node_modules",
"clean-all": "npm run clean && npm run clean-deps",
"test": "npm run test-unit-once",
"test-once": "npm run test-unit-once",
"test-unit-once": "node ./scripts/test.js",
"watch-dev": "node ./scripts/watch.js"
"test": "node ./scripts/test.js"
},
"repository": {
"type": "git",
+3 -6
View File
@@ -12,15 +12,12 @@
},
"homepage": "https://github.com/cypress-io/cypress-core-runner#readme",
"scripts": {
"build-dev": "node ./scripts/build-dev.js",
"build": "node ./scripts/build-dev.js",
"build-prod": "node ./scripts/build-prod.js",
"watch": "node ./scripts/watch.js",
"clean": "zunder clean",
"clean-deps": "rm -rf node_modules",
"clean-all": "npm run clean && npm run clean-deps",
"test": "npm run test-unit-once",
"test-once": "npm run test-unit-once",
"test-unit-once": "node ./scripts/test.js",
"watch-dev": "node ./scripts/watch.js",
"test": "node ./scripts/test.js",
"lint": "eslint src/**/*.jsx src/**/*.js"
},
"files": [
+1
View File
@@ -1,5 +1,6 @@
process.env.UV_THREADPOOL_SIZE = 128
require('graceful-fs').gracefulify(require('fs'))
require("../ts/register")
require("../coffee/register")
require && require.extensions && delete require.extensions[".litcoffee"]
require && require.extensions && delete require.extensions[".coffee.md"]
+1
View File
@@ -1,2 +1,3 @@
require("../ts/register")
require("../coffee/register")
require("./lib/repl")
+1 -1
View File
@@ -10,4 +10,4 @@ DEBUG=nock.*,-nock.common,-nock.scope,socket.io:*,xvfb-maybe \
BROWSER=$BROWSER \
xvfb-maybe --xvfb-run-args "-s \"-screen 0 1280x1024x8\"" mocha $SPEC \
--recursive \
--compilers coffee:../coffee/register
--compilers coffee:../coffee/register,ts:../ts/register
+1 -4
View File
@@ -6,10 +6,7 @@
"scripts": {
"test": "NODE_ENV=test mocha",
"test-watch": "NODE_ENV=test mocha --watch",
"test-once": "npm run test-unit-once",
"test-unit-once": "NODE_ENV=test mocha",
"clean-deps": "rm -rf node_modules",
"clean-all": "npm run clean-deps"
"clean-deps": "rm -rf node_modules"
},
"repository": {
"type": "git",
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "static",
"main": "index.js",
"scripts": {
"build-dev": "gulp build",
"build": "gulp build",
"test": "echo 'Nothing to test yet'"
},
"devDependencies": {
+20
View File
@@ -0,0 +1,20 @@
// missing type definitions for 3rd party libraries
// https://glebbahmutov.com/blog/trying-typescript/#manual-types-for-3rd-party-libraries
declare module 'execa' {
type ExecaResult = {
stdout: string
}
interface Execa {
shell: (cmd:string) => Promise<ExecaResult>
}
const execa: Execa
export = execa
}
declare module 'plist' {
interface Plist {
parse: (s:string) => any
}
const plist: Plist
export = plist
}
+3
View File
@@ -0,0 +1,3 @@
// gives anyone access to ts-node
// https://github.com/TypeStrong/ts-node#programmatic-usage
module.exports = require('ts-node')
+16
View File
@@ -0,0 +1,16 @@
{
"name": "ts",
"version": "1.0.0",
"description": "TypeScript runtime Node hook",
"main": "index.js",
"scripts": {
"test": "node test"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"ts-node": "^3.0.4",
"typescript": "^2.3.2"
}
}
+9
View File
@@ -0,0 +1,9 @@
// register TypeScript Node require hook
// https://github.com/TypeStrong/ts-node#programmatic-usage
const project = require('path').join(__dirname, '../tsconfig.json')
require('ts-node').register({
project
})
// do we need to prevent any other TypeScript hooks?
// like ../coffee/register.js does?
+2
View File
@@ -0,0 +1,2 @@
require('../register')
require('./spec')
+2
View File
@@ -0,0 +1,2 @@
const add = (a: number, b: number) => a + b
console.assert(add(10, 2) === 12, '10 + 2 should be 12')
@@ -10,8 +10,8 @@
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./lib", /* Redirect output structure to the directory. */
// "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "outDir": "./", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
@@ -19,11 +19,11 @@
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
"strictNullChecks": true, /* Enable strict null checks. */
"noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
"alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */
"noUnusedLocals": true, /* Report errors on unused locals. */
@@ -32,12 +32,12 @@
"noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
/* Module Resolution Options */
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
"baseUrl": "./src" /* Base directory to resolve non-absolute module names. */
"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [] /* List of folders to include type definitions from. */
// "types": [] /* Type declaration files to be included in compilation. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [] /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
/* Source Map Options */
@@ -49,9 +49,5 @@
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
},
"include": [
"./src/*.ts",
"./index.d.ts"
]
}
}