Repository: omergulen/copycat Branch: master Commit: c792cf7ff0a7 Files: 26 Total size: 98.3 KB Directory structure: gitextract_qjula_wf/ ├── .gitignore ├── LICENSE ├── README.md ├── config/ │ ├── env.js │ ├── jest/ │ │ ├── cssTransform.js │ │ └── fileTransform.js │ ├── paths.js │ ├── polyfills.js │ ├── webpack.config.dev.js │ ├── webpack.config.prod.js │ └── webpackDevServer.config.js ├── package.json ├── public/ │ ├── app/ │ │ └── background.js │ ├── index.html │ └── manifest.json ├── scripts/ │ ├── build.js │ ├── start.js │ └── test.js └── src/ ├── App.js ├── Commands.js ├── Constants.js ├── Generator.js ├── content.js ├── index.js ├── registerServiceWorker.js └── style.css ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ build/ package-lock.json node_modules/ .idea/ .vscode/ yarn.lock ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2018 Satendra Rai Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ [![Chrome Web Store](https://img.shields.io/chrome-web-store/v/dlbnejfbjfikckofdndbjndhhbplmnpj.svg?colorB=%234FC828&style=flat)](https://chrome.google.com/webstore/detail/testing-extension/dlbnejfbjfikckofdndbjndhhbplmnpj) [![Chrome Web Store Rating](https://img.shields.io/chrome-web-store/stars/ibomigipadcieapbemkegkmadbbanbgm.svg?colorB=%234FC828&label=rating&style=flat)](https://chrome.google.com/webstore/detail/testing-extension/dlbnejfbjfikckofdndbjndhhbplmnpj) [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg?style=flat)](https://github.com/omergulen/testing-extension/blob/master/LICENSE) # Copycat - Testing Extension ## (for jest-puppeteer) This extension is built to ease creating web tests. It is like Selenium-IDE, but for jest-puppeteer (for now). Also, this extension records actions on your own browser, so it doesn't need to open up new Selenium or Puppeteer window to record your actions on it. In recording state it records the events which are stated below with the target elements unique selector. ### Supported Actions #### Click origined events | Action Key | Description | | --------------------- | ------------- | | `click` | Mouse `click` event. | | `mousedown` | Mouse `mousedown` event. | | `drag-and-drop` | If `mouseup` event comes after `mousedown` event and the difference between their coordinates is greater than 10. | #### Key originated events | Action Key | Description | | --------------------- | ------------- | | `keydown` | Keyboard `keydown` event. It automaticly gathers the `keydown` events into one if they consecutive triggered and their selectors are the same. | | `combined-keydown` | It combines special keydown events if they are trigged at the same time, example: `Ctrl+A`. | #### Page change events | Action Key | Description | | --------------------- | ------------- | | `page-change` | If `onbeforeunload` event is triggered. | | `click-page-change` | If `onbeforeunload` event of the window comes after `click` or `mousedown` event. | #### Verify events Triggers with right click on the element and choose proper verify action. | Action Key | Description | | --------------------- | ------------- | | `verify-text` | It gets the right clicked element's `text` and matches with the `textContent` of the element in the test. | | `verify-link` | It gets the right clicked element's `href` and matches with the `href` of the element in the test. | | `verify-DOM` | It gets the right clicked element and check if it exists in the test. | ## Installation ### Google Web Store [Install on Chrome Web Store](https://chrome.google.com/webstore/detail/testing-extension/dlbnejfbjfikckofdndbjndhhbplmnpj) or ### Manual Installation ``` git clone https://github.com/omergulen/copycat.git ``` Go to `copycat` directory run ``` yarn install ``` Now build the extension using ``` yarn build ``` You will see a `build` folder generated inside `[PROJECT_HOME]` #### Adding Copycat to Chrome In Chrome browser, go to `chrome://extensions` page and switch on developer mode. This enables the ability to locally install a Chrome extension. Now click on the `LOAD UNPACKED` and browse to `[PROJECT_HOME]\build` ,This will install the React app as a Chrome extension. When you go to any website and click on extension icon, injected page will toggle. Remove unwanted actions on hover. ## Usage - Testing Environment ### Installation of jest-puppeteer ```bash # for jest 22~23 yarn add --save-dev jest-puppeteer@3.9.0 puppeteer jest # for jest 24+ yarn add --save-dev jest-puppeteer puppeteer jest ``` or ```bash # for jest 22~23 npm install --save-dev jest-puppeteer@3.9.0 puppeteer jest # for jest 24+ npm install --save-dev jest-puppeteer puppeteer jest ``` ### Update Jest configuration Create `jest.config.js` in the root of your testing environment. ``` module.exports = { "preset": "jest-puppeteer" } ``` ### Creating `__tests__` folder To work with default `jest-puppeteer` preset, you need to put your test files into the `__tests__` folder in the root of your testing environment. ### Basic Test Output Code Following test example in the GIF will generate such code. It starts in [my GitHub Profile](https://github.com/omergulen) and clicks one of the pinned repositories (testing-extension) and when page changes it checks for the repository title's `href` is `https://github.com/omergulen/copycat` or not. ``` describe('Test 1', () => { beforeAll(async () => { await page.goto('https://github.com/omergulen'); }); it('Test 1 - 1', async () => { await Promise.all([ page.click(':nth-child(2) > .Box > .pinned-item-list-item-content > .d-flex > .text-bold > .repo'), page.waitForNavigation() ]); var nodeLink = await page.$$eval('strong > a', el => el[0].href) expect(nodeLink).toBe('https://github.com/omergulen/copycat'); }, 60000); }); ``` ### Update Puppeteer configuration _(optional)_ Create `jest-puppeteer.config.js` in the root of your testing environment. ``` module.exports = { launch: { headless: false, // Disable headless chromium defaultViewport: null // Set page fit to the browser }, browserContext: 'default', } ``` ### Adding `test` command to the project configuration In your project's `package.json` file, insert `"test": "jest"` line into the `"scripts"` object. It will basicly look something like that: ``` { "scripts": { "test": "jest" }, "devDependencies": { "jest-puppeteer": "^4.3.0" }, "dependencies": { "jest": "^24.8.0", "puppeteer": "^1.19.0" } } ``` ### Running tests `yarn run test` or `npm run test` will do. ## Contribution Bug reports and pull requests are welcome on GitHub at https://github.com/omergulen/testing-extension. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct ## License The repo is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT). ================================================ FILE: config/env.js ================================================ 'use strict'; const fs = require('fs'); const path = require('path'); const paths = require('./paths'); // Make sure that including paths.js after env.js will read .env variables. delete require.cache[require.resolve('./paths')]; const NODE_ENV = process.env.NODE_ENV; if (!NODE_ENV) { throw new Error( 'The NODE_ENV environment variable is required but was not specified.' ); } // https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use var dotenvFiles = [ `${paths.dotenv}.${NODE_ENV}.local`, `${paths.dotenv}.${NODE_ENV}`, // Don't include `.env.local` for `test` environment // since normally you expect tests to produce the same // results for everyone NODE_ENV !== 'test' && `${paths.dotenv}.local`, paths.dotenv, ].filter(Boolean); // Load environment variables from .env* files. Suppress warnings using silent // if this file is missing. dotenv will never modify any environment variables // that have already been set. Variable expansion is supported in .env files. // https://github.com/motdotla/dotenv // https://github.com/motdotla/dotenv-expand dotenvFiles.forEach(dotenvFile => { if (fs.existsSync(dotenvFile)) { require('dotenv-expand')( require('dotenv').config({ path: dotenvFile, }) ); } }); // We support resolving modules according to `NODE_PATH`. // This lets you use absolute paths in imports inside large monorepos: // https://github.com/facebookincubator/create-react-app/issues/253. // It works similar to `NODE_PATH` in Node itself: // https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders // Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. // Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims. // https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421 // We also resolve them to make sure all tools using them work consistently. const appDirectory = fs.realpathSync(process.cwd()); process.env.NODE_PATH = (process.env.NODE_PATH || '') .split(path.delimiter) .filter(folder => folder && !path.isAbsolute(folder)) .map(folder => path.resolve(appDirectory, folder)) .join(path.delimiter); // Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be // injected into the application via DefinePlugin in Webpack configuration. const REACT_APP = /^REACT_APP_/i; function getClientEnvironment(publicUrl) { const raw = Object.keys(process.env) .filter(key => REACT_APP.test(key)) .reduce( (env, key) => { env[key] = process.env[key]; return env; }, { // Useful for determining whether we’re running in production mode. // Most importantly, it switches React into the correct mode. NODE_ENV: process.env.NODE_ENV || 'development', // Useful for resolving the correct path to static assets in `public`. // For example, . // This should only be used as an escape hatch. Normally you would put // images into the `src` and `import` them in code to get their paths. PUBLIC_URL: publicUrl, } ); // Stringify all values so we can feed into Webpack DefinePlugin const stringified = { 'process.env': Object.keys(raw).reduce((env, key) => { env[key] = JSON.stringify(raw[key]); return env; }, {}), }; return { raw, stringified }; } module.exports = getClientEnvironment; ================================================ FILE: config/jest/cssTransform.js ================================================ 'use strict'; // This is a custom Jest transformer turning style imports into empty objects. // http://facebook.github.io/jest/docs/en/webpack.html module.exports = { process() { return 'module.exports = {};'; }, getCacheKey() { // The output is always the same. return 'cssTransform'; }, }; ================================================ FILE: config/jest/fileTransform.js ================================================ 'use strict'; const path = require('path'); // This is a custom Jest transformer turning file imports into filenames. // http://facebook.github.io/jest/docs/en/webpack.html module.exports = { process(src, filename) { return `module.exports = ${JSON.stringify(path.basename(filename))};`; }, }; ================================================ FILE: config/paths.js ================================================ 'use strict'; const path = require('path'); const fs = require('fs'); const url = require('url'); // Make sure any symlinks in the project folder are resolved: // https://github.com/facebookincubator/create-react-app/issues/637 const appDirectory = fs.realpathSync(process.cwd()); const resolveApp = relativePath => path.resolve(appDirectory, relativePath); const envPublicUrl = process.env.PUBLIC_URL; function ensureSlash(path, needsSlash) { const hasSlash = path.endsWith('/'); if (hasSlash && !needsSlash) { return path.substr(path, path.length - 1); } else if (!hasSlash && needsSlash) { return `${path}/`; } else { return path; } } const getPublicUrl = appPackageJson => envPublicUrl || require(appPackageJson).homepage; // We use `PUBLIC_URL` environment variable or "homepage" field to infer // "public path" at which the app is served. // Webpack needs to know it to put the right