Skip to content

Commit 65a8679

Browse files
committed
first commit
0 parents  commit 65a8679

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+8922
-0
lines changed

.babelrc

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"plugins": ["@babel/plugin-syntax-dynamic-import"],
3+
"env": {
4+
"test": {
5+
"plugins": ["dynamic-import-node"],
6+
"presets": [
7+
[ "@babel/env", {
8+
"targets": { "node": "current" }
9+
}]
10+
]
11+
}
12+
},
13+
}

.circleci/config.yml

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
version: 2
2+
3+
defaults: &defaults
4+
working_directory: ~/project
5+
docker:
6+
- image: circleci/node:latest
7+
environment:
8+
NODE_ENV: test
9+
10+
jobs:
11+
setup:
12+
<<: *defaults
13+
steps:
14+
# Checkout repository
15+
- checkout
16+
17+
# Restore cache
18+
- restore_cache:
19+
key: yarn-{{ checksum "yarn.lock" }}
20+
21+
# Install dependencies
22+
- run:
23+
name: Install Dependencies
24+
command: NODE_ENV=dev yarn
25+
26+
# Keep cache
27+
- save_cache:
28+
key: yarn-{{ checksum "yarn.lock" }}
29+
paths:
30+
- "node_modules"
31+
32+
# Persist workspace
33+
- persist_to_workspace:
34+
root: ~/project
35+
paths:
36+
- node_modules
37+
38+
lint:
39+
<<: *defaults
40+
steps:
41+
- checkout
42+
- attach_workspace:
43+
at: ~/project
44+
- run:
45+
name: Lint
46+
command: yarn lint
47+
48+
audit:
49+
<<: *defaults
50+
steps:
51+
- checkout
52+
- attach_workspace:
53+
at: ~/project
54+
- run:
55+
name: Security Audit
56+
command: yarn audit
57+
58+
test-unit:
59+
<<: *defaults
60+
steps:
61+
- checkout
62+
- attach_workspace:
63+
at: ~/project
64+
- run:
65+
name: Unit Tests
66+
command: yarn test:unit --coverage && yarn coverage
67+
68+
test-e2e:
69+
docker:
70+
- image: circleci/node:latest-browsers
71+
steps:
72+
- checkout
73+
- attach_workspace:
74+
at: ~/project
75+
- run:
76+
name: E2E Tests
77+
command: yarn test:e2e
78+
79+
workflows:
80+
version: 2
81+
82+
commit:
83+
jobs:
84+
- setup
85+
- lint: { requires: [setup] }
86+
- audit: { requires: [setup] }
87+
- test-unit: { requires: [lint] }
88+
- test-e2e: { requires: [lint] }

.editorconfig

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
root = true
2+
3+
[*]
4+
indent_style = space
5+
indent_size = 2
6+
end_of_line = lf
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true
10+
11+
[*.md]
12+
trim_trailing_whitespace = false

.eslintignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
coverage
3+
test/fixtures/**

.eslintrc.js

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
module.exports = {
2+
root: true,
3+
env: {
4+
node: true,
5+
browser: true,
6+
'jest/globals': true
7+
},
8+
parser: 'babel-eslint',
9+
parserOptions: {
10+
sourceType: 'module'
11+
},
12+
extends: [
13+
'standard',
14+
'plugin:import/errors',
15+
'plugin:import/warnings',
16+
],
17+
plugins: [
18+
'jest'
19+
],
20+
rules: {
21+
// Enforce import order
22+
'import/order': 2,
23+
24+
// Imports should come first
25+
'import/first': 2,
26+
27+
// Other import rules
28+
'import/no-mutable-exports': 2,
29+
30+
// Allow unresolved imports
31+
'import/no-unresolved': 0,
32+
33+
// Allow paren-less arrow functions only when there's no braces
34+
'arrow-parens': [2, 'as-needed', { requireForBlockBody: true }],
35+
36+
// Allow async-await
37+
'generator-star-spacing': 0,
38+
39+
// Allow debugger during development
40+
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 1,
41+
'no-console': process.env.NODE_ENV === 'production' ? 2 : 1,
42+
43+
// Prefer const over let
44+
'prefer-const': [2, {
45+
'destructuring': 'any',
46+
'ignoreReadBeforeAssign': false
47+
}],
48+
49+
// No single if in an else block
50+
'no-lonely-if': 2,
51+
52+
// Force curly braces for control flow,
53+
// including if blocks with a single statement
54+
curly: [2, 'all'],
55+
56+
// No async function without await
57+
'require-await': 2,
58+
59+
// Force dot notation when possible
60+
'dot-notation': 2,
61+
62+
'no-var': 2,
63+
64+
// Force object shorthand where possible
65+
'object-shorthand': 2,
66+
67+
// No useless destructuring/importing/exporting renames
68+
'no-useless-rename': 2,
69+
70+
'space-before-function-paren': ['error', {
71+
anonymous: 'always',
72+
named: 'never',
73+
asyncArrow: 'always'
74+
}],
75+
}
76+
}

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
*.env
3+
*.log

README.md

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# test in browser (tib)
2+
3+
Helper classes for e2e browser testing in Node with a uniform interface.
4+
5+
Supported browsers (locally):
6+
- Puppeteer (core)
7+
- Selenium (generic)
8+
- Firefox
9+
- Chrome
10+
11+
Supported providers:
12+
- BrowserStack
13+
14+
All browser/provider specific dependencies are peer dependencies and are dynamically loaded
15+
16+
## Features
17+
18+
- Automatically starts Xvfb for non-headless support (on supported platforms)
19+
- Supports BrowserStack-Local to easily tests local code
20+
- Very easy to write scripts which run in the browser
21+
- just remember to only use language features the loaded page already has polyfills for
22+
23+
## Example
24+
25+
(and options list for now)
26+
27+
also check [our e2e tests](./test/e2e) for more information
28+
29+
```js
30+
import { browser, commands: { Xvfb, BrowserStackLocal } } from 'tib'
31+
32+
describe('e2e', () => {
33+
let myBrowser
34+
beforeAll(async () => {
35+
myBrowser = browser('windows 10/chrome 71/browserstack/local/1920x1080', {
36+
xvfb: false, // if true then Xvfb is automatically started before the browser
37+
// and the displayNum=99 added to the process.env
38+
BrowserStackLocal: {
39+
start: true, // default, if false then call 'const pid = await BrowserStackLocal.start()'
40+
stop: true, // default, if false then call 'await BrowserStackLocal.stop(pid)'
41+
user: process.env.BROWSERSTACK_USER,
42+
key: process.env.BROWSERSTACK_KEY,
43+
folder: process.cwd()
44+
},
45+
extendPage(page) {
46+
return {
47+
getRouteData() {
48+
return page.runScript(() => {
49+
// this function is executed within the page context
50+
// if you use features like Promises and are testing on
51+
// older browsers make sure you have a polyfill already
52+
// loaded
53+
return myRouter.currentRoute
54+
})
55+
},
56+
async navigate(path) {
57+
// IMPORTANT: if you use an (arrow) function then use
58+
// a block'ed body due to an upstream issue
59+
await page.runAsyncScript((path) => {
60+
// this function is executed within the page context
61+
// if you use features like Promises and are testing on
62+
// older browsers make sure you have a polyfill already
63+
// loaded
64+
return new Promise(resolve => {
65+
myRouter.on('navigationFinished', resolve)
66+
window.myRouter.navigate(path)
67+
})
68+
}, path)
69+
}
70+
}
71+
}
72+
})
73+
})
74+
75+
afterAll(() => {
76+
await myBrowser.close()
77+
})
78+
79+
test('router', async () => {
80+
// note: this method is only available for browserstack/local browsers
81+
const url = myBrowser.getLocalFolderUrl()
82+
83+
const page = await myBrowser.page(url)
84+
85+
// you should probably expect and not log this
86+
console.log(await page.getHtml())
87+
console.log(await page.getElement('div'))
88+
console.log(await page.getElements('div'))
89+
console.log(await page.getElementCount('div'))
90+
console.log(await page.getAttribute('div', 'id'))
91+
console.log(await page.getAttributes('div', 'id'))
92+
console.log(await page.getText('h1'))
93+
console.log(await page.getTexts('h1, h2'))
94+
console.log(await page.getTitle())
95+
96+
await page.navigate('/about')
97+
console.log(await page.getRouteData())
98+
99+
console.log(await page.getTitle())
100+
})
101+
})
102+
```
103+
104+
## Babel config
105+
106+
This package exports ES6 code, so you will probably need to tell Babel to also transpile this package
107+
108+
> use `babel.config.js` if Babel fails to transpile with `.babelrc.js`
109+
110+
Install the [dynamic-import-node](https://github.com/airbnb/babel-plugin-dynamic-import-node) plugin:
111+
```sh
112+
yarn add babel-plugin-dynamic-import-node
113+
```
114+
115+
```js
116+
module.exports = {
117+
env: {
118+
test: {
119+
exclude: /node_modules\/(?!(tib))/,
120+
plugins: ['dynamic-import-node'],
121+
presets: [
122+
[ '@babel/preset-env', {
123+
targets: {
124+
node: 'current'
125+
}
126+
}]
127+
]
128+
}
129+
},
130+
}
131+
```
132+
133+
## TODO
134+
- local ie/edge/safari
135+
- more platforms, which ones?
136+
- SauceLabs (unable to test as I have no key)
137+
- screenshotting
138+
- window sizes
139+
- testing
140+
- ?

jest.config.js

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
module.exports = {
2+
testEnvironment: 'node',
3+
4+
expand: true,
5+
6+
forceExit: false,
7+
8+
// https://github.com/facebook/jest/pull/6747 fix warning here
9+
// But its performance overhead is pretty bad (30+%).
10+
// detectOpenHandles: true
11+
12+
setupFilesAfterEnv: ['./test/utils/setup'],
13+
14+
coverageDirectory: './coverage',
15+
16+
collectCoverageFrom: [
17+
'**/src/**/*.js'
18+
],
19+
20+
coveragePathIgnorePatterns: [
21+
'node_modules',
22+
'src/utils/detectors/chrome.js'
23+
],
24+
25+
testPathIgnorePatterns: [
26+
'node_modules'
27+
],
28+
29+
transformIgnorePatterns: [
30+
'node_modules'
31+
],
32+
33+
transform: {
34+
'^.+\\.js$': 'babel-jest'
35+
},
36+
37+
moduleFileExtensions: [
38+
'ts',
39+
'js',
40+
'json'
41+
]
42+
}

0 commit comments

Comments
 (0)