├── cli ├── .nvmrc ├── bin │ ├── galen.cmd │ └── galen ├── .npmignore ├── runTests.cmd ├── test │ ├── specs │ │ └── bootstrap.gspec │ ├── galen.test │ └── config ├── runTests.sh ├── .snyk ├── jasmine.json ├── spec │ └── cli.spec.js ├── package.json ├── README.MD ├── postinstall.js └── .eslintrc.js ├── core ├── .nvmrc ├── bin │ ├── galen.cmd │ └── galen ├── .npmignore ├── .snyk ├── index.js ├── tsconfig.json ├── jasmine.json ├── spec │ └── core.spec.js ├── GalenApi.d.ts ├── package.json ├── README.MD ├── lib │ └── helper.js ├── .eslintrc.js └── postinstall.js ├── .dockerignore ├── docker-env.sh ├── etc ├── entrypoint.sh └── galen.code-workspace ├── docker-build-images.sh ├── galen.code-workspace ├── docker-compose.yml ├── .gitignore ├── .editorconfig ├── .github ├── CONTRIBUTING.md ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ └── build.yml ├── scripts ├── xvfb-firefox └── xvfb-chrome ├── release.sh ├── .vscode └── settings.json ├── appveyor.yml ├── LICENSE ├── .travis.yml ├── README.md ├── Dockerfile └── CHANGELOG.md /cli/.nvmrc: -------------------------------------------------------------------------------- 1 | v10 2 | -------------------------------------------------------------------------------- /core/.nvmrc: -------------------------------------------------------------------------------- 1 | v10 2 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | core 2 | cli 3 | -------------------------------------------------------------------------------- /cli/bin/galen.cmd: -------------------------------------------------------------------------------- 1 | @node "%~dpn0" %* -------------------------------------------------------------------------------- /core/bin/galen.cmd: -------------------------------------------------------------------------------- 1 | @node "%~dpn0" %* -------------------------------------------------------------------------------- /cli/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | node_modules/ 3 | test/ 4 | target/ -------------------------------------------------------------------------------- /core/.npmignore: -------------------------------------------------------------------------------- 1 | coverage/ 2 | node_modules/ 3 | test/ 4 | target/ -------------------------------------------------------------------------------- /docker-env.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export GALEN_VERSION=2.4.4 4 | -------------------------------------------------------------------------------- /etc/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | source /home/galen/nvm.sh 3 | exec "$@" 4 | -------------------------------------------------------------------------------- /docker-build-images.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source ./docker-env.sh 4 | 5 | docker-compose create 6 | -------------------------------------------------------------------------------- /galen.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "core" 5 | }, 6 | { 7 | "path": "cli" 8 | } 9 | ] 10 | } -------------------------------------------------------------------------------- /core/.snyk: -------------------------------------------------------------------------------- 1 | # Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. 2 | version: v1.10.1 3 | ignore: {} 4 | patch: {} 5 | -------------------------------------------------------------------------------- /core/index.js: -------------------------------------------------------------------------------- 1 | var helper = require('./lib/helper'); 2 | 3 | module.exports = { 4 | galenPath: helper.galenPath, 5 | helper: helper 6 | }; -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | galenframework: 4 | image: galenframework/cli:$GALEN_VERSION 5 | build: 6 | context: . 7 | dockerfile: Dockerfile 8 | -------------------------------------------------------------------------------- /cli/runTests.cmd: -------------------------------------------------------------------------------- 1 | cd test 2 | galen check specs/bootstrap.gspec --url "http://getbootstrap.com" --size "640x480" --htmlreport ../../../reports/ 3 | galen test galen.test -DwebsiteUrl="http://getbootstrap.com" 4 | -------------------------------------------------------------------------------- /cli/test/specs/bootstrap.gspec: -------------------------------------------------------------------------------- 1 | @objects 2 | bootstrap-logo .bd-masthead .img-fluid 3 | 4 | # concrete layout tests 5 | 6 | = Bootstrap logo should be visible = 7 | 8 | bootstrap-logo: 9 | visible 10 | -------------------------------------------------------------------------------- /cli/runTests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd test 4 | galen check specs/bootstrap.gspec --url "http://getbootstrap.com" --size "640x480" --htmlreport ../../../reports/ 5 | galen test galen.test -DwebsiteUrl="http://getbootstrap.com" 6 | cd .. 7 | -------------------------------------------------------------------------------- /etc/galen.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "/Users/mreinhardt/git/job/galen/galenframework-cli/cli" 5 | }, 6 | { 7 | "path": "/Users/mreinhardt/git/job/galen/galenframework-cli/core" 8 | }, 9 | { 10 | "path": "/Users/mreinhardt/git/job/galen/galenframework-cli" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | cc-test-reporter 3 | core/node_modules/* 4 | cli/node_modules/* 5 | core/lib/galen/* 6 | cli/lib/galen/* 7 | core/lib/location.js 8 | cli/ib/location.js 9 | core/coverage/* 10 | core/target/* 11 | cli/coverage/* 12 | cli/tmp/* 13 | cli/target/* 14 | lib/location.js 15 | 16 | # IDE 17 | .idea/* 18 | *.iml 19 | *.swp 20 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | charset = utf-8 7 | indent_style = space 8 | indent_size = 2 9 | end_of_line = lf 10 | insert_final_newline = true 11 | trim_trailing_whitespace = true 12 | 13 | [dropdown-toggle.js] 14 | trim_trailing_whitespace = false 15 | insert_final_newline = false 16 | 17 | [htmlparser.js] 18 | insert_final_newline = false -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | First search if the issue is already described! 2 | 3 | If not create a new issue: 4 | 5 | * Tell about your environment: 6 | * node version 7 | * java version 8 | * galen version 9 | * used browser and version 10 | * Describe your issue 11 | * describe your steps leading to the issue 12 | * attach error logs or screenshots 13 | * if possible provide test case or screenshots 14 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | # github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: galen 5 | #open_collective: moleculer 6 | #ko_fi: # Replace with a single Ko-fi username 7 | #tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | custom: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H8TR8246RCDJG 9 | -------------------------------------------------------------------------------- /cli/.snyk: -------------------------------------------------------------------------------- 1 | # Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities. 2 | version: v1.13.5 3 | ignore: {} 4 | # patches apply the minimum changes required to fix a vulnerability 5 | patch: 6 | 'npm:request:20160119': 7 | - galenframework > request: 8 | patched: '2018-02-15T16:29:24.906Z' 9 | SNYK-JS-HTTPSPROXYAGENT-469131: 10 | - geckodriver > https-proxy-agent: 11 | patched: '2019-10-04T07:42:24.535Z' 12 | -------------------------------------------------------------------------------- /scripts/xvfb-firefox: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | _kill_procs() { 4 | kill -TERM $ffproc 5 | wait $ffproc 6 | kill -TERM $xvfb 7 | } 8 | 9 | # Setup a trap to catch SIGTERM and relay it to child processes 10 | trap _kill_procs SIGTERM 11 | 12 | XVFB_WHD=${XVFB_WHD:-1024x768x16} 13 | 14 | # Start Xvfb 15 | Xvfb :100 -ac -screen 1 $XVFB_WHD +extension RANDR -nolisten tcp & 16 | xvfb=$! 17 | 18 | export DISPLAY=:100 19 | 20 | firefox $@ & 21 | ffproc=$! 22 | 23 | wait $ffproc 24 | wait $xvfb 25 | -------------------------------------------------------------------------------- /core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "moduleResolution": "node", 5 | "target": "es5", 6 | "experimentalDecorators": true, 7 | "emitDecoratorMetadata": true, 8 | "noEmitHelpers": true, 9 | "noEmitOnError": true, 10 | "lib": [ 11 | "es2015", 12 | "es2015.iterable", 13 | "dom" 14 | ], 15 | "types": [ 16 | "jasmine", 17 | "node" 18 | ] 19 | }, 20 | "exclude": [ 21 | "node_modules" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /scripts/xvfb-chrome: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | _kill_procs() { 4 | kill -TERM $chproc 5 | wait $chproc 6 | kill -TERM $xvfb 7 | } 8 | 9 | # Setup a trap to catch SIGTERM and relay it to child processes 10 | trap _kill_procs SIGTERM 11 | 12 | XVFB_WHD=${XVFB_WHD:-1024x768x16} 13 | 14 | # Start Xvfb 15 | Xvfb :99 -ac -screen 1 $XVFB_WHD +extension RANDR -nolisten tcp & 16 | xvfb=$! 17 | 18 | export DISPLAY=:99 19 | 20 | google-chrome-stable --no-sandbox $@ & 21 | chproc=$! 22 | 23 | wait $chproc 24 | wait $xvfb 25 | -------------------------------------------------------------------------------- /cli/test/galen.test: -------------------------------------------------------------------------------- 1 | @@ table browsers 2 | | browerName | browser | 3 | | Chrome | chrome | 4 | | Firefox | firefox | 5 | @@ table devices 6 | | deviceName | tags | size | 7 | | Mobile | mobile | 320x600 | 8 | | Tablet | tablet | 640x480 | 9 | | Desktop | desktop | 1024x800 | 10 | 11 | @@ parameterized using browsers 12 | @@ parameterized using devices 13 | @@ groups home, page 14 | bootstrap page on ${deviceName} in ${browerName} browser 15 | selenium ${browser} ${websiteUrl} ${size} 16 | check specs/bootstrap.gspec --include "${device}" 17 | -------------------------------------------------------------------------------- /release.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | PACKAGE_VERSION=$(cat cli/package.json \ 4 | | grep version \ 5 | | head -1 \ 6 | | awk -F: '{ print $2 }' \ 7 | | sed 's/[",]//g' | sed 's/[ ,]//g') 8 | 9 | git pull --rebase && \ 10 | conventional-changelog -p angular -i CHANGELOG.md -s -r 0 -k cli/package.json && \ 11 | git add CHANGELOG.md && git commit -m 'chore(changelog): Updated CHANGELOG.md' && \ 12 | git checkout master && git merge develop && git push && \ 13 | git tag -a "v$PACKAGE_VERSION" -m "Version $PACKAGE_VERSION" && git push --tags && \ 14 | echo "Created a new tag, v$PACKAGE_VERSION" && \ 15 | git checkout develop 16 | -------------------------------------------------------------------------------- /cli/jasmine.json: -------------------------------------------------------------------------------- 1 | 2 | // Spec directory path relative to the current working dir when jasmine is executed. 3 | "spec_dir": "spec", 4 | 5 | // Array of filepaths (and globs) relative to spec_dir to include and exclude 6 | "spec_files": [ 7 | "**/*[sS]pec.js", 8 | "!**/*nospec.js" 9 | ], 10 | 11 | // Array of filepaths (and globs) relative to spec_dir to include before jasmine specs 12 | "helpers": [ 13 | "helpers/**/*.js" 14 | ], 15 | 16 | // Stop execution of a spec after the first expectation failure in it 17 | "stopSpecOnExpectationFailure": false, 18 | 19 | // Run specs in semi-random order 20 | "random": false 21 | } 22 | -------------------------------------------------------------------------------- /core/jasmine.json: -------------------------------------------------------------------------------- 1 | 2 | // Spec directory path relative to the current working dir when jasmine is executed. 3 | "spec_dir": "spec", 4 | 5 | // Array of filepaths (and globs) relative to spec_dir to include and exclude 6 | "spec_files": [ 7 | "**/*[sS]pec.js", 8 | "!**/*nospec.js" 9 | ], 10 | 11 | // Array of filepaths (and globs) relative to spec_dir to include before jasmine specs 12 | "helpers": [ 13 | "helpers/**/*.js" 14 | ], 15 | 16 | // Stop execution of a spec after the first expectation failure in it 17 | "stopSpecOnExpectationFailure": false, 18 | 19 | // Run specs in semi-random order 20 | "random": false 21 | } 22 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.enable": false, 3 | "java.configuration.updateBuildConfiguration": "automatic", 4 | "editor.tabSize": 2, 5 | "files.exclude": { 6 | "**/.git": true, 7 | "**/.svn": true, 8 | "**/.hg": true, 9 | "**/CVS": true, 10 | "**/.DS_Store": true, 11 | // exclude .js and .js.map files, when in a TypeScript project 12 | "**/*.js": { 13 | "when": "$(basename).ts" 14 | }, 15 | "**/*.js.map": true, 16 | "**/*.ngfactory.ts": true, 17 | "**/*.ngsummary.json": true 18 | }, 19 | "vsicons.presets.angular": true, 20 | "json.format.enable": false, 21 | "javascript.format.enable": true, 22 | "typescript.format.enable": true 23 | } 24 | -------------------------------------------------------------------------------- /core/bin/galen: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var spawn = require('child_process').spawn; 4 | var path = require('path'); 5 | var baseDir = path.dirname(require.main.filename); 6 | var childProcessOptions = { 7 | stdio: 'inherit' 8 | }; 9 | 10 | // remove node args 11 | var args = process.argv.slice(2); 12 | 13 | var programPath; 14 | if (process.platform === 'win32') { 15 | programPath = path.resolve(baseDir, '../lib/galen/galen.bat'); 16 | } else { 17 | programPath = path.resolve(baseDir, '../lib/galen/galen'); 18 | } 19 | 20 | var galenProcess = spawn(programPath, args, childProcessOptions); 21 | 22 | galenProcess.on('error', function (error) { 23 | console.error(error); 24 | process.exit(1); 25 | }); 26 | 27 | galenProcess.on('exit', function (exitCode) { 28 | process.exit(exitCode); 29 | }); 30 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # appveyor file 2 | # http://www.appveyor.com/docs/appveyor-yml 3 | environment: 4 | matrix: 5 | - NODE_VERSION: "14" 6 | - NODE_VERSION: "16" 7 | - NODE_VERSION: "18" 8 | 9 | platform: 10 | - x86 11 | - x64 12 | 13 | cache: 14 | - AllReadyApp\Web-App\AllReady\node_modules # node modules for the app 15 | - '%APPDATA%\npm-cache' # npm cache 16 | 17 | install: 18 | - ps: Install-Product node $env:NODE_VERSION 19 | - node --version 20 | - npm --version 21 | - npm install -g jshint 22 | - npm install -g istanbul 23 | - npm install -g istanbul-coveralls 24 | - npm install -g nodeunit 25 | 26 | build: off 27 | 28 | test_script: 29 | - cd core 30 | - npm install . 31 | - npm test 32 | - npm install . -g --force 33 | - cd .. 34 | - cd cli 35 | - npm install . 36 | - npm test 37 | - npm install . -g --force 38 | - .\runTests 39 | -------------------------------------------------------------------------------- /cli/spec/cli.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * functional tests. Requires internet connection to validate phantom 3 | * functions correctly. 4 | */ 5 | 6 | const fs = require('fs'); 7 | const path = require('path'); 8 | const helper = require('galenframework/lib/helper'); 9 | 10 | describe("Galen CLI", function() { 11 | 12 | it("Clean path", function() { 13 | const binPath1 = helper.cleanPath('/Users/hypery2k/bin:./bin'); 14 | expect(binPath1).toBe('/Users/hypery2k/bin'); 15 | const binPath2 = helper.cleanPath('/Users/hypery2k/bin:./bin:/usr/bin'); 16 | expect(binPath2).toBe('/Users/hypery2k/bin:/usr/bin'); 17 | const binPath3 = helper.cleanPath('./bin:/usr/bin'); 18 | expect(binPath3).toBe('/usr/bin'); 19 | const binPath4 = helper.cleanPath('./bin'); 20 | expect(binPath4).toBe(''); 21 | const binPath5 = helper.cleanPath('/Work/bin:/Work/as/node_modules/.bin:/usr/bin'); 22 | expect(binPath5).toBe('/Work/bin:/usr/bin'); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | ## Prerequisites 8 | 9 | Please answer the following questions for yourself before submitting an issue. 10 | 11 | * [ ] I've read, understood, and done my best to follow the [*CONTRIBUTING guidelines](https://github.com/hypery2k/galenframework-cli/master/CONTRIBUTING.md). 12 | 13 | ## Changes 14 | 15 | **Is your feature request related to a problem? Please describe.** 16 | 17 | 18 | **Describe the solution you'd like** 19 | 20 | 21 | **Describe alternatives you've considered** 22 | 23 | 24 | **Additional context** 25 | 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Martin Reinhardt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /core/spec/core.spec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * functional tests. Requires internet connection to validate phantom 3 | * functions correctly. 4 | */ 5 | 6 | const fs = require('fs'); 7 | const path = require('path'); 8 | const helper = require('../lib/helper'); 9 | 10 | describe("Galen Core", function() { 11 | var a; 12 | 13 | it("Binary file should have been downloaded", function() { 14 | const binFileExists = fs.existsSync(helper.path); 15 | expect(binFileExists).toBeTruthy(); 16 | }); 17 | 18 | it("Clean path", function() { 19 | const binPath1 = helper.cleanPath('/Users/hypery2k/bin:./bin'); 20 | expect(binPath1).toBe('/Users/hypery2k/bin'); 21 | const binPath2 = helper.cleanPath('/Users/hypery2k/bin:./bin:/usr/bin'); 22 | expect(binPath2).toBe('/Users/hypery2k/bin:/usr/bin'); 23 | const binPath3 = helper.cleanPath('./bin:/usr/bin'); 24 | expect(binPath3).toBe('/usr/bin'); 25 | const binPath4 = helper.cleanPath('./bin'); 26 | expect(binPath4).toBe(''); 27 | const binPath5 = helper.cleanPath('/Work/bin:/Work/as/node_modules/.bin:/usr/bin'); 28 | expect(binPath5).toBe('/Work/bin:/usr/bin'); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | ## Prerequisites 8 | 9 | Please answer the following questions for yourself before submitting an issue. 10 | 11 | - [ ] I am running the latest version 12 | - [ ] I checked the documentation and found no answer 13 | - [ ] I checked to make sure that this issue has not already been filed 14 | - [ ] I'm reporting the issue to the correct repository 15 | 16 | ## Current Behavior 17 | 18 | 19 | 20 | ## Expected Behavior 21 | 22 | 23 | 24 | ## Failure Information 25 | 26 | 27 | 28 | ### Steps to Reproduce 29 | 30 | Please provide detailed steps for reproducing the issue. 31 | 32 | 1. step 1 33 | 2. step 2 34 | 3. you get it... 35 | 36 | 37 | ### Context 38 | 39 | Please provide any relevant information about your setup. This is important in case the issue is not reproducible except for under certain conditions. 40 | 41 | **Galen version:** 42 | **Java version:** 43 | **NodeJS and NPM version:** 44 | **Platform(s) running Galen:** 45 | 46 | ### Failure Logs 47 | ``` 48 | 49 | ``` 50 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## :memo: Description 2 | 3 | 4 | 5 | ### :dart: Relevant issues 6 | 7 | 8 | ### :gem: Type of change 9 | 10 | 11 | 12 | - [ ] Bug fix (non-breaking change which fixes an issue) 13 | - [ ] New feature (non-breaking change which adds functionality) 14 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 15 | - [ ] This change requires a documentation update 16 | 17 | ### :scroll: Example code 18 | ```js 19 | 20 | ``` 21 | 22 | ## :vertical_traffic_light: How Has This Been Tested? 23 | 24 | Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration 25 | 26 | - [ ] Test A 27 | - [ ] Test B 28 | 29 | ## :checkered_flag: Checklist: 30 | 31 | - [ ] My code follows the style guidelines of this project 32 | - [ ] I have performed a self-review of my own code 33 | - [ ] **I have added tests that prove my fix is effective or that my feature works** 34 | - [ ] **New and existing unit tests pass locally with my changes** 35 | - [ ] I have commented my code, particularly in hard-to-understand areas 36 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: focal 3 | language: node_js 4 | after_success: npm run coverage && cat ./coverage/lcov.info | coveralls 5 | 6 | env: 7 | matrix: 8 | - NODE_VERSION="12" DISPLAY=:99 9 | - NODE_VERSION="14" DISPLAY=:99 10 | 11 | services: 12 | - xvfb 13 | - docker 14 | 15 | addons: 16 | # From some tests it seems you can only have one firefox addon. 17 | # Adding two results in the last one defined being the one installed. 18 | firefox: latest 19 | apt: 20 | sources: 21 | - sourceline: 'deb http://dl.google.com/linux/chrome/deb/ stable main' 22 | packages: 23 | - google-chrome-stable 24 | cache: 25 | directories: 26 | - 'node_modules' 27 | 28 | before_script: 29 | - npm install -g jshint 30 | - npm install -g istanbul 31 | - npm install -g istanbul-coveralls 32 | - npm install -g nodeunit 33 | - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter 34 | - chmod +x ./cc-test-reporter 35 | - ./cc-test-reporter before-build 36 | script: 37 | - export COVERALLS_SERVICE_NAME=travis-ci 38 | - ./docker-build-images.sh 39 | - cd core 40 | - npm i 41 | - npm install . 42 | - npm run coverage 43 | - cd .. 44 | - cd cli 45 | - npm i 46 | - npm install . -g 47 | - xvfb-run npm run test 48 | - xvfb-run ./runTests.sh 49 | - cd .. 50 | - ./docker-build-images.sh 51 | after_script: 52 | - cd core 53 | - ../cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT || true 54 | before_install: 55 | # Prepare node and npm 56 | - nvm install $NODE_VERSION && nvm use $NODE_VERSION 57 | - npm install -g snyk 58 | # Show environment info 59 | - node --version 60 | - npm --version 61 | notifications: 62 | webhooks: 63 | urls: 64 | - https://webhooks.gitter.im/e/f3499197be7208e15199 65 | on_success: change # options: [always|never|change] default: always 66 | on_failure: always # options: [always|never|change] default: always 67 | on_start: false # default: false 68 | -------------------------------------------------------------------------------- /cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "galenframework-cli", 3 | "version": "2.4.4", 4 | "description": "Just the node wrapper for the Galen Framework.", 5 | "homepage": "https://github.com/hypery2k/galenframework-cli", 6 | "bugs": { 7 | "url": "https://github.com/hypery2k/galenframework-cli/issues" 8 | }, 9 | "keywords": [ 10 | "galen", 11 | "galenframework", 12 | "responsive", 13 | "test", 14 | "testing", 15 | "webdriver", 16 | "selenium", 17 | "TDD", 18 | "BDD" 19 | ], 20 | "author": "Martin Reinhardt", 21 | "scripts": { 22 | "galen": "bin/galen", 23 | "postinstall": "node postinstall.js", 24 | "test": "npm run check && npm run unit-test", 25 | "unit-test": "jasmine --reporter=jasmine-ts-console-reporter spec/*.spec.js", 26 | "lint": "eslint --fix *.js", 27 | "check": "npm audit", 28 | "coverage": "nyc --reporter=lcov --temp-dir=coverage npm run test && istanbul-coveralls --no-rm" 29 | }, 30 | "bin": { 31 | "galen": "bin/galen" 32 | }, 33 | "preferGlobal": true, 34 | "dependencies": { 35 | "check": "^1.0.0", 36 | "chromedriver": "^101.0.0", 37 | "fs-extra": "0.26.2", 38 | "galenframework": "^2.4.4-build43", 39 | "geckodriver": "^3.0.1", 40 | "httpreq": "^0.5.2", 41 | "yargs": "3.30.0" 42 | }, 43 | "devDependencies": { 44 | "@toolisticon/istanbul-coveralls": "1.0.0", 45 | "coveralls": "3.0.2", 46 | "ejs": "^3.1.7", 47 | "eslint": "^8.15.0", 48 | "jasmine": "^4.1.0", 49 | "jasmine-ts-console-reporter": "^3.1.1", 50 | "nyc": "^14.1.1" 51 | }, 52 | "repository": { 53 | "type": "git", 54 | "url": "git+https://github.com/hypery2k/galenframework-cli.git" 55 | }, 56 | "license": "MIT", 57 | "engine-strict": true, 58 | "engines": { 59 | "node": ">= 8", 60 | "npm": ">= 5" 61 | }, 62 | "snyk": true 63 | } 64 | -------------------------------------------------------------------------------- /core/GalenApi.d.ts: -------------------------------------------------------------------------------- 1 | declare interface GridSettings { 2 | browser: string; 3 | browserVersion: string; 4 | platform: string; 5 | size: string; 6 | desiredCapabilities: { key: string, value: string } 7 | } 8 | 9 | declare interface WebDriver { 10 | 11 | } 12 | 13 | export declare function load(jsFilePath: string): void 14 | 15 | export declare function createDriver(url: string, browserSize: string, browserType: string): WebDriver 16 | 17 | export declare function createGridDriver(gridHubUrl: string, settings: GridSettings): WebDriver 18 | 19 | export declare function resize(driver: WebDriver, size: string): void 20 | 21 | export declare function checkLayout(driver: WebDriver, specFile: String, tagsToInclude?: [string], tagsToExclude?: [string]): void 22 | 23 | export declare function checkLayout({}): void 24 | 25 | export declare function checkPageSpecLayout(driver: WebDriver, pageSpec: String, tagsToInclude?: [string], tagsToExclude?: [string]): void 26 | 27 | export declare function parsePageSpec({}): void 28 | 29 | export declare function loadProperties(filePath: String): Map 30 | 31 | export declare function readFile(filePath: String): string 32 | 33 | export declare function listDirectory(dirPath: String): [string] 34 | 35 | export declare function makeDirectory(dirPath: String): void 36 | 37 | export declare function fileExists(filePath: String): boolean 38 | 39 | export declare function isDirectory(dirPath: String): boolean 40 | 41 | export declare function retry(tries: number, callback: Function): void 42 | 43 | export declare function takeScreenshot(driver: WebDriver): string 44 | 45 | export declare function cookie(driver: WebDriver, cookieValue: string): void 46 | 47 | export declare function inject(driver: WebDriver, script: string): void 48 | 49 | export declare function createTestDataProvider(varableName: string): any 50 | 51 | export declare function dumpPage({}): void 52 | 53 | export declare function logged(text: string, callback: Function): void 54 | 55 | export declare function loggedFunction(textExpression: string, callback: Function): void 56 | -------------------------------------------------------------------------------- /core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "galenframework", 3 | "version": "2.4.4", 4 | "description": "The command line tool to use the Galen Framework. This includes the wrapper above and webdriver downloads for different browsers", 5 | "homepage": "https://github.com/hypery2k/galenframework-cli", 6 | "bugs": { 7 | "url": "https://github.com/hypery2k/galenframework-cli/issues" 8 | }, 9 | "keywords": [ 10 | "galen", 11 | "galenframework", 12 | "responsive", 13 | "test", 14 | "testing", 15 | "webdriver", 16 | "selenium", 17 | "TDD", 18 | "BDD" 19 | ], 20 | "author": "Martin Reinhardt", 21 | "scripts": { 22 | "galen": "bin/galen", 23 | "build": "npm run tsc", 24 | "tsc": "tsc", 25 | "postinstall": "node postinstall.js", 26 | "test": "npm run check && npm run unit-test", 27 | "unit-test": "jasmine --reporter=jasmine-ts-console-reporter spec/*.spec.js", 28 | "check": "npm audit", 29 | "lint": "eslint lib/*.js", 30 | "coverage": "nyc --reporter=lcov --temp-dir=coverage npm run test && istanbul-coveralls --no-rm" 31 | }, 32 | "bin": { 33 | "galen": "bin/galen" 34 | }, 35 | "main": "index", 36 | "dependencies": { 37 | "adm-zip": "^0.5.5", 38 | "fs-extra": "0.30.0", 39 | "kew": "0.7.0", 40 | "npm-which": "3.0.1", 41 | "npmconf": "^2.1.3", 42 | "npmlog": "^6.0.2", 43 | "progress": "1.1.8", 44 | "replace-in-file": "1.0.2", 45 | "request": "2.88.2", 46 | "request-progress": "0.3.1", 47 | "which": "1.3.1", 48 | "yargs": "^17.5.1" 49 | }, 50 | "devDependencies": { 51 | "@toolisticon/istanbul-coveralls": "1.0.0", 52 | "coveralls": "3.0.6", 53 | "ejs": "^3.1.7", 54 | "eslint": "^8.15.0", 55 | "handlebars": "^4.7.7", 56 | "jasmine": "^4.1.0", 57 | "jasmine-ts-console-reporter": "^3.1.1", 58 | "marked": "^4.0.15", 59 | "npm-force-resolutions": "0.0.3", 60 | "nyc": "^14.1.1", 61 | "typedoc": "^0.22.15", 62 | "typescript": "^4.6.4" 63 | }, 64 | "resolutions": { 65 | "handlebars": "^4.3.0" 66 | }, 67 | "repository": { 68 | "type": "git", 69 | "url": "git+https://github.com/hypery2k/galenframework-cli.git" 70 | }, 71 | "license": "MIT", 72 | "engine-strict": true, 73 | "engines": { 74 | "node": ">= 8", 75 | "npm": ">= 5" 76 | }, 77 | "_galenVersion": "2.4.4" 78 | } 79 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build-core: 7 | name: Build Core on node ${{ matrix.node_version }} and ${{ matrix.os }} 8 | runs-on: ${{ matrix.os }} 9 | strategy: 10 | matrix: 11 | node_version: [14, 16, 18] 12 | os: [ubuntu-latest, windows-latest, macOS-latest] 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | 17 | - name: Use Node.js ${{ matrix.node_version }} 18 | uses: actions/setup-node@v3 19 | with: 20 | node-version: ${{ matrix.node_version }} 21 | 22 | - name: npm install, build and test 23 | run: | 24 | cd core 25 | npm install 26 | npm test 27 | 28 | build-cli: 29 | name: Build CLI on node ${{ matrix.node_version }} and ${{ matrix.os }} 30 | runs-on: ${{ matrix.os }} 31 | strategy: 32 | matrix: 33 | node_version: [14, 16, 18] 34 | os: [ubuntu-latest, windows-latest, macOS-latest] 35 | 36 | steps: 37 | - uses: actions/checkout@v2 38 | - name: Use Node.js ${{ matrix.node_version }} 39 | uses: actions/setup-node@v3 40 | with: 41 | node-version: ${{ matrix.node_version }} 42 | 43 | - name: npm install, build and test 44 | run: | 45 | cd cli 46 | npm install 47 | npm install . -g 48 | npm test 49 | deploy: 50 | needs: [build-core, build-cli] 51 | runs-on: ubuntu-latest 52 | steps: 53 | - uses: actions/checkout@v2 54 | - uses: actions/setup-node@v3 55 | with: 56 | node-version: 16 57 | 58 | - name: publish release package 59 | env: 60 | NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} 61 | run: | 62 | echo "//registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN" >> ~/.npmrc 63 | (cd core && npm i && npm publish) 64 | (cd cli && npm i && npm publish) 65 | if: github.ref == 'master' 66 | 67 | - name: publish preview package 68 | env: 69 | NODE_AUTH_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }} 70 | run: | 71 | echo "//registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN" >> ~/.npmrc 72 | PACKAGE_VERSION=$(node -p -e "require('./core/package.json').version") 73 | CURRENT_TIME=$(date +%s) 74 | NEW_VERSION=${PACKAGE_VERSION}-build${CURRENT_TIME} 75 | (cd core && npm i && npm version $NEW_VERSION --no-git-tag-version && npm publish --tag next) 76 | (cd cli && npm i && npm i galenframework@next --E && npm version $NEW_VERSION && npm publish --tag next) 77 | if: github.ref == 'develop' 78 | -------------------------------------------------------------------------------- /core/README.MD: -------------------------------------------------------------------------------- 1 | # Galenframework Core 2 | 3 | [![License](https://img.shields.io/github/license/mashape/apistatus.svg)](LICENSE) [![npm version](https://badge.fury.io/js/galenframework.svg)](http://badge.fury.io/js/galenframework) 4 | [![Dependency Status](https://david-dm.org/hypery2k/galenframework.svg)](https://david-dm.org/hypery2k/galenframework) [![devDependency Status](https://david-dm.org/hypery2k/galenframework/dev-status.svg)](https://david-dm.org/hypery2k/galenframework#info=devDependencies)[![Coverage Status](https://coveralls.io/repos/hypery2k/galenframework/badge.svg?branch=master&service=github)](https://coveralls.io/github/hypery2k/galenframework?branch=master) 5 | 6 | [Galen](http://galenframework.com) allows automated testing of look and feel for your responsive websites. 7 | 8 | > Just the node wrapper for [Galen](http://galenframework.com). 9 | 10 | [![NPM](https://nodei.co/npm/galenframework.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/galenframework/) 11 | 12 | If you want to install Galen as CLI command install the [CLI-module](https://www.npmjs.com/package/galenframework-cli) 13 | 14 | 15 | > Feel free to **donate** 16 | > 17 | > Click here to lend your support to: NPM packages and make a donation at pledgie.com ! 18 | > 19 | > 20 | > 21 | > Or donate [Bitcoins](bitcoin:3NKtxw1SRYgess5ev4Ri54GekoAgkR213D): 22 | > [![Bitcoin](https://martinreinhardt-online.de/bitcoin.png)](bitcoin:3NKtxw1SRYgess5ev4Ri54GekoAgkR213D) 23 | > 24 | > Also via [greenaddress](https://greenaddress.it/pay/GA3ZPfh7As3Gc2oP6pQ1njxMij88u/) 25 | 26 | ## Installation 27 | 28 | You must have Java 6+ installed. 29 | 30 | > (sudo) npm install -g galenframework 31 | 32 | Or the develop build, which maybe **not be stable** 33 | 34 | > (sudo) npm install -g galenframework@next 35 | 36 | In case of errors within Ubuntu/Debian, e.g. 37 | ``` 38 | sh: 1: node: not find 39 | ``` 40 | 41 | Then you need to install nodejs-legacy: 42 | > (sudo) apt-get install nodejs-legacy 43 | 44 | 45 | ## Author 46 | 47 | [Martin Reinhardt](https://github.com/hypery2k) 48 | 49 | ![Martin Reinhardt](https://s.gravatar.com/avatar/9fa901119c90e051cd6a84ca26c99043?size=496&default=retro) 50 | 51 | Thanks for Obvious and their PhantomJS project for heavy inspiration! Check their project on [Github](https://github.com/Obvious/phantomjs). 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Galenframework commandline helpers 2 | 3 | [Galen](http://galenframework.com) allows automated testing of look and feel for your responsive websites. 4 | 5 | [![Build Status](https://travis-ci.org/hypery2k/galenframework-cli.svg?branch=master)](https://travis-ci.org/hypery2k/galenframework-cli) 6 | [![Build status](https://ci.appveyor.com/api/projects/status/fbwy88pc9ia6429w/branch/master?svg=true)](https://ci.appveyor.com/project/hypery2k/galenframework-cli/branch/master) 7 | [![License](https://img.shields.io/github/license/mashape/apistatus.svg)](LICENSE) 8 | [![Code Climate](https://codeclimate.com/github/hypery2k/galenframework-cli/badges/gpa.svg)](https://codeclimate.com/github/hypery2k/galenframework-cli) 9 | [![Coverage Status](https://coveralls.io/repos/github/hypery2k/galenframework-cli/badge.svg?branch=master)](https://coveralls.io/github/hypery2k/galenframework-cli?branch=master) 10 | 11 | The [core](core/) module is just the node wrapper (NodeJS 8+) for [Galen](http://galenframework.com) and can be used within CI environments 12 | 13 | [![Known Vulnerabilities](https://snyk.io/test/github/hypery2k/galenframework-cli/badge.svg?targetFile=core%2Fpackage.json)](https://snyk.io/test/github/hypery2k/galenframework-cli?targetFile=core%2Fpackage.json) 14 | 15 | The [cli](cli/) module is a command line module (NodeJS 8+) for [Galen](http://galenframework.com). This includes the core above and webdriver downloads for different browsers. You can also use the [docker image](https://hub.docker.com/r/galenframework/cli/) for easier setup. 16 | 17 | [![Known Vulnerabilities](https://snyk.io/test/github/hypery2k/galenframework-cli/badge.svg?targetFile=cli%2Fpackage.json)](https://snyk.io/test/github/hypery2k/galenframework-cli?targetFile=cli%2Fpackage.json) [![Docker Build Status](https://img.shields.io/docker/build/galenframework/cli.svg)](https://hub.docker.com/r/galenframework/cli/) 18 | 19 | ## Donation 20 | 21 | Feel free to [donate via Paypal](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H8TR8246RCDJG) or [Bitcoins ](bitcoin:3NKtxw1SRYgess5ev4Ri54GekoAgkR213D): bitcoin:3NKtxw1SRYgess5ev4Ri54GekoAgkR213D 22 | 23 | [![Bitcoin](https://martinreinhardt-online.de/assets/img/bitcoin.png)](bitcoin:3NKtxw1SRYgess5ev4Ri54GekoAgkR213D) 24 | Also via [greenaddress](https://greenaddress.it/pay/GA3ZPfh7As3Gc2oP6pQ1njxMij88u/) 25 | 26 | ## Docker 27 | 28 | ### Usage 29 | 30 | 31 | ``` 32 | docker run -v $(pwd)/galenframework-cli/core/test/:/var/test_scripts galenframework/cli galen test /var/test_scripts/... 33 | ``` 34 | 35 | ### Troubleshooting 36 | 37 | npm install throws "cannot access parent directories: Permission denied": 38 | ``` 39 | npm config set user 0 40 | npm config set unsafe-perm true 41 | ``` 42 | -------------------------------------------------------------------------------- /core/lib/helper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview Helpers made available via require('helper') once package is 3 | * installed. 4 | */ 5 | 6 | var fs = require('fs'), 7 | path = require('path'); 8 | 9 | 10 | /** 11 | * Where the phantom binary can be found. 12 | * @type {string} 13 | */ 14 | try { 15 | exports.path = path.resolve(__dirname, require('./location').location); 16 | } catch (e) { 17 | // Must be running inside install script. 18 | exports.path = null; 19 | } 20 | 21 | 22 | /** 23 | * The version of Galen installed by this package. 24 | * @type {number} 25 | */ 26 | exports.version = require('../package.json')._galenVersion; 27 | 28 | 29 | /** 30 | * Returns a clean path that helps avoid `which` finding bin files installed 31 | * by NPM for this repo. 32 | * @param {string} path 33 | * @return {string} 34 | */ 35 | exports.cleanPath = function (path) { 36 | 'use strict'; 37 | 38 | return path 39 | .replace(/:[^:]*node_modules[^:]*/g, '') 40 | .replace(/(^|:)\.\/bin(:|$)/g, ':') 41 | .replace(/^:+/, '') 42 | .replace(/:+$/, ''); 43 | }; 44 | 45 | 46 | // Make sure the binary is executable. For some reason doing this inside 47 | // install does not work correctly, likely due to some NPM step. 48 | if (exports.path) { 49 | try { 50 | // avoid touching the binary if it's already got the correct permissions 51 | var st = fs.statSync(exports.path); 52 | var mode = st.mode | 0555; // eslint-disable-line no-octal 53 | if (mode !== st.mode) { 54 | fs.chmodSync(exports.path, mode); 55 | } 56 | } catch (e) { 57 | // Just ignore error if we don't have permission. 58 | // We did our best. Likely because phantomjs was already installed. 59 | } 60 | } 61 | 62 | exports.galenPath = function () { 63 | return new Promise(function (resolve, reject) { 64 | 65 | var galenPath = path.resolve(__dirname + '/../node_modules/galenframework/bin/galen' + (process.platform === 'win32' ? '.cmd' : '')); 66 | fs.stat(galenPath, function (err) { 67 | // resolve for NPM3+ 68 | if (err) { 69 | galenPath = path.resolve(__dirname + '/../../galenframework/bin/galen' + (process.platform === 'win32' ? '.cmd' : '')); 70 | fs.stat(galenPath, function (err) { 71 | // resolve for NPM3+ 72 | if (err) { 73 | reject('Cannot find Galenframework at ' + galenPath); 74 | } else { 75 | resolve(galenPath); 76 | } 77 | }); 78 | } else { 79 | resolve(galenPath); 80 | } 81 | }); 82 | }); 83 | } -------------------------------------------------------------------------------- /cli/README.MD: -------------------------------------------------------------------------------- 1 | # Galenframework CLI 2 | 3 | [![License](https://img.shields.io/github/license/mashape/apistatus.svg)](LICENSE) 4 | [![npm version](https://badge.fury.io/js/galenframework-cli.svg)](http://badge.fury.io/js/galenframework-cli) 5 | [![Dependency Status](https://david-dm.org/hypery2k/galenframework-cli.svg)](https://david-dm.org/hypery2k/galenframework-cli) [![devDependency Status](https://david-dm.org/hypery2k/galenframework-cli/dev-status.svg)](https://david-dm.org/hypery2k/galenframework-cli#info=devDependencies) 6 | [![Coverage Status](https://coveralls.io/repos/hypery2k/galenframework-cli/badge.svg?branch=master&service=github)](https://coveralls.io/github/hypery2k/galenframework-cli?branch=master) 7 | 8 | 9 | [Galen](http://galenframework.com) allows automated testing of look and feel for your responsive websites. 10 | 11 | > The command line tool to use [Galen](http://galenframework.com). This includes the wrapper above and webdriver downloads for different browsers 12 | [![NPM](https://nodei.co/npm/galenframework-cli.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/galenframework-cli/) 13 | 14 | > Feel free to **donate** 15 | > 16 | > Click here to lend your support to: NPM packages and make a donation at pledgie.com ! 17 | > 18 | > 19 | > 20 | > Or donate [Bitcoins](bitcoin:3NKtxw1SRYgess5ev4Ri54GekoAgkR213D): 21 | > [![Bitcoin](https://martinreinhardt-online.de/bitcoin.png)](bitcoin:3NKtxw1SRYgess5ev4Ri54GekoAgkR213D) 22 | > 23 | > Also via [greenaddress](https://greenaddress.it/pay/GA3ZPfh7As3Gc2oP6pQ1njxMij88u/) 24 | 25 | 26 | ## Installation 27 | 28 | You must have Java 6+ installed. 29 | 30 | > (sudo) npm install -g galenframework-cli 31 | 32 | Or the develop build, which maybe **not be stable** 33 | 34 | > (sudo) npm install -g galenframework-cli@next 35 | 36 | If you want to enable tab completion on Linux, run 37 | 38 | > galen completion >> ~/.~/.bashrc 39 | or 40 | > galen completion >> ~/.~/.zshrc 41 | 42 | On Mac OS X, run 43 | > galen completion >> ~/.~/.profile 44 | 45 | In case of errors within Ubuntu/Debian, e.g. 46 | ``` 47 | sh: 1: node: not find 48 | ``` 49 | 50 | Then you need to install nodejs-legacy: 51 | > (sudo) apt-get install nodejs-legacy 52 | 53 | ## Advanced Usage 54 | 55 | ### Debugging 56 | 57 | If you need to debug the tests use the node-inspector: 58 | ``` 59 | NODE_DEBUG=galen node --debug-brk node_modules/galenframework-cli/bin/galen 60 | node-inspector --web-port=8282 61 | ``` 62 | 63 | You can then open chrome at *http://127.0.0.1:8282/?port=5858* for debugging. 64 | 65 | If you want to have verbose logging add NODE_DEBUG=galen: 66 | 67 | ``` 68 | NODE_DEBUG=galen node --debug-brk node_modules/galenframework-cli/bin/galen 69 | ``` 70 | 71 | ## Author 72 | 73 | [Martin Reinhardt](https://github.com/hypery2k) 74 | 75 | ![Martin Reinhardt](https://s.gravatar.com/avatar/9fa901119c90e051cd6a84ca26c99043?size=496&default=retro) 76 | 77 | Thanks for Obvious and their PhantomJS project for heavy inspiration! Check their project on [Github](https://github.com/Obvious/phantomjs). 78 | -------------------------------------------------------------------------------- /cli/test/config: -------------------------------------------------------------------------------- 1 | 2 | # Range approximation 3 | # ~~~~~~~~~~~~~~~~~~~~~ 4 | # Defines the approximation value for ranges when using "~" in galen page specs 5 | # This value means how many pixels or percents should it take constructing a range 6 | # e.g. if we define approximation as 5 then the following spec: 7 | # height: ~ 50 px 8 | # will actually be replaced by Galen with this: 9 | # height: 45 to 55px 10 | galen.range.approximation=3 11 | 12 | 13 | # Custom Listeners 14 | # ~~~~~~~~~~~~~~~~~~~~~~~ 15 | # A comma separated list of class paths to reporting listeners 16 | # The defined listeners will be picked up by Galen and used for reporting 17 | # 18 | # galen.reporting.listeners= 19 | 20 | 21 | # Using page urls from last checked page in HTML report 22 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23 | # This property enables the use of last page url in a page test 24 | # Needed when for some pages on the website there is no way to open it by direct url 25 | # galen.reporting.html.useLastPageUrls = true 26 | 27 | # Default browser 28 | # ~~~~~~~~~~~~~~~~~~~~~~~~ 29 | # A browser that should be used by default in case it was not specified in galen test 30 | galen.default.browser=firefox 31 | 32 | 33 | 34 | # Color scheme spec precision 35 | # ~~~~~~~~~~~~~~~~~~~~~~~~ 36 | # A value between 8 and 256 for color spectrum accuracy. 37 | spec.colorscheme.precision = 256 38 | 39 | 40 | # Full screenshots 41 | # ~~~~~~~~~~~~~~~~~~~~ 42 | # In some browsers it is not possible to create a complete screenshot of whole page. 43 | # With this property enabled Galen will scroll page and make screenshots of parts of it. 44 | # Then it will assemble it in a one big screenshot 45 | # 46 | galen.browser.screenshots.fullPage = false 47 | # the following parameter is need in case the upper parameter is set to true 48 | # it sets the amount of time in milliseconds needed for a check that the page was scrolled when taking full page screenshots 49 | galen.browser.screenshots.fullPage.scrollWait = 0 50 | 51 | 52 | 53 | # Color scheme spec test color range 54 | # ~~~~~~~~~~~~~~~~~~~~~~~~~ 55 | # A value between 0 and 256 which defined the range of nearby colors 56 | # in spectrum which will be picked up for calculating the percentage of usage 57 | spec.colorscheme.testrange = 6 58 | 59 | 60 | 61 | # Running in Selenium Grid 62 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 63 | # You can run your tests in Selenium Grid without modifying the tests. 64 | # Just enable the "galen.browserFactory.selenium.runInGrid" property 65 | # and Galen will always choose a Selenium Grid instead of running tests against local browsers 66 | # Also make sure you provide the proper url to grid 67 | # 68 | # galen.browserFactory.selenium.runInGrid = true 69 | # galen.browserFactory.selenium.grid.url = http://localhost:4444/wd/hub 70 | # galen.browserFactory.selenium.grid.browser = 71 | # galen.browserFactory.selenium.grid.browserVersion = 72 | # galen.browserFactory.selenium.grid.platform = 73 | 74 | 75 | # Exit with fail code in case of any failures 76 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 77 | # galen.use.fail.exit.code = true 78 | 79 | 80 | # Test file extension for standard test runner 81 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 82 | galen.test.suffix=.test 83 | 84 | 85 | # JavaScript Test file extension for JavaScript test runner 86 | # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 87 | galen.test.js.file.suffix=.test.js 88 | -------------------------------------------------------------------------------- /cli/bin/galen: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var util = require('util'), 4 | yargs = require('yargs'); 5 | 6 | var DEBUG_ENV = 'galen'; 7 | 8 | var debugLog = util.debuglog(DEBUG_ENV); 9 | 10 | // basic bash completion 11 | yargs 12 | .usage('Galen Framework is an open-source tool for testing layout and responsive design of web applications.\n\nUsage: $0 [options]') 13 | .completion('completion', function (current, argv) { 14 | var args = argv, 15 | result = [ 16 | 'test', 17 | 'check', 18 | 'dump', 19 | 'config', 20 | 'help', 21 | 'version' 22 | ]; 23 | // 'current' is the current command being completed. 24 | // 'argv' is the parsed arguments so far. 25 | // simply return an array of completions. 26 | if (current) { 27 | var currentCommand = current; 28 | argv = []; 29 | switch (current) { 30 | case 'test': 31 | result = [ 32 | '.gspec', 33 | '--htmlreport', 34 | '--testngreport', 35 | '--jsonreport', 36 | '--filter', 37 | '--parallel-tests', 38 | '--config' 39 | ]; 40 | break; 41 | case 'check': 42 | result = [ 43 | '.test', 44 | '--url', 45 | '--size', 46 | '--javascript', 47 | '--include', 48 | '--exclude', 49 | '--htmlreport', 50 | '--testngreport', 51 | '--jsonreport', 52 | '--config' 53 | ]; 54 | break; 55 | case 'dump': 56 | result = [ 57 | '.gspec', 58 | '--url', 59 | '--size', 60 | '--export', 61 | '--max-width', 62 | '--max-height', 63 | '--config' 64 | ]; 65 | break; 66 | } 67 | } 68 | return result; 69 | }).argv; 70 | 71 | 72 | var spawn = require('child_process').spawn; 73 | var path = require('path'); 74 | var baseDir = path.dirname(require.main.filename); 75 | var childProcessOptions = { 76 | stdio: 'inherit' 77 | }; 78 | 79 | // remove node args 80 | var args = process.argv.slice(2); 81 | 82 | function resolveModulePath(moduleName) { 83 | var pathItems = [].slice.call(arguments, 1); 84 | pathItems.unshift(path.dirname(require.resolve(moduleName))); 85 | 86 | return path.resolve.apply(null, pathItems); 87 | } 88 | 89 | // adding chromedriver 90 | var chromePath = resolveModulePath('chromedriver', 'chromedriver/chromedriver'); 91 | if (process.platform === 'win32') { 92 | chromePath += '.exe'; 93 | } 94 | args.push('-Dwebdriver.chrome.driver=' + chromePath); 95 | 96 | // adding geckodriver 97 | var geckoPath = resolveModulePath('geckodriver', '..', 'geckodriver'); 98 | if (process.platform === 'win32') { 99 | geckoPath += '.exe'; 100 | } 101 | args.push('-Dwebdriver.gecko.driver=' + geckoPath); 102 | 103 | var programPath = resolveModulePath('galenframework', 'lib/galen/galen'); 104 | if (process.platform === 'win32') { 105 | programPath += '.bat'; 106 | } 107 | 108 | debugLog('Using following programPath:', programPath); 109 | debugLog(' -> args:', args); 110 | debugLog(' -> childProcessOptions:', childProcessOptions); 111 | var galenProcess = spawn(programPath, args, childProcessOptions); 112 | 113 | galenProcess.on('error', function (error) { 114 | console.error(error); 115 | process.exit(1); 116 | }); 117 | 118 | galenProcess.on('exit', function (exitCode) { 119 | process.exit(exitCode); 120 | }); 121 | -------------------------------------------------------------------------------- /cli/postinstall.js: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Martin Reinhardt 2 | 3 | // This simply downloads Galen 4 | 5 | 'use strict'; 6 | 7 | const cp = require('child_process'); 8 | const fs = require('fs-extra'); 9 | const helper = require('galenframework/lib/helper'); 10 | const kew = require('kew'); 11 | const npmconf = require('npmconf'); 12 | const path = require('path'); 13 | const httpreq = require('httpreq'); 14 | const which = require('which'); 15 | const npmWhich = require('npm-which')(process.cwd()); 16 | const log = require('npmlog'); 17 | 18 | const originalPath = process.env.PATH; 19 | 20 | // If the process exits without going through exit(), then we did not complete. 21 | let validExit = false; 22 | 23 | process.on('exit', function () { 24 | if (!validExit) { 25 | log.info('Install exited unexpectedly'); 26 | exit(1); 27 | } 28 | }); 29 | 30 | // NPM adds bin directories to the path, which will cause `which` to find the 31 | // bin for this package not the actual galenframework-cli bin. Also help out people who 32 | // put ./bin on their path 33 | process.env.PATH = helper.cleanPath(originalPath); 34 | 35 | // If the user manually installed galen, we want 36 | // to use the existing version. 37 | // 38 | // Do not re-use a manually-installed galen with 39 | // a different version. 40 | // 41 | // Do not re-use an npm-installed galen, because 42 | // that can lead to weird circular dependencies between 43 | // local versions and global versions. 44 | const whichDeferred = kew.defer(); 45 | which('galen', whichDeferred.makeNodeResolver()); 46 | whichDeferred.promise 47 | .then((result) => installAdditionalDrivers(result)) 48 | .fail(() => npmWhich('galen', (err, result) => { 49 | if (err) { 50 | log.error('Galen installation failed', err, err.stack); 51 | exit(1); 52 | } else { 53 | return installAdditionalDrivers(result); 54 | } 55 | })); 56 | 57 | function installAdditionalDrivers(galenPath) { 58 | const defer = kew.defer(); 59 | defer.resolve(); 60 | defer.promise.then(() => { 61 | // Horrible hack to avoid problems during global install. We check to see if 62 | // the file `which` found is our own bin script. 63 | if (galenPath.indexOf(path.join('npm', 'galenframework-cli')) !== -1) { 64 | log.info('Looks like an `npm install -g` on windows; unable to check for already installed version.'); 65 | throw new Error('Global install'); 66 | } 67 | const contents = fs.readFileSync(galenPath, 'utf8'); 68 | if ((/NPM_INSTALL_MARKER/).test(contents)) { 69 | log.info('Looks like an `npm install -g`; unable to check for already installed version.'); 70 | throw new Error('Global install'); 71 | } else { 72 | var checkVersionDeferred = kew.defer(); 73 | cp.execFile(galenPath, ['--version'], checkVersionDeferred.makeNodeResolver()); 74 | 75 | return checkVersionDeferred.promise; 76 | } 77 | }).then(() => { 78 | log.info('galenframework-cli detected'); 79 | const npmconfDeferred = kew.defer(); 80 | npmconf.load(npmconfDeferred.makeNodeResolver()); 81 | 82 | return npmconfDeferred.promise; 83 | }) 84 | .then(() => { 85 | exit(0); 86 | }) 87 | } 88 | 89 | function exit(code) { 90 | validExit = true; 91 | process.env.PATH = originalPath; 92 | process.exit(code || 0); 93 | } 94 | 95 | 96 | if (process.platform === 'darwin') { 97 | console.info('\n\nTo \x1b[4menable CLI tab autocompletion\x1b[0m run: \n' + 98 | ' \x1b[7mgalen completion >> ~/.profile\x1b[0m ' + 99 | '\n\n'); 100 | } 101 | if (process.platform === 'linux') { 102 | console.info('\n\nTo \x1b[4menable CLI tab autocompletion\x1b[0m run: \n' + 103 | ' \x1b[7mgalen completion >> ~/.bashrc\x1b[0m \n' + 104 | 'or\n' + 105 | ' \x1b[7mgalen completion >> .~/.zshrc\x1b[0m ' + 106 | '\n\n'); 107 | } 108 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:16.04 2 | ENV SUMMARY="galne-runtime" 3 | ENV DESCRIPTION="Application runtime for Galenframework" 4 | ENV AUTHOR="Martin Reinhardt /etc/apt/sources.list && \ 27 | echo "deb http://archive.ubuntu.com/ubuntu xenial-updates main universe\n" >> /etc/apt/sources.list && \ 28 | echo "deb http://security.ubuntu.com/ubuntu xenial-security main universe\n" >> /etc/apt/sources.list 29 | 30 | # No interactive frontend during docker build 31 | ENV DEBIAN_FRONTEND=noninteractive \ 32 | DEBCONF_NONINTERACTIVE_SEEN=true 33 | 34 | #======================== 35 | # Miscellaneous packages 36 | # Includes minimal runtime used for executing non GUI Java programs 37 | #======================== 38 | RUN apt-get -qqy update \ 39 | && apt-get -qqy --no-install-recommends install \ 40 | bzip2 \ 41 | ca-certificates \ 42 | openjdk-8-jre-headless \ 43 | tzdata \ 44 | sudo \ 45 | unzip \ 46 | curl \ 47 | wget \ 48 | && rm -rf /var/lib/apt/lists/* /var/cache/apt/* \ 49 | && sed -i 's/securerandom\.source=file:\/dev\/random/securerandom\.source=file:\/dev\/urandom/' ./usr/lib/jvm/java-8-openjdk-amd64/jre/lib/security/java.security 50 | 51 | ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64/ 52 | 53 | #=================== 54 | # Timezone settings 55 | # Possible alternative: https://github.com/docker/docker/issues/3359#issuecomment-32150214 56 | #=================== 57 | ENV TZ "UTC" 58 | RUN echo "${TZ}" > /etc/timezone \ 59 | && dpkg-reconfigure --frontend noninteractive tzdata 60 | 61 | #======================================== 62 | # Add normal user with passwordless sudo 63 | #======================================== 64 | RUN useradd galen \ 65 | --shell /bin/bash \ 66 | --create-home \ 67 | && usermod -a -G sudo galen \ 68 | && echo 'ALL ALL = (ALL) NOPASSWD: ALL' >> /etc/sudoers \ 69 | && echo 'galen:secret' | chpasswd 70 | 71 | #=================================================== 72 | # Install xvfb 73 | #=================================================== 74 | RUN set -x && apt-get update && apt-get install -y xvfb 75 | 76 | #=================================================== 77 | # Install Chrome 78 | #=================================================== 79 | 80 | RUN echo 'deb http://dl.google.com/linux/chrome/deb/ stable main' > /etc/apt/sources.list.d/chrome.list && \ 81 | wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \ 82 | set -x && apt-get update && apt-get install -y google-chrome-stable 83 | 84 | ADD scripts/xvfb-chrome /usr/bin/xvfb-chrome 85 | RUN ln -sf /usr/bin/xvfb-chrome /usr/bin/google-chrome 86 | 87 | #=================================================== 88 | # Install firefox 89 | #=================================================== 90 | 91 | RUN set -x && apt-get update && apt-get install -y firefox 92 | 93 | ADD scripts/xvfb-firefox /usr/bin/xvfb-firefox 94 | RUN ln -sf /usr/bin/xvfb-firefox /usr/bin/firefox 95 | 96 | #=================================================== 97 | # This is needed for PhantomJS 98 | #=================================================== 99 | 100 | RUN set -x && apt-get update && apt-get install -y bzip2 zip 101 | 102 | # clean up 103 | RUN apt-get autoremove -y && rm -rf /var/lib/apt/lists/ 104 | 105 | #=================================================== 106 | # Run the following commands as non-privileged user 107 | #=================================================== 108 | USER galen 109 | 110 | #=================================================== 111 | # Install nvm with node and npm 112 | #=================================================== 113 | RUN curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash && \ 114 | . $NVM_DIR/nvm.sh && \ 115 | nvm install $NODE_VERSION && nvm alias default $NODE_VERSION && nvm use default && \ 116 | npm install -g galenframework-cli@$GALEN_VERSION 117 | 118 | VOLUME /var/test_scripts 119 | 120 | ADD ./etc/entrypoint.sh /entrypoint.sh 121 | ENTRYPOINT ["/entrypoint.sh"] 122 | -------------------------------------------------------------------------------- /cli/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "node": true, 4 | "es6": true 5 | }, 6 | "extends": "eslint:recommended", 7 | "parserOptions": { 8 | "ecmaVersion": 6 9 | }, 10 | "rules": { 11 | "accessor-pairs": "error", 12 | "array-bracket-newline": "error", 13 | "array-bracket-spacing": "error", 14 | "array-callback-return": "error", 15 | "array-element-newline": "error", 16 | "arrow-body-style": "error", 17 | "arrow-parens": "error", 18 | "arrow-spacing": "error", 19 | "block-scoped-var": "error", 20 | "block-spacing": "error", 21 | "brace-style": [ 22 | "error", 23 | "1tbs" 24 | ], 25 | "callback-return": "error", 26 | "camelcase": "error", 27 | "capitalized-comments": "off", 28 | "class-methods-use-this": "error", 29 | "comma-dangle": "error", 30 | "comma-spacing": [ 31 | "error", 32 | { 33 | "after": true, 34 | "before": false 35 | } 36 | ], 37 | "comma-style": [ 38 | "error", 39 | "last" 40 | ], 41 | "complexity": "error", 42 | "computed-property-spacing": "error", 43 | "consistent-return": "error", 44 | "consistent-this": "error", 45 | "curly": "error", 46 | "default-case": "error", 47 | "dot-location": [ 48 | "error", 49 | "property" 50 | ], 51 | "dot-notation": "error", 52 | "eol-last": "off", 53 | "eqeqeq": "error", 54 | "func-call-spacing": "error", 55 | "func-name-matching": "error", 56 | "func-names": [ 57 | "error", 58 | "never" 59 | ], 60 | "func-style": "error", 61 | "function-paren-newline": "error", 62 | "generator-star-spacing": "error", 63 | "global-require": "off", 64 | "guard-for-in": "error", 65 | "handle-callback-err": "error", 66 | "id-blacklist": "error", 67 | "id-length": "off", 68 | "id-match": "error", 69 | "implicit-arrow-linebreak": "error", 70 | "indent": "off", 71 | "indent-legacy": "off", 72 | "init-declarations": "error", 73 | "jsx-quotes": "error", 74 | "key-spacing": "error", 75 | "keyword-spacing": [ 76 | "error", 77 | { 78 | "after": true, 79 | "before": true 80 | } 81 | ], 82 | "line-comment-position": "error", 83 | "linebreak-style": [ 84 | "error", 85 | "unix" 86 | ], 87 | "lines-around-comment": "error", 88 | "lines-around-directive": "error", 89 | "lines-between-class-members": "error", 90 | "max-classes-per-file": "error", 91 | "max-depth": "error", 92 | "max-len": "off", 93 | "max-lines": "error", 94 | "max-lines-per-function": "error", 95 | "max-nested-callbacks": "error", 96 | "max-params": "error", 97 | "max-statements": "error", 98 | "max-statements-per-line": "error", 99 | "multiline-comment-style": [ 100 | "error", 101 | "separate-lines" 102 | ], 103 | "new-cap": "error", 104 | "new-parens": "error", 105 | "newline-after-var": "off", 106 | "newline-before-return": "error", 107 | "newline-per-chained-call": "error", 108 | "no-alert": "error", 109 | "no-array-constructor": "error", 110 | "no-async-promise-executor": "error", 111 | "no-await-in-loop": "error", 112 | "no-bitwise": "off", 113 | "no-buffer-constructor": "error", 114 | "no-caller": "error", 115 | "no-catch-shadow": "error", 116 | "no-confusing-arrow": "error", 117 | "no-continue": "error", 118 | "no-div-regex": "error", 119 | "no-duplicate-imports": "error", 120 | "no-else-return": "error", 121 | "no-empty-function": "error", 122 | "no-eq-null": "error", 123 | "no-eval": "error", 124 | "no-extend-native": "error", 125 | "no-extra-bind": "error", 126 | "no-extra-label": "error", 127 | "no-extra-parens": "error", 128 | "no-floating-decimal": "error", 129 | "no-implicit-coercion": "error", 130 | "no-implicit-globals": "off", 131 | "no-implied-eval": "error", 132 | "no-inline-comments": "off", 133 | "no-inner-declarations": [ 134 | "error", 135 | "functions" 136 | ], 137 | "no-invalid-this": "error", 138 | "no-iterator": "error", 139 | "no-label-var": "error", 140 | "no-labels": "error", 141 | "no-lone-blocks": "error", 142 | "no-lonely-if": "error", 143 | "no-loop-func": "error", 144 | "no-magic-numbers": "off", 145 | "no-misleading-character-class": "error", 146 | "no-mixed-operators": "error", 147 | "no-mixed-requires": "error", 148 | "no-multi-assign": "error", 149 | "no-multi-spaces": "error", 150 | "no-multi-str": "error", 151 | "no-multiple-empty-lines": "error", 152 | "no-native-reassign": "error", 153 | "no-negated-condition": "error", 154 | "no-negated-in-lhs": "error", 155 | "no-nested-ternary": "error", 156 | "no-new": "error", 157 | "no-new-func": "error", 158 | "no-new-object": "error", 159 | "no-new-require": "error", 160 | "no-new-wrappers": "error", 161 | "no-octal-escape": "error", 162 | "no-param-reassign": "error", 163 | "no-path-concat": "off", 164 | "no-plusplus": "error", 165 | "no-process-env": "off", 166 | "no-process-exit": "error", 167 | "no-proto": "error", 168 | "no-prototype-builtins": "error", 169 | "no-restricted-globals": "error", 170 | "no-restricted-imports": "error", 171 | "no-restricted-modules": "error", 172 | "no-restricted-properties": "error", 173 | "no-restricted-syntax": "error", 174 | "no-return-assign": "error", 175 | "no-return-await": "error", 176 | "no-script-url": "error", 177 | "no-self-compare": "error", 178 | "no-sequences": "error", 179 | "no-shadow": "off", 180 | "no-shadow-restricted-names": "error", 181 | "no-spaced-func": "error", 182 | "no-sync": [ 183 | "off", 184 | { 185 | "allowAtRootLevel": true 186 | } 187 | ], 188 | "no-tabs": "error", 189 | "no-template-curly-in-string": "error", 190 | "no-ternary": "off", 191 | "no-throw-literal": "error", 192 | "no-trailing-spaces": "error", 193 | "no-undef-init": "error", 194 | "no-undefined": "error", 195 | "no-underscore-dangle": "off", 196 | "no-unmodified-loop-condition": "error", 197 | "no-unneeded-ternary": "error", 198 | "no-unused-expressions": "error", 199 | "no-use-before-define": "error", 200 | "no-useless-call": "error", 201 | "no-useless-computed-key": "error", 202 | "no-useless-concat": "error", 203 | "no-useless-constructor": "error", 204 | "no-useless-rename": "error", 205 | "no-useless-return": "error", 206 | "no-var": "off", 207 | "no-void": "error", 208 | "no-warning-comments": "error", 209 | "no-whitespace-before-property": "error", 210 | "no-with": "error", 211 | "nonblock-statement-body-position": "error", 212 | "object-curly-newline": "error", 213 | "object-curly-spacing": "error", 214 | "object-property-newline": "error", 215 | "object-shorthand": "error", 216 | "one-var": "off", 217 | "one-var-declaration-per-line": "error", 218 | "operator-assignment": "error", 219 | "operator-linebreak": "error", 220 | "padded-blocks": "off", 221 | "padding-line-between-statements": "error", 222 | "prefer-arrow-callback": "off", 223 | "prefer-const": "error", 224 | "prefer-destructuring": "error", 225 | "prefer-numeric-literals": "error", 226 | "prefer-object-spread": "error", 227 | "prefer-promise-reject-errors": "off", 228 | "prefer-reflect": "error", 229 | "prefer-rest-params": "error", 230 | "prefer-spread": "error", 231 | "prefer-template": "off", 232 | "quote-props": "error", 233 | "quotes": [ 234 | "error", 235 | "single" 236 | ], 237 | "radix": "error", 238 | "require-atomic-updates": "error", 239 | "require-await": "error", 240 | "require-jsdoc": "error", 241 | "require-unicode-regexp": "off", 242 | "rest-spread-spacing": "error", 243 | "semi": "off", 244 | "semi-spacing": "error", 245 | "semi-style": [ 246 | "error", 247 | "last" 248 | ], 249 | "sort-imports": "error", 250 | "sort-keys": "error", 251 | "sort-vars": "error", 252 | "space-before-blocks": "error", 253 | "space-before-function-paren": "off", 254 | "space-in-parens": [ 255 | "error", 256 | "never" 257 | ], 258 | "space-infix-ops": "error", 259 | "space-unary-ops": "error", 260 | "spaced-comment": [ 261 | "error", 262 | "always" 263 | ], 264 | "strict": "off", 265 | "switch-colon-spacing": "error", 266 | "symbol-description": "error", 267 | "template-curly-spacing": "error", 268 | "template-tag-spacing": "error", 269 | "unicode-bom": [ 270 | "error", 271 | "never" 272 | ], 273 | "valid-jsdoc": "off", 274 | "vars-on-top": "off", 275 | "wrap-iife": "error", 276 | "wrap-regex": "error", 277 | "yield-star-spacing": "error", 278 | "yoda": [ 279 | "error", 280 | "never" 281 | ] 282 | } 283 | }; -------------------------------------------------------------------------------- /core/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | "env": { 3 | "node": true, 4 | "es6": true 5 | }, 6 | "extends": "eslint:recommended", 7 | "parserOptions": { 8 | "ecmaVersion": 6 9 | }, 10 | "rules": { 11 | "accessor-pairs": "error", 12 | "array-bracket-newline": "error", 13 | "array-bracket-spacing": "error", 14 | "array-callback-return": "error", 15 | "array-element-newline": "error", 16 | "arrow-body-style": "error", 17 | "arrow-parens": "error", 18 | "arrow-spacing": "error", 19 | "block-scoped-var": "error", 20 | "block-spacing": "error", 21 | "brace-style": [ 22 | "error", 23 | "1tbs" 24 | ], 25 | "callback-return": "error", 26 | "camelcase": "error", 27 | "capitalized-comments": "off", 28 | "class-methods-use-this": "error", 29 | "comma-dangle": "error", 30 | "comma-spacing": [ 31 | "error", 32 | { 33 | "after": true, 34 | "before": false 35 | } 36 | ], 37 | "comma-style": [ 38 | "error", 39 | "last" 40 | ], 41 | "complexity": "error", 42 | "computed-property-spacing": "error", 43 | "consistent-return": "error", 44 | "consistent-this": "error", 45 | "curly": "error", 46 | "default-case": "error", 47 | "dot-location": [ 48 | "error", 49 | "property" 50 | ], 51 | "dot-notation": "error", 52 | "eol-last": "off", 53 | "eqeqeq": "error", 54 | "func-call-spacing": "error", 55 | "func-name-matching": "error", 56 | "func-names": [ 57 | "error", 58 | "never" 59 | ], 60 | "func-style": "error", 61 | "function-paren-newline": "error", 62 | "generator-star-spacing": "error", 63 | "global-require": "off", 64 | "guard-for-in": "error", 65 | "handle-callback-err": "error", 66 | "id-blacklist": "error", 67 | "id-length": "off", 68 | "id-match": "error", 69 | "implicit-arrow-linebreak": "error", 70 | "indent": "off", 71 | "indent-legacy": "off", 72 | "init-declarations": "error", 73 | "jsx-quotes": "error", 74 | "key-spacing": "error", 75 | "keyword-spacing": [ 76 | "error", 77 | { 78 | "after": true, 79 | "before": true 80 | } 81 | ], 82 | "line-comment-position": "error", 83 | "linebreak-style": [ 84 | "error", 85 | "unix" 86 | ], 87 | "lines-around-comment": "error", 88 | "lines-around-directive": "error", 89 | "lines-between-class-members": "error", 90 | "max-classes-per-file": "error", 91 | "max-depth": "error", 92 | "max-len": "off", 93 | "max-lines": "error", 94 | "max-lines-per-function": "error", 95 | "max-nested-callbacks": "error", 96 | "max-params": "error", 97 | "max-statements": "error", 98 | "max-statements-per-line": "error", 99 | "multiline-comment-style": [ 100 | "error", 101 | "separate-lines" 102 | ], 103 | "new-cap": "error", 104 | "new-parens": "error", 105 | "newline-after-var": "off", 106 | "newline-before-return": "error", 107 | "newline-per-chained-call": "error", 108 | "no-alert": "error", 109 | "no-array-constructor": "error", 110 | "no-async-promise-executor": "error", 111 | "no-await-in-loop": "error", 112 | "no-bitwise": "off", 113 | "no-buffer-constructor": "error", 114 | "no-caller": "error", 115 | "no-catch-shadow": "error", 116 | "no-confusing-arrow": "error", 117 | "no-continue": "error", 118 | "no-div-regex": "error", 119 | "no-duplicate-imports": "error", 120 | "no-else-return": "error", 121 | "no-empty-function": "error", 122 | "no-eq-null": "error", 123 | "no-eval": "error", 124 | "no-extend-native": "error", 125 | "no-extra-bind": "error", 126 | "no-extra-label": "error", 127 | "no-extra-parens": "error", 128 | "no-floating-decimal": "error", 129 | "no-implicit-coercion": "error", 130 | "no-implicit-globals": "off", 131 | "no-implied-eval": "error", 132 | "no-inline-comments": "off", 133 | "no-inner-declarations": [ 134 | "error", 135 | "functions" 136 | ], 137 | "no-invalid-this": "error", 138 | "no-iterator": "error", 139 | "no-label-var": "error", 140 | "no-labels": "error", 141 | "no-lone-blocks": "error", 142 | "no-lonely-if": "error", 143 | "no-loop-func": "error", 144 | "no-magic-numbers": "off", 145 | "no-misleading-character-class": "error", 146 | "no-mixed-operators": "error", 147 | "no-mixed-requires": "error", 148 | "no-multi-assign": "error", 149 | "no-multi-spaces": "error", 150 | "no-multi-str": "error", 151 | "no-multiple-empty-lines": "error", 152 | "no-native-reassign": "error", 153 | "no-negated-condition": "error", 154 | "no-negated-in-lhs": "error", 155 | "no-nested-ternary": "error", 156 | "no-new": "error", 157 | "no-new-func": "error", 158 | "no-new-object": "error", 159 | "no-new-require": "error", 160 | "no-new-wrappers": "error", 161 | "no-octal-escape": "error", 162 | "no-param-reassign": "error", 163 | "no-path-concat": "off", 164 | "no-plusplus": "error", 165 | "no-process-env": "off", 166 | "no-process-exit": "error", 167 | "no-proto": "error", 168 | "no-prototype-builtins": "error", 169 | "no-restricted-globals": "error", 170 | "no-restricted-imports": "error", 171 | "no-restricted-modules": "error", 172 | "no-restricted-properties": "error", 173 | "no-restricted-syntax": "error", 174 | "no-return-assign": "error", 175 | "no-return-await": "error", 176 | "no-script-url": "error", 177 | "no-self-compare": "error", 178 | "no-sequences": "error", 179 | "no-shadow": "off", 180 | "no-shadow-restricted-names": "error", 181 | "no-spaced-func": "error", 182 | "no-sync": [ 183 | "off", 184 | { 185 | "allowAtRootLevel": true 186 | } 187 | ], 188 | "no-tabs": "error", 189 | "no-template-curly-in-string": "error", 190 | "no-ternary": "off", 191 | "no-throw-literal": "error", 192 | "no-trailing-spaces": "error", 193 | "no-undef-init": "error", 194 | "no-undefined": "error", 195 | "no-underscore-dangle": "off", 196 | "no-unmodified-loop-condition": "error", 197 | "no-unneeded-ternary": "error", 198 | "no-unused-expressions": "error", 199 | "no-use-before-define": "error", 200 | "no-useless-call": "error", 201 | "no-useless-computed-key": "error", 202 | "no-useless-concat": "error", 203 | "no-useless-constructor": "error", 204 | "no-useless-rename": "error", 205 | "no-useless-return": "error", 206 | "no-var": "off", 207 | "no-void": "error", 208 | "no-warning-comments": "error", 209 | "no-whitespace-before-property": "error", 210 | "no-with": "error", 211 | "nonblock-statement-body-position": "error", 212 | "object-curly-newline": "error", 213 | "object-curly-spacing": "error", 214 | "object-property-newline": "error", 215 | "object-shorthand": "error", 216 | "one-var": "off", 217 | "one-var-declaration-per-line": "error", 218 | "operator-assignment": "error", 219 | "operator-linebreak": "error", 220 | "padded-blocks": "off", 221 | "padding-line-between-statements": "error", 222 | "prefer-arrow-callback": "off", 223 | "prefer-const": "error", 224 | "prefer-destructuring": "error", 225 | "prefer-numeric-literals": "error", 226 | "prefer-object-spread": "error", 227 | "prefer-promise-reject-errors": "off", 228 | "prefer-reflect": "error", 229 | "prefer-rest-params": "error", 230 | "prefer-spread": "error", 231 | "prefer-template": "off", 232 | "quote-props": "error", 233 | "quotes": [ 234 | "error", 235 | "single" 236 | ], 237 | "radix": "error", 238 | "require-atomic-updates": "error", 239 | "require-await": "error", 240 | "require-jsdoc": "error", 241 | "require-unicode-regexp": "off", 242 | "rest-spread-spacing": "error", 243 | "semi": "off", 244 | "semi-spacing": "error", 245 | "semi-style": [ 246 | "error", 247 | "last" 248 | ], 249 | "sort-imports": "error", 250 | "sort-keys": "error", 251 | "sort-vars": "error", 252 | "space-before-blocks": "error", 253 | "space-before-function-paren": "off", 254 | "space-in-parens": [ 255 | "error", 256 | "never" 257 | ], 258 | "space-infix-ops": "error", 259 | "space-unary-ops": "error", 260 | "spaced-comment": [ 261 | "error", 262 | "always" 263 | ], 264 | "strict": "off", 265 | "switch-colon-spacing": "error", 266 | "symbol-description": "error", 267 | "template-curly-spacing": "error", 268 | "template-tag-spacing": "error", 269 | "unicode-bom": [ 270 | "error", 271 | "never" 272 | ], 273 | "valid-jsdoc": "off", 274 | "vars-on-top": "off", 275 | "wrap-iife": "error", 276 | "wrap-regex": "error", 277 | "yield-star-spacing": "error", 278 | "yoda": [ 279 | "error", 280 | "never" 281 | ] 282 | } 283 | }; -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [2.4.4](https://github.com/hypery2k/galenframework-cli/compare/v2.4.3...v2.4.4) (2019-03-15) 2 | 3 | 4 | ### Bug Fixes 5 | 6 | * **Geckodriver:** Use newer version ([30e790c](https://github.com/hypery2k/galenframework-cli/commit/30e790c)) 7 | 8 | 9 | ### Features 10 | 11 | * **Galen:** Use latest Galen version ([df0eefb](https://github.com/hypery2k/galenframework-cli/commit/df0eefb)) 12 | * **Galen:** Use latest Galen version ([c676fc5](https://github.com/hypery2k/galenframework-cli/commit/c676fc5)) 13 | 14 | 15 | 16 | ## [2.4.3](https://github.com/hypery2k/galenframework-cli/compare/v2.4.2...v2.4.3) (2019-02-18) 17 | 18 | 19 | ### Features 20 | 21 | * **Docker:** Proper labels for docker runtime ([db5aec1](https://github.com/hypery2k/galenframework-cli/commit/db5aec1)) 22 | * **Galen:** Use latest Galen version ([5a3c61a](https://github.com/hypery2k/galenframework-cli/commit/5a3c61a)) 23 | * **Security:** Resolve security alerts ([667e898](https://github.com/hypery2k/galenframework-cli/commit/667e898)) 24 | * **Webdriver:** Use latest chromedriver and pin geckodriver ([99cb4af](https://github.com/hypery2k/galenframework-cli/commit/99cb4af)) 25 | 26 | 27 | 28 | ## [2.4.2](https://github.com/hypery2k/galenframework-cli/compare/v2.4.1...v2.4.2) (2019-01-31) 29 | 30 | 31 | ### Bug Fixes 32 | 33 | * **Build:** Disable coverage check on Windows CI build ([afa5c2b](https://github.com/hypery2k/galenframework-cli/commit/afa5c2b)) 34 | * **Build:** Ignore cc-report error code ([04b6a39](https://github.com/hypery2k/galenframework-cli/commit/04b6a39)) 35 | * **CI:** Disable git autocrlf ([343b392](https://github.com/hypery2k/galenframework-cli/commit/343b392)) 36 | * **Windows:** Use supported NodeJS version on Win CI build ([b820eb9](https://github.com/hypery2k/galenframework-cli/commit/b820eb9)), closes [#62](https://github.com/hypery2k/galenframework-cli/issues/62) 37 | 38 | 39 | ### Features 40 | 41 | * **CodeQuality:** Adding codeclimate support ([e14606c](https://github.com/hypery2k/galenframework-cli/commit/e14606c)) 42 | * **Galen:** Use latest Galen version ([0934523](https://github.com/hypery2k/galenframework-cli/commit/0934523)) 43 | * **Safari:** Drop Safari extentsion installation ([0317629](https://github.com/hypery2k/galenframework-cli/commit/0317629)) 44 | * **Webdriver:** Update geckodriver and chromedriver ([b13d3df](https://github.com/hypery2k/galenframework-cli/commit/b13d3df)) 45 | 46 | 47 | ### BREAKING CHANGES 48 | 49 | * **Safari:** No legacy safari webdriver extension for Selenium 50 | 51 | 52 | 53 | ## [2.4.1](https://github.com/hypery2k/galenframework-cli/compare/v2.4.0...v2.4.1) (2018-12-23) 54 | 55 | 56 | ### Features 57 | 58 | * **Galen:** Use latest Galen version ([8a068a8](https://github.com/hypery2k/galenframework-cli/commit/8a068a8)) 59 | 60 | 61 | 62 | # [2.4.0](https://github.com/hypery2k/galenframework-cli/compare/v2.3.7...v2.4.0) (2018-11-04) 63 | 64 | 65 | ### Bug Fixes 66 | 67 | * **build:** Disable failing checks for now ([55f1f59](https://github.com/hypery2k/galenframework-cli/commit/55f1f59)) 68 | * **Build:** Disable coverage ([d7a776b](https://github.com/hypery2k/galenframework-cli/commit/d7a776b)) 69 | * **Build:** Disable coverage for now ([c62b83e](https://github.com/hypery2k/galenframework-cli/commit/c62b83e)) 70 | * **Docker:** Corrected docker path run error ([420a5a8](https://github.com/hypery2k/galenframework-cli/commit/420a5a8)), closes [#60](https://github.com/hypery2k/galenframework-cli/issues/60) 71 | * **security:** Overwrite version to overcome vulnerabilities ([e01cced](https://github.com/hypery2k/galenframework-cli/commit/e01cced)) 72 | * cli/package.json to reduce vulnerabilities ([5b496ce](https://github.com/hypery2k/galenframework-cli/commit/5b496ce)) 73 | * core/package.json to reduce vulnerabilities ([7f20753](https://github.com/hypery2k/galenframework-cli/commit/7f20753)) 74 | * core/package.json to reduce vulnerabilities ([04308b1](https://github.com/hypery2k/galenframework-cli/commit/04308b1)) 75 | * **Security:** Corrected dependencies for adm-zip ([e8cd733](https://github.com/hypery2k/galenframework-cli/commit/e8cd733)) 76 | * **Security:** Use new lodash to solve dependency issues ([5df0d34](https://github.com/hypery2k/galenframework-cli/commit/5df0d34)) 77 | * **Tests:** Corrected test run ([06f28ea](https://github.com/hypery2k/galenframework-cli/commit/06f28ea)) 78 | 79 | 80 | ### Features 81 | 82 | * **Docker:** Use NodeJS in Docker ([ea647c4](https://github.com/hypery2k/galenframework-cli/commit/ea647c4)) 83 | * **Galen:** Use Galen version 2.4.0 ([5d153bf](https://github.com/hypery2k/galenframework-cli/commit/5d153bf)) 84 | * **Galen:** Use latest Galen version ([cdbb474](https://github.com/hypery2k/galenframework-cli/commit/cdbb474)) 85 | * **nodejs:** Drop older NodeJS support ([0b568ad](https://github.com/hypery2k/galenframework-cli/commit/0b568ad)) 86 | * **NodeJS:** Drop support for older NodeJS versions ([0286768](https://github.com/hypery2k/galenframework-cli/commit/0286768)) 87 | * **Security:** Drop insecure nsp package in favour to `npm audit` ([318be32](https://github.com/hypery2k/galenframework-cli/commit/318be32)) 88 | * **Security:** Resolve vulnerabilities ([4725410](https://github.com/hypery2k/galenframework-cli/commit/4725410)) 89 | 90 | 91 | ### Reverts 92 | 93 | * **CLI:** disable eslint tests ([608ce44](https://github.com/hypery2k/galenframework-cli/commit/608ce44)) 94 | 95 | 96 | ### BREAKING CHANGES 97 | 98 | * **NodeJS:** Neede NodeJS 8+ from now on! 99 | * **nodejs:** Only support most recent NodeJS runtimes 100 | 101 | 102 | 103 | ## [2.3.7](https://github.com/hypery2k/galenframework-cli/compare/v2.3.6...v2.3.7) (2018-05-26) 104 | 105 | 106 | ### Bug Fixes 107 | 108 | * cli/package.json & cli/.snyk to reduce vulnerabilities ([d0328b6](https://github.com/hypery2k/galenframework-cli/commit/d0328b6)) 109 | * **docker:** Basic docker integration ([d332566](https://github.com/hypery2k/galenframework-cli/commit/d332566)), closes [#49](https://github.com/hypery2k/galenframework-cli/issues/49) 110 | * **nodejs:** Resolve nodejs errors ([a564c7f](https://github.com/hypery2k/galenframework-cli/commit/a564c7f)), closes [#51](https://github.com/hypery2k/galenframework-cli/issues/51) 111 | 112 | 113 | ### Features 114 | 115 | * **docker:** Adding Chrome and Firefox to Docker image ([d50f07c](https://github.com/hypery2k/galenframework-cli/commit/d50f07c)), closes [#49](https://github.com/hypery2k/galenframework-cli/issues/49) 116 | * **docker:** Basic CI for Docker ([c845838](https://github.com/hypery2k/galenframework-cli/commit/c845838)), closes [#49](https://github.com/hypery2k/galenframework-cli/issues/49) 117 | * **docker:** Fix Docker build issues ([bf4a4d3](https://github.com/hypery2k/galenframework-cli/commit/bf4a4d3)), closes [#49](https://github.com/hypery2k/galenframework-cli/issues/49) 118 | * **Galen:** Use newer Galen Version 2.3.7 ([2a3c53d](https://github.com/hypery2k/galenframework-cli/commit/2a3c53d)) 119 | * **security:** Enable security checks ([4e1a449](https://github.com/hypery2k/galenframework-cli/commit/4e1a449)) 120 | 121 | 122 | 123 | ## [2.3.6](https://github.com/hypery2k/galenframework-cli/compare/v2.3.5...v2.3.6) (2017-12-15) 124 | 125 | 126 | ### Bug Fixes 127 | 128 | * **windows:** Resolve windows runtime error ([bca7ed8](https://github.com/hypery2k/galenframework-cli/commit/bca7ed8)) 129 | 130 | 131 | ### Features 132 | 133 | * **auto-update-webdriver:** Enable auto update for chromedriver and geckodriver ([#48](https://github.com/hypery2k/galenframework-cli/issues/48)) ([0ab4b1e](https://github.com/hypery2k/galenframework-cli/commit/0ab4b1e)) 134 | * **docker:** Create Docker image ([694998d](https://github.com/hypery2k/galenframework-cli/commit/694998d)) 135 | * **galen:** Update Galen Version ([20fab19](https://github.com/hypery2k/galenframework-cli/commit/20fab19)) 136 | 137 | 138 | 139 | ## [2.3.5](https://github.com/hypery2k/galenframework-cli/compare/v2.3.4...v2.3.5) (2017-09-07) 140 | 141 | 142 | ### Bug Fixes 143 | 144 | * **package:** update chromedriver to version 2.31.0 ([6188fd8](https://github.com/hypery2k/galenframework-cli/commit/6188fd8)) 145 | 146 | 147 | ### Features 148 | 149 | * **debugging:** Adding debugging feature ([1856ccb](https://github.com/hypery2k/galenframework-cli/commit/1856ccb)), closes [#13](https://github.com/hypery2k/galenframework-cli/issues/13) [#46](https://github.com/hypery2k/galenframework-cli/issues/46) 150 | * **debugging:** Adding debugging feature ([510f8ec](https://github.com/hypery2k/galenframework-cli/commit/510f8ec)), closes [#13](https://github.com/hypery2k/galenframework-cli/issues/13) [#46](https://github.com/hypery2k/galenframework-cli/issues/46) 151 | 152 | 153 | 154 | ## [2.3.4](https://github.com/hypery2k/galenframework-cli/compare/v2.3.3...v2.3.4) (2017-06-14) 155 | 156 | 157 | ### Bug Fixes 158 | 159 | * **install-error:** Disable node resolver ([#44](https://github.com/hypery2k/galenframework-cli/issues/44)) ([fe3124b](https://github.com/hypery2k/galenframework-cli/commit/fe3124b)) 160 | * **install-error:** see [#44](https://github.com/hypery2k/galenframework-cli/issues/44) ([229abb0](https://github.com/hypery2k/galenframework-cli/commit/229abb0)) 161 | * **local-install-error:** [#44](https://github.com/hypery2k/galenframework-cli/issues/44) ([9037f36](https://github.com/hypery2k/galenframework-cli/commit/9037f36)) 162 | * **local-install-error:** [#44](https://github.com/hypery2k/galenframework-cli/issues/44) ([e7b0503](https://github.com/hypery2k/galenframework-cli/commit/e7b0503)) 163 | 164 | 165 | ### Features 166 | 167 | * **Galen-Update:** Use Galen Framework 2.3.4 ([68e86e4](https://github.com/hypery2k/galenframework-cli/commit/68e86e4)) 168 | * **Galen-Update:** Use Galen Framework 2.3.4 ([8741adc](https://github.com/hypery2k/galenframework-cli/commit/8741adc)) 169 | 170 | 171 | 172 | ## [2.3.3](https://github.com/hypery2k/galenframework-cli/compare/v2.3.2...v2.3.3) (2017-04-03) 173 | 174 | 175 | ### Features 176 | 177 | * **galen-update:** Use newer galen ([48a797a](https://github.com/hypery2k/galenframework-cli/commit/48a797a)) 178 | * **galen-update:** Use newer galen ([b5109c6](https://github.com/hypery2k/galenframework-cli/commit/b5109c6)) 179 | * **galen-update:** Use newer galen core module ([cfc3008](https://github.com/hypery2k/galenframework-cli/commit/cfc3008)) 180 | * **webdriver:** Support geckodriver ([16635ad](https://github.com/hypery2k/galenframework-cli/commit/16635ad)) 181 | * **webdriver:** Use newer webdriver ([a14fc6c](https://github.com/hypery2k/galenframework-cli/commit/a14fc6c)) 182 | 183 | 184 | 185 | ## [2.3.2](https://github.com/hypery2k/galenframework-cli/compare/v2.3.1...v2.3.2) (2016-11-21) 186 | 187 | 188 | ### Features 189 | 190 | * **galen:** Update to recent galen version ([dd80b7b](https://github.com/hypery2k/galenframework-cli/commit/dd80b7b)) 191 | * **galen:** Update to recent galen version ([852b601](https://github.com/hypery2k/galenframework-cli/commit/852b601)) 192 | 193 | 194 | 195 | # [2.3.0](https://github.com/hypery2k/galenframework-cli/compare/v2.2.6...v2.3.0) (2016-07-14) 196 | 197 | 198 | 199 | ## [2.2.6](https://github.com/hypery2k/galenframework-cli/compare/v2.2.5...v2.2.6) (2016-07-09) 200 | 201 | 202 | 203 | ## [2.2.2](https://github.com/hypery2k/galenframework-cli/compare/v2.2.1...v2.2.2) (2016-03-01) 204 | 205 | 206 | 207 | ## [2.2.1](https://github.com/hypery2k/galenframework-cli/compare/v2.2.0...v2.2.1) (2015-12-15) 208 | 209 | 210 | 211 | # [2.2.0](https://github.com/hypery2k/galenframework-cli/compare/v2.1.3...v2.2.0) (2015-12-06) 212 | 213 | 214 | 215 | ## [2.1.3](https://github.com/hypery2k/galenframework-cli/compare/v2.1.2...v2.1.3) (2015-11-23) 216 | 217 | 218 | 219 | ## [2.1.2](https://github.com/hypery2k/galenframework-cli/compare/v2.1.1...v2.1.2) (2015-10-03) 220 | 221 | 222 | 223 | ## [2.1.1](https://github.com/hypery2k/galenframework-cli/compare/v2.1.0...v2.1.1) (2015-10-03) 224 | 225 | 226 | 227 | # [2.1.0](https://github.com/hypery2k/galenframework-cli/compare/v2.0.10...v2.1.0) (2015-09-24) 228 | 229 | 230 | 231 | ## [2.0.10](https://github.com/hypery2k/galenframework-cli/compare/v2.0.9...v2.0.10) (2015-09-21) 232 | 233 | 234 | 235 | ## [2.0.9](https://github.com/hypery2k/galenframework-cli/compare/v2.0.8...v2.0.9) (2015-09-14) 236 | 237 | 238 | 239 | ## [2.0.8](https://github.com/hypery2k/galenframework-cli/compare/v2.0.7...v2.0.8) (2015-08-27) 240 | 241 | 242 | 243 | ## [2.0.7](https://github.com/hypery2k/galenframework-cli/compare/v2.0.6...v2.0.7) (2015-08-14) 244 | 245 | 246 | 247 | ## [2.0.6](https://github.com/hypery2k/galenframework-cli/compare/v2.0.5...v2.0.6) (2015-08-12) 248 | 249 | 250 | 251 | ## [2.0.5](https://github.com/hypery2k/galenframework-cli/compare/v2.0.4...v2.0.5) (2015-08-04) 252 | 253 | 254 | 255 | ## [2.0.4](https://github.com/hypery2k/galenframework-cli/compare/v2.0.3...v2.0.4) (2015-08-03) 256 | 257 | 258 | 259 | ## [1.6.4](https://github.com/hypery2k/galenframework-cli/compare/v1.6.3...v1.6.4) (2015-06-17) 260 | 261 | 262 | 263 | ## [1.6.3](https://github.com/hypery2k/galenframework-cli/compare/v1.6.2...v1.6.3) (2015-05-03) 264 | 265 | 266 | 267 | ## 1.6.2 (2015-04-24) 268 | 269 | 270 | 271 | -------------------------------------------------------------------------------- /core/postinstall.js: -------------------------------------------------------------------------------- 1 | // Copyright 2016 Martin Reinhardt 2 | 3 | /* 4 | * This simply downloads Galen 5 | */ 6 | 7 | 'use strict'; 8 | 9 | const requestProgress = require('request-progress'); 10 | const replace = require('replace-in-file'); 11 | const Progress = require('progress'); 12 | const AdmZip = require('adm-zip'); 13 | const cp = require('child_process'); 14 | const fs = require('fs-extra'); 15 | const helper = require('./lib/helper'); 16 | const kew = require('kew'); 17 | const npmconf = require('npmconf'); 18 | const path = require('path'); 19 | const request = require('request'); 20 | const url = require('url'); 21 | const which = require('which'); 22 | const log = require('npmlog'); 23 | 24 | const cdnUrl = process.env.npm_config_galen_url || process.env.GALEN_CDNURL || 'https://github.com/galenframework/galen/releases/download/'; 25 | const downloadUrl = cdnUrl + '/galen-' + helper.version + '/galen-bin-' + helper.version + '.zip'; 26 | 27 | const originalPath = process.env.PATH; 28 | 29 | // If the process exits without going through exit(), then we did not complete. 30 | var validExit = false; 31 | 32 | process.on('exit', function () { 33 | if (!validExit) { 34 | log.error('Install exited unexpectedly'); 35 | exit(1); 36 | } 37 | }); 38 | 39 | // NPM adds bin directories to the path, which will cause `which` to find the 40 | // bin for this package not the actual galenframework bin. Also help out people who 41 | // put ./bin on their path 42 | process.env.PATH = helper.cleanPath(originalPath); 43 | 44 | const libPath = path.join(__dirname, 'lib'); 45 | const pkgPath = path.join(libPath, 'galen'); 46 | let galenPath = null; 47 | let tmpPath = null; 48 | 49 | // If the user manually installed galen, we want 50 | // to use the existing version. 51 | // 52 | // Do not re-use a manually-installed galen with 53 | // a different version. 54 | // 55 | // Do not re-use an npm-installed galen, because 56 | // that can lead to weird circular dependencies between 57 | // local versions and global versions. 58 | const whichDeferred = kew.defer(); 59 | which('galen', whichDeferred.makeNodeResolver()); 60 | whichDeferred.promise 61 | .then((result) => { 62 | galenPath = result; 63 | // Horrible hack to avoid problems during global install. We check to see if 64 | // the file `which` found is our own bin script. 65 | if (galenPath.indexOf(path.join('npm', 'galenframework')) !== -1) { 66 | log.info('Looks like an `npm install -g` on windows; unable to check for already installed version.'); 67 | throw new Error('Global install'); 68 | } 69 | 70 | const contents = fs.readFileSync(galenPath, 'utf8'); 71 | if (/NPM_INSTALL_MARKER/.test(contents)) { 72 | log.info('Looks like an `npm install -g`; unable to check for already installed version.'); 73 | throw new Error('Global install'); 74 | } else { 75 | const checkVersionDeferred = kew.defer(); 76 | cp.execFile(galenPath, ['--version'], checkVersionDeferred.makeNodeResolver()); 77 | return checkVersionDeferred.promise; 78 | } 79 | }) 80 | .then((stdout) => { 81 | const regex = /^Version: ([0-9\.]+)$/; 82 | const result = stdout.trim().match(regex); 83 | const version = result[1]; 84 | if (helper.version === version) { 85 | writeLocationFile(galenPath); 86 | log.info('galenframework is already installed at', galenPath + '.'); 87 | exit(0); 88 | } else { 89 | log.info('galenframework detected, but wrong version', stdout.trim(), '@', galenPath + '.'); 90 | downloadAndInstallGalen(); 91 | } 92 | }) 93 | .fail(downloadAndInstallGalen); 94 | 95 | 96 | function downloadAndInstallGalen() { 97 | // Trying to use a local file failed, so initiate download and install 98 | // steps instead. 99 | const npmconfDeferred = kew.defer(); 100 | npmconf.load(npmconfDeferred.makeNodeResolver()); 101 | return npmconfDeferred.promise.then((conf) => { 102 | tmpPath = findSuitableTempDirectory(conf); 103 | 104 | const fileName = downloadUrl.split('/').pop(); 105 | const downloadedFile = path.join(tmpPath, fileName); 106 | 107 | log.info('Running at platform: ' + process.platform); 108 | 109 | // Start the install. 110 | if (!fs.existsSync(downloadedFile)) { 111 | log.info('Downloading', downloadUrl); 112 | log.info('Saving to', downloadedFile); 113 | return requestBinary(getRequestOptions(conf), downloadedFile); 114 | } else { 115 | log.info('Download already available at', downloadedFile); 116 | return { 117 | requestOptions: getRequestOptions(conf), 118 | downloadedFile: downloadedFile 119 | }; 120 | } 121 | }) 122 | .then((response) => extractDownload(response.downloadedFile, response.requestOptions, false)) 123 | .then((extractedPath) => copyIntoPlace(extractedPath, pkgPath)) 124 | .then(() => { 125 | const location = libPath; 126 | writeLocationFile(location); 127 | 128 | log.info('Done. galen binary available at ', location); 129 | // Ensure executable is executable by all users 130 | fs.chmodSync(location, '755'); 131 | fs.chmodSync(location + '/galen/galen', '755'); 132 | fs.chmodSync(location + '/galen/galen.bat', '755'); 133 | replace({ 134 | files: location + '/galen/galen.bat', 135 | replace: 'com.galenframework.GalenMain %*', 136 | with: 'com.galenframework.GalenMain %* -Djna.nosys=true' 137 | }, (error, changedFiles) => { 138 | //Catch errors 139 | if (error) { 140 | log.error('Error occurred:', error); 141 | } 142 | //List changed files 143 | log.info('Modified files:', changedFiles.join(', ')); 144 | exit(0); 145 | }); 146 | }) 147 | .fail(function (err) { 148 | log.error('Galen installation failed', err, err.stack); 149 | exit(1); 150 | }); 151 | } 152 | 153 | /** 154 | * Save the destination directory back 155 | * @param {string} location - path of the directory 156 | */ 157 | function writeLocationFile(location) { 158 | log.info('Writing location.js file'); 159 | if (process.platform === 'win32') { 160 | location = location.replace(/\\/g, '\\\\'); 161 | } 162 | fs.writeFileSync(path.join(libPath, 'location.js'), 163 | 'module.exports.location = \'' + location + '\';'); 164 | } 165 | 166 | /** 167 | * Exit helper function 168 | * @param {int} code - exit code 169 | * @function 170 | */ 171 | function exit(code) { 172 | validExit = true; 173 | process.env.PATH = originalPath; 174 | process.exit(code || 0); 175 | } 176 | 177 | /** 178 | * Function to find an writable temp directory 179 | * @param {object} npmConf - current NPM configuration 180 | * @returns {string} representing suitable temp directory 181 | * @function 182 | */ 183 | function findSuitableTempDirectory(npmConf) { 184 | const now = Date.now(); 185 | const candidateTmpDirs = [ 186 | process.env.TMPDIR || process.env.TEMP || npmConf.get('tmp'), 187 | path.join(process.cwd(), 'tmp', 188 | '/tmp') 189 | ]; 190 | 191 | for (let i = 0; i < candidateTmpDirs.length; i++) { 192 | const candidatePath = path.join(candidateTmpDirs[i], 'galenframework'); 193 | 194 | try { 195 | fs.mkdirsSync(candidatePath, '0777'); 196 | // Make double sure we have 0777 permissions; some operating systems 197 | // default umask does not allow write by default. 198 | fs.chmodSync(candidatePath, '0777'); 199 | const testFile = path.join(candidatePath, now + '.tmp'); 200 | fs.writeFileSync(testFile, 'test'); 201 | fs.unlinkSync(testFile); 202 | return candidatePath; 203 | } catch (e) { 204 | log.info(candidatePath, 'is not writable:', e.message); 205 | } 206 | } 207 | 208 | log.error('Can not find a writable tmp directory.'); 209 | exit(1); 210 | } 211 | 212 | /** 213 | * Create request opions object 214 | * @param {object} conf - current NPM config 215 | * @returns {{uri: string, encoding: null, followRedirect: boolean, headers: {}, strictSSL: *}} 216 | * @function 217 | */ 218 | function getRequestOptions(conf) { 219 | const strictSSL = conf.get('strict-ssl'); 220 | 221 | let options = { 222 | uri: downloadUrl, 223 | encoding: null, // Get response as a buffer 224 | followRedirect: true, // The default download path redirects to a CDN URL. 225 | headers: {}, 226 | strictSSL: strictSSL 227 | }; 228 | 229 | let proxyUrl = conf.get('https-proxy') || conf.get('http-proxy') || conf.get('proxy'); 230 | if (proxyUrl) { 231 | 232 | // Print using proxy 233 | let proxy = url.parse(proxyUrl); 234 | if (proxy.auth) { 235 | // Mask password 236 | proxy.auth = proxy.auth.replace(/:.*$/, ':******'); 237 | } 238 | log.info('Using proxy ' + url.format(proxy)); 239 | 240 | // Enable proxy 241 | options.proxy = proxyUrl; 242 | 243 | // If going through proxy, use the user-agent string from the npm config 244 | options.headers['User-Agent'] = conf.get('user-agent'); 245 | } 246 | 247 | // Use certificate authority settings from npm 248 | const ca = conf.get('ca'); 249 | if (ca) { 250 | log.info('Using npmconf ca'); 251 | options.ca = ca; 252 | } 253 | 254 | return options; 255 | } 256 | 257 | /** 258 | * Downloads binary file 259 | * @param {object} requestOptions - to use for HTTP call 260 | * @param {string} filePath - download URL 261 | * @returns {*} 262 | * @function 263 | */ 264 | function requestBinary(requestOptions, filePath) { 265 | const deferred = kew.defer(); 266 | const writePath = filePath + '-download-' + Date.now(); 267 | 268 | log.info('Receiving...'); 269 | let bar = null; 270 | requestProgress(request(requestOptions, (error, response, body) => { 271 | log.info(''); 272 | if (!error && response.statusCode === 200) { 273 | fs.writeFileSync(writePath, body); 274 | log.info('Received ' + Math.floor(body.length / 1024) + 'K total.'); 275 | fs.renameSync(writePath, filePath); 276 | deferred.resolve({ 277 | requestOptions: requestOptions, 278 | downloadedFile: filePath 279 | }); 280 | 281 | } else if (response) { 282 | log.error('Error requesting archive.\n' + 283 | 'Status: ' + response.statusCode + '\n' + 284 | 'Request options: ' + JSON.stringify(requestOptions, null, 2) + '\n' + 285 | 'Response headers: ' + JSON.stringify(response.headers, null, 2) + '\n' + 286 | 'Make sure your network and proxy settings are correct.\n\n'); 287 | exit(1); 288 | } else if (error && error.stack && error.stack.indexOf('SELF_SIGNED_CERT_IN_CHAIN') != -1) { 289 | log.error('Error making request.'); 290 | exit(1); 291 | } else if (error) { 292 | log.error('Error making request.\n' + error.stack + '\n\n' + 293 | 'Please report this full log at https://github.com/hypery2k/galenframework-cli/issues'); 294 | exit(1); 295 | } else { 296 | log.error('Something unexpected happened, please report this full ' + 297 | 'log at https://github.com/hypery2k/galenframework-cli/issues'); 298 | exit(1); 299 | } 300 | })).on('progress', (state) => { 301 | if (!bar) { 302 | bar = new Progress(' [:bar] :percent :etas', { total: state.total, width: 40 }); 303 | } 304 | bar.curr = state.received; 305 | bar.tick(0); 306 | }); 307 | 308 | return deferred.promise; 309 | } 310 | 311 | /** 312 | * Extracts the given Archive 313 | * @param {string} filePath - path of the ZIP archive to extract 314 | * @param {object} requestOptions - request options for retry attempt 315 | * @param {boolean} retry - set to true if it's already an retry attempt 316 | * @returns {*} - path of the extracted archive content 317 | * @function 318 | */ 319 | function extractDownload(filePath, requestOptions, retry) { 320 | const deferred = kew.defer(); 321 | // extract to a unique directory in case multiple processes are 322 | // installing and extracting at once 323 | const extractedPath = filePath + '-extract-' + Date.now(); 324 | let options = { cwd: extractedPath }; 325 | 326 | fs.mkdirsSync(extractedPath, '0777'); 327 | // Make double sure we have 0777 permissions; some operating systems 328 | // default umask does not allow write by default. 329 | fs.chmodSync(extractedPath, '0777'); 330 | 331 | if (filePath.substr(-4) === '.zip') { 332 | log.info('Extracting zip contents'); 333 | 334 | try { 335 | let zip = new AdmZip(filePath); 336 | zip.extractAllTo(extractedPath, true); 337 | deferred.resolve(extractedPath); 338 | } catch (err) { 339 | log.error('Error extracting zip'); 340 | deferred.reject(err); 341 | } 342 | 343 | } else { 344 | log.info('Extracting tar contents (via spawned process)'); 345 | cp.execFile('tar', ['jxf', filePath], options, function (err) { 346 | if (err) { 347 | if (!retry) { 348 | log.info('Error during extracting. Trying to download again.'); 349 | fs.unlinkSync(filePath); 350 | return requestBinary(requestOptions, filePath).then(function (downloadedFile) { 351 | return extractDownload(downloadedFile, requestOptions, true); 352 | }); 353 | } else { 354 | deferred.reject(err); 355 | log.error('Error extracting archive'); 356 | } 357 | } else { 358 | deferred.resolve(extractedPath); 359 | } 360 | }); 361 | } 362 | return deferred.promise; 363 | } 364 | 365 | /** 366 | * Helper function to move folder contents to target directory 367 | * @param {string} extractedPath - source directory path 368 | * @param {string} targetPath - target directory path 369 | * @returns {string} {!Promise.} promise for chaing 370 | * @function 371 | */ 372 | function copyIntoPlace(extractedPath, targetPath) { 373 | log.info('Removing', targetPath); 374 | return kew.nfcall(fs.remove, targetPath).then(function () { 375 | // Look for the extracted directory, so we can rename it. 376 | const files = fs.readdirSync(extractedPath); 377 | for (let i = 0; i < files.length; i++) { 378 | const file = path.join(extractedPath, files[i]); 379 | if (fs.statSync(file).isDirectory() && file.indexOf(helper.version) !== -1) { 380 | log.info('Copying extracted folder', file, '->', targetPath); 381 | return kew.nfcall(fs.move, file, targetPath); 382 | } 383 | } 384 | log.info('Could not find extracted file', files); 385 | throw new Error('Could not find extracted file'); 386 | }); 387 | } 388 | --------------------------------------------------------------------------------