diff --git a/.github/workflows/codeceptjs-reporting.yml b/.github/workflows/codeceptjs-reporting.yml new file mode 100644 index 00000000..ea3a6709 --- /dev/null +++ b/.github/workflows/codeceptjs-reporting.yml @@ -0,0 +1,37 @@ +# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions +# - cron: "0 5 */2 * *" +name: CodeceptJS example reporting results + +on: + schedule: + - cron: "0 5 */6 * *" + +jobs: + reporting: + runs-on: ubuntu-latest + + defaults: + run: + working-directory: ./codeceptJS + + strategy: + matrix: + node-version: [18.x] + + steps: + - uses: actions/checkout@v3 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + - name: Setup dependancies + run: npm i + - name: Playwright browser updates + run: npx playwright install + - name: Run tests + run: bash run-tests-and-check-results.sh + env: + TESTOMATIO: "${{ secrets.TESTOMATIO }}" + TESTOMATIO_URL: "${{ secrets.TESTOMATIO_URL }}" + CODECEPT_GROUP_TESTS: "${{ secrets.CODECEPT_GROUP_TESTS }}" \ No newline at end of file diff --git a/.github/workflows/cypress-reporting.yml b/.github/workflows/cypress-reporting.yml new file mode 100644 index 00000000..cd31ef83 --- /dev/null +++ b/.github/workflows/cypress-reporting.yml @@ -0,0 +1,34 @@ +# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions +# - cron: "10 5 */2 * *" +name: Cypress example reporting results + +on: + schedule: + - cron: "10 5 */6 * *" + +jobs: + reporting: + runs-on: ubuntu-latest + + defaults: + run: + working-directory: ./cypress + + strategy: + matrix: + node-version: [18.x] + + steps: + - uses: actions/checkout@v3 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + - name: Setup dependancies + run: npm i + - name: Run tests + run: bash run-tests-and-check-results.sh + env: + TESTOMATIO: "${{ secrets.TESTOMATIO_CYPRESS }}" + TESTOMATIO_URL: "${{ secrets.TESTOMATIO_URL }}" \ No newline at end of file diff --git a/.github/workflows/newman-tests.yml b/.github/workflows/newman-tests.yml new file mode 100644 index 00000000..b73999b1 --- /dev/null +++ b/.github/workflows/newman-tests.yml @@ -0,0 +1,35 @@ +name: newman tests +on: + pull_request: + branches: [master] + +concurrency: + group: newman-tests-${{github.event.pull_request.number}} + cancel-in-progress: true + +jobs: + newman-global: + runs-on: ubuntu-latest + defaults: + run: + working-directory: newman + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v2 + with: + node-version: 18.x + - run: npm i newman-reporter-testomatio newman -g + - run: TESTOMATIO=m6ef70356h7c newman run collection.json -e env.json -r testomatio + + newman-local: + runs-on: ubuntu-latest + defaults: + run: + working-directory: newman + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v2 + with: + node-version: 18.x + - run: npm i + - run: TESTOMATIO=m6ef70356h7c npm run test diff --git a/.github/workflows/playwright-reporting.yml b/.github/workflows/playwright-reporting.yml new file mode 100644 index 00000000..c98a58f8 --- /dev/null +++ b/.github/workflows/playwright-reporting.yml @@ -0,0 +1,36 @@ +# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions +# - cron: "20 5 */2 * *" +name: Playwright example reporting results + +on: + schedule: + - cron: "20 5 */6 * *" + +jobs: + reporting: + runs-on: ubuntu-latest + + defaults: + run: + working-directory: ./playwright + + strategy: + matrix: + node-version: [18.x] + + steps: + - uses: actions/checkout@v3 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + - name: Setup dependancies + run: npm i + - name: Playwright browser updates + run: npx playwright install + - name: Run tests + run: bash run-tests-and-check-results.sh + env: + TESTOMATIO: "${{ secrets.TESTOMATIO_PLAYWRIGHT }}" + TESTOMATIO_URL: "${{ secrets.TESTOMATIO_URL }}" \ No newline at end of file diff --git a/codeceptJS-typescript/.gitignore b/codeceptJS-typescript/.gitignore new file mode 100644 index 00000000..b56eea18 --- /dev/null +++ b/codeceptJS-typescript/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +output/ \ No newline at end of file diff --git a/codeceptJS-typescript/__tests__/open-google_test.ts b/codeceptJS-typescript/__tests__/open-google_test.ts new file mode 100644 index 00000000..e21a5690 --- /dev/null +++ b/codeceptJS-typescript/__tests__/open-google_test.ts @@ -0,0 +1,6 @@ +Feature('Test feature name'); + +Scenario('test something', ({ I }) => { + I.amOnPage('https://www.google.com/'); + I.see('Google'); +}); diff --git a/codeceptJS-typescript/codecept.conf.ts b/codeceptJS-typescript/codecept.conf.ts new file mode 100644 index 00000000..181c188a --- /dev/null +++ b/codeceptJS-typescript/codecept.conf.ts @@ -0,0 +1,30 @@ +import { setHeadlessWhen, setCommonPlugins } from '@codeceptjs/configure'; +// turn on headless mode when running with HEADLESS=true environment variable +// export HEADLESS=true && npx codeceptjs run +setHeadlessWhen(process.env.HEADLESS); + +// enable all common plugins https://github.com/codeceptjs/configure#setcommonplugins +setCommonPlugins(); + +export const config: CodeceptJS.MainConfig = { + tests: './__tests__/**/*_test.ts', + output: './output', + helpers: { + Playwright: { + browser: 'chromium', + url: 'http://localhost', + show: false + } + }, + include: { + I: './steps_file' + }, + name: 'codeceptJS-typescript', + + plugins: { + testomatio: { + enabled: true, + require: '@testomatio/reporter/lib/adapter/codecept', + } + } +} \ No newline at end of file diff --git a/codeceptJS-typescript/package.json b/codeceptJS-typescript/package.json new file mode 100644 index 00000000..865ce9e8 --- /dev/null +++ b/codeceptJS-typescript/package.json @@ -0,0 +1,19 @@ +{ + "name": "codeceptjs-typescript", + "version": "1.0.0", + "description": "Example project for CodeceptJS + TypeScript", + "scripts": { + "test": "npx codeceptjs run --steps" + }, + "author": "Oleksandr Pelykh / Testomatio", + "license": "ISC", + "dependencies": { + "codeceptjs": "^3.5.11", + "playwright": "^1.40.1" + }, + "devDependencies": { + "@types/node": "^20.10.7", + "ts-node": "^10.9.2", + "typescript": "^5.3.3" + } +} diff --git a/codeceptJS-typescript/steps.d.ts b/codeceptJS-typescript/steps.d.ts new file mode 100644 index 00000000..49d8f0f8 --- /dev/null +++ b/codeceptJS-typescript/steps.d.ts @@ -0,0 +1,11 @@ +/// +type steps_file = typeof import('./steps_file'); + +declare namespace CodeceptJS { + interface SupportObject { I: I, current: any } + interface Methods extends Playwright {} + interface I extends ReturnType {} + namespace Translation { + interface Actions {} + } +} diff --git a/codeceptJS-typescript/steps_file.ts b/codeceptJS-typescript/steps_file.ts new file mode 100644 index 00000000..1083a858 --- /dev/null +++ b/codeceptJS-typescript/steps_file.ts @@ -0,0 +1,10 @@ +// in this file you can append custom step methods to 'I' object + +export = function() { + return actor({ + + // Define custom steps here, use 'this' to access default methods of I. + // It is recommended to place a general 'login' function here. + + }); +} diff --git a/codeceptJS-typescript/tsconfig.json b/codeceptJS-typescript/tsconfig.json new file mode 100644 index 00000000..a4a3e5f9 --- /dev/null +++ b/codeceptJS-typescript/tsconfig.json @@ -0,0 +1,16 @@ +{ + "ts-node": { + "files": true + }, + "compilerOptions": { + "target": "es2018", + "lib": ["es2018", "DOM"], + "esModuleInterop": true, + "module": "commonjs", + "strictNullChecks": false, + "types": ["codeceptjs", "node"], + "declaration": true, + "skipLibCheck": true + }, + "exclude": ["node_modules"] +} \ No newline at end of file diff --git a/codeceptJS/artifacts/artifact-test-image.png b/codeceptJS/artifacts/artifact-test-image.png new file mode 100644 index 00000000..f844619a Binary files /dev/null and b/codeceptJS/artifacts/artifact-test-image.png differ diff --git a/codeceptJS/artifacts/artifact-test-text.txt b/codeceptJS/artifacts/artifact-test-text.txt new file mode 100644 index 00000000..a250a0b1 --- /dev/null +++ b/codeceptJS/artifacts/artifact-test-text.txt @@ -0,0 +1 @@ +this is test artifact content \ No newline at end of file diff --git a/codeceptJS/codecept.conf.js b/codeceptJS/codecept.conf.js index 87f8ff8c..ee265def 100644 --- a/codeceptJS/codecept.conf.js +++ b/codeceptJS/codecept.conf.js @@ -4,12 +4,17 @@ const { setHeadlessWhen } = require('@codeceptjs/configure'); setHeadlessWhen(process.env.HEADLESS); +const tests = process.env.codecept_GROUP_TESTS === "quick" + ? './todomvc-tests/todo-mvc_test.js' + : './todomvc-tests/**/*_test.js' + exports.config = { - tests: './todomvc-tests/**/*_test.js', + tests, output: './output', helpers: { Playwright: { video: true, + trace: true, url: 'http://localhost', waitForTimeout: 5000, waitForNavigation: 'networkidle0', @@ -33,6 +38,9 @@ exports.config = { require: '@testomatio/reporter/lib/adapter/codecept', apiKey: process.env.TESTOMATIO, }, + screenshotOnFail: { + enabled: false + } }, bootstrap: null, mocha: {}, diff --git a/codeceptJS/package.json b/codeceptJS/package.json index b4c4bec8..eb1d8c73 100644 --- a/codeceptJS/package.json +++ b/codeceptJS/package.json @@ -1,19 +1,20 @@ { "name": "@codeceptjs/examples", - "version": "1.1.2", + "version": "1.1.3", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "npx codeceptjs run", + "test:artifact": "npx codeceptjs run artifact-tests/**" }, "keywords": [], - "author": "kaflan, davert", + "author": "kaflan, davert, mihaylukvv", "license": "ISC", "dependencies": { - "@testomatio/reporter": "^0.6.3", - "axios": "^0.19.2", - "check-tests": "^0.7.6", - "dotenv": "^8.6.0", - "playwright": "^1.23.0" + "@testomatio/reporter": "latest", + "axios": "^1.4.0", + "check-tests": "^0.8.16", + "dotenv": "^16.3.1", + "playwright": "^1.36.0" }, "repository": { "type": "git", @@ -23,10 +24,10 @@ "url": "https://github.com/codecept-js/examples/issues" }, "homepage": "https://github.com/codecept-js/examples#readme", - "description": "", + "description": "Running and Monitoring CodeceptJS Tests with TESTOMATIO Reporter", "devDependencies": { - "@codeceptjs/configure": "^0.4.0", - "@codeceptjs/ui": "^0.2.0", - "codeceptjs": "^3.3.3" + "@codeceptjs/configure": "^0.10.0", + "@codeceptjs/ui": "^0.5.0", + "codeceptjs": "latest" } } diff --git a/codeceptJS/run-tests-and-check-results.sh b/codeceptJS/run-tests-and-check-results.sh new file mode 100644 index 00000000..c40cf0ba --- /dev/null +++ b/codeceptJS/run-tests-and-check-results.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +npx codeceptjs run > test-results.txt +fail_tests=$(grep -oE '\b[0-9]+\s+failed\b' test-results.txt | grep -oE '[0-9]+') +echo "Number of failed tests: $fail_tests" +if [ "$fail_tests" -gt 12 ]; then + echo "More than 12 failed tests. Exiting with error." + exit 1 +else + exit 0 +fi diff --git a/codeceptJS/tests-usage-examples/functions.test.js b/codeceptJS/tests-usage-examples/functions.test.js new file mode 100644 index 00000000..29e8a378 --- /dev/null +++ b/codeceptJS/tests-usage-examples/functions.test.js @@ -0,0 +1,22 @@ +const testomat = require('@testomatio/reporter'); + +Feature('Testomat functions'); + +Scenario('Upload file', async () => { + testomat.artifact('artifacts/artifact-test-text.txt'); +}); + +Scenario('Upload image', async () => { + testomat.artifact({ + path: 'artifacts/artifact-test-image.png', + }); +}); + +Scenario('Add Step to report', async () => { + testomat.step('This is step message'); +}); + +Scenario('Add log message to report', async () => { + testomat.log('This is log message'); + testomat.log`This is log message with template literal`; +}); diff --git a/codeceptJS/tests-usage-examples/logger.test.js b/codeceptJS/tests-usage-examples/logger.test.js new file mode 100644 index 00000000..e5600122 --- /dev/null +++ b/codeceptJS/tests-usage-examples/logger.test.js @@ -0,0 +1,20 @@ +const { logger, log } = require('@testomatio/reporter'); + +// console messages are added to report by default when import "logger" from reporter +// but to prevent unsused variable warning, you can call next code: +logger; + +Feature('Logger @Sebd746ef'); + +Scenario('Intercept console logs @Tebebb252', async () => { + console.warn('This is warning message'); +}); + +Scenario('Add own log message @T35d1887d', async () => { + const someObject = { + name: 'John', + surname: 'Doe', + age: 30, + }; + log('This is log message', someObject); +}); diff --git a/codeceptJS/todomvc-tests/create-todos_test.js b/codeceptJS/todomvc-tests/create-todos_test.js index 0320fcf6..0363ae15 100644 --- a/codeceptJS/todomvc-tests/create-todos_test.js +++ b/codeceptJS/todomvc-tests/create-todos_test.js @@ -1,3 +1,5 @@ +const {testomatioLogger} = require('@testomatio/reporter'); + Feature('@first Create Tasks @step:06 @smoke @story:12345') Before(async ({ I, TodosPage }) => { @@ -8,6 +10,8 @@ Before(async ({ I, TodosPage }) => { * Happy Path tests */ Scenario('Create a new todo item', async ({ I, TodosPage }) => { + console.log('console log message'); + testomatioLogger.info('testomatio info log message'); I.say('Given I have an empty todo list') I.say('When I create a todo "foo"') diff --git a/codeceptJS/todomvc-tests/pages/todos.page.js b/codeceptJS/todomvc-tests/pages/todos.page.js index d2377a11..717df9b0 100644 --- a/codeceptJS/todomvc-tests/pages/todos.page.js +++ b/codeceptJS/todomvc-tests/pages/todos.page.js @@ -8,13 +8,13 @@ const I = actor(); // const nthTodoItem = nth => `.todo-list li:nth-child(${nth})` // ({ xpath: `(//*[contains(@class,"todo-list")]/li)[${nth}]`}) const nthTodoCheckbox = nth => locate('div > input').inside(`.todo-list li:nth-child(${nth})`) -const nthTTodoDeleteButton = nth => locate('div > button').inside(`.todo-list li:nth-child(${nth})`).as(`${nth}nth delete button`) -const nthTodoEditField = nth => locate('form > input').inside(`.todo-list li:nth-child(${nth})`).as(`${nth}nth todo input`) +const nthTTodoDeleteButton = nth => locate('div > button.destroy').inside(`.todo-list li:nth-child(${nth})`).as(`${nth}nth delete button`) +const nthTodoEditField = nth => locate('input#edit-todo-input').inside(`.todo-list li:nth-child(${nth})`).as(`${nth}nth todo input`) const nthTodoItem = nth => locate('.todo-list li').at(nth).as(`${nth} todo item`) module.exports = { goto() { - I.amOnPage('http://todomvc.com/examples/angularjs/#/') + I.amOnPage('https://todomvc.com/examples/angular/dist/browser/#/all') I.refreshPage() I.executeScript(() => sessionStorage.clear()) I.executeScript(() => console.error('Boom!')) @@ -33,7 +33,9 @@ module.exports = { }, async markNthAsCompleted(nthTodo) { - const classNames = await I.grabAttributeFrom(nthTodoItem(nthTodo), 'class') + let classNames = await I.grabAttributeFrom(nthTodoItem(nthTodo), 'class') + if (!classNames) classNames = []; + assert(classNames.indexOf('completed') < 0, 'Expected todo to be not already marked as completed') I.click(nthTodoCheckbox(nthTodo)) }, @@ -86,7 +88,7 @@ module.exports = { todos = [todos] } - assert(todos[nthTodo - 1] === 1, `Expected "${todo}" but got "${todos[nthTodo - 1]}"`) + assert(todos[nthTodo - 1] === todo, `Expected "${todo}" but got "${todos[nthTodo - 1]}"`) return todos }, diff --git a/codeceptJS/todomvc-tests/todo-mvc_test.js b/codeceptJS/todomvc-tests/todo-mvc_test.js index b56fdfba..6061c0ee 100644 --- a/codeceptJS/todomvc-tests/todo-mvc_test.js +++ b/codeceptJS/todomvc-tests/todo-mvc_test.js @@ -1,7 +1,9 @@ Feature('codepress demo') Before(async ({ I }) => { - I.amOnPage('http://todomvc.com/examples/angularjs/#/') + I.amOnPage('https://todomvc.com/examples/angular/dist/browser/#/all') + + console.log("Test Before hoooks quick test"); I.say('Given I already have some todos') const todoItems = [ diff --git a/codeception/composer.json b/codeception/composer.json index 4720a704..0553ef62 100644 --- a/codeception/composer.json +++ b/codeception/composer.json @@ -56,7 +56,7 @@ "symfony/phpunit-bridge": "*", "symfony/stopwatch": "*", "testomatio/list-tests": ">=0.1.4", - "testomatio/reporter": "^0.1.5", + "testomatio/reporter": "^0.2.0", "vlucas/phpdotenv": ">2.4" }, "config": { diff --git a/codeceptjs-cucumber/todomvc-tests/pages/todos.page.js b/codeceptjs-cucumber/todomvc-tests/pages/todos.page.js index 740056fc..cbcb497c 100644 --- a/codeceptjs-cucumber/todomvc-tests/pages/todos.page.js +++ b/codeceptjs-cucumber/todomvc-tests/pages/todos.page.js @@ -8,13 +8,13 @@ const I = actor(); // const nthTodoItem = nth => `.todo-list li:nth-child(${nth})` // ({ xpath: `(//*[contains(@class,"todo-list")]/li)[${nth}]`}) const nthTodoCheckbox = nth => locate('div > input').inside(`.todo-list li:nth-child(${nth})`) -const nthTTodoDeleteButton = nth => locate('div > button').inside(`.todo-list li:nth-child(${nth})`).as(`${nth}nth delete button`) -const nthTodoEditField = nth => locate('form > input').inside(`.todo-list li:nth-child(${nth})`).as(`${nth}nth todo input`) +const nthTTodoDeleteButton = nth => locate('div > button.destroy').inside(`.todo-list li:nth-child(${nth})`).as(`${nth}nth delete button`) +const nthTodoEditField = nth => locate('input#edit-todo-input').inside(`.todo-list li:nth-child(${nth})`).as(`${nth}nth todo input`) const nthTodoItem = nth => locate('.todo-list li').at(nth).as(`${nth} todo item`) module.exports = { goto() { - I.amOnPage('http://todomvc.com/examples/angularjs/#/') + I.amOnPage('https://todomvc.com/examples/angular/dist/browser/#/all') I.refreshPage() I.executeScript(() => sessionStorage.clear()) I.executeScript(() => console.error('Boom!')) diff --git a/codeceptjs-typescript b/codeceptjs-typescript deleted file mode 160000 index a6e0a0ee..00000000 --- a/codeceptjs-typescript +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a6e0a0ee6a9a9813a4dcf6abeb5b0d6215b0db36 diff --git a/cucumber-new/artifacts/artifact-test-image.png b/cucumber-new/artifacts/artifact-test-image.png new file mode 100644 index 00000000..f844619a Binary files /dev/null and b/cucumber-new/artifacts/artifact-test-image.png differ diff --git a/cucumber-new/features/artifact.feature b/cucumber-new/features/artifact.feature new file mode 100644 index 00000000..7acfd907 --- /dev/null +++ b/cucumber-new/features/artifact.feature @@ -0,0 +1,5 @@ +Feature: Artifact + + Scenario: Upload artifact + When I add the artifact + Then artifact should be attached to report diff --git a/cucumber-new/features/greeting.feature b/cucumber-new/features/greeting.feature new file mode 100644 index 00000000..2a92e543 --- /dev/null +++ b/cucumber-new/features/greeting.feature @@ -0,0 +1,5 @@ +Feature: Greeting + + Scenario: Say hello + When the greeter says hello + Then I should have heard "hello" diff --git a/cucumber-new/features/logger.feature b/cucumber-new/features/logger.feature new file mode 100644 index 00000000..b58ed98b --- /dev/null +++ b/cucumber-new/features/logger.feature @@ -0,0 +1,5 @@ +Feature: Logger + + Scenario: Intercept console message + When The logger intercepts console message + Then log message should be added to report diff --git a/cucumber-new/features/step.feature b/cucumber-new/features/step.feature new file mode 100644 index 00000000..ae4b325a --- /dev/null +++ b/cucumber-new/features/step.feature @@ -0,0 +1,5 @@ +Feature: Step + + Scenario: Add step to report + When I add the step + Then step should be added to report diff --git a/cucumber-new/features/step_definitions/steps.js b/cucumber-new/features/step_definitions/steps.js new file mode 100644 index 00000000..7321d4a7 --- /dev/null +++ b/cucumber-new/features/step_definitions/steps.js @@ -0,0 +1,39 @@ +import assert from 'assert'; +import { When, Then } from '@cucumber/cucumber'; +import { Greeter } from '../../src/index.js'; +import testomat, { logger, log } from '@testomatio/reporter'; + +logger; + +When('the greeter says hello', function () { + this.whatIHeard = new Greeter().sayHello(); +}); + +Then('I should have heard {string}', function (expectedResponse) { + assert.equal(this.whatIHeard, expectedResponse); +}); + +When('The logger intercepts console message', function () { + console.error('This is error message'); + log`This is log message`; +}); + +Then('log message should be added to report', function () { + assert.equal(true, true); +}); + +When('I add the step', function () { + testomat.step('This is step'); +}); + +Then('step should be added to report', function () { + assert.equal(true, true); +}); + +When('I add the artifact', function () { + testomat.artifact('artifacts/artifact-test-image.png'); +}); + +Then('artifact should be attached to report', function () { + assert.equal(true, true); +}); diff --git a/cucumber-new/package.json b/cucumber-new/package.json new file mode 100644 index 00000000..a12469f5 --- /dev/null +++ b/cucumber-new/package.json @@ -0,0 +1,16 @@ +{ + "name": "cucumber-new", + "version": "1.0.0", + "description": "", + "main": "index.js", + "type": "module", + "scripts": { + "test": "cucumber-js" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@cucumber/cucumber": "^10.0.1", + "@testomatio/reporter": "latest" + } +} diff --git a/cucumber-new/src/index.js b/cucumber-new/src/index.js new file mode 100644 index 00000000..b0d37ce9 --- /dev/null +++ b/cucumber-new/src/index.js @@ -0,0 +1,5 @@ +export class Greeter { + sayHello() { + return 'hello'; + } +} diff --git a/cucumber/package.json b/cucumber/package.json index 4b2b730e..1a816506 100644 --- a/cucumber/package.json +++ b/cucumber/package.json @@ -9,9 +9,9 @@ "author": "", "license": "ISC", "dependencies": { + "@cucumber/cucumber": "^10.0.1", "@testomatio/reporter": "latest", "cucumber": "^6.0.5" }, - "devDependencies": {}, "description": "" } diff --git a/cypress-cucumber/README.md b/cypress-cucumber/README.md index cdae5bad..2e8e4c1d 100644 --- a/cypress-cucumber/README.md +++ b/cypress-cucumber/README.md @@ -4,10 +4,13 @@ This repo contains tests for **Cypress.io test application in Gherkin language** This is a playground for your first steps in testing, so instead of installing it from NPM it is recommended to clone it from repo instead. +**If you're using `npm` to install this example, we support only _Node.js_ 18.x and above** +|So you should install latest Node.js or switch using `nvm` + 1) Clone this repository ``` -git clone git@github.com:testomatio/examples.git && cd examples/cypress +git clone git@github.com:testomatio/examples.git && cd examples/cypress-cucumber ``` 2) Install dependencies via npm: @@ -16,6 +19,18 @@ git clone git@github.com:testomatio/examples.git && cd examples/cypress npm i ``` +### Confirm test results localy + +To open the example with the Cypress browser and execute .feature specs: +``` +npx cypress open +``` + +To execute tests in console log only(get screens + videos + logs): +``` +npx cypress run +``` + This will install cypress & Testomat.io reporter ## Loading Tests to Testomat.io diff --git a/cypress-cucumber/cypress.config.js b/cypress-cucumber/cypress.config.js new file mode 100644 index 00000000..11ef6b28 --- /dev/null +++ b/cypress-cucumber/cypress.config.js @@ -0,0 +1,23 @@ +const { defineConfig } = require("cypress"); +const createBundler = require("@bahmutov/cypress-esbuild-preprocessor"); +const addCucumberPreprocessorPlugin = require("@badeball/cypress-cucumber-preprocessor").addCucumberPreprocessorPlugin; +const createEsbuildPlugin = require("@badeball/cypress-cucumber-preprocessor/esbuild").createEsbuildPlugin; +const testomatioReporter = require('@testomatio/reporter/lib/adapter/cypress-plugin'); + +module.exports = defineConfig({ + e2e: { + async setupNodeEvents(on, config) { + // implement node event listeners here + const bundler = createBundler({ + plugins: [createEsbuildPlugin(config)], + }); + on("file:preprocessor", bundler); + await addCucumberPreprocessorPlugin(on, config); + //Testomat.io reporter + testomatioReporter(on, config); + + return config; + }, + specPattern: "cypress/integration/**/*.feature", + }, +}); \ No newline at end of file diff --git a/cypress-cucumber/cypress.json b/cypress-cucumber/cypress.json deleted file mode 100644 index 9e26dfee..00000000 --- a/cypress-cucumber/cypress.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/cypress-cucumber/cypress/integration/features/github.feature b/cypress-cucumber/cypress/integration/features/github.feature deleted file mode 100644 index 21d373a7..00000000 --- a/cypress-cucumber/cypress/integration/features/github.feature +++ /dev/null @@ -1,15 +0,0 @@ -Feature: "Github header" - - Scenario: Checking GitHub header - - When I open the GitHub home page - Then I should see correct h1 - - Scenario Outline: Checking web pages - - Given I open page - - Examples: - | url | - | "https://testomat.io" | - | "https://lb.ua1" | diff --git a/cypress-cucumber/cypress/integration/features/homePage.feature b/cypress-cucumber/cypress/integration/features/homePage.feature new file mode 100644 index 00000000..aa6d9cab --- /dev/null +++ b/cypress-cucumber/cypress/integration/features/homePage.feature @@ -0,0 +1,27 @@ +Feature: Home page verification + + Background: + Given I visit Home page + + Scenario: I should see the UI Test Automation Playground title + Then I should see UI Test Automation Playground title + + Scenario: I should see that Home is active menu + Then I should see that Home menu is active by default + + Scenario: I verify that Home menu attr equal /home + Then Home menu should be home + + Scenario: TOP h1 header should be visisble + Then I should see the Playground h1 header at the TOP page part + + Scenario: cube image should be visible + Then I should see the cude image + + Scenario: I want to search the links in Home page + Given Verify additional links + + Examples: + | count | + | 18 | + \ No newline at end of file diff --git a/cypress-cucumber/cypress/integration/features/invalidPwdLogin.feature b/cypress-cucumber/cypress/integration/features/invalidPwdLogin.feature new file mode 100644 index 00000000..23eafd8b --- /dev/null +++ b/cypress-cucumber/cypress/integration/features/invalidPwdLogin.feature @@ -0,0 +1,6 @@ +Feature: Login to App + + Scenario: Login to the application as not-existing user + When I visit sampleapp page + Then I login as user with invalid pwd + Then I should see invalid message \ No newline at end of file diff --git a/cypress-cucumber/cypress/integration/features/loginpageVerification.feature b/cypress-cucumber/cypress/integration/features/loginpageVerification.feature new file mode 100644 index 00000000..5763b73b --- /dev/null +++ b/cypress-cucumber/cypress/integration/features/loginpageVerification.feature @@ -0,0 +1,13 @@ +Feature: Login page verification + + Background: + When I visit sampleapp page + + Scenario: I should see the the h3 header + Then I should see the the h3 header + + Scenario: I should see the Login button + Then I should see the Login button + + Scenario: I should see placeholder in User Name field + Then I should see placeholder in User Name field \ No newline at end of file diff --git a/cypress-cucumber/cypress/integration/features/successfullLogin.feature b/cypress-cucumber/cypress/integration/features/successfullLogin.feature new file mode 100644 index 00000000..bee77a35 --- /dev/null +++ b/cypress-cucumber/cypress/integration/features/successfullLogin.feature @@ -0,0 +1,6 @@ +Feature: Login to App + + Scenario: Login to the application as an exist user + When I visit sampleapp page + Then I login as valid user + Then I should see successfully message \ No newline at end of file diff --git a/cypress-cucumber/cypress/plugins/index.js b/cypress-cucumber/cypress/plugins/index.js deleted file mode 100644 index b1bf2c6a..00000000 --- a/cypress-cucumber/cypress/plugins/index.js +++ /dev/null @@ -1,26 +0,0 @@ -// *********************************************************** -// This example plugins/index.js can be used to load plugins -// -// You can change the location of this file or turn off loading -// the plugins file with the 'pluginsFile' configuration option. -// -// You can read more here: -// https://on.cypress.io/plugins-guide -// *********************************************************** - -// This function is called when a project is opened or re-opened (e.g. due to -// the project's config changing) - -const cucumber = require('cypress-cucumber-preprocessor').default; -const testomatioReporter = require('@testomatio/reporter/lib/adapter/cypress-plugin'); - -module.exports = (on, config) => { - // `on` is used to hook into various events Cypress emits - // `config` is the resolved Cypress config - - on('file:preprocessor', cucumber()); - - testomatioReporter(on, config); - - return config; -}; diff --git a/cypress-cucumber/cypress/support/index.js b/cypress-cucumber/cypress/support/e2e.js similarity index 88% rename from cypress-cucumber/cypress/support/index.js rename to cypress-cucumber/cypress/support/e2e.js index d68db96d..0e7290a1 100644 --- a/cypress-cucumber/cypress/support/index.js +++ b/cypress-cucumber/cypress/support/e2e.js @@ -1,5 +1,5 @@ // *********************************************************** -// This example support/index.js is processed and +// This example support/e2e.js is processed and // loaded automatically before your test files. // // This is a great place to put global configuration and @@ -17,4 +17,4 @@ import './commands' // Alternatively you can use CommonJS syntax: -// require('./commands') +// require('./commands') \ No newline at end of file diff --git a/cypress-cucumber/cypress/support/pages/HomePage.js b/cypress-cucumber/cypress/support/pages/HomePage.js new file mode 100644 index 00000000..88846bff --- /dev/null +++ b/cypress-cucumber/cypress/support/pages/HomePage.js @@ -0,0 +1,28 @@ +class HomePage { + openHomePage() { + return cy.visit("http://uitestingplayground.com"); + } + verifyHomepageTitle(title) { + return cy.title().should('eq', title); + } + verifyHomepageActiveMenuName() { + return cy.get(".nav-item.active > a").should('have.text', 'Home'); + } + verifyHomepageActiveMenuAttr() { + return cy.get(".nav-item.active > a").should('have.attr', 'href', '/home'); + } + playgroundTitleShouldBeVisible() { + return cy.contains("Playground").should('be.visible'); + } + cubeImageShouldBeVisible() { + return cy.get("img.img-fluid").should('be.visible'); + } + verifyLinkCount(count) { + return cy.get("h3 > a").should('have.length', count); + } +} + +const homePage = new HomePage(); + +export default homePage; + diff --git a/cypress-cucumber/cypress/support/pages/LoginPage.js b/cypress-cucumber/cypress/support/pages/LoginPage.js new file mode 100644 index 00000000..3c02f9e6 --- /dev/null +++ b/cypress-cucumber/cypress/support/pages/LoginPage.js @@ -0,0 +1,29 @@ +class LoginPage { + openLoginPage() { + return cy.visit("http://uitestingplayground.com/sampleapp"); + } + loginToApp(userName, password) { + cy.get('input[name="UserName"]').type(userName); + cy.get('input[name="Password"]').type(password); + cy.get('#login').click(); + } + verifyLoginStatus(status) { + return cy.get('#loginstatus').should('have.text', status); + } + verifyH3Header(header) { + return cy.get('.container > h3').should('have.text', header); + } + loginBtnIsVisible() { + return cy.get('#login').should('be.visible'); + } + verifyUserNamePlaceholder() { + return cy.get('input[name="UserName"]') + .should('have.attr', 'placeholder') + .and('eq', 'User Name'); + } +} + +const loginPage = new LoginPage(); + +export default loginPage; + diff --git a/cypress-cucumber/cypress/support/step_definitions/github.js b/cypress-cucumber/cypress/support/step_definitions/github.js deleted file mode 100644 index cf901aa4..00000000 --- a/cypress-cucumber/cypress/support/step_definitions/github.js +++ /dev/null @@ -1,19 +0,0 @@ -import { Given, When, Then } from 'cypress-cucumber-preprocessor/steps'; - -When('I open the GitHub home page', () => { - cy.visit('https://github.com'); -}); - -Then('I should see correct h1', () => { - cy.get('h1') - .next() - .should( - 'have.text', - 'Millions of developers and companies build, ship, and maintain their software on GitHub—the largest and most advanced development platform in the world.' - ); -}); - -Given('I open {string} page', (url) => { - cy.visit(url); -}); - diff --git a/cypress-cucumber/cypress/support/step_definitions/homePage.js b/cypress-cucumber/cypress/support/step_definitions/homePage.js new file mode 100644 index 00000000..4d470d9d --- /dev/null +++ b/cypress-cucumber/cypress/support/step_definitions/homePage.js @@ -0,0 +1,30 @@ +import { Given, Then } from "@badeball/cypress-cucumber-preprocessor"; +import homePage from "../pages/HomePage"; + +Given("I visit Home page", () => { + homePage.openHomePage(); +}); + +Then("I should see UI Test Automation Playground title", () => { + homePage.verifyHomepageTitle("UI Test Automation Playground"); +}); + +Then("I should see the Playground h1 header at the TOP page part", () => { + homePage.playgroundTitleShouldBeVisible(); +}); + +Then("I should see the cude image", () => { + homePage.cubeImageShouldBeVisible(); +}); + +Then("I should see that Home menu is active by default", () => { + homePage.verifyHomepageActiveMenuName(); +}); + +Then("Home menu should be home", () => { + homePage.verifyHomepageActiveMenuAttr(); +}); + +Given('Verify additional links {int}', (count) => { + homePage.verifyLinkCount(count); +}); \ No newline at end of file diff --git a/cypress-cucumber/cypress/support/step_definitions/loginToApp.js b/cypress-cucumber/cypress/support/step_definitions/loginToApp.js new file mode 100644 index 00000000..8ce0b094 --- /dev/null +++ b/cypress-cucumber/cypress/support/step_definitions/loginToApp.js @@ -0,0 +1,36 @@ +import { When, Then } from "@badeball/cypress-cucumber-preprocessor"; +import loginPage from "../pages/LoginPage"; + +const userName = "sampleUser"; + +When("I visit sampleapp page", () => { + loginPage.openLoginPage(); +}); + +Then("I login as valid user", () => { + loginPage.loginToApp(userName, "pwd"); +}); + +Then("I login as user with invalid pwd", () => { + loginPage.loginToApp(userName, "Errorpwd"); +}); + +Then("I should see successfully message", () => { + loginPage.verifyLoginStatus(`Welcome, ${userName}!`); +}); + +Then("I should see invalid message", () => { + loginPage.verifyLoginStatus("Invalid username/password"); +}); + +Then("I should see the the h3 header", () => { + loginPage.verifyH3Header("Sample App"); +}); + +Then("I should see the Login button", () => { + loginPage.loginBtnIsVisible(); +}); + +Then("I should see placeholder in User Name field", () => { + loginPage.verifyUserNamePlaceholder(); +}); diff --git a/cypress-cucumber/package.json b/cypress-cucumber/package.json index bbcee635..a05807cf 100644 --- a/cypress-cucumber/package.json +++ b/cypress-cucumber/package.json @@ -11,10 +11,15 @@ "keywords": [], "author": "", "license": "ISC", + "dependencies": { + "@testomatio/reporter": "^0.7.5", + "cypress": "^12.7.0" + }, "devDependencies": { - "@testomatio/reporter": "^0.5.10", - "cypress": "9.2.0", - "cypress-cucumber-preprocessor": "4.3.1", - "mocha": "^9.1.3" + "@badeball/cypress-cucumber-preprocessor": "^15.1.4", + "@bahmutov/cypress-esbuild-preprocessor": "^2.2.0" + }, + "engines": { + "node": ">=v18.13.0" } } diff --git a/cypress/README.md b/cypress/README.md index d359a84c..5719d2b6 100644 --- a/cypress/README.md +++ b/cypress/README.md @@ -24,7 +24,7 @@ npm i 2. Run `npx check-tests` to upload tests data into testomat.io. Pass `{API_KEY}` as `TESTOMATIO` environment variable: ```bash -TESTOMATIO={API_KEY} npx check-tests cypress "**/**.spec.js" -d cypress/integration/* +TESTOMATIO={API_KEY} npx check-tests cypress "**/**.spec.js" -d cypress/** ``` > **Environment variables** It is recommended to store Testomatio `{API_KEY}` as environment variable and never save it in the source code. Set them directly when running tests or use [dotenv](https://www.npmjs.com/package/dotenv) package to save environment variable in a file and load them for tests. diff --git a/cypress/cypress.config.js b/cypress/cypress.config.js index 684bf070..3d0fb259 100644 --- a/cypress/cypress.config.js +++ b/cypress/cypress.config.js @@ -5,8 +5,9 @@ module.exports = defineConfig({ // We've imported your old cypress plugins here. // You may want to clean this up later by importing these. setupNodeEvents(on, config) { - require('@testomatio/reporter/lib/adapter/cypress-plugin')(on, config); - return require('./cypress/plugins/index.js')(on, config) + // require('@testomatio/reporter/lib/adapter/cypress-plugin')(on, config); + // return require('./cypress/plugins/index.js')(on, config) + return require('@testomatio/reporter/lib/adapter/cypress-plugin')(on, config) }, }, }) diff --git a/cypress/cypress/plugins/index.js b/cypress/cypress/plugins/index.js index c3ec1bc5..5601b0ce 100644 --- a/cypress/cypress/plugins/index.js +++ b/cypress/cypress/plugins/index.js @@ -12,7 +12,7 @@ // This function is called when a project is opened or re-opened (e.g. due to // the project's config changing) -const testomatioReporter = require('@testomatio/reporter/lib/adapter/cypress-plugin'); +// const testomatioReporter = require('@testomatio/reporter/lib/adapter/cypress-plugin'); /** * @type {Cypress.PluginConfig} @@ -21,7 +21,7 @@ module.exports = (on, config) => { // `on` is used to hook into various events Cypress emits // `config` is the resolved Cypress config - testomatioReporter(on, config); + // testomatioReporter(on, config); return config; }; diff --git a/cypress/package.json b/cypress/package.json index 427012c6..c875cc3d 100644 --- a/cypress/package.json +++ b/cypress/package.json @@ -1,15 +1,20 @@ { - "name": "cypress-example", - "version": "1.0.0", - "description": "", + "name": "cypress-example-project", + "version": "1.0.1", + "description": "Running and Monitoring Cypress tests with TESTOMATIO Reporter", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "npx cypress run" }, - "author": "", + "keywords": [ + "e2e", + "testomatio", + "cypress" + ], + "author": "davert, mihaylukvv", "license": "ISC", "devDependencies": { - "@testomatio/reporter": "^0.6.0", - "cypress": "^10" + "@testomatio/reporter": "latest", + "cypress": "^12.17.1" } } diff --git a/cypress/run-tests-and-check-results.sh b/cypress/run-tests-and-check-results.sh new file mode 100644 index 00000000..8846ef5b --- /dev/null +++ b/cypress/run-tests-and-check-results.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +npx cypress run > test-cypress-results.txt +fail_tests=$(grep -oE '\b[0-9]+\s+failing\b' test-cypress-results.txt | grep -oE '[0-9]+') +echo "Number of failed tests: $fail_tests" +if [ "$fail_tests" -gt 1 ]; then + echo "More than 1 failed tests. Exiting with error." + exit 1 +else + exit 0 +fi diff --git a/jest/__tests__/logger-parallel.test.js b/jest/__tests__/logger-parallel.test.js new file mode 100644 index 00000000..472f3dad --- /dev/null +++ b/jest/__tests__/logger-parallel.test.js @@ -0,0 +1,8 @@ +import { logger } from '@testomatio/reporter'; + +describe('Logger test 2', function () { + it('logs should be added to the testomatio report 2', async function () { + console.log('this is 2nd console log message from Jest'); + logger.warn('this is 2nd logger warn message from Jest'); + }); +}); diff --git a/jest/__tests__/logger.test.js b/jest/__tests__/logger.test.js new file mode 100644 index 00000000..c76e2860 --- /dev/null +++ b/jest/__tests__/logger.test.js @@ -0,0 +1,8 @@ +import { logger } from '@testomatio/reporter'; + +describe('Logger test', function () { + it('logs should be added to the testomatio report @T9b799166', async function () { + console.log('this is console log message from Jest'); + logger.warn('this is logger warn message from Jest'); + }); +}); diff --git a/jest/__tests__/testomat-functions.test.js b/jest/__tests__/testomat-functions.test.js new file mode 100644 index 00000000..f56ff52e --- /dev/null +++ b/jest/__tests__/testomat-functions.test.js @@ -0,0 +1,15 @@ +import testomat from '@testomatio/reporter'; + +describe('suite name', () => { + it('artifact is uploaded', async function () { + testomat.artifact('artifacts/artifact-test-text.txt'); + }); + + it('log', async function () { + testomat.log`This is log message`; + }); + + it('step', async function () { + testomat.step('This is step'); + }); +}) diff --git a/jest/artifacts/artifact-test-image.png b/jest/artifacts/artifact-test-image.png new file mode 100644 index 00000000..f844619a Binary files /dev/null and b/jest/artifacts/artifact-test-image.png differ diff --git a/jest/artifacts/artifact-test-text.txt b/jest/artifacts/artifact-test-text.txt new file mode 100644 index 00000000..a250a0b1 --- /dev/null +++ b/jest/artifacts/artifact-test-text.txt @@ -0,0 +1 @@ +this is test artifact content \ No newline at end of file diff --git a/jest/jest.config.js b/jest/jest.config.js index 6ad480ba..17e9c53d 100644 --- a/jest/jest.config.js +++ b/jest/jest.config.js @@ -1,3 +1,5 @@ +require('dotenv').config(); + module.exports = { testEnvironment: "node", reporters: ['default', ['@testomatio/reporter/lib/adapter/jest.js', { apiKey: process.env.TESTOMATIO }]], diff --git a/jest/package.json b/jest/package.json index 9b5bdefe..86767195 100644 --- a/jest/package.json +++ b/jest/package.json @@ -6,8 +6,9 @@ "author": "Koushik Mohan ", "license": "MIT", "dependencies": { - "@testomatio/reporter": "^0.6.5", - "check-tests": "^0.7.3", + "@testomatio/reporter": "latest", + "check-tests": "latest", + "jest": "^29.7.0", "jest-junit": "^13.2.0" }, "devDependencies": { @@ -17,8 +18,7 @@ "eslint": "^6.7.2", "eslint-config-airbnb": "^18.0.1", "eslint-config-airbnb-base": "^14.0.0", - "eslint-plugin-import": "^2.18.2", - "jest": "^24.9.0" + "eslint-plugin-import": "^2.18.2" }, "scripts": { "test": "jest" diff --git a/mocha-ts-multi-reporters/.env.example b/mocha-ts-multi-reporters/.env.example new file mode 100644 index 00000000..e95861d1 --- /dev/null +++ b/mocha-ts-multi-reporters/.env.example @@ -0,0 +1 @@ +TESTOMATIO= diff --git a/mocha-ts-multi-reporters/.eslintrc.json b/mocha-ts-multi-reporters/.eslintrc.json new file mode 100644 index 00000000..1d1c7e17 --- /dev/null +++ b/mocha-ts-multi-reporters/.eslintrc.json @@ -0,0 +1,55 @@ +{ + "env": { + "browser": true, + "es2021": true, + "node": true + }, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:prettier/recommended", + "plugin:import/recommended", + "plugin:import/typescript" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 12, + "sourceType": "module", + "project": "./tsconfig.json", + "tsconfigRootDir": "./" + }, + "plugins": ["@typescript-eslint", "prettier", "no-only-tests"], + "rules": { + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/explicit-module-boundary-types": [ + "off", + { + "allowArgumentsExplicitlyTypedAsAny": true + } + ], + "indent": ["error", 2], + "quotes": ["error", "single", {"avoidEscape": true}], + "semi": ["error", "never"], + "no-undef": "off", + "no-only-tests/no-only-tests": ["error", {"fix": true}], + "prettier/prettier": [ + "error", + { + "semi": false, + "singleQuote": true, + "printWidth": 80, + "tabWidth": 2, + "arrowParens": "avoid", + "trailingComma": "none", + "endOfLine": "auto" + } + ] + }, + "settings": { + "import/resolver": { + "typescript": { + "alwaysTryTypes": true + } + } + } +} diff --git a/mocha-ts-multi-reporters/.gitignore b/mocha-ts-multi-reporters/.gitignore new file mode 100644 index 00000000..0eaacc0e --- /dev/null +++ b/mocha-ts-multi-reporters/.gitignore @@ -0,0 +1,107 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +/node_modules/* +/jspm_packages/* + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# Next.js build output +.next + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and *not* Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +#idea basic folder +.idea/* \ No newline at end of file diff --git a/mocha-ts-multi-reporters/.mocharc.js b/mocha-ts-multi-reporters/.mocharc.js new file mode 100644 index 00000000..67698760 --- /dev/null +++ b/mocha-ts-multi-reporters/.mocharc.js @@ -0,0 +1,6 @@ +module.exports = { + require: ['ts-node/register', 'dotenv/config'], + spec: './spec/**/*.spec.ts', + reporter: 'mocha-multi-reporters', + reporterOptions: ['configFile=reporter.conf.js'] +} diff --git a/mocha-ts-multi-reporters/README.md b/mocha-ts-multi-reporters/README.md new file mode 100644 index 00000000..a1b9f8e2 --- /dev/null +++ b/mocha-ts-multi-reporters/README.md @@ -0,0 +1,68 @@ +# 📊 Mocha + TypeScript + Multi Reporters Example +This repo contains simple template for testing project with Multiple reports based on the stack = Mocha + TypeScript + Spec report & Testomat.io plugins. + +# Installation +This is a playground for your first steps in testing, so instead of installing it from NPM it is recommended to clone it from repo instead. + +1) Clone this repository: + +``` +git clone git@github.com:testomatio/examples.git && cd examples/mocha-ts-multi-reporters +``` +## Requirements: + **in order to run this project, NodeJS (version 18+) must be installed** + + +2) Install dependencies via npm: + +``` +npm i +``` + +_This will install mocha & typescript env + Testomat.io reporter_ + +3) Run tests localy without sending report to the Testomat.io: + +``` +npm tests +``` +_(if the tests are completed => you can start setting up the testomat.io reporter)_ + +## Loading Tests to Testomat.io + +1. Create empty project in Testomat.io +2. Obtain API key from Testomat.io +2. Run `npx check-tests` to upload tests data into testomat.io. Pass api key as `TESTOMATIO` environment variable: + +``` +TESTOMATIO={apiKey} npx check-tests@latest mocha "**/*{.,_}{test,spec}.ts" --typescript -d spec +``` + +## Publishing Test Results to Testomat.io + +1. Get API key from a project in Testomat.io. + +2. Create a specific .env file: +> **Environment variables** +```.env``` file using ```env.example``` as a template +### SET key variable +**(if you don't want to use the TESTOMATIO API key when running testomatIO, then you can store the token in the ```.env``` file (see env.example example))** + +3. Run tests and generate reports(Testomat.io): + +``` +npx mocha +``` +OR +``` +npm test +``` + +### reporterOptions additinal options +**In our case, we use multiple reporters: spec & testomatio.** + +_!! Pay Attantion on the rpConfgi.js file. Using key-name should be equal path to the testomatio adapter(testomatio/reporter/lib/adapter/mocha.js)._ + Like: +``` +testomatioReporterLibAdapterMochaJsReporterOptions +``` \ No newline at end of file diff --git a/mocha-ts-multi-reporters/artifacts/artifact-test-image.png b/mocha-ts-multi-reporters/artifacts/artifact-test-image.png new file mode 100644 index 00000000..f844619a Binary files /dev/null and b/mocha-ts-multi-reporters/artifacts/artifact-test-image.png differ diff --git a/mocha-ts-multi-reporters/artifacts/artifact-test-text.txt b/mocha-ts-multi-reporters/artifacts/artifact-test-text.txt new file mode 100644 index 00000000..a250a0b1 --- /dev/null +++ b/mocha-ts-multi-reporters/artifacts/artifact-test-text.txt @@ -0,0 +1 @@ +this is test artifact content \ No newline at end of file diff --git a/mocha-ts-multi-reporters/package.json b/mocha-ts-multi-reporters/package.json new file mode 100644 index 00000000..90243fdd --- /dev/null +++ b/mocha-ts-multi-reporters/package.json @@ -0,0 +1,40 @@ +{ + "name": "mocha-typescript", + "version": "1.0.1", + "description": "Example testomatio project with Mocha+TypeScript", + "main": "index.js", + "scripts": { + "test": "mocha" + }, + "keywords": [ + "mocha", + "typescript", + "e2e", + "test automation" + ], + "author": "Vitalii Mykhailiuk (vmykhailiuk.chanel@gmail.com)", + "license": "MIT", + "dependencies": { + "@testomatio/reporter": "latest", + "@types/chai": "4.3.4", + "@types/mocha": "10.0.1", + "@types/node": "18.11.18", + "chai": "4.3.7", + "dotenv": "16.0.3", + "mocha": "10.2.0", + "mocha-multi-reporters": "1.5.1", + "ts-node": "10.9.1", + "typescript": "4.9.4" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "5.48.2", + "@typescript-eslint/parser": "5.48.2", + "eslint": "8.32.0", + "eslint-config-prettier": "8.6.0", + "eslint-import-resolver-typescript": "3.5.3", + "eslint-plugin-import": "2.27.5", + "eslint-plugin-no-only-tests": "3.1.0", + "eslint-plugin-prettier": "4.2.1", + "prettier": "2.8.3" + } +} diff --git a/mocha-ts-multi-reporters/reporter.conf.js b/mocha-ts-multi-reporters/reporter.conf.js new file mode 100644 index 00000000..cdb8fbfe --- /dev/null +++ b/mocha-ts-multi-reporters/reporter.conf.js @@ -0,0 +1,6 @@ +module.exports = { + reporterEnabled: 'spec, @testomatio/reporter/lib/adapter/mocha.js', + testomatioReporterLibAdapterMochaJsReporterOptions: { + apiKey: process.env.TESTOMATIO + } +} diff --git a/mocha-ts-multi-reporters/spec/logger.spec.ts b/mocha-ts-multi-reporters/spec/logger.spec.ts new file mode 100644 index 00000000..74234156 --- /dev/null +++ b/mocha-ts-multi-reporters/spec/logger.spec.ts @@ -0,0 +1,9 @@ +import { logger, log } from '@testomatio/reporter'; + +describe('Logger test @S2f6e76f8', function () { + it('logs should be added to the testomatio report @T7f509392', async function () { + console.log('this is console log message'); + logger.warn('this is logger warn message'); + log`This is log message` + }); +}); diff --git a/mocha-ts-multi-reporters/spec/test.example.spec.ts b/mocha-ts-multi-reporters/spec/test.example.spec.ts new file mode 100644 index 00000000..4cfd951b --- /dev/null +++ b/mocha-ts-multi-reporters/spec/test.example.spec.ts @@ -0,0 +1,79 @@ +import { testomatioLogger } from '@testomatio/reporter'; +import { expect } from 'chai'; + +describe("Array", function() { + let arr; + + beforeEach(function() { + arr = [1, 2, 3]; + }); + + // Test Case 1 + it("should return -1 when the value is not present", function() { + expect(arr.indexOf(4)).to.equal(-1); + }); + + // Test Case 2 + it("should return the index of the element when it is present", function() { + expect(arr.indexOf(2)).to.equal(1); + }); + + // Test Case 3 + it("should return the length of the array after adding an element", function() { + arr.push(4); + expect(arr.length).to.equal(4); + }); + + it("should fail and return -1 as the value is not present", function() { + expect(arr.indexOf(4)).to.equal(3); + }); + + it.skip("should be skipped", function() { + arr.push(4); + expect(arr.length).to.equal(4); + }); + + // Test Case 4 + it("should return the first element of the array", function() { + expect(arr[0]).to.equal(1); + }); + + // Test Case 5 + it("should return the sum of all elements in the array", function() { + expect(arr.reduce((a, b) => a + b, 0)).to.equal(6); + }); + + // Test Case 6 + it("should return the last element of the array", function() { + expect(arr[2]).to.equal(3); + }); + + // Test Case 7 + it("should return a reversed array", function() { + expect(arr.reverse()).to.deep.equal([3, 2, 1]); + }); + + // Test Case 8 + it("should return the array after removing the first element", function() { + expect(arr.slice(1)).to.deep.equal([2, 3]); + }); + + // Test Case 9 + it("should return a new array with all elements multiplied by 2", function() { + expect(arr.map(x => x * 2)).to.deep.equal([2, 4, 6]); + }); + + // Test Case 10 + it("should return a sorted array in ascending order", function() { + expect([3, 2, 1].sort()).to.deep.equal([1, 2, 3]); + }); + + + // Test Case 11 + it("should attach logs", function () { + console.warn('console warn message'); + testomatioLogger.debug('testomatio logger debug message'); + expect(arr.indexOf(4)).to.equal(-1); + }); +}); + diff --git a/mocha-ts-multi-reporters/spec/testomat-functions.spec.ts b/mocha-ts-multi-reporters/spec/testomat-functions.spec.ts new file mode 100644 index 00000000..2dfae297 --- /dev/null +++ b/mocha-ts-multi-reporters/spec/testomat-functions.spec.ts @@ -0,0 +1,16 @@ +import testomat, { log } from '@testomatio/reporter'; + +describe('Testomat functions @S43849225', () => { + it('attach image @T93dc3526', () => { + + testomat.artifact('artifacts/artifact-test-image.png'); + }); + + it('log message @T6fdfc777', () => { + log`This is log message`; + }); + + it('add step @T2fa88ab9', () => { + testomat.step('This is step message'); + }); +}); diff --git a/mocha-ts-multi-reporters/tsconfig.json b/mocha-ts-multi-reporters/tsconfig.json new file mode 100644 index 00000000..2adf7221 --- /dev/null +++ b/mocha-ts-multi-reporters/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "esModuleInterop": true, + "moduleResolution": "Node", + "module": "commonjs", + "outDir": "built", + "target": "ES2019", + "sourceMap": true + }, + "include": ["**/*.ts", "**/*.js"], + "exclude": ["node_modules"] +} \ No newline at end of file diff --git a/newman/README.md b/newman/README.md new file mode 100644 index 00000000..3d43a935 --- /dev/null +++ b/newman/README.md @@ -0,0 +1,47 @@ +### Example project for newman-reporter-testomatio + +This is example project for [newman-reporter-testomatio](https://www.npmjs.com/package/newman-reporter-testomatio) package usage. + +# Usage + +### Running in this project +1. Install modules: +\ +`npm i` + +2. Run tests +- `TESTOMATIO= npm run test` +- `TESTOMATIO= npm run test:fail` + + +### Running in **your** project +1. Install package +\ +`npm i newman-reporter-testomatio` + +2. Run collection and specify `testomatio` as reporter: +\ +`TESTOMATIO= npx newman run -e -r testomatio ` +\ +> -e (environment) is optional param; others are required + +Examples: +\ +`TESTOMATIO= npx newman run collection.json -e env.json -r testomatio` +\ +`TESTOMATIO= npx newman run collection_fail.json -e env.json -r testomatio` + +> No need to pass `TESTOMATIO_CREATE=1`. This param is already set by default when using `newman-reporter-testomatio`. + +## Troubleshooting +### If you got an error running your collection _("could not find testomatio reporter")_, read next +\ +`newman` and `newman-reporter-testomatio` should be installed in the same directory. +- If you run your tests using **globally** installed newman (`newman run ...`): +\ +intall `newman-reporter-testomatio` globally too (`npm i newman-reporter-testomatio -g`). +- If you use **locally** installed newman (within the project) (`npx newman run ...`): +\ +Follow default flow – just `npm i` + +You can verify installed packages via `npm list` or `npm list -g` diff --git a/newman/collection.json b/newman/collection.json new file mode 100644 index 00000000..3663af09 --- /dev/null +++ b/newman/collection.json @@ -0,0 +1,259 @@ +{ + "info": { + "_postman_id": "74f760d2-689d-4064-bd69-77752ad0c3a9", + "name": "Echo collection", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "11123710" + }, + "item": [ + { + "name": "Request with url params", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status test\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Status test\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.args.paramName).to.equal('paramValue');", + "});", + "", + "pm.test(\"Variable value is updated in pre-request script\", function () {", + " const updateVariableValue = pm.environment.get('textVar');", + " pm.expect(updateVariableValue).to.equal('textVarValue');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "postman-echo.com/get?paramName=paramValue", + "host": [ + "postman-echo", + "com" + ], + "path": [ + "get" + ], + "query": [ + { + "key": "paramName", + "value": "paramValue" + } + ] + } + }, + "response": [] + }, + { + "name": "Request with pre-request script", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Variable value is updated in pre-request script\", function () {", + " const updateVariableValue = pm.environment.get('textVar');", + " pm.expect(updateVariableValue).to.equal('updatedTextVar');", + "});", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "console.log('This is pre-request script');", + "pm.environment.set('textVar', 'updatedTextVar');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "postman-echo.com/get?paramName=paramValue", + "host": [ + "postman-echo", + "com" + ], + "path": [ + "get" + ], + "query": [ + { + "key": "paramName", + "value": "paramValue" + } + ] + } + }, + "response": [] + }, + { + "name": "Post request with env variables", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "console.log('This is pre-request script');", + "console.log('Printing environment variable value:', pm.environment.get('url'));", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Environment variables are got properly\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.data.testKey).to.equal(13);", + " ", + " const paramName = pm.environment.get('paramName');", + " const paramValue = pm.environment.get('paramValue');", + " pm.expect(responseJson.args[paramName]).to.equal(paramValue);", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"testKey\": {{numberVar}}\n}\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{url}}/post?{{paramName}}={{paramValue}}", + "host": [ + "{{url}}" + ], + "path": [ + "post" + ], + "query": [ + { + "key": "{{paramName}}", + "value": "{{paramValue}}" + } + ] + } + }, + "response": [] + }, + { + "name": "Put request with body", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status test\", function () {", + " pm.response.to.have.status(200);", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"key1\": \"someValue\",\n \"key2\": 13\n}\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://postman-echo.com/put", + "protocol": "https", + "host": [ + "postman-echo", + "com" + ], + "path": [ + "put" + ] + } + }, + "response": [] + }, + { + "name": "Request with auth", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status test\", function () {", + " pm.expect(pm.request.auth.type).to.equal('apikey');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "apikey", + "apikey": [ + { + "key": "key", + "value": "testTokenName", + "type": "string" + }, + { + "key": "value", + "value": "testTokenValue", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "https://postman-echo.com/get", + "protocol": "https", + "host": [ + "postman-echo", + "com" + ], + "path": [ + "get" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/newman/collection_fail.json b/newman/collection_fail.json new file mode 100644 index 00000000..66f32a98 --- /dev/null +++ b/newman/collection_fail.json @@ -0,0 +1,291 @@ +{ + "info": { + "_postman_id": "74f760d2-689d-4064-bd69-77752ad0c3a9", + "name": "Echo collection", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "11123710" + }, + "item": [ + { + "name": "Request with url params", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status test\", function () {", + " pm.response.to.have.status(200);", + "});", + "", + "pm.test(\"Status test\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.args.paramName).to.equal('paramValue');", + "});", + "", + "pm.test(\"Variable value is updated in pre-request script\", function () {", + " const updateVariableValue = pm.environment.get('textVar');", + " pm.expect(updateVariableValue).to.equal('textVarValue');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "postman-echo.com/get?paramName=paramValue", + "host": [ + "postman-echo", + "com" + ], + "path": [ + "get" + ], + "query": [ + { + "key": "paramName", + "value": "paramValue" + } + ] + } + }, + "response": [] + }, + { + "name": "Request with pre-request script", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Variable value is updated in pre-request script\", function () {", + " const updateVariableValue = pm.environment.get('textVar');", + " pm.expect(updateVariableValue).to.equal('updatedTextVar');", + "});", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "console.log('This is pre-request script');", + "pm.environment.set('textVar', 'updatedTextVar');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "postman-echo.com/get?paramName=paramValue", + "host": [ + "postman-echo", + "com" + ], + "path": [ + "get" + ], + "query": [ + { + "key": "paramName", + "value": "paramValue" + } + ] + } + }, + "response": [] + }, + { + "name": "Post request with env variables", + "event": [ + { + "listen": "prerequest", + "script": { + "exec": [ + "console.log('This is pre-request script');", + "console.log('Printing environment variable value:', pm.environment.get('url'));", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Environment variables are got properly\", function () {", + " const responseJson = pm.response.json();", + " pm.expect(responseJson.data.testKey).to.equal(13);", + " ", + " const paramName = pm.environment.get('paramName');", + " const paramValue = pm.environment.get('paramValue');", + " pm.expect(responseJson.args[paramName]).to.equal(paramValue);", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"testKey\": {{numberVar}}\n}\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "{{url}}/post?{{paramName}}={{paramValue}}", + "host": [ + "{{url}}" + ], + "path": [ + "post" + ], + "query": [ + { + "key": "{{paramName}}", + "value": "{{paramValue}}" + } + ] + } + }, + "response": [] + }, + { + "name": "Put request with body", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status test\", function () {", + " pm.response.to.have.status(200);", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [], + "body": { + "mode": "raw", + "raw": "{\n \"key1\": \"someValue\",\n \"key2\": 13\n}\n", + "options": { + "raw": { + "language": "json" + } + } + }, + "url": { + "raw": "https://postman-echo.com/put", + "protocol": "https", + "host": [ + "postman-echo", + "com" + ], + "path": [ + "put" + ] + } + }, + "response": [] + }, + { + "name": "Request with auth", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status test\", function () {", + " pm.expect(pm.request.auth.type).to.equal('apikey');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "apikey", + "apikey": [ + { + "key": "key", + "value": "testTokenName", + "type": "string" + }, + { + "key": "value", + "value": "testTokenValue", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "https://postman-echo.com/get", + "protocol": "https", + "host": [ + "postman-echo", + "com" + ], + "path": [ + "get" + ] + } + }, + "response": [] + }, + { + "name": "Failing tests", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"This test will fail\", function () {", + " pm.response.to.have.status(222);", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "postman-echo.com/get", + "host": [ + "postman-echo", + "com" + ], + "path": [ + "get" + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/newman/collection_with_folders.json b/newman/collection_with_folders.json new file mode 100644 index 00000000..aece8d93 --- /dev/null +++ b/newman/collection_with_folders.json @@ -0,0 +1,204 @@ +{ + "info": { + "_postman_id": "3ae15048-6df3-4905-b68a-ec869d4c348b", + "name": "Echo collection with folders", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", + "_exporter_id": "11123710" + }, + "item": [ + { + "name": "Folder 1", + "item": [ + { + "name": "Request with url params", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "postman-echo.com/get", + "host": [ + "postman-echo", + "com" + ], + "path": [ + "get" + ] + } + }, + "response": [] + }, + { + "name": "Request with pre-request script", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Variable value is updated in pre-request script\", function () {", + " const updateVariableValue = pm.environment.get('textVar');", + " pm.expect(updateVariableValue).to.equal('updatedTextVar');", + "});", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "console.log('This is pre-request script');", + "pm.environment.set('textVar', 'updatedTextVar');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "postman-echo.com/get?paramName=paramValue", + "host": [ + "postman-echo", + "com" + ], + "path": [ + "get" + ], + "query": [ + { + "key": "paramName", + "value": "paramValue" + } + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Folder 2", + "item": [ + { + "name": "Nested folder", + "item": [ + { + "name": "Request inside nested folder", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Status test\", function () {", + " pm.expect(pm.request.auth.type).to.equal('apikey');", + "});", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "auth": { + "type": "apikey", + "apikey": [ + { + "key": "key", + "value": "testTokenName", + "type": "string" + }, + { + "key": "value", + "value": "testTokenValue", + "type": "string" + } + ] + }, + "method": "GET", + "header": [], + "url": { + "raw": "https://postman-echo.com/get", + "protocol": "https", + "host": [ + "postman-echo", + "com" + ], + "path": [ + "get" + ] + } + }, + "response": [] + } + ] + } + ] + }, + { + "name": "Empty folder", + "item": [] + }, + { + "name": "Request within collection (not in folder)", + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test(\"Variable value is updated in pre-request script\", function () {", + " const updateVariableValue = pm.environment.get('textVar');", + " pm.expect(updateVariableValue).to.equal('updatedTextVar');", + "});", + "" + ], + "type": "text/javascript" + } + }, + { + "listen": "prerequest", + "script": { + "exec": [ + "console.log('This is pre-request script');", + "pm.environment.set('textVar', 'updatedTextVar');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "postman-echo.com/get?paramName=paramValue", + "host": [ + "postman-echo", + "com" + ], + "path": [ + "get" + ], + "query": [ + { + "key": "paramName", + "value": "paramValue" + } + ] + } + }, + "response": [] + } + ] +} \ No newline at end of file diff --git a/newman/env.json b/newman/env.json new file mode 100644 index 00000000..ba325f8c --- /dev/null +++ b/newman/env.json @@ -0,0 +1,39 @@ +{ + "id": "90577d60-1765-4393-a768-571eba881da3", + "name": "testomatio", + "values": [ + { + "key": "url", + "value": "postman-echo.com", + "type": "default", + "enabled": true + }, + { + "key": "paramName", + "value": "someParamName", + "type": "default", + "enabled": true + }, + { + "key": "textVar", + "value": "textVarValue", + "type": "default", + "enabled": true + }, + { + "key": "paramValue", + "value": "someParamValue", + "type": "default", + "enabled": true + }, + { + "key": "numberVar", + "value": "13", + "type": "default", + "enabled": true + } + ], + "_postman_variable_scope": "environment", + "_postman_exported_at": "2023-03-12T08:55:53.203Z", + "_postman_exported_using": "Postman/10.11.2" +} \ No newline at end of file diff --git a/newman/package.json b/newman/package.json new file mode 100644 index 00000000..0d15a235 --- /dev/null +++ b/newman/package.json @@ -0,0 +1,16 @@ +{ + "name": "example-project-for-newman-reporter-testomatio", + "version": "0.0.1", + "description": "Example project for testomatio reporter using newman", + "main": "index.js", + "scripts": { + "test": "npx newman run collection.json -e env.json -r testomatio", + "test:fail": "npx newman run collection_fail.json -e env.json -r testomatio" + }, + "author": "", + "license": "ISC", + "dependencies": { + "newman": "^5.3.2", + "newman-reporter-testomatio": "latest" + } +} diff --git a/playwright/.gitignore b/playwright/.gitignore index bf771ee0..8461164f 100644 --- a/playwright/.gitignore +++ b/playwright/.gitignore @@ -2,3 +2,6 @@ node_modules/ test-results/ playwright-report/ .env +/test-results/ +/playwright-report/ +/playwright/.cache/ diff --git a/playwright/README.md b/playwright/README.md index 838f10bb..d9f40e59 100644 --- a/playwright/README.md +++ b/playwright/README.md @@ -16,6 +16,24 @@ git clone git@github.com:testomatio/examples.git && cd examples/playwright npm i ``` +2.1) Run tests to check if they work (via npm): + +``` +npm run test:e2e +``` + +2.2) Run only smoke tests (via npm): + +```sh +npm run test:smoke-examples +``` + +2.3) Run only e2e tests (via npm): + +```sh +npm run test:e2e-examples +``` + This will install Playwright with puppeteer & Testomat.io reporter ## Loading Tests to Testomat.io @@ -25,17 +43,22 @@ This will install Playwright with puppeteer & Testomat.io reporter 2. Run `npx check-tests` to upload tests data into testomat.io. Pass api key as `TESTOMATIO` environment variable: ``` -TESTOMATIO={apiKey} npx check-tests playwright --typescript "**/*{.,_}spec.ts" +TESTOMATIO={apiKey} npx check-tests@latest Playwright "**/*{.,_}{test,spec,cy}.ts" --typescript ``` > **Environment variables** It is recommended to store Testomatio API Key as environment variable and never save it in the source code. Set them directly when running tests or use [dotenv](https://www.npmjs.com/package/dotenv) package to save environment variable in a file and load them for tests. -## Publishing Test Results to Testomat.io +## Publishing Test Results to Testomat.io (all available tests) Get API key from a project in Testomat.io and set it as environment variable `TESTOMATIO`: ``` -TESTOMATIO={apiKey} npx playwright tests +TESTOMATIO={apiKey} npx playwright test +``` + +_or only smoke tests:_ +``` +TESTOMATIO={key} npx playwright test --config e2e-examples/playwright-smoke.config.ts ``` ### Configuration @@ -50,3 +73,7 @@ reporter: [ }] ], ``` + +### Pay attention + +_One test has a "FAIL" status... to fix it, see the instructions in the TODO section in file => e2e-examples/e2e-tests/1-getting-started.spec.ts_ \ No newline at end of file diff --git a/playwright/artifacts/artifact-test-image.png b/playwright/artifacts/artifact-test-image.png new file mode 100644 index 00000000..f844619a Binary files /dev/null and b/playwright/artifacts/artifact-test-image.png differ diff --git a/playwright/artifacts/artifact-test-text.txt b/playwright/artifacts/artifact-test-text.txt new file mode 100644 index 00000000..a250a0b1 --- /dev/null +++ b/playwright/artifacts/artifact-test-text.txt @@ -0,0 +1 @@ +this is test artifact content \ No newline at end of file diff --git a/playwright/e2e-examples/README.md b/playwright/e2e-examples/README.md index ad807c66..3051cd2a 100644 --- a/playwright/e2e-examples/README.md +++ b/playwright/e2e-examples/README.md @@ -2,7 +2,23 @@ This directory contains examples for Playwright. Run them with the following command: +### e2e tests only + ```sh npm run test:e2e-examples yarn test:e2e-examples ``` + +### smoke tests only + +```sh +npm run test:smoke-examples +yarn test:smoke-examples +``` + +### all available tests + +```sh +npm run test:e2e +yarn test:e2e +``` \ No newline at end of file diff --git a/playwright/e2e-examples/1-getting-started.spec.ts b/playwright/e2e-examples/e2e-tests/1-getting-started.spec.ts similarity index 76% rename from playwright/e2e-examples/1-getting-started.spec.ts rename to playwright/e2e-examples/e2e-tests/1-getting-started.spec.ts index fcc82835..7eb053a1 100644 --- a/playwright/e2e-examples/1-getting-started.spec.ts +++ b/playwright/e2e-examples/e2e-tests/1-getting-started.spec.ts @@ -13,5 +13,6 @@ test('basic test', async ({ page }) => { await inputBox.fill('Learn Playwright'); await inputBox.press('Enter'); - await expect(todoList).toHaveText('Le1arn Playwright'); + // example of test with status FAIL + await expect(todoList).toHaveText('Le1arn Playwright'); //TODO: To fix update text to => 'Learn Playwright' }); diff --git a/playwright/e2e-examples/2-actions.spec.ts b/playwright/e2e-examples/e2e-tests/2-actions.spec.ts similarity index 96% rename from playwright/e2e-examples/2-actions.spec.ts rename to playwright/e2e-examples/e2e-tests/2-actions.spec.ts index 18634ff0..58c73804 100644 --- a/playwright/e2e-examples/2-actions.spec.ts +++ b/playwright/e2e-examples/e2e-tests/2-actions.spec.ts @@ -44,7 +44,7 @@ test('element selectors', async ({ page }) => { await page.click('.todoapp .footer >> text=Completed'); // Selecting based on layout, with css selector - expect(await page.innerText('a:right-of(:text("Active"))')).toBe('Completed'); + expect(await page.innerText('a:right-of(:text("Active"))')).toBe('Completed1'); //TODO: to fix this test use ".toBe('Completed')" // Only visible elements, with css selector await page.click('text=Completed >> visible=true'); diff --git a/playwright/e2e-examples/3-assertions.spec.ts b/playwright/e2e-examples/e2e-tests/3-assertions.spec.ts similarity index 100% rename from playwright/e2e-examples/3-assertions.spec.ts rename to playwright/e2e-examples/e2e-tests/3-assertions.spec.ts diff --git a/playwright/e2e-examples/4-file-uploads.spec.ts b/playwright/e2e-examples/e2e-tests/4-file-uploads.spec.ts similarity index 100% rename from playwright/e2e-examples/4-file-uploads.spec.ts rename to playwright/e2e-examples/e2e-tests/4-file-uploads.spec.ts diff --git a/playwright/e2e-examples/5-networking.spec.ts b/playwright/e2e-examples/e2e-tests/5-networking.spec.ts similarity index 100% rename from playwright/e2e-examples/5-networking.spec.ts rename to playwright/e2e-examples/e2e-tests/5-networking.spec.ts diff --git a/playwright/e2e-examples/server/assets/api/v1/users.json b/playwright/e2e-examples/e2e-tests/server/assets/api/v1/users.json similarity index 100% rename from playwright/e2e-examples/server/assets/api/v1/users.json rename to playwright/e2e-examples/e2e-tests/server/assets/api/v1/users.json diff --git a/playwright/e2e-examples/server/assets/file-uploads.html b/playwright/e2e-examples/e2e-tests/server/assets/file-uploads.html similarity index 100% rename from playwright/e2e-examples/server/assets/file-uploads.html rename to playwright/e2e-examples/e2e-tests/server/assets/file-uploads.html diff --git a/playwright/e2e-examples/server/assets/header.html b/playwright/e2e-examples/e2e-tests/server/assets/header.html similarity index 100% rename from playwright/e2e-examples/server/assets/header.html rename to playwright/e2e-examples/e2e-tests/server/assets/header.html diff --git a/playwright/e2e-examples/server/assets/index.html b/playwright/e2e-examples/e2e-tests/server/assets/index.html similarity index 100% rename from playwright/e2e-examples/server/assets/index.html rename to playwright/e2e-examples/e2e-tests/server/assets/index.html diff --git a/playwright/e2e-examples/server/assets/network.html b/playwright/e2e-examples/e2e-tests/server/assets/network.html similarity index 100% rename from playwright/e2e-examples/server/assets/network.html rename to playwright/e2e-examples/e2e-tests/server/assets/network.html diff --git a/playwright/e2e-examples/server/index.js b/playwright/e2e-examples/e2e-tests/server/index.js similarity index 100% rename from playwright/e2e-examples/server/index.js rename to playwright/e2e-examples/e2e-tests/server/index.js diff --git a/playwright/e2e-examples/playwright.config.ts b/playwright/e2e-examples/playwright-e2e.config.ts similarity index 65% rename from playwright/e2e-examples/playwright.config.ts rename to playwright/e2e-examples/playwright-e2e.config.ts index 021eeb31..e7537f1f 100644 --- a/playwright/e2e-examples/playwright.config.ts +++ b/playwright/e2e-examples/playwright-e2e.config.ts @@ -5,9 +5,16 @@ const config: PlaywrightTestConfig = { // Run your local dev server before starting the tests: // https://playwright.dev/docs/test-advanced#launching-a-development-web-server-during-the-tests webServer: { - command: 'node ./server', + command: 'node ./e2e-tests/server', port: 4345, cwd: __dirname, }, + testMatch: '*e2e-tests/*.spec.ts', + reporter: [ + ['list'], + ['@testomatio/reporter/lib/adapter/playwright.js', { + apiKey: process.env.TESTOMATIO, + }] + ] }; export default config; diff --git a/playwright/e2e-examples/playwright-smoke.config.ts b/playwright/e2e-examples/playwright-smoke.config.ts new file mode 100644 index 00000000..8c3b704b --- /dev/null +++ b/playwright/e2e-examples/playwright-smoke.config.ts @@ -0,0 +1,13 @@ +import { PlaywrightTestConfig } from '@playwright/test'; + +// Reference: https://playwright.dev/docs/test-configuration +const config: PlaywrightTestConfig = { + testMatch: '*smoke-tests/*.spec.ts', + reporter: [ + ['list'], + ['@testomatio/reporter/lib/adapter/playwright.js', { + apiKey: process.env.TESTOMATIO, + }] + ] +}; +export default config; diff --git a/playwright/e2e-examples/smoke-tests/smoke-test-1.spec.ts b/playwright/e2e-examples/smoke-tests/smoke-test-1.spec.ts new file mode 100644 index 00000000..e8e2cc9e --- /dev/null +++ b/playwright/e2e-examples/smoke-tests/smoke-test-1.spec.ts @@ -0,0 +1,17 @@ +import { test, expect } from '@playwright/test'; +import Basic from "../src/Basic"; + +const basic = new Basic(); + +test.describe('Smoke case-1', () => { + const basicPage = basic.basicPageUrl(); + + test.beforeEach(async ({ page }) => { + await page.goto(basicPage); + }); + + test('has title', async ({ page }) => { + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle(/Playwright/); + }); +}); \ No newline at end of file diff --git a/playwright/e2e-examples/smoke-tests/smoke-test-2.spec.ts b/playwright/e2e-examples/smoke-tests/smoke-test-2.spec.ts new file mode 100644 index 00000000..d6c6d69f --- /dev/null +++ b/playwright/e2e-examples/smoke-tests/smoke-test-2.spec.ts @@ -0,0 +1,35 @@ +import { test, expect } from '@playwright/test'; +import Basic from "../src/Basic"; + +const basic = new Basic(); + +test.describe('Basic', () => { + const basicPage = basic.basicPageUrl(); + + test.beforeEach(async ({ page }) => { + await page.goto(basicPage); + }); + test.describe('Main Basic tests', () => { + test.describe('[Case 1] Basic page checks 1', () => { + test('get started link', async ({ page }) => { + await test.step(`[Check 1.1] Basic page - click the link`, async () => { + await page.getByRole('link', { name: 'Get started' }).click(); + }); + await test.step(`[Check 1.2] Get started - Expects the URL to contain intro.`, async () => { + await expect(page).toHaveURL(/.*intro/); + }); + }); + }); + + test.describe('[Case 2] Basic page checks 2', () => { + test('get started link', async ({ page }) => { + await test.step(`[Check 2.1] Basic page - click the link`, async () => { + await page.getByRole('link', { name: 'Get started' }).click(); + }); + await test.step(`[Check 2.2] Get started - Expects the URL to contain intro.`, async () => { + await expect(page).toHaveURL(/.*intro/); + }); + }); + }); + }); +}); \ No newline at end of file diff --git a/playwright/e2e-examples/smoke-tests/smoke-test-3.spec.ts b/playwright/e2e-examples/smoke-tests/smoke-test-3.spec.ts new file mode 100644 index 00000000..982a2e85 --- /dev/null +++ b/playwright/e2e-examples/smoke-tests/smoke-test-3.spec.ts @@ -0,0 +1,36 @@ +import { test, expect } from '@playwright/test'; + +test.describe( + 'simple url cheks', + () => { + // Suite + test.describe('Check home page url', () => { + test('get started link', async ({ page }) => { + // Access to the basic page + await page.goto('https://playwright.dev/'); + + // Expects the 'Get started' is shown + await expect(page.getByRole('link', { name: 'Get started' })).toBeVisible(); + }); + }); + + test.describe.skip('Check home page url (skip)', () => { + test('get started link (skip)', async ({ page }) => { + // Access to the basic page + await page.goto('https://playwright.dev/'); + + // Expects the 'Get started' is shown + await expect(page.getByRole('link', { name: 'Get started' })).toBeVisible(); + }); + }); + + test.describe.fixme('Check home page url (fixme)', () => { + test('get started link (fixme)', async ({ page }) => { + // Access to the basic page + await page.goto('https://playwright.dev/'); + + // Expects the 'Get started' is shown + await expect(page.getByRole('link', { name: 'Get started' })).toBeVisible(); + }); + }); + }); \ No newline at end of file diff --git a/playwright/e2e-examples/smoke-tests/smoke-test-4.spec.ts b/playwright/e2e-examples/smoke-tests/smoke-test-4.spec.ts new file mode 100644 index 00000000..5b93826d --- /dev/null +++ b/playwright/e2e-examples/smoke-tests/smoke-test-4.spec.ts @@ -0,0 +1,20 @@ +import { test, expect } from '@playwright/test'; + +test.describe.skip('Skip condition testing', () => { + test.describe('All tests should be skipped', () => { + test('Test-1: get started linkshould be visible (first skipped)', async ({ page }) => { + // Access to the basic page + await page.goto('https://playwright.dev/'); + + // Expects the 'Get started' is shown + await expect(page.getByRole('link', { name: 'Get started' })).toBeVisible(); + }); + test('Test-2: get started linkshould be visible (second skipped)', async ({ page }) => { + // Access to the basic page + await page.goto('https://playwright.dev/'); + + // Expects the 'Get started' is shown + await expect(page.getByRole('link', { name: 'Get started' })).toBeVisible(); + }); + }); +}); \ No newline at end of file diff --git a/playwright/e2e-examples/smoke-tests/smoke-test-5.spec.ts b/playwright/e2e-examples/smoke-tests/smoke-test-5.spec.ts new file mode 100644 index 00000000..f29110f9 --- /dev/null +++ b/playwright/e2e-examples/smoke-tests/smoke-test-5.spec.ts @@ -0,0 +1,69 @@ +import { test, expect, type Page } from '@playwright/test'; + +const TODO_ITEMS = [ + 'buy some cheese', + 'feed the cat', + 'book a doctors appointment' +]; +const URL = 'https://demo.playwright.dev/todomvc'; + +test.describe('New Todo', () => { + let newTodo: any; + + test.beforeEach(async ({ page }) => { + await page.goto(URL); + }); + + test.fixme('[Need to fix] should allow me to add todo items', async ({ page }) => { + await test.step(`[Check 1.1] create a new todo locator`, async () => { + // create a new todo locator + const newTodo = page.getByPlaceholder('What needs to be done?'); + + // Create 1st todo. + await newTodo.fill(TODO_ITEMS[0]); + await newTodo.press('Enter'); + + // Make sure the list only has one todo item. + await expect(page.getByTestId('todo-title')).toHaveText([ + TODO_ITEMS[0] + ]); + }); + }); + test('should allow me to add todo items', async ({ page }) => { + await test.step(`[Check 1.1] create a new todo locator`, async () => { + // create a new todo locator + const newTodo = page.getByPlaceholder('What needs to be done?'); + + // Create 1st todo. + await newTodo.fill(TODO_ITEMS[0]); + await newTodo.press('Enter'); + + // Make sure the list only has one todo item. + await expect(page.getByTestId('todo-title')).toHaveText([ + TODO_ITEMS[0] + ]); + }); + }); + test('should allow me to add todo items (part 1)', async ({ page }) => { + await test.step(`[Check 1.2] create a new todo locator`, async () => { + // create a new todo locator + newTodo = page.getByPlaceholder('What needs to be done?'); + }); + await test.step(`[Check 1.3] Create 1st todo.`, async () => { + // Create 1st todo. + await newTodo.fill(TODO_ITEMS[0]); + await newTodo.press('Enter'); + }); + // Make sure the list only has one todo item. + await expect(page.getByTestId('todo-title')).toHaveText([ + TODO_ITEMS[0] + ]); + await checkNumberOfTodosInLocalStorage(page, 1); + }); +}); + +async function checkNumberOfTodosInLocalStorage(page: Page, expected: number) { + return await page.waitForFunction(e => { + return JSON.parse(localStorage['react-todos']).length === e; + }, expected); +} \ No newline at end of file diff --git a/playwright/e2e-examples/src/Basic.ts b/playwright/e2e-examples/src/Basic.ts new file mode 100644 index 00000000..80dc58d3 --- /dev/null +++ b/playwright/e2e-examples/src/Basic.ts @@ -0,0 +1,11 @@ +export default class Basic { + private url: string; + + public constructor() { + this.url = 'https://playwright.dev/'; + } + + public basicPageUrl(): string { + return this.url; + } +} \ No newline at end of file diff --git a/playwright/e2e/example.spec.ts b/playwright/e2e/example.spec.ts deleted file mode 100644 index 5381600b..00000000 --- a/playwright/e2e/example.spec.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { test, expect } from '@playwright/test'; - -test('basic test', async ({ page }) => { - await page.goto('https://playwright.dev/'); - await page.locator('text=Get started').click(); - await expect(page).toHaveTitle(/Getting started/); -}); diff --git a/playwright/package.json b/playwright/package.json index a84b4ff6..66377af0 100644 --- a/playwright/package.json +++ b/playwright/package.json @@ -1,20 +1,21 @@ { - "name": "new-project", - "version": "1.0.0", - "description": "", + "name": "playwright-new-project", + "version": "1.1.1", + "description": "Running and Monitoring Playwright tests with TESTOMATIO Reporter", "main": "index.js", "scripts": { - "test:e2e-examples": "playwright test --config e2e-examples/playwright.config.ts", + "test:e2e-examples": "playwright test --config e2e-examples/playwright-e2e.config.ts", + "test:smoke-examples": "playwright test --config e2e-examples/playwright-smoke.config.ts", "test:e2e": "playwright test" }, - "keywords": [], - "author": "", + "keywords": ["e2e", "testomatio", "playwright"], + "author": "davert, mihaylukvv", "license": "ISC", "devDependencies": { - "@playwright/test": "^1.20.1" + "@playwright/test": "^1.36.1" }, "dependencies": { - "@testomatio/reporter": "^0.4.6", - "dotenv": "^10.0.0" + "@testomatio/reporter": "latest", + "dotenv": "^16.3.1" } } diff --git a/playwright/playwright.config.ts b/playwright/playwright.config.ts index 199ae740..da6a79aa 100644 --- a/playwright/playwright.config.ts +++ b/playwright/playwright.config.ts @@ -1,7 +1,6 @@ import { PlaywrightTestConfig, devices } from '@playwright/test'; -import path from 'path'; -require('dotenv').config() +require('dotenv').config(); // Reference: https://playwright.dev/docs/test-configuration const config: PlaywrightTestConfig = { @@ -16,10 +15,11 @@ const config: PlaywrightTestConfig = { // Run your local dev server before starting the tests: // https://playwright.dev/docs/test-advanced#launching-a-development-web-server-during-the-tests - // webServer: { - // command: 'npm run start', - // port: 3000, - // }, + webServer: { + command: 'node ./e2e-examples/e2e-tests/server', + port: 4345, + cwd: __dirname, + }, reporter: [ ['list'], ['@testomatio/reporter/lib/adapter/playwright.js', { @@ -30,7 +30,7 @@ const config: PlaywrightTestConfig = { use: { // Retry a test if its failing with enabled tracing. This allows you to analyse the DOM, console logs, network traffic etc. // More information: https://playwright.dev/docs/trace-viewer - trace: 'on-first-retry', + trace: 'retain-on-failure', // All available context options: https://playwright.dev/docs/api/class-browser#browser-new-context contextOptions: { @@ -39,16 +39,16 @@ const config: PlaywrightTestConfig = { screenshot: 'on', - // video: 'retain-on-failure', + video: 'retain-on-failure', }, - - // projects: [ - // { - // name: 'Desktop Chrome', - // use: { - // ...devices['Desktop Chrome'], - // }, - // }, + //TODO: only Chrome mode + projects: [ + { + name: 'Desktop Chrome', + use: { + ...devices['Desktop Chrome'], + }, + }, // { // name: 'Desktop Firefox', // use: { @@ -72,6 +72,6 @@ const config: PlaywrightTestConfig = { // name: 'Mobile Safari', // use: devices['iPhone 12'], // }, - // ], + ] }; export default config; diff --git a/playwright/run-tests-and-check-results.sh b/playwright/run-tests-and-check-results.sh new file mode 100644 index 00000000..4028431a --- /dev/null +++ b/playwright/run-tests-and-check-results.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +npx playwright test > test-playwright-results.txt +fail_tests=$(grep -oE '\b[0-9]+\s+failed\b' test-playwright-results.txt | grep -oE '[0-9]+') +echo "Number of failed tests: $fail_tests" +if [ "$fail_tests" -gt 7 ]; then + echo "More than 7 failed tests. Exiting with error." + exit 1 +else + exit 0 +fi diff --git a/playwright/tests/image-artifact.test.js b/playwright/tests/image-artifact.test.js new file mode 100644 index 00000000..ed67f351 --- /dev/null +++ b/playwright/tests/image-artifact.test.js @@ -0,0 +1,8 @@ +import { test } from '@playwright/test'; +import testomat from '@testomatio/reporter'; + +test.describe('upload artifact 2', () => { + test(`upload image`, async () => { + testomat.artifact('artifacts/artifact-test-image.png'); + }); +}); diff --git a/playwright/tests/logger.test.js b/playwright/tests/logger.test.js new file mode 100644 index 00000000..79e7441c --- /dev/null +++ b/playwright/tests/logger.test.js @@ -0,0 +1,20 @@ +import { test } from '@playwright/test'; +import { logger, log } from '@testomatio/reporter'; + +logger.configure({ + level: 'info', + prettyObjects: true, +}); + +test.describe('Logger', () => { + test(`logger`, async () => { + logger.warn('testomatio logger warn message'); + console.log('console log message'); + + + }); + + test(`simple log`, async () => { + log`This is log message`; + }); +}); diff --git a/playwright/tests/multiple-artifacts.test.js b/playwright/tests/multiple-artifacts.test.js new file mode 100644 index 00000000..d35521a1 --- /dev/null +++ b/playwright/tests/multiple-artifacts.test.js @@ -0,0 +1,17 @@ +import { test } from '@playwright/test'; +import testomat from '@testomatio/reporter'; + +test.describe('upload artifacts 1', () => { + test.beforeEach(async () => { + console.log('beforeEach executed'); + }); + + test(`upload text file`, async () => { + testomat.artifact('artifacts/artifact-test-text.txt'); + }); + + test(`upload second text file`, async () => { + testomat.step('step 1 - login'); + testomat.artifact('artifacts/artifact-test-text2.txt'); + }); +}); diff --git a/playwright/tests/testomat-functions.test.js b/playwright/tests/testomat-functions.test.js new file mode 100644 index 00000000..7d63876d --- /dev/null +++ b/playwright/tests/testomat-functions.test.js @@ -0,0 +1,12 @@ +import { test } from '@playwright/test'; +import testomat from '@testomatio/reporter'; + +test.describe('Testomat functions', () => { + test('artifact @T64346bdd', async () => { + testomat.artifact('artifacts/artifact-test-image.png'); + }); + + test('testomat log', async () => { + testomat.log`This is log message`; + }); +}); diff --git a/wdio/cucumber/.gitignore b/wdio/cucumber/.gitignore new file mode 100644 index 00000000..3c3629e6 --- /dev/null +++ b/wdio/cucumber/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/wdio/cucumber/README.md b/wdio/cucumber/README.md new file mode 100644 index 00000000..05adc039 --- /dev/null +++ b/wdio/cucumber/README.md @@ -0,0 +1,5 @@ +### Prepare +`npm i` + +### Run +`npm test` \ No newline at end of file diff --git a/wdio/cucumber/features/addNumbers.feature b/wdio/cucumber/features/addNumbers.feature new file mode 100644 index 00000000..3207c7f5 --- /dev/null +++ b/wdio/cucumber/features/addNumbers.feature @@ -0,0 +1,13 @@ +@Sad520f3c +Feature: Add number + I want to check if two numbers can be added + + @some-tag1 @Tf37e0731 + Scenario: Add two positive numbers + When I add two numbers 2 and 3 + Then return the sum of 2 and 3 as 5 + + @some-tag2 @T6e4a0318 + Scenario: Should fail + When I add two numbers 2 and 3 + Then return the sum of 2 and 3 as 6 diff --git a/wdio/cucumber/package.json b/wdio/cucumber/package.json new file mode 100644 index 00000000..2c2e6343 --- /dev/null +++ b/wdio/cucumber/package.json @@ -0,0 +1,34 @@ +{ + "author": "Oleksandr Pelykh", + "license": "MIT", + "name": "wdio-cucumber-example", + "version": "0.0.1", + "description": "Boilerplate project to run WebdriverIO tests with Cucumber and report to Testomat.io", + "scripts": { + "test": "wdio run wdio.conf.ts" + }, + "devDependencies": { + "@testomatio/reporter": "file:../../../reporter/testomatio-reporter-1.3.0.tgz", + "@types/chai": "^4.3.14", + "@typescript-eslint/eslint-plugin": "^7.0.1", + "@typescript-eslint/parser": "^7.0.1", + "@wdio/cli": "^8.32.2", + "@wdio/config": "^8.32.2", + "@wdio/cucumber-framework": "^8.32.2", + "@wdio/globals": "^8.32.2", + "@wdio/local-runner": "^8.32.2", + "@wdio/spec-reporter": "^8.32.2", + "@wdio/static-server-service": "^8.32.2", + "eslint": "^8.56.0", + "eslint-config-airbnb-base": "^15.0.0", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-wdio": "^8.24.12", + "npm-run-all": "^4.1.5", + "ts-node": "^10.9.2", + "typescript": "^5.3.3", + "webdriverio": "^8.32.2" + }, + "dependencies": { + "chai": "^5.1.0" + } +} diff --git a/wdio/cucumber/src/steps/script.ts b/wdio/cucumber/src/steps/script.ts new file mode 100644 index 00000000..089f6946 --- /dev/null +++ b/wdio/cucumber/src/steps/script.ts @@ -0,0 +1,3 @@ +export function addTwoNumbers(a: number, b: number) { + return a + b; +} diff --git a/wdio/cucumber/src/steps/then.ts b/wdio/cucumber/src/steps/then.ts new file mode 100644 index 00000000..9e69d38b --- /dev/null +++ b/wdio/cucumber/src/steps/then.ts @@ -0,0 +1,8 @@ +import { Then } from '@cucumber/cucumber'; +import { addTwoNumbers } from './script'; +import assert from 'assert'; + +// result should correspond to the sum of the two numbers +Then(/^return the sum of (\d+) and (\d+) as (\d+)$/, (num1: number, num2: number, result: number) => { + assert(addTwoNumbers(num1, num2) === result, 'The result is not correct'); +}); diff --git a/wdio/cucumber/src/steps/when.ts b/wdio/cucumber/src/steps/when.ts new file mode 100644 index 00000000..adc1b8fe --- /dev/null +++ b/wdio/cucumber/src/steps/when.ts @@ -0,0 +1,7 @@ +import { When } from '@cucumber/cucumber'; +import { addTwoNumbers } from './script'; + +When( + /I add two numbers (\d+) and (\d+)/, + addTwoNumbers +); diff --git a/wdio/cucumber/tsconfig.json b/wdio/cucumber/tsconfig.json new file mode 100644 index 00000000..f3f81fed --- /dev/null +++ b/wdio/cucumber/tsconfig.json @@ -0,0 +1,75 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "module": "CommonJS", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + "target": "es2022", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + // "lib": [], /* Specify library files to be included in the compilation. */ + "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + // "outDir": "./", /* Redirect output structure to the directory. */ + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + + /* Module Resolution Options */ + "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + "types": [ + "node", + "@wdio/globals/types", + "@wdio/cucumber-framework", + "expect-webdriverio" + ], /* Type declaration files to be included in compilation. */ + "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true, /* Skip type checking of declaration files. */ + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + } +} diff --git a/wdio/cucumber/wdio.conf.ts b/wdio/cucumber/wdio.conf.ts new file mode 100644 index 00000000..facf733d --- /dev/null +++ b/wdio/cucumber/wdio.conf.ts @@ -0,0 +1,176 @@ +import type { Options } from '@wdio/types' +// const testomatio = require('@testomatio/reporter/lib/adapter/wdio-cucumber'); +const testomatio = require('@testomatio/reporter/lib/adapter/webdriver'); + +export const config: Options.Testrunner = { + // + // ==================== + // Runner Configuration + // ==================== + // WebdriverIO supports running e2e tests as well as unit and component tests. + runner: 'local', + autoCompileOpts: { + autoCompile: true, + tsNodeOpts: { + project: './tsconfig.json', + transpileOnly: true + } + }, + + // + // ================== + // Specify Test Files + // ================== + // Define which test specs should run. The pattern is relative to the directory + // of the configuration file being run. + // + // The specs are defined as an array of spec files (optionally using wildcards + // that will be expanded). The test for each spec file will be run in a separate + // worker process. In order to have a group of spec files run in the same worker + // process simply enclose them in an array within the specs array. + // + // The path of the spec files will be resolved relative from the directory of + // of the config file unless it's absolute. + // + specs: [ + './features/**/*.feature', + ], + // Patterns to exclude. + exclude: [ + // 'path/to/excluded/files' + ], + // + // ============ + // Capabilities + // ============ + // Define your capabilities here. WebdriverIO can run multiple capabilities at the same + // time. Depending on the number of capabilities, WebdriverIO launches several test + // sessions. Within your capabilities you can overwrite the spec and exclude options in + // order to group specific specs to a specific capability. + // + // First, you can define how many instances should be started at the same time. Let's + // say you have 3 different capabilities (Chrome, Firefox, and Safari) and you have + // set maxInstances to 1; wdio will spawn 3 processes. Therefore, if you have 10 spec + // files and you set maxInstances to 10, all spec files will get tested at the same time + // and 30 processes will get spawned. The property handles how many capabilities + // from the same test should run tests. + // + maxInstances: 5, + // + // If you have trouble getting all important capabilities together, check out the + // Sauce Labs platform configurator - a great tool to configure your capabilities: + // https://saucelabs.com/platform/platform-configurator + // + capabilities: [{ + browserName: 'chrome', + 'goog:chromeOptions': { + args: ['headless', 'disable-gpu'] + } + }], + + // + // =================== + // Test Configurations + // =================== + // Define all options that are relevant for the WebdriverIO instance here + // + // Level of logging verbosity: trace | debug | info | warn | error | silent + logLevel: 'warn', + // + // Set specific log levels per logger + // loggers: + // - webdriver, webdriverio + // - @wdio/browserstack-service, @wdio/devtools-service, @wdio/sauce-service + // - @wdio/mocha-framework, @wdio/jasmine-framework + // - @wdio/local-runner + // - @wdio/sumologic-reporter + // - @wdio/cli, @wdio/config, @wdio/utils + // Level of logging verbosity: trace | debug | info | warn | error | silent + // logLevels: { + // webdriver: 'info', + // '@wdio/appium-service': 'info' + // }, + // + // If you only want to run your tests until a specific amount of tests have failed use + // bail (default is 0 - don't bail, run all tests). + bail: 0, + // + // Set a base URL in order to shorten url command calls. If your `url` parameter starts + // with `/`, the base url gets prepended, not including the path portion of your baseUrl. + // If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url + // gets prepended directly. + // baseUrl: 'http://localhost:8080', + // + // Default timeout for all waitFor* commands. + waitforTimeout: 10000, + // + // Default timeout in milliseconds for request + // if browser driver or grid doesn't send response + connectionRetryTimeout: 120000, + // + // Default request retries count + connectionRetryCount: 3, + // + // Test runner services + // Services take over a specific job you don't want to take care of. They enhance + // your test setup with almost no effort. Unlike plugins, they don't add new + // commands. Instead, they hook themselves up into the test process. + // services: [], + // + // Framework you want to run your specs with. + // The following are supported: Mocha, Jasmine, and Cucumber + // see also: https://webdriver.io/docs/frameworks + // + // Make sure you have the wdio adapter package for the specific framework installed + // before running any tests. + framework: 'cucumber', + + cucumberOpts: { + backtrace: false, + requireModule: [], + failAmbiguousDefinitions: true, + failFast: false, + ignoreUndefinedDefinitions: false, + names: [], + snippets: true, + source: true, + profile: [], + require: [ + './src/steps/then.ts', + './src/steps/when.ts', + ], + scenarioLevelReporter: false, + order: 'defined', + snippetSyntax: undefined, + strict: true, + tagExpression: 'not @Pending', + tagsInTitle: false, + timeout: 20000, + } as WebdriverIO.CucumberOpts, + + // + // The number of times to retry the entire specfile when it fails as a whole + // specFileRetries: 1, + // + // Delay in seconds between the spec file retry attempts + // specFileRetriesDelay: 0, + // + // Whether or not retried spec files should be retried immediately or deferred to the end of the queue + // specFileRetriesDeferred: false, + // + // Test reporter for stdout. + // The only one supported by default is 'dot' + // see also: https://webdriver.io/docs/dot-reporter + reporters: ['spec', + [testomatio, { + apiKey: `${process.env.TESTOMATIO}` + }] + ], + + // Options to be passed to Mocha. + // See the full list at http://mochajs.org/ + mochaOpts: { + ui: 'bdd', + timeout: 60000 + }, +} diff --git a/wdio/v7/package.json b/wdio/v7/package.json new file mode 100644 index 00000000..7d780306 --- /dev/null +++ b/wdio/v7/package.json @@ -0,0 +1,25 @@ +{ + "name": "testomat-example-wdio-v7", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "npx start-test-run -c 'wdio run ./test/wdio.conf.ts' --env-file .env" + }, + "author": "", + "license": "ISC", + "devDependencies": { + "@wdio/cli": "^7.34.0", + "@wdio/local-runner": "^7.34.0", + "@wdio/mocha-framework": "^7.33.0", + "@wdio/spec-reporter": "^7.33.0", + "chromedriver": "^121.0.0", + "ts-node": "^10.9.2", + "typescript": "^5.3.3", + "wdio-chromedriver-service": "^8.1.1" + }, + "dependencies": { + "@testomatio/reporter": "file:../../../reporter/testomatio-reporter-1.1.1.tgz", + "webdriverio": "^7.34.0" + } +} diff --git a/wdio/v7/test/pageobjects/login.page.ts b/wdio/v7/test/pageobjects/login.page.ts new file mode 100644 index 00000000..b117fb0d --- /dev/null +++ b/wdio/v7/test/pageobjects/login.page.ts @@ -0,0 +1,42 @@ +import { ChainablePromiseElement } from 'webdriverio'; + +import Page from './page'; + +/** + * sub page containing specific selectors and methods for a specific page + */ +class LoginPage extends Page { + /** + * define selectors using getter methods + */ + public get inputUsername () { + return $('#username'); + } + + public get inputPassword () { + return $('#password'); + } + + public get btnSubmit () { + return $('button[type="submit"]'); + } + + /** + * a method to encapsule automation code to interact with the page + * e.g. to login using username and password + */ + public async login (username: string, password: string) { + await this.inputUsername.setValue(username); + await this.inputPassword.setValue(password); + await this.btnSubmit.click(); + } + + /** + * overwrite specific options to adapt it to page object + */ + public open () { + return super.open('login'); + } +} + +export default new LoginPage(); diff --git a/wdio/v7/test/pageobjects/page.ts b/wdio/v7/test/pageobjects/page.ts new file mode 100644 index 00000000..fc8be333 --- /dev/null +++ b/wdio/v7/test/pageobjects/page.ts @@ -0,0 +1,13 @@ +/** +* main page object containing all methods, selectors and functionality +* that is shared across all page objects +*/ +export default class Page { + /** + * Opens a sub page of the page + * @param path path of the sub page (e.g. /path/to/page.html) + */ + public open (path: string) { + return browser.url(`https://the-internet.herokuapp.com/${path}`) + } +} diff --git a/wdio/v7/test/pageobjects/secure.page.ts b/wdio/v7/test/pageobjects/secure.page.ts new file mode 100644 index 00000000..35b7dca1 --- /dev/null +++ b/wdio/v7/test/pageobjects/secure.page.ts @@ -0,0 +1,17 @@ +import { ChainablePromiseElement } from 'webdriverio'; + +import Page from './page'; + +/** + * sub page containing specific selectors and methods for a specific page + */ +class SecurePage extends Page { + /** + * define selectors using getter methods + */ + public get flashAlert () { + return $('#flash'); + } +} + +export default new SecurePage(); diff --git a/wdio/v7/test/specs/example.e2e.ts b/wdio/v7/test/specs/example.e2e.ts new file mode 100644 index 00000000..c382b88f --- /dev/null +++ b/wdio/v7/test/specs/example.e2e.ts @@ -0,0 +1,15 @@ +import LoginPage from '../pageobjects/login.page'; +import SecurePage from '../pageobjects/secure.page'; + +describe('My Login application @S1806fa9f', () => { + it('should login with valid credentials @T6980b031', async () => { + await LoginPage.open(); + + await LoginPage.login('tomsmith', 'SuperSecretPassword!'); + await expect(SecurePage.flashAlert).toBeExisting(); + await expect(SecurePage.flashAlert).toHaveTextContaining( + 'You logged into a secure area!'); + }); +}); + + diff --git a/wdio/v7/test/tsconfig.json b/wdio/v7/test/tsconfig.json new file mode 100644 index 00000000..c53bd32d --- /dev/null +++ b/wdio/v7/test/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "moduleResolution": "node", + "types": [ + "node", + "webdriverio/async", + "@wdio/mocha-framework", + "expect-webdriverio" + ], + "target": "es2019" + } +} \ No newline at end of file diff --git a/wdio/v7/test/wdio.conf.ts b/wdio/v7/test/wdio.conf.ts new file mode 100644 index 00000000..237c1df4 --- /dev/null +++ b/wdio/v7/test/wdio.conf.ts @@ -0,0 +1,325 @@ +import type { Options } from '@wdio/types' +const testomatio = require('@testomatio/reporter/lib/adapter/webdriver'); + +require('dotenv').config({ path: './.env' }); + +export const config: Options.Testrunner = { + // + // ==================== + // Runner Configuration + // ==================== + // + // + // ===================== + // ts-node Configurations + // ===================== + // + // You can write tests using TypeScript to get autocompletion and type safety. + // You will need typescript and ts-node installed as devDependencies. + // WebdriverIO will automatically detect if these dependencies are installed + // and will compile your config and tests for you. + // If you need to configure how ts-node runs please use the + // environment variables for ts-node or use wdio config's autoCompileOpts section. + // + + autoCompileOpts: { + autoCompile: true, + // see https://github.com/TypeStrong/ts-node#cli-and-programmatic-options + // for all available options + tsNodeOpts: { + transpileOnly: true, + project: 'test/tsconfig.json' + } + // tsconfig-paths is only used if "tsConfigPathsOpts" are provided, if you + // do please make sure "tsconfig-paths" is installed as dependency + // tsConfigPathsOpts: { + // baseUrl: './' + // } + }, + // + // ================== + // Specify Test Files + // ================== + // Define which test specs should run. The pattern is relative to the directory + // from which `wdio` was called. + // + // The specs are defined as an array of spec files (optionally using wildcards + // that will be expanded). The test for each spec file will be run in a separate + // worker process. In order to have a group of spec files run in the same worker + // process simply enclose them in an array within the specs array. + // + // If you are calling `wdio` from an NPM script (see https://docs.npmjs.com/cli/run-script), + // then the current working directory is where your `package.json` resides, so `wdio` + // will be called from there. + // + specs: [ + './test/specs/**/*.ts' + ], + // Patterns to exclude. + exclude: [ + // 'path/to/excluded/files' + ], + // + // ============ + // Capabilities + // ============ + // Define your capabilities here. WebdriverIO can run multiple capabilities at the same + // time. Depending on the number of capabilities, WebdriverIO launches several test + // sessions. Within your capabilities you can overwrite the spec and exclude options in + // order to group specific specs to a specific capability. + // + // First, you can define how many instances should be started at the same time. Let's + // say you have 3 different capabilities (Chrome, Firefox, and Safari) and you have + // set maxInstances to 1; wdio will spawn 3 processes. Therefore, if you have 10 spec + // files and you set maxInstances to 10, all spec files will get tested at the same time + // and 30 processes will get spawned. The property handles how many capabilities + // from the same test should run tests. + // + maxInstances: 10, + // + // If you have trouble getting all important capabilities together, check out the + // Sauce Labs platform configurator - a great tool to configure your capabilities: + // https://saucelabs.com/platform/platform-configurator + // + capabilities: [{ + + // maxInstances can get overwritten per capability. So if you have an in-house Selenium + // grid with only 5 firefox instances available you can make sure that not more than + // 5 instances get started at a time. + maxInstances: 5, + // + browserName: 'chrome', + acceptInsecureCerts: true + // If outputDir is provided WebdriverIO can capture driver session logs + // it is possible to configure which logTypes to include/exclude. + // excludeDriverLogs: ['*'], // pass '*' to exclude all driver session logs + // excludeDriverLogs: ['bugreport', 'server'], + }], + // + // =================== + // Test Configurations + // =================== + // Define all options that are relevant for the WebdriverIO instance here + // + // Level of logging verbosity: trace | debug | info | warn | error | silent + logLevel: 'warn', + // + // Set specific log levels per logger + // loggers: + // - webdriver, webdriverio + // - @wdio/browserstack-service, @wdio/devtools-service, @wdio/sauce-service + // - @wdio/mocha-framework, @wdio/jasmine-framework + // - @wdio/local-runner + // - @wdio/sumologic-reporter + // - @wdio/cli, @wdio/config, @wdio/utils + // Level of logging verbosity: trace | debug | info | warn | error | silent + // logLevels: { + // webdriver: 'info', + // '@wdio/appium-service': 'info' + // }, + // + // If you only want to run your tests until a specific amount of tests have failed use + // bail (default is 0 - don't bail, run all tests). + bail: 0, + // + // Set a base URL in order to shorten url command calls. If your `url` parameter starts + // with `/`, the base url gets prepended, not including the path portion of your baseUrl. + // If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url + // gets prepended directly. + baseUrl: 'http://localhost', + // + // Default timeout for all waitFor* commands. + waitforTimeout: 10000, + // + // Default timeout in milliseconds for request + // if browser driver or grid doesn't send response + connectionRetryTimeout: 120000, + // + // Default request retries count + connectionRetryCount: 3, + // + // Test runner services + // Services take over a specific job you don't want to take care of. They enhance + // your test setup with almost no effort. Unlike plugins, they don't add new + // commands. Instead, they hook themselves up into the test process. + services: ['chromedriver'], + + // Framework you want to run your specs with. + // The following are supported: Mocha, Jasmine, and Cucumber + // see also: https://webdriver.io/docs/frameworks + // + // Make sure you have the wdio adapter package for the specific framework installed + // before running any tests. + framework: 'mocha', + // + // The number of times to retry the entire specfile when it fails as a whole + // specFileRetries: 1, + // + // Delay in seconds between the spec file retry attempts + // specFileRetriesDelay: 0, + // + // Whether or not retried specfiles should be retried immediately or deferred to the end of the queue + // specFileRetriesDeferred: false, + // + // Test reporter for stdout. + // The only one supported by default is 'dot' + // see also: https://webdriver.io/docs/dot-reporter + reporters: ['spec', + [testomatio, { apiKey: process.env.TESTOMATIO }] + ], + + // + // Options to be passed to Mocha. + // See the full list at http://mochajs.org/ + mochaOpts: { + ui: 'bdd', + timeout: 60000 + }, + // + // ===== + // Hooks + // ===== + // WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance + // it and to build services around it. You can either apply a single function or an array of + // methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got + // resolved to continue. + /** + * Gets executed once before all workers get launched. + * @param {Object} config wdio configuration object + * @param {Array.} capabilities list of capabilities details + */ + // onPrepare: function (config, capabilities) { + // }, + /** + * Gets executed before a worker process is spawned and can be used to initialise specific service + * for that worker as well as modify runtime environments in an async fashion. + * @param {String} cid capability id (e.g 0-0) + * @param {[type]} caps object containing capabilities for session that will be spawn in the worker + * @param {[type]} specs specs to be run in the worker process + * @param {[type]} args object that will be merged with the main configuration once worker is initialized + * @param {[type]} execArgv list of string arguments passed to the worker process + */ + // onWorkerStart: function (cid, caps, specs, args, execArgv) { + // }, + /** + * Gets executed just after a worker process has exited. + * @param {String} cid capability id (e.g 0-0) + * @param {Number} exitCode 0 - success, 1 - fail + * @param {[type]} specs specs to be run in the worker process + * @param {Number} retries number of retries used + */ + // onWorkerEnd: function (cid, exitCode, specs, retries) { + // }, + /** + * Gets executed just before initialising the webdriver session and test framework. It allows you + * to manipulate configurations depending on the capability or spec. + * @param {Object} config wdio configuration object + * @param {Array.} capabilities list of capabilities details + * @param {Array.} specs List of spec file paths that are to be run + * @param {String} cid worker id (e.g. 0-0) + */ + // beforeSession: function (config, capabilities, specs, cid) { + // }, + /** + * Gets executed before test execution begins. At this point you can access to all global + * variables like `browser`. It is the perfect place to define custom commands. + * @param {Array.} capabilities list of capabilities details + * @param {Array.} specs List of spec file paths that are to be run + * @param {Object} browser instance of created browser/device session + */ + // before: function (capabilities, specs) { + // }, + /** + * Runs before a WebdriverIO command gets executed. + * @param {String} commandName hook command name + * @param {Array} args arguments that command would receive + */ + // beforeCommand: function (commandName, args) { + // }, + /** + * Hook that gets executed before the suite starts + * @param {Object} suite suite details + */ + // beforeSuite: function (suite) { + // }, + /** + * Function to be executed before a test (in Mocha/Jasmine) starts. + */ + // beforeTest: function (test, context) { + // }, + /** + * Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling + * beforeEach in Mocha) + */ + // beforeHook: function (test, context) { + // }, + /** + * Hook that gets executed _after_ a hook within the suite starts (e.g. runs after calling + * afterEach in Mocha) + */ + // afterHook: function (test, context, { error, result, duration, passed, retries }) { + // }, + /** + * Function to be executed after a test (in Mocha/Jasmine only) + * @param {Object} test test object + * @param {Object} context scope object the test was executed with + * @param {Error} result.error error object in case the test fails, otherwise `undefined` + * @param {Any} result.result return object of test function + * @param {Number} result.duration duration of test + * @param {Boolean} result.passed true if test has passed, otherwise false + * @param {Object} result.retries informations to spec related retries, e.g. `{ attempts: 0, limit: 0 }` + */ + // afterTest: function(test, context, { error, result, duration, passed, retries }) { + // }, + + + /** + * Hook that gets executed after the suite has ended + * @param {Object} suite suite details + */ + // afterSuite: function (suite) { + // }, + /** + * Runs after a WebdriverIO command gets executed + * @param {String} commandName hook command name + * @param {Array} args arguments that command would receive + * @param {Number} result 0 - command success, 1 - command error + * @param {Object} error error object if any + */ + // afterCommand: function (commandName, args, result, error) { + // }, + /** + * Gets executed after all tests are done. You still have access to all global variables from + * the test. + * @param {Number} result 0 - test pass, 1 - test fail + * @param {Array.} capabilities list of capabilities details + * @param {Array.} specs List of spec file paths that ran + */ + // after: function (result, capabilities, specs) { + // }, + /** + * Gets executed right after terminating the webdriver session. + * @param {Object} config wdio configuration object + * @param {Array.} capabilities list of capabilities details + * @param {Array.} specs List of spec file paths that ran + */ + // afterSession: function (config, capabilities, specs) { + // }, + /** + * Gets executed after all workers got shut down and the process is about to exit. An error + * thrown in the onComplete hook will result in the test run failing. + * @param {Object} exitCode 0 - success, 1 - fail + * @param {Object} config wdio configuration object + * @param {Array.} capabilities list of capabilities details + * @param {} results object containing test results + */ + // onComplete: function(exitCode, config, capabilities, results) { + // }, + /** + * Gets executed when a refresh happens. + * @param {String} oldSessionId session ID of the old session + * @param {String} newSessionId session ID of the new session + */ + // onReload: function(oldSessionId, newSessionId) { + // } +} diff --git a/wdio/v7/tsconfig.json b/wdio/v7/tsconfig.json new file mode 100644 index 00000000..312a48e1 --- /dev/null +++ b/wdio/v7/tsconfig.json @@ -0,0 +1,106 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + "types": [ + "node", + "webdriverio/async", + "@wdio/mocha-framework", + "expect-webdriverio" + ], + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + /* Type Checking */ + "strict": true, + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} \ No newline at end of file diff --git a/wdio/v8/package.json b/wdio/v8/package.json new file mode 100644 index 00000000..5b4dcfb8 --- /dev/null +++ b/wdio/v8/package.json @@ -0,0 +1,23 @@ +{ + "name": "testomat-example-wdio-v8", + "version": "1.0.0", + "description": "Example project for Testomat.io with WebdriverIO v8", + "main": "index.js", + "scripts": { + "test": "npx start-test-run -c 'wdio run ./wdio.conf.ts'" + }, + "author": "Oleksandr Pelykh / Testomat.io", + "license": "ISC", + "devDependencies": { + "@wdio/cli": "^8.32.1", + "@wdio/local-runner": "^8.32.1", + "@wdio/mocha-framework": "^8.31.1", + "@wdio/spec-reporter": "^8.31.1", + "ts-node": "^10.9.2", + "typescript": "^5.3.3", + "wdio-html-nice-reporter": "^8.1.4" + }, + "dependencies": { + "@testomatio/reporter": "^1.2.0" + } +} diff --git a/wdio/v8/test/pageobjects/login.page.ts b/wdio/v8/test/pageobjects/login.page.ts new file mode 100644 index 00000000..4b548287 --- /dev/null +++ b/wdio/v8/test/pageobjects/login.page.ts @@ -0,0 +1,41 @@ +import { $ } from '@wdio/globals' +import Page from './page'; + +/** + * sub page containing specific selectors and methods for a specific page + */ +class LoginPage extends Page { + /** + * define selectors using getter methods + */ + public get inputUsername () { + return $('#username'); + } + + public get inputPassword () { + return $('#password'); + } + + public get btnSubmit () { + return $('button[type="submit"]'); + } + + /** + * a method to encapsule automation code to interact with the page + * e.g. to login using username and password + */ + public async login (username: string, password: string) { + await this.inputUsername.setValue(username); + await this.inputPassword.setValue(password); + await this.btnSubmit.click(); + } + + /** + * overwrite specific options to adapt it to page object + */ + public open () { + return super.open('login'); + } +} + +export default new LoginPage(); diff --git a/wdio/v8/test/pageobjects/page.ts b/wdio/v8/test/pageobjects/page.ts new file mode 100644 index 00000000..6a20f1ce --- /dev/null +++ b/wdio/v8/test/pageobjects/page.ts @@ -0,0 +1,15 @@ +import { browser } from '@wdio/globals' + +/** +* main page object containing all methods, selectors and functionality +* that is shared across all page objects +*/ +export default class Page { + /** + * Opens a sub page of the page + * @param path path of the sub page (e.g. /path/to/page.html) + */ + public open (path: string) { + return browser.url(`https://the-internet.herokuapp.com/${path}`) + } +} diff --git a/wdio/v8/test/pageobjects/secure.page.ts b/wdio/v8/test/pageobjects/secure.page.ts new file mode 100644 index 00000000..b8d60f89 --- /dev/null +++ b/wdio/v8/test/pageobjects/secure.page.ts @@ -0,0 +1,16 @@ +import { $ } from '@wdio/globals' +import Page from './page'; + +/** + * sub page containing specific selectors and methods for a specific page + */ +class SecurePage extends Page { + /** + * define selectors using getter methods + */ + public get flashAlert () { + return $('#flash'); + } +} + +export default new SecurePage(); diff --git a/wdio/v8/test/specs/test.test.ts b/wdio/v8/test/specs/test.test.ts new file mode 100644 index 00000000..358c57c8 --- /dev/null +++ b/wdio/v8/test/specs/test.test.ts @@ -0,0 +1,20 @@ +import { expect } from '@wdio/globals' +import LoginPage from '../pageobjects/login.page' +import SecurePage from '../pageobjects/secure.page' + +describe('My Login application', () => { + it('username input should be visible', async () => { + await LoginPage.open() + + await expect(LoginPage.inputUsername).toBeExisting() + }); + + it('should login with valid credentials', async () => { + await LoginPage.open() + + await LoginPage.login('tomsmith', 'SuperSecretPassword!') + await expect(SecurePage.flashAlert).toBeExisting() + await expect(SecurePage.flashAlert).toHaveTextContaining( + 'You logged into a secure area!') + }); +}) diff --git a/wdio/v8/test/specs/test2.test.ts b/wdio/v8/test/specs/test2.test.ts new file mode 100644 index 00000000..4427f1e0 --- /dev/null +++ b/wdio/v8/test/specs/test2.test.ts @@ -0,0 +1,19 @@ +import { expect } from '@wdio/globals' + +function sum(a: number, b: number): number { + return a + b; +} + +describe('Function test', () => { + it('1+2', async () => { + expect(sum(1, 2)).toBe(3); + }); + + it('3+4', async () => { + expect(sum(3, 4)).toBe(7); + }); + + it('5+6', async () => { + expect(sum(5, 6)).toBe(11); + }); +}) diff --git a/wdio/v8/tsconfig.json b/wdio/v8/tsconfig.json new file mode 100644 index 00000000..910b6790 --- /dev/null +++ b/wdio/v8/tsconfig.json @@ -0,0 +1,30 @@ +{ + "compilerOptions": { + "moduleResolution": "node", + "module": "commonjs", + "target": "es2022", + "lib": [ + "es2022", + "dom" + ], + "types": [ + "node", + "@wdio/globals/types", + "expect-webdriverio", + "@wdio/mocha-framework" + ], + "skipLibCheck": true, + "noEmit": true, + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": [ + "test", + "wdio.conf.ts" + ] +} \ No newline at end of file diff --git a/wdio/v8/wdio.conf.ts b/wdio/v8/wdio.conf.ts new file mode 100644 index 00000000..12d4fbb7 --- /dev/null +++ b/wdio/v8/wdio.conf.ts @@ -0,0 +1,309 @@ +import type { Options } from '@wdio/types' +const testomatio = require('@testomatio/reporter/lib/adapter/webdriver'); + +export const config: Options.Testrunner = { + // + // ==================== + // Runner Configuration + // ==================== + // WebdriverIO supports running e2e tests as well as unit and component tests. + runner: 'local', + autoCompileOpts: { + autoCompile: true, + tsNodeOpts: { + project: './tsconfig.json', + transpileOnly: true + } + }, + + // + // ================== + // Specify Test Files + // ================== + // Define which test specs should run. The pattern is relative to the directory + // of the configuration file being run. + // + // The specs are defined as an array of spec files (optionally using wildcards + // that will be expanded). The test for each spec file will be run in a separate + // worker process. In order to have a group of spec files run in the same worker + // process simply enclose them in an array within the specs array. + // + // The path of the spec files will be resolved relative from the directory of + // of the config file unless it's absolute. + // + specs: [ + './test/specs/**/*.ts' + ], + // Patterns to exclude. + exclude: [ + // 'path/to/excluded/files' + ], + // + // ============ + // Capabilities + // ============ + // Define your capabilities here. WebdriverIO can run multiple capabilities at the same + // time. Depending on the number of capabilities, WebdriverIO launches several test + // sessions. Within your capabilities you can overwrite the spec and exclude options in + // order to group specific specs to a specific capability. + // + // First, you can define how many instances should be started at the same time. Let's + // say you have 3 different capabilities (Chrome, Firefox, and Safari) and you have + // set maxInstances to 1; wdio will spawn 3 processes. Therefore, if you have 10 spec + // files and you set maxInstances to 10, all spec files will get tested at the same time + // and 30 processes will get spawned. The property handles how many capabilities + // from the same test should run tests. + // + maxInstances: 10, + // + // If you have trouble getting all important capabilities together, check out the + // Sauce Labs platform configurator - a great tool to configure your capabilities: + // https://saucelabs.com/platform/platform-configurator + // + capabilities: [{ + browserName: 'chrome' + }], + + // + // =================== + // Test Configurations + // =================== + // Define all options that are relevant for the WebdriverIO instance here + // + // Level of logging verbosity: trace | debug | info | warn | error | silent + logLevel: 'warn', + // + // Set specific log levels per logger + // loggers: + // - webdriver, webdriverio + // - @wdio/browserstack-service, @wdio/devtools-service, @wdio/sauce-service + // - @wdio/mocha-framework, @wdio/jasmine-framework + // - @wdio/local-runner + // - @wdio/sumologic-reporter + // - @wdio/cli, @wdio/config, @wdio/utils + // Level of logging verbosity: trace | debug | info | warn | error | silent + // logLevels: { + // webdriver: 'info', + // '@wdio/appium-service': 'info' + // }, + // + // If you only want to run your tests until a specific amount of tests have failed use + // bail (default is 0 - don't bail, run all tests). + bail: 0, + // + // Set a base URL in order to shorten url command calls. If your `url` parameter starts + // with `/`, the base url gets prepended, not including the path portion of your baseUrl. + // If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url + // gets prepended directly. + // baseUrl: 'http://localhost:8080', + // + // Default timeout for all waitFor* commands. + waitforTimeout: 10000, + // + // Default timeout in milliseconds for request + // if browser driver or grid doesn't send response + connectionRetryTimeout: 120000, + // + // Default request retries count + connectionRetryCount: 3, + // + // Test runner services + // Services take over a specific job you don't want to take care of. They enhance + // your test setup with almost no effort. Unlike plugins, they don't add new + // commands. Instead, they hook themselves up into the test process. + // services: [], + // + // Framework you want to run your specs with. + // The following are supported: Mocha, Jasmine, and Cucumber + // see also: https://webdriver.io/docs/frameworks + // + // Make sure you have the wdio adapter package for the specific framework installed + // before running any tests. + framework: 'mocha', + + // + // The number of times to retry the entire specfile when it fails as a whole + // specFileRetries: 1, + // + // Delay in seconds between the spec file retry attempts + // specFileRetriesDelay: 0, + // + // Whether or not retried spec files should be retried immediately or deferred to the end of the queue + // specFileRetriesDeferred: false, + // + // Test reporter for stdout. + // The only one supported by default is 'dot' + // see also: https://webdriver.io/docs/dot-reporter + reporters: ['spec', + [testomatio, { + apiKey: `${process.env.TESTOMATIO}` + }] + ], + + // Options to be passed to Mocha. + // See the full list at http://mochajs.org/ + mochaOpts: { + ui: 'bdd', + timeout: 60000 + }, + + // + // ===== + // Hooks + // ===== + // WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance + // it and to build services around it. You can either apply a single function or an array of + // methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got + // resolved to continue. + /** + * Gets executed once before all workers get launched. + * @param {object} config wdio configuration object + * @param {Array.} capabilities list of capabilities details + */ + // onPrepare: function (config, capabilities) { + // }, + /** + * Gets executed before a worker process is spawned and can be used to initialize specific service + * for that worker as well as modify runtime environments in an async fashion. + * @param {string} cid capability id (e.g 0-0) + * @param {object} caps object containing capabilities for session that will be spawn in the worker + * @param {object} specs specs to be run in the worker process + * @param {object} args object that will be merged with the main configuration once worker is initialized + * @param {object} execArgv list of string arguments passed to the worker process + */ + // onWorkerStart: function (cid, caps, specs, args, execArgv) { + // }, + /** + * Gets executed just after a worker process has exited. + * @param {string} cid capability id (e.g 0-0) + * @param {number} exitCode 0 - success, 1 - fail + * @param {object} specs specs to be run in the worker process + * @param {number} retries number of retries used + */ + // onWorkerEnd: function (cid, exitCode, specs, retries) { + // }, + /** + * Gets executed just before initialising the webdriver session and test framework. It allows you + * to manipulate configurations depending on the capability or spec. + * @param {object} config wdio configuration object + * @param {Array.} capabilities list of capabilities details + * @param {Array.} specs List of spec file paths that are to be run + * @param {string} cid worker id (e.g. 0-0) + */ + // beforeSession: function (config, capabilities, specs, cid) { + // }, + /** + * Gets executed before test execution begins. At this point you can access to all global + * variables like `browser`. It is the perfect place to define custom commands. + * @param {Array.} capabilities list of capabilities details + * @param {Array.} specs List of spec file paths that are to be run + * @param {object} browser instance of created browser/device session + */ + // before: function (capabilities, specs) { + // }, + /** + * Runs before a WebdriverIO command gets executed. + * @param {string} commandName hook command name + * @param {Array} args arguments that command would receive + */ + // beforeCommand: function (commandName, args) { + // }, + /** + * Hook that gets executed before the suite starts + * @param {object} suite suite details + */ + // beforeSuite: function (suite) { + // }, + /** + * Function to be executed before a test (in Mocha/Jasmine) starts. + */ + // beforeTest: function (test, context) { + // }, + /** + * Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling + * beforeEach in Mocha) + */ + // beforeHook: function (test, context, hookName) { + // }, + /** + * Hook that gets executed _after_ a hook within the suite starts (e.g. runs after calling + * afterEach in Mocha) + */ + // afterHook: function (test, context, { error, result, duration, passed, retries }, hookName) { + // }, + /** + * Function to be executed after a test (in Mocha/Jasmine only) + * @param {object} test test object + * @param {object} context scope object the test was executed with + * @param {Error} result.error error object in case the test fails, otherwise `undefined` + * @param {*} result.result return object of test function + * @param {number} result.duration duration of test + * @param {boolean} result.passed true if test has passed, otherwise false + * @param {object} result.retries information about spec related retries, e.g. `{ attempts: 0, limit: 0 }` + */ + // afterTest: function(test, context, { error, result, duration, passed, retries }) { + // }, + + + /** + * Hook that gets executed after the suite has ended + * @param {object} suite suite details + */ + // afterSuite: function (suite) { + // }, + /** + * Runs after a WebdriverIO command gets executed + * @param {string} commandName hook command name + * @param {Array} args arguments that command would receive + * @param {number} result 0 - command success, 1 - command error + * @param {object} error error object if any + */ + // afterCommand: function (commandName, args, result, error) { + // }, + /** + * Gets executed after all tests are done. You still have access to all global variables from + * the test. + * @param {number} result 0 - test pass, 1 - test fail + * @param {Array.} capabilities list of capabilities details + * @param {Array.} specs List of spec file paths that ran + */ + // after: function (result, capabilities, specs) { + // }, + /** + * Gets executed right after terminating the webdriver session. + * @param {object} config wdio configuration object + * @param {Array.} capabilities list of capabilities details + * @param {Array.} specs List of spec file paths that ran + */ + // afterSession: function (config, capabilities, specs) { + // }, + /** + * Gets executed after all workers got shut down and the process is about to exit. An error + * thrown in the onComplete hook will result in the test run failing. + * @param {object} exitCode 0 - success, 1 - fail + * @param {object} config wdio configuration object + * @param {Array.} capabilities list of capabilities details + * @param {} results object containing test results + */ + // onComplete: function(exitCode, config, capabilities, results) { + // }, + /** + * Gets executed when a refresh happens. + * @param {string} oldSessionId session ID of the old session + * @param {string} newSessionId session ID of the new session + */ + // onReload: function(oldSessionId, newSessionId) { + // } + /** + * Hook that gets executed before a WebdriverIO assertion happens. + * @param {object} params information about the assertion to be executed + */ + // beforeAssertion: function(params) { + // } + /** + * Hook that gets executed after a WebdriverIO assertion happened. + * @param {object} params information about the assertion that was executed, including its results + */ + // afterAssertion: function(params) { + // } +}