From bb092fe07535d2c6cb4f5d73122ea1f3a439c932 Mon Sep 17 00:00:00 2001 From: Thomas Hohn Date: Tue, 12 Nov 2024 15:19:30 +0100 Subject: [PATCH 01/16] Removed some tests --- package.json | 1 - .../codecept.WebDriver.devtools.coverage.js | 49 - .../acceptance/codecept.WebDriver.devtools.js | 42 - test/helper/WebDriver_devtools_test.js | 1251 ----------------- 4 files changed, 1343 deletions(-) delete mode 100644 test/acceptance/codecept.WebDriver.devtools.coverage.js delete mode 100644 test/acceptance/codecept.WebDriver.devtools.js delete mode 100644 test/helper/WebDriver_devtools_test.js diff --git a/package.json b/package.json index 3492267df..ed8c5d54e 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,6 @@ "test:unit:webbapi:puppeteer": "mocha test/helper/Puppeteer_test.js", "test:unit:webbapi:webDriver": "mocha test/helper/WebDriver_test.js", "test:unit:webbapi:webDriver:noSeleniumServer": "mocha test/helper/WebDriver.noSeleniumServer_test.js", - "test:unit:webbapi:webDriver:devtools": "mocha test/helper/WebDriver_devtools_test.js --exit", "test:unit:webbapi:testCafe": "mocha test/helper/TestCafe_test.js", "test:unit:expect": "mocha test/helper/Expect_test.js", "test:plugin": "mocha test/plugin/plugin_test.js", diff --git a/test/acceptance/codecept.WebDriver.devtools.coverage.js b/test/acceptance/codecept.WebDriver.devtools.coverage.js deleted file mode 100644 index 3d771815d..000000000 --- a/test/acceptance/codecept.WebDriver.devtools.coverage.js +++ /dev/null @@ -1,49 +0,0 @@ -const TestHelper = require('../support/TestHelper') - -module.exports.config = { - tests: './*_test.js', - timeout: 10000, - output: './output', - helpers: { - WebDriver: { - url: TestHelper.siteUrl(), - browser: 'Chromium', - windowSize: '500x700', - devtoolsProtocol: true, - waitForTimeout: 5000, - capabilities: { - chromeOptions: { - args: ['--headless', '--disable-gpu', '--window-size=500,700'], - }, - }, - }, - ScreenshotSessionHelper: { - require: '../support/ScreenshotSessionHelper.js', - outputPath: './output', - }, - ExpectHelper: {}, - }, - include: {}, - mocha: {}, - name: 'acceptance', - plugins: { - screenshotOnFail: { - enabled: true, - }, - coverage: { - enabled: true, - debug: true, - name: 'CodeceptJS Coverage Report', - sourceFilter: '**/src/**', - sourcePath: { - 'todomvc-react/': '', - 'todomvc.com/examples/react/': '', - }, - outputDir: 'output/coverage', - }, - }, - gherkin: { - features: './gherkin/*.feature', - steps: ['./gherkin/steps.js'], - }, -} diff --git a/test/acceptance/codecept.WebDriver.devtools.js b/test/acceptance/codecept.WebDriver.devtools.js deleted file mode 100644 index 755e950d5..000000000 --- a/test/acceptance/codecept.WebDriver.devtools.js +++ /dev/null @@ -1,42 +0,0 @@ -const TestHelper = require('../support/TestHelper') - -module.exports.config = { - tests: './*_test.js', - timeout: 10000, - output: './output', - helpers: { - WebDriver: { - url: TestHelper.siteUrl(), - browser: 'Chromium', - windowSize: '500x700', - devtoolsProtocol: true, - waitForTimeout: 5000, - capabilities: { - chromeOptions: { - args: ['--headless', '--disable-gpu', '--window-size=500,700'], - }, - }, - }, - ScreenshotSessionHelper: { - require: '../support/ScreenshotSessionHelper.js', - outputPath: './output', - }, - ExpectHelper: {}, - }, - include: {}, - bootstrap: async () => - new Promise((done) => { - setTimeout(done, 5000) - }), // let's wait for selenium - mocha: {}, - name: 'acceptance', - plugins: { - screenshotOnFail: { - enabled: true, - }, - }, - gherkin: { - features: './gherkin/*.feature', - steps: ['./gherkin/steps.js'], - }, -} diff --git a/test/helper/WebDriver_devtools_test.js b/test/helper/WebDriver_devtools_test.js deleted file mode 100644 index 84dad90a1..000000000 --- a/test/helper/WebDriver_devtools_test.js +++ /dev/null @@ -1,1251 +0,0 @@ -const assert = require('assert') - -let expect -import('chai').then((chai) => { - expect = chai.expect -}) -const path = require('path') -const fs = require('fs') - -const TestHelper = require('../support/TestHelper') -const WebDriver = require('../../lib/helper/WebDriver') -const AssertionFailedError = require('../../lib/assert/error') -const webApiTests = require('./webapi') -const Secret = require('../../lib/secret') -global.codeceptjs = require('../../lib') - -const siteUrl = TestHelper.siteUrl() -let wd - -describe('WebDriver - Devtools Protocol', function () { - this.retries(1) - this.timeout(35000) - - before(() => { - global.codecept_dir = path.join(__dirname, '/../data') - try { - fs.unlinkSync(dataFile) - } catch (err) { - // continue regardless of error - } - - process.env.DevTools = 'true' - - wd = new WebDriver({ - url: siteUrl, - browser: 'Chromium', - windowSize: '500x700', - devtoolsProtocol: true, - waitForTimeout: 5000, - capabilities: { - chromeOptions: { - args: ['--headless', '--disable-gpu', '--window-size=500,700'], - }, - }, - customLocatorStrategies: { - customSelector: (selector) => ({ 'element-6066-11e4-a52e-4f735466cecf': `${selector}-foobar` }), - }, - }) - }) - - beforeEach(async () => { - webApiTests.init({ I: wd, siteUrl }) - this.wdBrowser = await wd._before() - return this.wdBrowser - }) - - afterEach(async () => wd._after()) - - // load common test suite - webApiTests.tests() - - describe('customLocatorStrategies', () => { - it('should locate through custom selector', async () => { - const el = await this.wdBrowser.custom$('customSelector', '.test') - expect(el.elementId).to.equal('.test-foobar') - }) - - it('should include the custom strategy', async () => { - expect(wd.customLocatorStrategies.customSelector).to.not.be.undefined - }) - - it('should be added to the browser locator strategies', async () => { - expect(this.wdBrowser.addLocatorStrategy).to.not.be.undefined - }) - - it('throws on invalid custom selector', async () => { - try { - await wd.waitForEnabled({ madeUpSelector: '#text' }, 2) - } catch (e) { - expect(e.message).to.include('Please define "customLocatorStrategies"') - } - }) - }) - - describe('open page : #amOnPage', () => { - it('should open main page of configured site', async () => { - await wd.amOnPage('/') - const url = await wd.grabCurrentUrl() - url.should.eql(`${siteUrl}/`) - }) - - it('should open any page of configured site', async () => { - await wd.amOnPage('/info') - const url = await wd.grabCurrentUrl() - url.should.eql(`${siteUrl}/info`) - }) - - it('should open absolute url', async () => { - await wd.amOnPage(siteUrl) - const url = await wd.grabCurrentUrl() - url.should.eql(`${siteUrl}/`) - }) - }) - - describe('see text : #see', () => { - it('should fail when text is not on site', async () => { - await wd.amOnPage('/') - - try { - await wd.see('Something incredible!') - } catch (e) { - e.should.be.instanceOf(AssertionFailedError) - e.inspect().should.include('web page') - } - - try { - await wd.dontSee('Welcome') - } catch (e) { - e.should.be.instanceOf(AssertionFailedError) - e.inspect().should.include('web page') - } - }) - }) - - describe('check fields: #seeInField, #seeCheckboxIsChecked, ...', () => { - it('should throw error if field is not empty', async () => { - await wd.amOnPage('/form/empty') - - try { - await wd.seeInField('#empty_input', 'Ayayay') - } catch (e) { - e.should.be.instanceOf(AssertionFailedError) - e.inspect().should.be.equal('expected fields by #empty_input to include "Ayayay"') - } - }) - - it('should check values in checkboxes', async () => { - await wd.amOnPage('/form/field_values') - await wd.dontSeeInField('checkbox[]', 'not seen one') - await wd.seeInField('checkbox[]', 'see test one') - await wd.dontSeeInField('checkbox[]', 'not seen two') - await wd.seeInField('checkbox[]', 'see test two') - await wd.dontSeeInField('checkbox[]', 'not seen three') - await wd.seeInField('checkbox[]', 'see test three') - }) - - it('should check values are the secret type in checkboxes', async () => { - await wd.amOnPage('/form/field_values') - await wd.dontSeeInField('checkbox[]', Secret.secret('not seen one')) - await wd.seeInField('checkbox[]', Secret.secret('see test one')) - await wd.dontSeeInField('checkbox[]', Secret.secret('not seen two')) - await wd.seeInField('checkbox[]', Secret.secret('see test two')) - await wd.dontSeeInField('checkbox[]', Secret.secret('not seen three')) - await wd.seeInField('checkbox[]', Secret.secret('see test three')) - }) - - it('should check values with boolean', async () => { - await wd.amOnPage('/form/field_values') - await wd.seeInField('checkbox1', true) - await wd.dontSeeInField('checkbox1', false) - await wd.seeInField('checkbox2', false) - await wd.dontSeeInField('checkbox2', true) - await wd.seeInField('radio2', true) - await wd.dontSeeInField('radio2', false) - await wd.seeInField('radio3', false) - await wd.dontSeeInField('radio3', true) - }) - - it('should check values in radio', async () => { - await wd.amOnPage('/form/field_values') - await wd.seeInField('radio1', 'see test one') - await wd.dontSeeInField('radio1', 'not seen one') - await wd.dontSeeInField('radio1', 'not seen two') - await wd.dontSeeInField('radio1', 'not seen three') - }) - - it('should return error when element has no value attribute', async () => { - await wd.amOnPage('https://codecept.io/quickstart') - - try { - await wd.seeInField('#search_input_react', 'WebDriver1') - } catch (e) { - e.should.be.instanceOf(Error) - } - }) - }) - - describe('Force Right Click: #forceRightClick', () => { - it('it should forceRightClick', async () => { - await wd.amOnPage('/form/rightclick') - await wd.dontSee('right clicked') - await wd.forceRightClick('Lorem Ipsum') - await wd.see('right clicked') - }) - - it('it should forceRightClick by locator', async () => { - await wd.amOnPage('/form/rightclick') - await wd.dontSee('right clicked') - await wd.forceRightClick('.context a') - await wd.see('right clicked') - }) - - it('it should forceRightClick by locator and context', async () => { - await wd.amOnPage('/form/rightclick') - await wd.dontSee('right clicked') - await wd.forceRightClick('Lorem Ipsum', '.context') - await wd.see('right clicked') - }) - }) - - describe.skip('#pressKey, #pressKeyDown, #pressKeyUp', () => { - it('should be able to send special keys to element', async () => { - await wd.amOnPage('/form/field') - await wd.appendField('Name', '-') - - await wd.pressKey(['Right Shift', 'Home']) - await wd.pressKey('Delete') - - // Sequence only executes up to first non-modifier key ('Digit1') - await wd.pressKey(['SHIFT_RIGHT', 'Digit1', 'Digit4']) - await wd.pressKey('1') - await wd.pressKey('2') - await wd.pressKey('3') - await wd.pressKey('ArrowLeft') - await wd.pressKey('Left Arrow') - await wd.pressKey('arrow_left') - await wd.pressKeyDown('Shift') - await wd.pressKey('a') - await wd.pressKey('KeyB') - await wd.pressKeyUp('ShiftLeft') - await wd.pressKey('C') - await wd.seeInField('Name', '!ABC123') - }) - - it('should use modifier key based on operating system', async () => { - await wd.amOnPage('/form/field') - await wd.fillField('Name', 'value that is cleared using select all shortcut') - - await wd.pressKey(['CommandOrControl', 'A']) - await wd.pressKey('Backspace') - await wd.dontSeeInField('Name', 'value that is cleared using select all shortcut') - }) - - it('should show correct numpad or punctuation key when Shift modifier is active', async () => { - await wd.amOnPage('/form/field') - await wd.fillField('Name', '') - - await wd.pressKey(';') - await wd.pressKey(['Shift', ';']) - await wd.pressKey(['Shift', 'Semicolon']) - await wd.pressKey('=') - await wd.pressKey(['Shift', '=']) - await wd.pressKey(['Shift', 'Equal']) - await wd.pressKey('*') - await wd.pressKey(['Shift', '*']) - await wd.pressKey(['Shift', 'Multiply']) - await wd.pressKey('+') - await wd.pressKey(['Shift', '+']) - await wd.pressKey(['Shift', 'Add']) - await wd.pressKey(',') - await wd.pressKey(['Shift', ',']) - await wd.pressKey(['Shift', 'Comma']) - await wd.pressKey(['Shift', 'NumpadComma']) - await wd.pressKey(['Shift', 'Separator']) - await wd.pressKey('-') - await wd.pressKey(['Shift', '-']) - await wd.pressKey(['Shift', 'Subtract']) - await wd.pressKey('.') - await wd.pressKey(['Shift', '.']) - await wd.pressKey(['Shift', 'Decimal']) - await wd.pressKey(['Shift', 'Period']) - await wd.pressKey('/') - await wd.pressKey(['Shift', '/']) - await wd.pressKey(['Shift', 'Divide']) - await wd.pressKey(['Shift', 'Slash']) - - await wd.seeInField('Name', ';::=++***+++,<<<<-_-.>.>/?/?') - }) - - it('should show correct number key when Shift modifier is active', async () => { - await wd.amOnPage('/form/field') - await wd.fillField('Name', '') - - await wd.pressKey('0') - await wd.pressKeyDown('Shift') - await wd.pressKey('0') - await wd.pressKey('Digit0') - await wd.pressKeyUp('Shift') - - await wd.pressKey('1') - await wd.pressKeyDown('Shift') - await wd.pressKey('1') - await wd.pressKey('Digit1') - await wd.pressKeyUp('Shift') - - await wd.pressKey('2') - await wd.pressKeyDown('Shift') - await wd.pressKey('2') - await wd.pressKey('Digit2') - await wd.pressKeyUp('Shift') - - await wd.pressKey('3') - await wd.pressKeyDown('Shift') - await wd.pressKey('3') - await wd.pressKey('Digit3') - await wd.pressKeyUp('Shift') - - await wd.pressKey('4') - await wd.pressKeyDown('Shift') - await wd.pressKey('4') - await wd.pressKey('Digit4') - await wd.pressKeyUp('Shift') - - await wd.pressKey('5') - await wd.pressKeyDown('Shift') - await wd.pressKey('5') - await wd.pressKey('Digit5') - await wd.pressKeyUp('Shift') - - await wd.pressKey('6') - await wd.pressKeyDown('Shift') - await wd.pressKey('6') - await wd.pressKey('Digit6') - await wd.pressKeyUp('Shift') - - await wd.pressKey('7') - await wd.pressKeyDown('Shift') - await wd.pressKey('7') - await wd.pressKey('Digit7') - await wd.pressKeyUp('Shift') - - await wd.pressKey('8') - await wd.pressKeyDown('Shift') - await wd.pressKey('8') - await wd.pressKey('Digit8') - await wd.pressKeyUp('Shift') - - await wd.pressKey('9') - await wd.pressKeyDown('Shift') - await wd.pressKey('9') - await wd.pressKey('Digit9') - await wd.pressKeyUp('Shift') - - await wd.seeInField('Name', '0))1!!2@@3##4$$5%%6^^7&&8**9((') - }) - }) - - describe('#seeInSource, #grabSource', () => { - it('should check for text to be in HTML source', async () => { - await wd.amOnPage('/') - await wd.seeInSource('TestEd Beta 2.0') - await wd.dontSeeInSource(' { - await wd.amOnPage('/') - const source = await wd.grabSource() - assert.notEqual(source.indexOf('TestEd Beta 2.0'), -1, 'Source html should be retrieved') - }) - - it('should grab the innerHTML for an element', async () => { - await wd.amOnPage('/') - const source = await wd.grabHTMLFrom('#area1') - assert.deepEqual( - source, - ` - Test Link -`, - ) - }) - }) - - describe('#seeTitleEquals', () => { - it('should check that title is equal to provided one', async () => { - await wd.amOnPage('/') - - try { - await wd.seeTitleEquals('TestEd Beta 2.0') - await wd.seeTitleEquals('TestEd Beta 2.') - } catch (e) { - assert.equal(e.message, 'expected web page title to be TestEd Beta 2., but found TestEd Beta 2.0') - } - }) - }) - - describe('#seeTextEquals', () => { - it('should check text is equal to provided one', async () => { - await wd.amOnPage('/') - await wd.seeTextEquals('Welcome to test app!', 'h1') - - try { - await wd.seeTextEquals('Welcome to test app', 'h1') - assert.equal(true, false, 'Throw an error because it should not get this far!') - } catch (e) { - e.should.be.instanceOf(Error) - e.message.should.be.equal('expected element h1 "Welcome to test app" to equal "Welcome to test app!"') - // e.should.be.instanceOf(AssertionFailedError); - } - }) - - it('should check text is not equal to empty string of element text', async () => { - await wd.amOnPage('https://codecept.io') - - try { - await wd.seeTextEquals('', '.logo') - await wd.seeTextEquals('This is not empty', '.logo') - } catch (e) { - e.should.be.instanceOf(Error) - e.message.should.be.equal('expected element .logo "This is not empty" to equal ""') - } - }) - }) - - describe('#waitForFunction', () => { - it('should wait for function returns true', async () => { - await wd.amOnPage('/form/wait_js') - await wd.waitForFunction(() => window.__waitJs, 3) - }) - - it('should pass arguments and wait for function returns true', async () => { - await wd.amOnPage('/form/wait_js') - await wd.waitForFunction((varName) => window[varName], ['__waitJs'], 3) - }) - }) - - describe('#waitForEnabled', () => { - it('should wait for input text field to be enabled', async () => { - await wd.amOnPage('/form/wait_enabled') - await wd.waitForEnabled('#text', 2) - await wd.fillField('#text', 'hello world') - await wd.seeInField('#text', 'hello world') - }) - - it('should wait for input text field to be enabled by xpath', async () => { - await wd.amOnPage('/form/wait_enabled') - await wd.waitForEnabled("//*[@name = 'test']", 2) - await wd.fillField('#text', 'hello world') - await wd.seeInField('#text', 'hello world') - }) - - it('should wait for a button to be enabled', async () => { - await wd.amOnPage('/form/wait_enabled') - await wd.waitForEnabled('#text', 2) - await wd.click('#button') - await wd.see('button was clicked') - }) - }) - - describe('#waitForValue', () => { - it('should wait for expected value for given locator', async () => { - await wd.amOnPage('/info') - await wd.waitForValue('//input[@name= "rus"]', 'Верно') - - try { - await wd.waitForValue('//input[@name= "rus"]', 'Верно3', 0.1) - throw Error('It should never get this far') - } catch (e) { - e.message.should.include( - 'element (//input[@name= "rus"]) is not in DOM or there is no element(//input[@name= "rus"]) with value "Верно3" after 0.1 sec', - ) - } - }) - - it('should wait for expected value for given css locator', async () => { - await wd.amOnPage('/form/wait_value') - await wd.seeInField('#text', 'Hamburg') - await wd.waitForValue('#text', 'Brisbane', 2.5) - await wd.seeInField('#text', 'Brisbane') - }) - - it('should wait for expected value for given xpath locator', async () => { - await wd.amOnPage('/form/wait_value') - await wd.seeInField('#text', 'Hamburg') - await wd.waitForValue('//input[@value = "Grüße aus Hamburg"]', 'Brisbane', 2.5) - await wd.seeInField('#text', 'Brisbane') - }) - - it('should only wait for one of the matching elements to contain the value given xpath locator', async () => { - await wd.amOnPage('/form/wait_value') - await wd.waitForValue('//input[@type = "text"]', 'Brisbane', 4) - await wd.seeInField('#text', 'Brisbane') - await wd.seeInField('#text2', 'London') - }) - - it('should only wait for one of the matching elements to contain the value given css locator', async () => { - await wd.amOnPage('/form/wait_value') - await wd.waitForValue('.inputbox', 'Brisbane', 4) - await wd.seeInField('#text', 'Brisbane') - await wd.seeInField('#text2', 'London') - }) - }) - - describe('#waitNumberOfVisibleElements', () => { - it('should wait for a specified number of elements on the page', () => { - return wd - .amOnPage('/info') - .then(() => wd.waitNumberOfVisibleElements('//div[@id = "grab-multiple"]//a', 3)) - .then(() => wd.waitNumberOfVisibleElements('//div[@id = "grab-multiple"]//a', 2, 0.1)) - .then(() => { - throw Error('It should never get this far') - }) - .catch((e) => { - e.message.should.include('The number of elements (//div[@id = "grab-multiple"]//a) is not 2 after 0.1 sec') - }) - }) - - it('should be no [object Object] in the error message', () => { - return wd - .amOnPage('/info') - .then(() => wd.waitNumberOfVisibleElements({ css: '//div[@id = "grab-multiple"]//a' }, 3)) - .then(() => { - throw Error('It should never get this far') - }) - .catch((e) => { - e.message.should.not.include('[object Object]') - }) - }) - - it('should wait for a specified number of elements on the page using a css selector', () => { - return wd - .amOnPage('/info') - .then(() => wd.waitNumberOfVisibleElements('#grab-multiple > a', 3)) - .then(() => wd.waitNumberOfVisibleElements('#grab-multiple > a', 2, 0.1)) - .then(() => { - throw Error('It should never get this far') - }) - .catch((e) => { - e.message.should.include('The number of elements (#grab-multiple > a) is not 2 after 0.1 sec') - }) - }) - - it('should wait for a specified number of elements which are not yet attached to the DOM', () => { - return wd - .amOnPage('/form/wait_num_elements') - .then(() => wd.waitNumberOfVisibleElements('.title', 2, 3)) - .then(() => wd.see('Hello')) - .then(() => wd.see('World')) - }) - - it('should wait for 0 number of visible elements', async () => { - await wd.amOnPage('/form/wait_invisible') - await wd.waitNumberOfVisibleElements('#step_1', 0) - }) - }) - - describe('#waitForVisible', () => { - it('should be no [object Object] in the error message', () => { - return wd - .amOnPage('/info') - .then(() => wd.waitForVisible('//div[@id = "grab-multiple"]//a', 3)) - .then(() => { - throw Error('It should never get this far') - }) - .catch((e) => { - e.message.should.not.include('[object Object]') - }) - }) - }) - - describe('#waitForInvisible', () => { - it('should be no [object Object] in the error message', () => { - return wd - .amOnPage('/info') - .then(() => wd.waitForInvisible('//div[@id = "grab-multiple"]//a', 3)) - .then(() => { - throw Error('It should never get this far') - }) - .catch((e) => { - e.message.should.not.include('[object Object]') - }) - }) - - it('should wait for a specified element to be invisible', () => { - return wd - .amOnPage('/form/wait_invisible') - .then(() => wd.waitForInvisible('#step1', 3)) - .then(() => wd.dontSeeElement('#step1')) - }) - }) - - describe('#moveCursorTo', () => { - it('should trigger hover event', async () => { - await wd.amOnPage('/form/hover') - await wd.moveCursorTo('#hover') - await wd.see('Hovered', '#show') - }) - - it('should not trigger hover event because of the offset is beyond the element', async () => { - await wd.amOnPage('/form/hover') - await wd.moveCursorTo('#hover', 120, 120) - await wd.dontSee('Hovered!', '#show') - }) - }) - - describe('#switchToNextTab, #switchToPreviousTab, #openNewTab, #closeCurrentTab, #closeOtherTabs, #grabNumberOfOpenTabs', () => { - it('should only have 1 tab open when the browser starts and navigates to the first page', async () => { - await wd.amOnPage('/') - const numPages = await wd.grabNumberOfOpenTabs() - assert.equal(numPages, 1) - }) - - it('should switch to next tab', async () => { - wd.amOnPage('/info') - const numPages = await wd.grabNumberOfOpenTabs() - assert.equal(numPages, 1) - - await wd.click('New tab') - await wd.switchToNextTab() - await wd.waitInUrl('/login') - const numPagesAfter = await wd.grabNumberOfOpenTabs() - assert.equal(numPagesAfter, 2) - }) - - it('should assert when there is no ability to switch to next tab', () => { - return wd - .amOnPage('/') - .then(() => wd.click('More info')) - .then(() => wd.wait(1)) // Wait is required because the url is change by previous statement (maybe related to #914) - .then(() => wd.switchToNextTab(2)) - .then(() => assert.equal(true, false, 'Throw an error if it gets this far (which it should not)!')) - .catch((e) => { - assert.equal(e.message, 'There is no ability to switch to next tab with offset 2') - }) - }) - - it('should close current tab', () => { - return wd - .amOnPage('/info') - .then(() => wd.click('New tab')) - .then(() => wd.switchToNextTab()) - .then(() => wd.seeInCurrentUrl('/login')) - .then(() => wd.grabNumberOfOpenTabs()) - .then((numPages) => assert.equal(numPages, 2)) - .then(() => wd.closeCurrentTab()) - .then(() => wd.seeInCurrentUrl('/info')) - .then(() => wd.grabNumberOfOpenTabs()) - }) - - it('should close other tabs', () => { - return wd - .amOnPage('/') - .then(() => wd.openNewTab()) - .then(() => wd.seeInCurrentUrl('about:blank')) - .then(() => wd.amOnPage('/info')) - .then(() => wd.click('New tab')) - .then(() => wd.switchToNextTab()) - .then(() => wd.seeInCurrentUrl('/login')) - .then(() => wd.closeOtherTabs()) - .then(() => wd.seeInCurrentUrl('/login')) - .then(() => wd.grabNumberOfOpenTabs()) - }) - - it('should open new tab', () => { - return wd - .amOnPage('/info') - .then(() => wd.openNewTab()) - .then(() => wd.waitInUrl('about:blank')) - .then(() => wd.grabNumberOfOpenTabs()) - .then((numPages) => assert.equal(numPages, 2)) - }) - - it('should switch to previous tab', () => { - return wd - .amOnPage('/info') - .then(() => wd.openNewTab()) - .then(() => wd.waitInUrl('about:blank')) - .then(() => wd.switchToPreviousTab()) - .then(() => wd.waitInUrl('/info')) - }) - - it('should assert when there is no ability to switch to previous tab', () => { - return wd - .amOnPage('/info') - .then(() => wd.openNewTab()) - .then(() => wd.waitInUrl('about:blank')) - .then(() => wd.switchToPreviousTab(2)) - .then(() => wd.waitInUrl('/info')) - .catch((e) => { - assert.equal(e.message, 'There is no ability to switch to previous tab with offset 2') - }) - }) - }) - - describe('popup : #acceptPopup, #seeInPopup, #cancelPopup', () => { - it('should accept popup window', () => { - return wd - .amOnPage('/form/popup') - .then(() => wd.click('Confirm')) - .then(() => wd.acceptPopup()) - .then(() => wd.see('Yes', '#result')) - }) - - it('should cancel popup', () => { - return wd - .amOnPage('/form/popup') - .then(() => wd.click('Confirm')) - .then(() => wd.cancelPopup()) - .then(() => wd.see('No', '#result')) - }) - - it('should check text in popup', () => { - return wd - .amOnPage('/form/popup') - .then(() => wd.click('Alert')) - .then(() => wd.seeInPopup('Really?')) - .then(() => wd.cancelPopup()) - }) - - it('should grab text from popup', () => { - return wd - .amOnPage('/form/popup') - .then(() => wd.click('Alert')) - .then(() => wd.grabPopupText()) - .then((text) => assert.equal(text, 'Really?')) - }) - - it('should return null if no popup is visible (do not throw an error)', () => { - return wd - .amOnPage('/form/popup') - .then(() => wd.grabPopupText()) - .then((text) => assert.equal(text, null)) - }) - }) - - describe('#waitForText', () => { - it('should return error if not present', () => { - return wd - .amOnPage('/dynamic') - .then(() => wd.waitForText('Nothing here', 1, '#text')) - .catch((e) => { - e.message.should.be.equal( - 'element (#text) is not in DOM or there is no element(#text) with text "Nothing here" after 1 sec', - ) - }) - }) - - it('should return error if waiting is too small', () => { - return wd - .amOnPage('/dynamic') - .then(() => wd.waitForText('Dynamic text', 0.1)) - .catch((e) => { - e.message.should.be.equal( - 'element (body) is not in DOM or there is no element(body) with text "Dynamic text" after 0.1 sec', - ) - }) - }) - }) - - describe('#seeNumberOfElements', () => { - it('should return 1 as count', async () => { - await wd.amOnPage('/') - await wd.seeNumberOfElements('#area1', 1) - }) - }) - - describe.skip('#switchTo', () => { - it('should switch reference to iframe content', async () => { - await wd.amOnPage('/iframe') - await wd.switchTo('[name="content"]') - await wd.see('Information\nLots of valuable data here') - }) - - it('should return error if iframe selector is invalid', async () => { - await wd.amOnPage('/iframe') - - try { - await wd.switchTo('#invalidIframeSelector') - } catch (e) { - e.should.be.instanceOf(Error) - e.message.should.be.equal('Element "#invalidIframeSelector" was not found by text|CSS|XPath') - } - }) - - it('should return error if iframe selector is not iframe', async () => { - await wd.amOnPage('/iframe') - - try { - await wd.switchTo('h1') - } catch (e) { - e.should.be.instanceOf(Error) - e.message.should.contain('no such frame') - } - }) - - it('should return to parent frame given a null locator', async () => { - await wd.amOnPage('/iframe') - await wd.switchTo('[name="content"]') - await wd.see('Information\nLots of valuable data here') - await wd.switchTo(null) - await wd.see('Iframe test') - }) - }) - - describe('click context', () => { - it('should click on inner text', async () => { - await wd.amOnPage('/form/checkbox') - await wd.click('Submit', '//input[@type = "submit"]') - await wd.waitInUrl('/form/complex') - }) - - it('should click on input in inner element', async () => { - await wd.amOnPage('/form/checkbox') - await wd.click('Submit', '//form') - await wd.waitInUrl('/form/complex') - }) - - it('should click by accessibility_id', async () => { - await wd.amOnPage('/info') - await wd.click('~index via aria-label') - await wd.see('Welcome to test app!') - }) - }) - - describe('window size #resizeWindow', () => { - it('should set initial window size', async () => { - await wd.amOnPage('/form/resize') - await wd.click('Window Size') - await wd.see('Height 700', '#height') - await wd.see('Width 500', '#width') - }) - - it('should set window size on new session', () => { - return wd - .amOnPage('/info') - .then(() => wd._session()) - .then((session) => - session.start().then((browser) => ({ - browser, - session, - })), - ) - .then(({ session, browser }) => session.loadVars(browser)) - .then(() => wd.amOnPage('/form/resize')) - .then(() => wd.click('Window Size')) - .then(() => wd.see('Height 700', '#height')) - .then(() => wd.see('Width 500', '#width')) - }) - - it.skip('should resize window to specific dimensions', async () => { - await wd.amOnPage('/form/resize') - await wd.resizeWindow(950, 600) - await wd.click('Window Size') - await wd.see('Height 600', '#height') - await wd.see('Width 950', '#width') - }) - - xit('should resize window to maximum screen dimensions', async () => { - await wd.amOnPage('/form/resize') - await wd.resizeWindow(500, 400) - await wd.click('Window Size') - await wd.see('Height 400', '#height') - await wd.see('Width 500', '#width') - await wd.resizeWindow('maximize') - await wd.click('Window Size') - await wd.dontSee('Height 400', '#height') - await wd.dontSee('Width 500', '#width') - }) - }) - - describe('SmartWait', () => { - before(() => (wd.options.smartWait = 3000)) - after(() => (wd.options.smartWait = 0)) - - it('should wait for element to appear', async () => { - await wd.amOnPage('/form/wait_element') - await wd.dontSeeElement('h1') - await wd.seeElement('h1') - }) - - it('should wait for clickable element appear', async () => { - await wd.amOnPage('/form/wait_clickable') - await wd.dontSeeElement('#click') - await wd.click('#click') - await wd.see('Hi!') - }) - - it('should wait for clickable context to appear', async () => { - await wd.amOnPage('/form/wait_clickable') - await wd.dontSeeElement('#linkContext') - await wd.click('Hello world', '#linkContext') - await wd.see('Hi!') - }) - - it('should wait for text context to appear', async () => { - await wd.amOnPage('/form/wait_clickable') - await wd.dontSee('Hello world') - await wd.see('Hello world', '#linkContext') - }) - - it('should work with grabbers', async () => { - await wd.amOnPage('/form/wait_clickable') - await wd.dontSee('Hello world') - const res = await wd.grabAttributeFrom('#click', 'id') - assert.equal(res, 'click') - }) - }) - - describe('#_locateClickable', () => { - it('should locate a button to click', async () => { - await wd.amOnPage('/form/checkbox') - const res = await wd._locateClickable('Submit') - res.length.should.be.equal(1) - }) - - it('should not locate a non-existing checkbox', async () => { - await wd.amOnPage('/form/checkbox') - const res = await wd._locateClickable('I disagree') - res.length.should.be.equal(0) - }) - }) - - describe('#_locateCheckable', () => { - it('should locate a checkbox', async () => { - await wd.amOnPage('/form/checkbox') - const res = await wd._locateCheckable('I Agree') - res.length.should.be.equal(1) - }) - - it('should not locate a non-existing checkbox', async () => { - await wd.amOnPage('/form/checkbox') - const res = await wd._locateCheckable('I disagree') - res.length.should.be.equal(0) - }) - }) - - describe('#_locateFields', () => { - it('should locate a field', async () => { - await wd.amOnPage('/form/field') - const res = await wd._locateFields('Name') - res.length.should.be.equal(1) - }) - - it('should not locate a non-existing field', async () => { - await wd.amOnPage('/form/field') - const res = await wd._locateFields('Mother-in-law') - res.length.should.be.equal(0) - }) - }) - - xdescribe('#grabBrowserLogs', () => { - it('should grab browser logs', async () => { - await wd.amOnPage('/') - await wd.executeScript(() => { - console.log('Test log entry') - }) - const logs = await wd.grabBrowserLogs() - console.log('lololo', logs) - - const matchingLogs = logs.filter((log) => log.message.indexOf('Test log entry') > -1) - assert.equal(matchingLogs.length, 1) - }) - - it('should grab browser logs across pages', async () => { - wd.amOnPage('/') - await wd.executeScript(() => { - console.log('Test log entry 1') - }) - await wd.openNewTab() - await wd.amOnPage('/info') - await wd.executeScript(() => { - console.log('Test log entry 2') - }) - - const logs = await wd.grabBrowserLogs() - - const matchingLogs = logs.filter((log) => log.message.indexOf('Test log entry') > -1) - assert.equal(matchingLogs.length, 2) - }) - }) - - describe('#dragAndDrop', () => { - it('Drag item from source to target (no iframe) @dragNdrop', async () => { - await wd.amOnPage('http://jqueryui.com/resources/demos/droppable/default.html') - await wd.seeElementInDOM('#draggable') - await wd.dragAndDrop('#draggable', '#droppable') - await wd.see('Dropped') - }) - - it.skip('Drag and drop from within an iframe', async () => { - await wd.amOnPage('http://jqueryui.com/droppable') - await wd.resizeWindow(700, 700) - await wd.switchTo('//iframe[@class="demo-frame"]') - await wd.seeElementInDOM('#draggable') - await wd.dragAndDrop('#draggable', '#droppable') - await wd.see('Dropped') - }) - }) - - describe('#switchTo frame', () => { - it('should switch to frame using name', async () => { - await wd.amOnPage('/iframe') - await wd.see('Iframe test', 'h1') - await wd.dontSee('Information', 'h1') - await wd.switchTo('iframe') - await wd.see('Information', 'h1') - await wd.dontSee('Iframe test', 'h1') - }) - - it('should switch to root frame', async () => { - await wd.amOnPage('/iframe') - await wd.see('Iframe test', 'h1') - await wd.dontSee('Information', 'h1') - await wd.switchTo('iframe') - await wd.see('Information', 'h1') - await wd.dontSee('Iframe test', 'h1') - await wd.switchTo() - await wd.see('Iframe test', 'h1') - }) - - it('should switch to frame using frame number', async () => { - await wd.amOnPage('/iframe') - await wd.see('Iframe test', 'h1') - await wd.dontSee('Information', 'h1') - await wd.switchTo(0) - await wd.see('Information', 'h1') - await wd.dontSee('Iframe test', 'h1') - }) - }) - - describe('#AttachFile', () => { - it('should attach to regular input element', async () => { - await wd.amOnPage('/form/file') - await wd.attachFile('Avatar', './app/avatar.jpg') - await wd.seeInField('Avatar', 'avatar.jpg') - }) - - it('should attach to invisible input element', async () => { - await wd.amOnPage('/form/file') - await wd.attachFile('hidden', '/app/avatar.jpg') - }) - }) - - describe('#dragSlider', () => { - it('should drag scrubber to given position', async () => { - await wd.amOnPage('/form/page_slider') - await wd.seeElementInDOM('#slidecontainer input') - - const before = await wd.grabValueFrom('#slidecontainer input') - await wd.dragSlider('#slidecontainer input', 20) - const after = await wd.grabValueFrom('#slidecontainer input') - - assert.notEqual(before, after) - }) - }) - - describe('#uncheckOption', () => { - it('should uncheck option that is currently checked', async () => { - await wd.amOnPage('/info') - await wd.uncheckOption('interesting') - await wd.dontSeeCheckboxIsChecked('interesting') - }) - - it('should NOT uncheck option that is NOT currently checked', async () => { - await wd.amOnPage('/info') - await wd.uncheckOption('interesting') - // Unchecking again should not affect the current 'unchecked' status - await wd.uncheckOption('interesting') - await wd.dontSeeCheckboxIsChecked('interesting') - }) - }) - - describe('allow back and forth between handles: #grabAllWindowHandles #grabCurrentWindowHandle #switchToWindow', () => { - it.skip('should open main page of configured site, open a popup, switch to main page, then switch to popup, close popup, and go back to main page', async () => { - await wd.amOnPage('/') - const handleBeforePopup = await wd.grabCurrentWindowHandle() - const urlBeforePopup = await wd.grabCurrentUrl() - - const allHandlesBeforePopup = await wd.grabAllWindowHandles() - allHandlesBeforePopup.length.should.eql(1) - - await wd.executeScript(() => { - window.open( - 'https://www.w3schools.com/', - 'new window', - 'toolbar=yes,scrollbars=yes,resizable=yes,width=400,height=400', - ) - }) - - const allHandlesAfterPopup = await wd.grabAllWindowHandles() - allHandlesAfterPopup.length.should.eql(1) - - await wd.switchToWindow(allHandlesAfterPopup[1]) - const urlAfterPopup = await wd.grabCurrentUrl() - urlAfterPopup.should.eql('https://www.w3schools.com/') - - handleBeforePopup.should.eql(allHandlesAfterPopup[0]) - await wd.switchToWindow(handleBeforePopup) - const currentURL = await wd.grabCurrentUrl() - currentURL.should.eql(urlBeforePopup) - - await wd.switchToWindow(allHandlesAfterPopup[1]) - const urlAfterSwitchBack = await wd.grabCurrentUrl() - urlAfterSwitchBack.should.eql('https://www.w3schools.com/') - await wd.closeCurrentTab() - - const allHandlesAfterPopupClosed = await wd.grabAllWindowHandles() - allHandlesAfterPopupClosed.length.should.eql(1) - const currentWindowHandle = await wd.grabCurrentWindowHandle() - currentWindowHandle.should.eql(handleBeforePopup) - }) - }) - - describe('#waitForClickable', () => { - it('should wait for clickable', async () => { - await wd.amOnPage('/form/wait_for_clickable') - await wd.waitForClickable({ css: 'input#text' }) - }) - - it('should wait for clickable by XPath', async () => { - await wd.amOnPage('/form/wait_for_clickable') - await wd.waitForClickable({ xpath: './/input[@id="text"]' }) - }) - - it('should fail for disabled element', async () => { - await wd.amOnPage('/form/wait_for_clickable') - await wd - .waitForClickable({ css: '#button' }, 0.1) - .then((isClickable) => { - if (isClickable) throw new Error('Element is clickable, but must be unclickable') - }) - .catch((e) => { - e.message.should.include('element #button still not clickable after 0.1 sec') - }) - }) - - it('should fail for disabled element by XPath', async () => { - await wd.amOnPage('/form/wait_for_clickable') - await wd - .waitForClickable({ xpath: './/button[@id="button"]' }, 0.1) - .then((isClickable) => { - if (isClickable) throw new Error('Element is clickable, but must be unclickable') - }) - .catch((e) => { - e.message.should.include('element .//button[@id="button"] still not clickable after 0.1 sec') - }) - }) - - it('should fail for element not in viewport by top', async () => { - await wd.amOnPage('/form/wait_for_clickable') - await wd - .waitForClickable({ css: '#notInViewportTop' }, 0.1) - .then((isClickable) => { - if (isClickable) throw new Error('Element is clickable, but must be unclickable') - }) - .catch((e) => { - e.message.should.include('element #notInViewportTop still not clickable after 0.1 sec') - }) - }) - - it('should fail for element not in viewport by bottom', async () => { - await wd.amOnPage('/form/wait_for_clickable') - await wd - .waitForClickable({ css: '#notInViewportBottom' }, 0.1) - .then((isClickable) => { - if (isClickable) throw new Error('Element is clickable, but must be unclickable') - }) - .catch((e) => { - e.message.should.include('element #notInViewportBottom still not clickable after 0.1 sec') - }) - }) - - it('should fail for element not in viewport by left', async () => { - await wd.amOnPage('/form/wait_for_clickable') - await wd - .waitForClickable({ css: '#notInViewportLeft' }, 0.1) - .then((isClickable) => { - if (isClickable) throw new Error('Element is clickable, but must be unclickable') - }) - .catch((e) => { - e.message.should.include('element #notInViewportLeft still not clickable after 0.1 sec') - }) - }) - - it('should fail for element not in viewport by right', async () => { - await wd.amOnPage('/form/wait_for_clickable') - await wd - .waitForClickable({ css: '#notInViewportRight' }, 0.1) - .then((isClickable) => { - if (isClickable) throw new Error('Element is clickable, but must be unclickable') - }) - .catch((e) => { - e.message.should.include('element #notInViewportRight still not clickable after 0.1 sec') - }) - }) - - it('should fail for overlapping element', async () => { - await wd.amOnPage('/form/wait_for_clickable') - await wd.waitForClickable({ css: '#div2_button' }, 0.1) - await wd - .waitForClickable({ css: '#div1_button' }, 0.1) - .then((isClickable) => { - if (isClickable) throw new Error('Element is clickable, but must be unclickable') - }) - .catch((e) => { - e.message.should.include('element #div1_button still not clickable after 0.1 sec') - }) - }) - }) - - describe('GeoLocation', () => { - it('should set the geoLocation', async () => { - await wd.setGeoLocation(37.4043, -122.0748) - const geoLocation = await wd.grabGeoLocation() - assert.equal(geoLocation.latitude, 37.4043, 'The latitude is not properly set') - assert.equal(geoLocation.longitude, -122.0748, 'The longitude is not properly set') - }) - }) - - describe('#grabElementBoundingRect', () => { - it('should get the element size', async () => { - await wd.amOnPage('/form/hidden') - const size = await wd.grabElementBoundingRect('input[type=submit]') - expect(size.x).is.greaterThan(0) - expect(size.y).is.greaterThan(0) - expect(size.width).is.greaterThan(0) - expect(size.height).is.greaterThan(0) - }) - - it('should get the element width', async () => { - await wd.amOnPage('/form/hidden') - const width = await wd.grabElementBoundingRect('input[type=submit]', 'width') - expect(width).is.greaterThan(0) - }) - - it('should get the element height', async () => { - await wd.amOnPage('/form/hidden') - const height = await wd.grabElementBoundingRect('input[type=submit]', 'height') - expect(height).is.greaterThan(0) - }) - }) - - describe('#scrollIntoView', () => { - it.skip('should scroll element into viewport', async () => { - await wd.amOnPage('/form/scroll_into_view') - const element = await wd.browser.$('#notInViewportByDefault') - expect(await element.isDisplayedInViewport()).to.be.false - await wd.scrollIntoView('#notInViewportByDefault') - expect(await element.isDisplayedInViewport()).to.be.true - }) - }) - - describe('#useWebDriverTo', () => { - it('should return title', async () => { - await wd.amOnPage('/') - const title = await wd.useWebDriverTo('test', async ({ browser }) => { - return browser.getTitle() - }) - assert.equal('TestEd Beta 2.0', title) - }) - }) -}) From 8df0d27b115cf05760ba17da03891ac79264a524 Mon Sep 17 00:00:00 2001 From: Thomas Hohn Date: Tue, 12 Nov 2024 15:37:13 +0100 Subject: [PATCH 02/16] Removed reference --- test/plugin/plugin_test.js | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/test/plugin/plugin_test.js b/test/plugin/plugin_test.js index 2aca83c17..70d398f33 100644 --- a/test/plugin/plugin_test.js +++ b/test/plugin/plugin_test.js @@ -48,21 +48,6 @@ describe('CodeceptJS plugin', function () { }) }) - it('should generate the coverage report - WebDriver - Devtools protocol', (done) => { - exec(`${config_run_config('codecept.WebDriver.devtools.coverage.js', '@coverage')} --debug`, (err, stdout) => { - const lines = stdout.split('\n') - expect(lines).toEqual( - expect.arrayContaining([ - expect.stringContaining('writing output/coverage'), - expect.stringContaining('generated coverage reports:'), - expect.stringContaining('output/coverage/index.html'), - ]), - ) - expect(err).toBeFalsy() - done() - }) - }) - it('should retry to failure', (done) => { exec( `${config_run_config('codecept.Playwright.retryTo.js', 'Should fail after reached max retries')} --verbose`, From 4027e8216d2442e92d7d2b41402101263279007d Mon Sep 17 00:00:00 2001 From: Thomas Hohn Date: Tue, 12 Nov 2024 15:52:56 +0100 Subject: [PATCH 03/16] Remove options --- lib/helper/WebDriver.js | 71 ++--------------------------------------- 1 file changed, 3 insertions(+), 68 deletions(-) diff --git a/lib/helper/WebDriver.js b/lib/helper/WebDriver.js index 9bd253405..4f3a989e1 100644 --- a/lib/helper/WebDriver.js +++ b/lib/helper/WebDriver.js @@ -614,11 +614,6 @@ class WebDriver extends Helper { delete this.options.capabilities.hostname delete this.options.capabilities.port delete this.options.capabilities.path - if (this.options.devtoolsProtocol) { - if (!['chrome', 'chromium'].includes(this.options.browser.toLowerCase())) - throw Error('The devtools protocol is only working with Chrome or Chromium') - this.options.automationProtocol = 'devtools' - } this.browser = await webdriverio.remote(this.options) } } catch (err) { @@ -649,10 +644,8 @@ class WebDriver extends Helper { this.browser.capabilities.platformName = this.browser.capabilities.platformName.toLowerCase() } - if (this.options.automationProtocol) { - this.puppeteerBrowser = await this.browser.getPuppeteer() - this.page = (await this.puppeteerBrowser.pages())[0] - } + this.puppeteerBrowser = await this.browser.getPuppeteer() + this.page = (await this.puppeteerBrowser.pages())[0] return this.browser } @@ -1143,10 +1136,6 @@ class WebDriver extends Helper { assertElementExists(res, field, 'Field') const elem = usingFirstElement(res) highlightActiveElement.call(this, elem) - if (this.options.automationProtocol) { - const curentValue = await elem.getValue() - return elem.setValue(curentValue + value.toString()) - } return elem.addValue(value.toString()) } @@ -1159,9 +1148,6 @@ class WebDriver extends Helper { assertElementExists(res, field, 'Field') const elem = usingFirstElement(res) highlightActiveElement.call(this, elem) - if (this.options.automationProtocol) { - return elem.setValue('') - } return elem.clearValue(getElementId(elem)) } @@ -1231,7 +1217,7 @@ class WebDriver extends Helper { const el = usingFirstElement(res) // Remote Upload (when running Selenium Server) - if (this.options.remoteFileUpload && !this.options.automationProtocol) { + if (this.options.remoteFileUpload) { try { this.debugSection('File', 'Uploading file to remote server') file = await this.browser.uploadFile(file) @@ -2593,9 +2579,6 @@ class WebDriver extends Helper { async switchTo(locator) { this.browser.isInsideFrame = true if (Number.isInteger(locator)) { - if (this.options.automationProtocol) { - return this.browser.switchToFrame(locator + 1) - } return this.browser.switchToFrame(locator) } if (!locator) { @@ -2741,12 +2724,6 @@ class WebDriver extends Helper { * {{> setGeoLocation }} */ async setGeoLocation(latitude, longitude) { - if (!this.options.automationProtocol) { - console.log(`setGeoLocation deprecated: - * This command is deprecated due to using deprecated JSON Wire Protocol command. More info: https://webdriver.io/docs/api/jsonwp/#setgeolocation - * Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration`) - return - } this.geoLocation = { latitude, longitude } await this.browser.call(async () => { @@ -2762,12 +2739,6 @@ class WebDriver extends Helper { * */ async grabGeoLocation() { - if (!this.options.automationProtocol) { - console.log(`grabGeoLocation deprecated: - * This command is deprecated due to using deprecated JSON Wire Protocol command. More info: https://webdriver.io/docs/api/jsonwp/#getgeolocation - * Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration`) - return - } if (!this.geoLocation) return 'No GeoLocation is set!' return this.geoLocation } @@ -2818,12 +2789,6 @@ class WebDriver extends Helper { * {{> flushNetworkTraffics }} */ flushNetworkTraffics() { - if (!this.options.automationProtocol) { - console.log( - '* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration', - ) - return - } this.requests = [] } @@ -2834,12 +2799,6 @@ class WebDriver extends Helper { * {{> stopRecordingTraffic }} */ stopRecordingTraffic() { - if (!this.options.automationProtocol) { - console.log( - '* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration', - ) - return - } this.page.removeAllListeners('request') this.recording = false } @@ -2852,12 +2811,6 @@ class WebDriver extends Helper { * */ async startRecordingTraffic() { - if (!this.options.automationProtocol) { - console.log( - '* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration', - ) - return - } this.flushNetworkTraffics() this.recording = true this.recordedAtLeastOnce = true @@ -2890,12 +2843,6 @@ class WebDriver extends Helper { * {{> grabRecordedNetworkTraffics }} */ async grabRecordedNetworkTraffics() { - if (!this.options.automationProtocol) { - console.log( - '* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration', - ) - return - } return grabRecordedNetworkTraffics.call(this) } @@ -2906,12 +2853,6 @@ class WebDriver extends Helper { * {{> seeTraffic }} */ async seeTraffic({ name, url, parameters, requestPostData, timeout = 10 }) { - if (!this.options.automationProtocol) { - console.log( - '* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration', - ) - return - } await seeTraffic.call(this, ...arguments) } @@ -2923,12 +2864,6 @@ class WebDriver extends Helper { * */ dontSeeTraffic({ name, url }) { - if (!this.options.automationProtocol) { - console.log( - '* Switch to devtools protocol to use this command by setting devtoolsProtocol: true in the configuration', - ) - return - } dontSeeTraffic.call(this, ...arguments) } } From b49f34135a161d9f3e30921d3622d982e43bc747 Mon Sep 17 00:00:00 2001 From: Thomas Hohn Date: Tue, 12 Nov 2024 16:53:18 +0100 Subject: [PATCH 04/16] Cleanup docs --- docs/changelog.md | 1 - docs/helpers/WebDriver.md | 1 - lib/helper/WebDriver.js | 1 - 3 files changed, 3 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index bd22e1210..8fb6ca31c 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -591,7 +591,6 @@ Running with devtools protocol WebDriver : { url: "http://localhost", browser: "chrome", - devtoolsProtocol: true, desiredCapabilities: { chromeOptions: { args: [ "--headless", "--disable-gpu", "--no-sandbox" ] diff --git a/docs/helpers/WebDriver.md b/docs/helpers/WebDriver.md index 7417312a5..3ecaa0acf 100644 --- a/docs/helpers/WebDriver.md +++ b/docs/helpers/WebDriver.md @@ -147,7 +147,6 @@ website][4]. WebDriver : { url: "http://localhost", browser: "chrome", - devtoolsProtocol: true, desiredCapabilities: { chromeOptions: { args: [ "--headless", "--disable-gpu", "--no-sandbox" ] diff --git a/lib/helper/WebDriver.js b/lib/helper/WebDriver.js index 4f3a989e1..2074fa747 100644 --- a/lib/helper/WebDriver.js +++ b/lib/helper/WebDriver.js @@ -180,7 +180,6 @@ const config = {} * WebDriver : { * url: "http://localhost", * browser: "chrome", - * devtoolsProtocol: true, * desiredCapabilities: { * chromeOptions: { * args: [ "--headless", "--disable-gpu", "--no-sandbox" ] From c655b34615adcea681ce2a7a40fd332fd5ff699c Mon Sep 17 00:00:00 2001 From: Thomas Hohn Date: Tue, 12 Nov 2024 18:04:08 +0100 Subject: [PATCH 05/16] Fix tests --- lib/helper/WebDriver.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/helper/WebDriver.js b/lib/helper/WebDriver.js index 2074fa747..938d08d82 100644 --- a/lib/helper/WebDriver.js +++ b/lib/helper/WebDriver.js @@ -643,8 +643,9 @@ class WebDriver extends Helper { this.browser.capabilities.platformName = this.browser.capabilities.platformName.toLowerCase() } - this.puppeteerBrowser = await this.browser.getPuppeteer() - this.page = (await this.puppeteerBrowser.pages())[0] + // @TODO Remove for "test" + // this.puppeteerBrowser = await this.browser.getPuppeteer() + // this.page = (await this.puppeteerBrowser.pages())[0] return this.browser } From 8daa759b32b7976a08c63f5d3563e93731ab8431 Mon Sep 17 00:00:00 2001 From: Thomas Hohn Date: Tue, 12 Nov 2024 19:02:53 +0100 Subject: [PATCH 06/16] Cleanup --- lib/helper/WebDriver.js | 116 ---------------------------------------- 1 file changed, 116 deletions(-) diff --git a/lib/helper/WebDriver.js b/lib/helper/WebDriver.js index 938d08d82..2065deaec 100644 --- a/lib/helper/WebDriver.js +++ b/lib/helper/WebDriver.js @@ -72,7 +72,6 @@ const webRoot = 'body' * @prop {object} [timeouts] [WebDriver timeouts](http://webdriver.io/docs/timeouts.html) defined as hash. * @prop {boolean} [highlightElement] - highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose). * @prop {string} [logLevel=silent] - level of logging verbosity. Default: silent. Options: trace | debug | info | warn | error | silent. More info: https://webdriver.io/docs/configuration/#loglevel - * @prop {boolean} [devtoolsProtocol=false] - enable devtools protocol. Default: false. More info: https://webdriver.io/docs/automationProtocols/#devtools-protocol. */ const config = {} @@ -643,10 +642,6 @@ class WebDriver extends Helper { this.browser.capabilities.platformName = this.browser.capabilities.platformName.toLowerCase() } - // @TODO Remove for "test" - // this.puppeteerBrowser = await this.browser.getPuppeteer() - // this.page = (await this.puppeteerBrowser.pages())[0] - return this.browser } @@ -2717,32 +2712,6 @@ class WebDriver extends Helper { return this.executeScript(getScrollPosition) } - /** - * This method is **deprecated**. - * - * - * {{> setGeoLocation }} - */ - async setGeoLocation(latitude, longitude) { - this.geoLocation = { latitude, longitude } - - await this.browser.call(async () => { - const pages = await this.puppeteerBrowser.pages() - await pages[0].setGeolocation({ latitude, longitude }) - }) - } - - /** - * This method is **deprecated**. - * - * {{> grabGeoLocation }} - * - */ - async grabGeoLocation() { - if (!this.geoLocation) return 'No GeoLocation is set!' - return this.geoLocation - } - /** * {{> grabElementBoundingRect }} */ @@ -2781,91 +2750,6 @@ class WebDriver extends Helper { runInWeb(fn) { return fn() } - - /** - * - * _Note:_ Only works when devtoolsProtocol is enabled. - * - * {{> flushNetworkTraffics }} - */ - flushNetworkTraffics() { - this.requests = [] - } - - /** - * - * _Note:_ Only works when devtoolsProtocol is enabled. - * - * {{> stopRecordingTraffic }} - */ - stopRecordingTraffic() { - this.page.removeAllListeners('request') - this.recording = false - } - - /** - * - * _Note:_ Only works when devtoolsProtocol is enabled. - * - * {{> startRecordingTraffic }} - * - */ - async startRecordingTraffic() { - this.flushNetworkTraffics() - this.recording = true - this.recordedAtLeastOnce = true - - await this.page.setRequestInterception(true) - - this.page.on('request', (request) => { - const information = { - url: request.url(), - method: request.method(), - requestHeaders: request.headers(), - requestPostData: request.postData(), - response: request.response(), - } - - this.debugSection('REQUEST: ', JSON.stringify(information)) - - if (typeof information.requestPostData === 'object') { - information.requestPostData = JSON.parse(information.requestPostData) - } - request.continue() - this.requests.push(information) - }) - } - - /** - * - * _Note:_ Only works when devtoolsProtocol is enabled. - * - * {{> grabRecordedNetworkTraffics }} - */ - async grabRecordedNetworkTraffics() { - return grabRecordedNetworkTraffics.call(this) - } - - /** - * - * _Note:_ Only works when devtoolsProtocol is enabled. - * - * {{> seeTraffic }} - */ - async seeTraffic({ name, url, parameters, requestPostData, timeout = 10 }) { - await seeTraffic.call(this, ...arguments) - } - - /** - * - * _Note:_ Only works when devtoolsProtocol is enabled. - * - * {{> dontSeeTraffic }} - * - */ - dontSeeTraffic({ name, url }) { - dontSeeTraffic.call(this, ...arguments) - } } async function proceedSee(assertType, text, context, strict = false) { From c952efea3bac14f3cf058107b3d402eea8e80315 Mon Sep 17 00:00:00 2001 From: Thomas Hohn Date: Tue, 12 Nov 2024 19:18:23 +0100 Subject: [PATCH 07/16] Fix types --- typings/tests/helpers/WebDriverIO.types.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/typings/tests/helpers/WebDriverIO.types.ts b/typings/tests/helpers/WebDriverIO.types.ts index 137f55e7e..449d2dafc 100644 --- a/typings/tests/helpers/WebDriverIO.types.ts +++ b/typings/tests/helpers/WebDriverIO.types.ts @@ -405,11 +405,6 @@ expectType(wd.scrollPageToTop()); expectType(wd.scrollPageToBottom()); -expectError(wd.setGeoLocation()); -expectError(wd.setGeoLocation(num)); -expectType(wd.setGeoLocation(num, num)); -expectType(wd.setGeoLocation(num, num, num)); - expectError(wd.dontSeeCookie()); expectType(wd.dontSeeCookie(str)); @@ -480,8 +475,6 @@ psp.then( }, ); -expectType>(wd.grabGeoLocation()); - expectError(wd.grabElementBoundingRect()); //expectType>(wd.grabElementBoundingRect('h3')); //expectType>(wd.grabElementBoundingRect('h3', 'width')); From 157d53131209ebc516bd31008d3603f7f3868cf2 Mon Sep 17 00:00:00 2001 From: Thomas Hohn Date: Tue, 12 Nov 2024 20:01:11 +0100 Subject: [PATCH 08/16] Cleanup and package.json update --- package.json | 3 +-- test/helper/WebDriver.noSeleniumServer_test.js | 10 ---------- test/helper/WebDriver_test.js | 10 ---------- 3 files changed, 1 insertion(+), 22 deletions(-) diff --git a/package.json b/package.json index ed8c5d54e..2bf4d19e0 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,6 @@ "cross-spawn": "7.0.5", "css-to-xpath": "0.1.0", "csstoxpath": "1.6.0", - "devtools": "8.40.2", "envinfo": "7.14.0", "escape-string-regexp": "4.0.0", "figures": "3.2.0", @@ -166,7 +165,7 @@ "typedoc-plugin-markdown": "4.2.10", "typescript": "5.6.3", "wdio-docker-service": "1.5.0", - "webdriverio": "8.39.1", + "webdriverio": "9.2.12", "xml2js": "0.6.2", "xpath": "0.0.34" }, diff --git a/test/helper/WebDriver.noSeleniumServer_test.js b/test/helper/WebDriver.noSeleniumServer_test.js index af956c1da..208201865 100644 --- a/test/helper/WebDriver.noSeleniumServer_test.js +++ b/test/helper/WebDriver.noSeleniumServer_test.js @@ -1204,16 +1204,6 @@ describe('WebDriver - No Selenium server started', function () { }) }) - describe('GeoLocation', () => { - // deprecated JSON Wire method commands - it.skip('should set the geoLocation', async () => { - await wd.setGeoLocation(37.4043, -122.0748) - const geoLocation = await wd.grabGeoLocation() - assert.equal(geoLocation.latitude, 37.4043, 'The latitude is not properly set') - assert.equal(geoLocation.longitude, -122.0748, 'The longitude is not properly set') - }) - }) - describe('#grabElementBoundingRect', () => { it('should get the element size', async () => { await wd.amOnPage('/form/hidden') diff --git a/test/helper/WebDriver_test.js b/test/helper/WebDriver_test.js index 830b6c4fb..4ad6a5977 100644 --- a/test/helper/WebDriver_test.js +++ b/test/helper/WebDriver_test.js @@ -1219,16 +1219,6 @@ describe('WebDriver', function () { }) }) - describe('GeoLocation', () => { - // deprecated JSON Wire method commands - it.skip('should set the geoLocation', async () => { - await wd.setGeoLocation(37.4043, -122.0748) - const geoLocation = await wd.grabGeoLocation() - assert.equal(geoLocation.latitude, 37.4043, 'The latitude is not properly set') - assert.equal(geoLocation.longitude, -122.0748, 'The longitude is not properly set') - }) - }) - describe('#grabElementBoundingRect', () => { it('should get the element size', async () => { await wd.amOnPage('/form/hidden') From b9361baf8cee43665aa0e20c15d6d6085ff2df1c Mon Sep 17 00:00:00 2001 From: Thomas Hohn Date: Tue, 12 Nov 2024 20:10:33 +0100 Subject: [PATCH 09/16] Back to previous versions --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 2bf4d19e0..ed8c5d54e 100644 --- a/package.json +++ b/package.json @@ -89,6 +89,7 @@ "cross-spawn": "7.0.5", "css-to-xpath": "0.1.0", "csstoxpath": "1.6.0", + "devtools": "8.40.2", "envinfo": "7.14.0", "escape-string-regexp": "4.0.0", "figures": "3.2.0", @@ -165,7 +166,7 @@ "typedoc-plugin-markdown": "4.2.10", "typescript": "5.6.3", "wdio-docker-service": "1.5.0", - "webdriverio": "9.2.12", + "webdriverio": "8.39.1", "xml2js": "0.6.2", "xpath": "0.0.34" }, From 73cde5cac1b043cac6a0a1309ce95d4a27612bb2 Mon Sep 17 00:00:00 2001 From: Thomas Hohn Date: Tue, 12 Nov 2024 20:24:29 +0100 Subject: [PATCH 10/16] Removed dependency to devtools --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index ed8c5d54e..265ca60b6 100644 --- a/package.json +++ b/package.json @@ -89,7 +89,6 @@ "cross-spawn": "7.0.5", "css-to-xpath": "0.1.0", "csstoxpath": "1.6.0", - "devtools": "8.40.2", "envinfo": "7.14.0", "escape-string-regexp": "4.0.0", "figures": "3.2.0", From fe5ad5a02e3473ea2ad0beec6ae8eaa7fb2e07ce Mon Sep 17 00:00:00 2001 From: Thomas Hohn Date: Tue, 12 Nov 2024 20:46:22 +0100 Subject: [PATCH 11/16] Update webdriverio to latest 8.x version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 265ca60b6..fa7278d77 100644 --- a/package.json +++ b/package.json @@ -165,7 +165,7 @@ "typedoc-plugin-markdown": "4.2.10", "typescript": "5.6.3", "wdio-docker-service": "1.5.0", - "webdriverio": "8.39.1", + "webdriverio": "8.40.6", "xml2js": "0.6.2", "xpath": "0.0.34" }, From 8b48342167c6c7e15ab24f8869b6876c31808b2c Mon Sep 17 00:00:00 2001 From: Thomas Hohn Date: Wed, 13 Nov 2024 06:54:08 +0100 Subject: [PATCH 12/16] Cleanups and regenerate docs --- docs/helpers/WebDriver.md | 364 +++++++++++--------------------------- lib/plugin/coverage.js | 3 - test/helper/webapi.js | 4 +- 3 files changed, 108 insertions(+), 263 deletions(-) diff --git a/docs/helpers/WebDriver.md b/docs/helpers/WebDriver.md index 3ecaa0acf..19d6f8bfa 100644 --- a/docs/helpers/WebDriver.md +++ b/docs/helpers/WebDriver.md @@ -37,24 +37,23 @@ Type: [object][17] - `browser` **[string][18]** Browser in which to perform testing. - `basicAuth` **[string][18]?** (optional) the basic authentication to pass to base url. Example: {username: 'username', password: 'password'} - `host` **[string][18]?** WebDriver host to connect. -- `port` **[number][24]?** WebDriver port to connect. +- `port` **[number][23]?** WebDriver port to connect. - `protocol` **[string][18]?** protocol for WebDriver server. - `path` **[string][18]?** path to WebDriver server. -- `restart` **[boolean][34]?** restart browser between tests. -- `smartWait` **([boolean][34] | [number][24])?** **enables [SmartWait][38]**; wait for additional milliseconds for element to appear. Enable for 5 secs: "smartWait": 5000. -- `disableScreenshots` **[boolean][34]?** don't save screenshots on failure. -- `fullPageScreenshots` **[boolean][34]?** (optional - make full page screenshots on failure. -- `uniqueScreenshotNames` **[boolean][34]?** option to prevent screenshot override if you have scenarios with the same name in different suites. -- `keepBrowserState` **[boolean][34]?** keep browser state between tests when `restart` is set to false. -- `keepCookies` **[boolean][34]?** keep cookies between tests when `restart` set to false. +- `restart` **[boolean][33]?** restart browser between tests. +- `smartWait` **([boolean][33] | [number][23])?** **enables [SmartWait][37]**; wait for additional milliseconds for element to appear. Enable for 5 secs: "smartWait": 5000. +- `disableScreenshots` **[boolean][33]?** don't save screenshots on failure. +- `fullPageScreenshots` **[boolean][33]?** (optional - make full page screenshots on failure. +- `uniqueScreenshotNames` **[boolean][33]?** option to prevent screenshot override if you have scenarios with the same name in different suites. +- `keepBrowserState` **[boolean][33]?** keep browser state between tests when `restart` is set to false. +- `keepCookies` **[boolean][33]?** keep cookies between tests when `restart` set to false. - `windowSize` **[string][18]?** default window size. Set to `maximize` or a dimension in the format `640x480`. -- `waitForTimeout` **[number][24]?** sets default wait time in _ms_ for all `wait*` functions. +- `waitForTimeout` **[number][23]?** sets default wait time in _ms_ for all `wait*` functions. - `desiredCapabilities` **[object][17]?** Selenium's [desired capabilities][7]. -- `manualStart` **[boolean][34]?** do not start browser before a test, start it manually inside a helper with `this.helpers["WebDriver"]._startBrowser()`. -- `timeouts` **[object][17]?** [WebDriver timeouts][39] defined as hash. -- `highlightElement` **[boolean][34]?** highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose). -- `logLevel` **[string][18]?** level of logging verbosity. Default: silent. Options: trace | debug | info | warn | error | silent. More info: [https://webdriver.io/docs/configuration/#loglevel][40] -- `devtoolsProtocol` **[boolean][34]?** enable devtools protocol. Default: false. More info: [https://webdriver.io/docs/automationProtocols/#devtools-protocol][41]. +- `manualStart` **[boolean][33]?** do not start browser before a test, start it manually inside a helper with `this.helpers["WebDriver"]._startBrowser()`. +- `timeouts` **[object][17]?** [WebDriver timeouts][38] defined as hash. +- `highlightElement` **[boolean][33]?** highlight the interacting elements. Default: false. Note: only activate under verbose mode (--verbose). +- `logLevel` **[string][18]?** level of logging verbosity. Default: silent. Options: trace | debug | info | warn | error | silent. More info: [https://webdriver.io/docs/configuration/#loglevel][39] @@ -855,27 +854,6 @@ I.dontSeeInTitle('Error'); Returns **void** automatically synchronized promise through #recorder -### dontSeeTraffic - -_Note:_ Only works when devtoolsProtocol is enabled. - -Verifies that a certain request is not part of network traffic. - -Examples: - -```js -I.dontSeeTraffic({ name: 'Unexpected API Call', url: 'https://api.example.com' }); -I.dontSeeTraffic({ name: 'Unexpected API Call of "user" endpoint', url: /api.example.com.*user/ }); -``` - -#### Parameters - -- `opts` **[Object][17]** options when checking the traffic network. - - `opts.name` **[string][18]** A name of that request. Can be any value. Only relevant to have a more meaningful error message in case of fail. - - `opts.url` **([string][18] | [RegExp][23])** Expected URL of request in network traffic. Can be a string or a regular expression. - -Returns **void** automatically synchronized promise through #recorder - ### doubleClick Performs a double-click on an element matched by link|button|label|CSS or XPath. @@ -928,7 +906,7 @@ I.dragSlider('#slider', -70); #### Parameters - `locator` **([string][18] | [object][17])** located by label|name|CSS|XPath|strict locator. -- `offsetX` **[number][24]** position to drag. +- `offsetX` **[number][23]** position to drag. Returns **void** automatically synchronized promise through #recorder @@ -937,7 +915,7 @@ Returns **void** automatically synchronized promise through #recorder Executes async script on page. Provided function should execute a passed callback (as first argument) to signal it is finished. -Example: In Vue.js to make components completely rendered we are waiting for [nextTick][25]. +Example: In Vue.js to make components completely rendered we are waiting for [nextTick][24]. ```js I.executeAsyncScript(function(done) { @@ -958,13 +936,13 @@ let val = await I.executeAsyncScript(function(url, done) { #### Parameters - `args` **...any** to be passed to function. -- `fn` **([string][18] | [function][26])** function to be executed in browser context. +- `fn` **([string][18] | [function][25])** function to be executed in browser context. -Returns **[Promise][27]<any>** script return value +Returns **[Promise][26]<any>** script return value ### executeScript -Wraps [execute][28] command. +Wraps [execute][27] command. Executes sync script on a page. Pass arguments to function as additional parameters. @@ -993,9 +971,9 @@ let date = await I.executeScript(function(el) { #### Parameters - `args` **...any** to be passed to function. -- `fn` **([string][18] | [function][26])** function to be executed in browser context. +- `fn` **([string][18] | [function][25])** function to be executed in browser context. -Returns **[Promise][27]<any>** script return value +Returns **[Promise][26]<any>** script return value ### fillField @@ -1025,16 +1003,6 @@ This action supports [React locators](https://codecept.io/react#locators) {{ custom }} -### flushNetworkTraffics - -_Note:_ Only works when devtoolsProtocol is enabled. - -Resets all recorded network requests. - -```js -I.flushNetworkTraffics(); -``` - ### focus Calls [focus][20] on the matching element. @@ -1050,7 +1018,7 @@ I.see('#add-to-cart-bnt'); #### Parameters - `locator` **([string][18] | [object][17])** field located by label|name|CSS|XPath|strict locator. -- `options` **any?** Playwright only: [Additional options][29] for available options object as 2nd argument. +- `options` **any?** Playwright only: [Additional options][28] for available options object as 2nd argument. Returns **void** automatically synchronized promise through #recorder @@ -1129,7 +1097,7 @@ Useful for referencing a specific handle when calling `I.switchToWindow(handle)` const windows = await I.grabAllWindowHandles(); ``` -Returns **[Promise][27]<[Array][30]<[string][18]>>** +Returns **[Promise][26]<[Array][29]<[string][18]>>** ### grabAttributeFrom @@ -1146,7 +1114,7 @@ let hint = await I.grabAttributeFrom('#tooltip', 'title'); - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. - `attr` **[string][18]** attribute name. -Returns **[Promise][27]<[string][18]>** attribute value +Returns **[Promise][26]<[string][18]>** attribute value ### grabAttributeFromAll @@ -1162,7 +1130,7 @@ let hints = await I.grabAttributeFromAll('.tooltip', 'title'); - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. - `attr` **[string][18]** attribute name. -Returns **[Promise][27]<[Array][30]<[string][18]>>** attribute value +Returns **[Promise][26]<[Array][29]<[string][18]>>** attribute value ### grabBrowserLogs @@ -1174,7 +1142,7 @@ let logs = await I.grabBrowserLogs(); console.log(JSON.stringify(logs)) ``` -Returns **([Promise][27]<[Array][30]<[object][17]>> | [undefined][31])** all browser logs +Returns **([Promise][26]<[Array][29]<[object][17]>> | [undefined][30])** all browser logs ### grabCookie @@ -1208,7 +1176,7 @@ const value = await I.grabCssPropertyFrom('h3', 'font-weight'); - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. - `cssProperty` **[string][18]** CSS property name. -Returns **[Promise][27]<[string][18]>** CSS value +Returns **[Promise][26]<[string][18]>** CSS value ### grabCssPropertyFromAll @@ -1224,7 +1192,7 @@ const values = await I.grabCssPropertyFromAll('h3', 'font-weight'); - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. - `cssProperty` **[string][18]** CSS property name. -Returns **[Promise][27]<[Array][30]<[string][18]>>** CSS value +Returns **[Promise][26]<[Array][29]<[string][18]>>** CSS value ### grabCurrentUrl @@ -1236,7 +1204,7 @@ let url = await I.grabCurrentUrl(); console.log(`Current URL is [${url}]`); ``` -Returns **[Promise][27]<[string][18]>** current URL +Returns **[Promise][26]<[string][18]>** current URL ### grabCurrentWindowHandle @@ -1247,7 +1215,7 @@ Useful for referencing it when calling `I.switchToWindow(handle)` const window = await I.grabCurrentWindowHandle(); ``` -Returns **[Promise][27]<[string][18]>** +Returns **[Promise][26]<[string][18]>** ### grabElementBoundingRect @@ -1275,20 +1243,7 @@ const width = await I.grabElementBoundingRect('h3', 'width'); - `prop` - `elementSize` **[string][18]?** x, y, width or height of the given element. -Returns **([Promise][27]<DOMRect> | [Promise][27]<[number][24]>)** Element bounding rectangle - -### grabGeoLocation - -This method is **deprecated**. - -Return the current geo location -Resumes test execution, so **should be used inside async function with `await`** operator. - -```js -let geoLocation = await I.grabGeoLocation(); -``` - -Returns **[Promise][27]<{latitude: [number][24], longitude: [number][24], altitude: [number][24]}>** +Returns **([Promise][26]<DOMRect> | [Promise][26]<[number][23]>)** Element bounding rectangle ### grabHTMLFrom @@ -1305,7 +1260,7 @@ let postHTML = await I.grabHTMLFrom('#post'); - `locator` - `element` **([string][18] | [object][17])** located by CSS|XPath|strict locator. -Returns **[Promise][27]<[string][18]>** HTML code for an element +Returns **[Promise][26]<[string][18]>** HTML code for an element ### grabHTMLFromAll @@ -1321,7 +1276,7 @@ let postHTMLs = await I.grabHTMLFromAll('.post'); - `locator` - `element` **([string][18] | [object][17])** located by CSS|XPath|strict locator. -Returns **[Promise][27]<[Array][30]<[string][18]>>** HTML code for an element +Returns **[Promise][26]<[Array][29]<[string][18]>>** HTML code for an element ### grabNumberOfOpenTabs @@ -1332,7 +1287,7 @@ Resumes test execution, so **should be used inside async function with `await`** let tabs = await I.grabNumberOfOpenTabs(); ``` -Returns **[Promise][27]<[number][24]>** number of open tabs +Returns **[Promise][26]<[number][23]>** number of open tabs ### grabNumberOfVisibleElements @@ -1347,7 +1302,7 @@ let numOfElements = await I.grabNumberOfVisibleElements('p'); - `locator` **([string][18] | [object][17])** located by CSS|XPath|strict locator. -Returns **[Promise][27]<[number][24]>** number of visible elements +Returns **[Promise][26]<[number][23]>** number of visible elements ### grabPageScrollPosition @@ -1358,7 +1313,7 @@ Resumes test execution, so **should be used inside an async function with `await let { x, y } = await I.grabPageScrollPosition(); ``` -Returns **[Promise][27]<PageScrollPosition>** scroll position +Returns **[Promise][26]<PageScrollPosition>** scroll position ### grabPopupText @@ -1368,22 +1323,7 @@ Grab the text within the popup. If no popup is visible then it will return null. await I.grabPopupText(); ``` -Returns **[Promise][27]<[string][18]>** - -### grabRecordedNetworkTraffics - -_Note:_ Only works when devtoolsProtocol is enabled. - -Grab the recording network traffics - -```js -const traffics = await I.grabRecordedNetworkTraffics(); -expect(traffics[0].url).to.equal('https://reqres.in/api/comments/1'); -expect(traffics[0].response.status).to.equal(200); -expect(traffics[0].response.body).to.contain({ name: 'this was mocked' }); -``` - -Returns **[Array][30]** recorded network traffics +Returns **[Promise][26]<[string][18]>** ### grabSource @@ -1394,7 +1334,7 @@ Resumes test execution, so **should be used inside async function with `await`** let pageSource = await I.grabSource(); ``` -Returns **[Promise][27]<[string][18]>** source code +Returns **[Promise][26]<[string][18]>** source code ### grabTextFrom @@ -1411,7 +1351,7 @@ If multiple elements found returns first element. - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -Returns **[Promise][27]<[string][18]>** attribute value +Returns **[Promise][26]<[string][18]>** attribute value ### grabTextFromAll @@ -1426,7 +1366,7 @@ let pins = await I.grabTextFromAll('#pin li'); - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -Returns **[Promise][27]<[Array][30]<[string][18]>>** attribute value +Returns **[Promise][26]<[Array][29]<[string][18]>>** attribute value ### grabTitle @@ -1437,7 +1377,7 @@ Resumes test execution, so **should be used inside async with `await`** operator let title = await I.grabTitle(); ``` -Returns **[Promise][27]<[string][18]>** title +Returns **[Promise][26]<[string][18]>** title ### grabValueFrom @@ -1453,7 +1393,7 @@ let email = await I.grabValueFrom('input[name=email]'); - `locator` **([string][18] | [object][17])** field located by label|name|CSS|XPath|strict locator. -Returns **[Promise][27]<[string][18]>** attribute value +Returns **[Promise][26]<[string][18]>** attribute value ### grabValueFromAll @@ -1468,7 +1408,7 @@ let inputs = await I.grabValueFromAll('//form/input'); - `locator` **([string][18] | [object][17])** field located by label|name|CSS|XPath|strict locator. -Returns **[Promise][27]<[Array][30]<[string][18]>>** attribute value +Returns **[Promise][26]<[Array][29]<[string][18]>>** attribute value ### grabWebElements @@ -1483,7 +1423,7 @@ const webElements = await I.grabWebElements('#button'); - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -Returns **[Promise][27]<any>** WebElement of being used Web helper +Returns **[Promise][26]<any>** WebElement of being used Web helper ### moveCursorTo @@ -1500,8 +1440,8 @@ I.moveCursorTo('#submit', 5,5); - `locator` **([string][18] | [object][17])** located by CSS|XPath|strict locator. - `xOffset` - `yOffset` -- `offsetX` **[number][24]** (optional, `0` by default) X-axis offset. -- `offsetY` **[number][24]** (optional, `0` by default) Y-axis offset. +- `offsetX` **[number][23]** (optional, `0` by default) X-axis offset. +- `offsetY` **[number][23]** (optional, `0` by default) Y-axis offset. Returns **void** automatically synchronized promise through #recorder @@ -1526,7 +1466,7 @@ _Note:_ In case a text field or textarea is focused be aware that some browsers Presses a key in the browser (on a focused element). -_Hint:_ For populating text field or textarea, it is recommended to use [`fillField`][32]. +_Hint:_ For populating text field or textarea, it is recommended to use [`fillField`][31]. ```js I.pressKey('Backspace'); @@ -1585,7 +1525,7 @@ Some of the supported key names are: #### Parameters -- `key` **([string][18] | [Array][30]<[string][18]>)** key or array of keys to press. +- `key` **([string][18] | [Array][29]<[string][18]>)** key or array of keys to press. Returns **void** automatically synchronized promise through #recorder @@ -1593,7 +1533,7 @@ Returns **void** automatically synchronized promise through #recorder Presses a key in the browser and leaves it in a down state. -To make combinations with modifier key and user operation (e.g. `'Control'` + [`click`][33]). +To make combinations with modifier key and user operation (e.g. `'Control'` + [`click`][32]). ```js I.pressKeyDown('Control'); @@ -1611,7 +1551,7 @@ Returns **void** automatically synchronized promise through #recorder Releases a key in the browser which was previously set to a down state. -To make combinations with modifier key and user operation (e.g. `'Control'` + [`click`][33]). +To make combinations with modifier key and user operation (e.g. `'Control'` + [`click`][32]). ```js I.pressKeyDown('Control'); @@ -1644,8 +1584,8 @@ First parameter can be set to `maximize`. #### Parameters -- `width` **[number][24]** width in pixels or `maximize`. -- `height` **[number][24]** height in pixels. +- `width` **[number][23]** width in pixels or `maximize`. +- `height` **[number][23]** height in pixels. Returns **void** automatically synchronized promise through #recorder @@ -1729,7 +1669,7 @@ I.saveScreenshot('debug.png', true) //resizes to available scrollHeight and scro #### Parameters - `fileName` **[string][18]** file name to save. -- `fullPage` **[boolean][34]** (optional, `false` by default) flag to enable fullscreen screenshot mode. +- `fullPage` **[boolean][33]** (optional, `false` by default) flag to enable fullscreen screenshot mode. Returns **void** automatically synchronized promise through #recorder @@ -1746,7 +1686,7 @@ I.scrollIntoView('#submit', { behavior: "smooth", block: "center", inline: "cent #### Parameters - `locator` **([string][18] | [object][17])** located by CSS|XPath|strict locator. -- `scrollIntoViewOptions` **(ScrollIntoViewOptions | [boolean][34])** either alignToTop=true|false or scrollIntoViewOptions. See [https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView][35]. +- `scrollIntoViewOptions` **(ScrollIntoViewOptions | [boolean][33])** either alignToTop=true|false or scrollIntoViewOptions. See [https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView][34]. Returns **void** automatically synchronized promise through #recorder @@ -1783,8 +1723,8 @@ I.scrollTo('#submit', 5, 5); #### Parameters - `locator` **([string][18] | [object][17])** located by CSS|XPath|strict locator. -- `offsetX` **[number][24]** (optional, `0` by default) X-axis offset. -- `offsetY` **[number][24]** (optional, `0` by default) Y-axis offset. +- `offsetX` **[number][23]** (optional, `0` by default) X-axis offset. +- `offsetY` **[number][23]** (optional, `0` by default) Y-axis offset. Returns **void** automatically synchronized promise through #recorder @@ -2004,7 +1944,7 @@ I.seeNumberOfElements('#submitBtn', 1); #### Parameters - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -- `num` **[number][24]** number of elements. +- `num` **[number][23]** number of elements. Returns **void** automatically synchronized promise through #recorder @@ -2024,7 +1964,7 @@ I.seeNumberOfVisibleElements('.buttons', 3); #### Parameters - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -- `num` **[number][24]** number of elements. +- `num` **[number][23]** number of elements. Returns **void** automatically synchronized promise through #recorder @@ -2061,50 +2001,6 @@ I.seeTitleEquals('Test title.'); Returns **void** automatically synchronized promise through #recorder -### seeTraffic - -_Note:_ Only works when devtoolsProtocol is enabled. - -Verifies that a certain request is part of network traffic. - -```js -// checking the request url contains certain query strings -I.amOnPage('https://openai.com/blog/chatgpt'); -I.startRecordingTraffic(); -await I.seeTraffic({ - name: 'sentry event', - url: 'https://images.openai.com/blob/cf717bdb-0c8c-428a-b82b-3c3add87a600', - parameters: { - width: '1919', - height: '1138', - }, - }); -``` - -```js -// checking the request url contains certain post data -I.amOnPage('https://openai.com/blog/chatgpt'); -I.startRecordingTraffic(); -await I.seeTraffic({ - name: 'event', - url: 'https://cloudflareinsights.com/cdn-cgi/rum', - requestPostData: { - st: 2, - }, - }); -``` - -#### Parameters - -- `opts` **[Object][17]** options when checking the traffic network. - - `opts.name` **[string][18]** A name of that request. Can be any value. Only relevant to have a more meaningful error message in case of fail. - - `opts.url` **[string][18]** Expected URL of request in network traffic - - `opts.parameters` **[Object][17]?** Expected parameters of that request in network traffic - - `opts.requestPostData` **[Object][17]?** Expected that request contains post data in network traffic - - `opts.timeout` **[number][24]?** Timeout to wait for request in seconds. Default is 10 seconds. - -Returns **void** automatically synchronized promise through #recorder - ### selectOption Selects an option in a drop-down select. @@ -2129,13 +2025,13 @@ I.selectOption('Which OS do you use?', ['Android', 'iOS']); #### Parameters - `select` **([string][18] | [object][17])** field located by label|name|CSS|XPath|strict locator. -- `option` **([string][18] | [Array][30]<any>)** visible text or value of option. +- `option` **([string][18] | [Array][29]<any>)** visible text or value of option. Returns **void** automatically synchronized promise through #recorder ### setCookie -Uses Selenium's JSON [cookie format][36]. +Uses Selenium's JSON [cookie format][35]. Sets cookie(s). Can be a single cookie object or an array of cookies: @@ -2152,52 +2048,10 @@ I.setCookie([ #### Parameters -- `cookie` **(Cookie | [Array][30]<Cookie>)** a cookie object or array of cookie objects. +- `cookie` **(Cookie | [Array][29]<Cookie>)** a cookie object or array of cookie objects. Returns **void** automatically synchronized promise through #recorder -### setGeoLocation - -This method is **deprecated**. - -Set the current geo location - -```js -I.setGeoLocation(121.21, 11.56); -I.setGeoLocation(121.21, 11.56, 10); -``` - -#### Parameters - -- `latitude` **[number][24]** to set. -- `longitude` **[number][24]** to set -- `altitude` **[number][24]?** (optional, null by default) to set - -Returns **void** automatically synchronized promise through #recorder - -### startRecordingTraffic - -_Note:_ Only works when devtoolsProtocol is enabled. - -Starts recording the network traffics. -This also resets recorded network requests. - -```js -I.startRecordingTraffic(); -``` - -Returns **void** automatically synchronized promise through #recorder - -### stopRecordingTraffic - -_Note:_ Only works when devtoolsProtocol is enabled. - -Stops recording of network traffic. Recorded traffic is not flashed. - -```js -I.stopRecordingTraffic(); -``` - ### switchTo Switches frame or in case of null locator reverts to parent. @@ -2224,8 +2078,8 @@ I.switchToNextTab(2); #### Parameters -- `num` **[number][24]?** (optional) number of tabs to switch forward, default: 1. -- `sec` **([number][24] | null)?** (optional) time in seconds to wait. +- `num` **[number][23]?** (optional) number of tabs to switch forward, default: 1. +- `sec` **([number][23] | null)?** (optional) time in seconds to wait. Returns **void** automatically synchronized promise through #recorder @@ -2240,8 +2094,8 @@ I.switchToPreviousTab(2); #### Parameters -- `num` **[number][24]?** (optional) number of tabs to switch backward, default: 1. -- `sec` **[number][24]??** (optional) time in seconds to wait. +- `num` **[number][23]?** (optional) number of tabs to switch backward, default: 1. +- `sec` **[number][23]??** (optional) time in seconds to wait. Returns **void** automatically synchronized promise through #recorder @@ -2267,7 +2121,7 @@ await I.switchToWindow( window ); Types out the given text into an active field. To slow down typing use a second parameter, to set interval between key presses. -_Note:_ Should be used when [`fillField`][32] is not an option. +_Note:_ Should be used when [`fillField`][31] is not an option. ```js // passing in a string @@ -2286,8 +2140,8 @@ I.type(secret('123456')); #### Parameters - `keys` -- `delay` **[number][24]?** (optional) delay in ms between key presses -- `key` **([string][18] | [Array][30]<[string][18]>)** or array of keys to type. +- `delay` **[number][23]?** (optional) delay in ms between key presses +- `key` **([string][18] | [Array][29]<[string][18]>)** or array of keys to type. Returns **void** automatically synchronized promise through #recorder @@ -2314,12 +2168,12 @@ Returns **void** automatically synchronized promise through #recorder ### useWebDriverTo -Use [webdriverio][37] API inside a test. +Use [webdriverio][36] API inside a test. First argument is a description of an action. Second argument is async function that gets this helper as parameter. -{ [`browser`][37]) } object from WebDriver API is available. +{ [`browser`][36]) } object from WebDriver API is available. ```js I.useWebDriverTo('open multiple windows', async ({ browser }) { @@ -2331,7 +2185,7 @@ I.useWebDriverTo('open multiple windows', async ({ browser }) { #### Parameters - `description` **[string][18]** used to show in logs. -- `fn` **[function][26]** async functuion that executed with WebDriver helper as argument +- `fn` **[function][25]** async functuion that executed with WebDriver helper as argument ### wait @@ -2343,7 +2197,7 @@ I.wait(2); // wait 2 secs #### Parameters -- `sec` **[number][24]** number of second to wait. +- `sec` **[number][23]** number of second to wait. Returns **void** automatically synchronized promise through #recorder @@ -2361,7 +2215,7 @@ I.waitForClickable('.btn.continue', 5); // wait for 5 secs - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. - `waitTimeout` -- `sec` **[number][24]?** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]?** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2376,7 +2230,7 @@ I.waitForCookie("token"); #### Parameters - `name` **[string][18]** expected cookie name. -- `sec` **[number][24]** (optional, `3` by default) time in seconds to wait +- `sec` **[number][23]** (optional, `3` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2392,7 +2246,7 @@ I.waitForDetached('#popup'); #### Parameters - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -- `sec` **[number][24]** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2409,7 +2263,7 @@ I.waitForElement('.btn.continue', 5); // wait for 5 secs #### Parameters - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -- `sec` **[number][24]?** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]?** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2421,7 +2275,7 @@ Element can be located by CSS or XPath. #### Parameters - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -- `sec` **[number][24]** (optional) time in seconds to wait, 1 by default. +- `sec` **[number][23]** (optional) time in seconds to wait, 1 by default. Returns **void** automatically synchronized promise through #recorder @@ -2442,9 +2296,9 @@ I.waitForFunction((count) => window.requests == count, [3], 5) // pass args and #### Parameters -- `fn` **([string][18] | [function][26])** to be executed in browser context. -- `argsOrSec` **([Array][30]<any> | [number][24])?** (optional, `1` by default) arguments for function or seconds. -- `sec` **[number][24]?** (optional, `1` by default) time in seconds to wait +- `fn` **([string][18] | [function][25])** to be executed in browser context. +- `argsOrSec` **([Array][29]<any> | [number][23])?** (optional, `1` by default) arguments for function or seconds. +- `sec` **[number][23]?** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2460,7 +2314,7 @@ I.waitForInvisible('#popup'); #### Parameters - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -- `sec` **[number][24]** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2474,8 +2328,8 @@ I.waitForNumberOfTabs(2); #### Parameters -- `expectedTabs` **[number][24]** expecting the number of tabs. -- `sec` **[number][24]** number of secs to wait. +- `expectedTabs` **[number][23]** expecting the number of tabs. +- `sec` **[number][23]** number of secs to wait. Returns **void** automatically synchronized promise through #recorder @@ -2493,7 +2347,7 @@ I.waitForText('Thank you, form has been submitted', 5, '#modal'); #### Parameters - `text` **[string][18]** to wait for. -- `sec` **[number][24]** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]** (optional, `1` by default) time in seconds to wait - `context` **([string][18] | [object][17])?** (optional) element located by CSS|XPath|strict locator. Returns **void** automatically synchronized promise through #recorder @@ -2510,7 +2364,7 @@ I.waitForValue('//input', "GoodValue"); - `field` **([string][18] | [object][17])** input field. - `value` **[string][18]** expected value. -- `sec` **[number][24]** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2526,7 +2380,7 @@ I.waitForVisible('#popup'); #### Parameters - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -- `sec` **[number][24]** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2541,7 +2395,7 @@ I.waitInUrl('/info', 2); #### Parameters - `urlPart` **[string][18]** value to check. -- `sec` **[number][24]** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2556,8 +2410,8 @@ I.waitNumberOfVisibleElements('a', 3); #### Parameters - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -- `num` **[number][24]** number of elements. -- `sec` **[number][24]** (optional, `1` by default) time in seconds to wait +- `num` **[number][23]** number of elements. +- `sec` **[number][23]** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2573,7 +2427,7 @@ I.waitToHide('#popup'); #### Parameters - `locator` **([string][18] | [object][17])** element located by CSS|XPath|strict locator. -- `sec` **[number][24]** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2589,7 +2443,7 @@ I.waitUrlEquals('http://127.0.0.1:8000/info'); #### Parameters - `urlPart` **[string][18]** value to check. -- `sec` **[number][24]** (optional, `1` by default) time in seconds to wait +- `sec` **[number][23]** (optional, `1` by default) time in seconds to wait Returns **void** automatically synchronized promise through #recorder @@ -2637,40 +2491,36 @@ Returns **void** automatically synchronized promise through #recorder [22]: https://webdriver.io/docs/timeouts.html -[23]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/RegExp - -[24]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number - -[25]: https://vuejs.org/v2/api/#Vue-nextTick +[23]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number -[26]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function +[24]: https://vuejs.org/v2/api/#Vue-nextTick -[27]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise +[25]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function -[28]: http://webdriver.io/api/protocol/execute.html +[26]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise -[29]: https://playwright.dev/docs/api/class-locator#locator-focus +[27]: http://webdriver.io/api/protocol/execute.html -[30]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array +[28]: https://playwright.dev/docs/api/class-locator#locator-focus -[31]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined +[29]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array -[32]: #fillfield +[30]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined -[33]: #click +[31]: #fillfield -[34]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean +[32]: #click -[35]: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView +[33]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean -[36]: https://code.google.com/p/selenium/wiki/JsonWireProtocol#Cookie_JSON_Object +[34]: https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView -[37]: https://webdriver.io/docs/api.html +[35]: https://code.google.com/p/selenium/wiki/JsonWireProtocol#Cookie_JSON_Object -[38]: http://codecept.io/acceptance/#smartwait +[36]: https://webdriver.io/docs/api.html -[39]: http://webdriver.io/docs/timeouts.html +[37]: http://codecept.io/acceptance/#smartwait -[40]: https://webdriver.io/docs/configuration/#loglevel +[38]: http://webdriver.io/docs/timeouts.html -[41]: https://webdriver.io/docs/automationProtocols/#devtools-protocol +[39]: https://webdriver.io/docs/configuration/#loglevel diff --git a/lib/plugin/coverage.js b/lib/plugin/coverage.js index d4e8da72d..9f2bd8e6e 100644 --- a/lib/plugin/coverage.js +++ b/lib/plugin/coverage.js @@ -143,9 +143,6 @@ module.exports = function (config) { const helper = helpers[helperName] - if (helperName === 'WebDriver' && !helper.config.devtoolsProtocol) - throw Error('Coverage is currently supporting the WebDriver running with Devtools protocol.') - const v8Helper = v8CoverageHelpers[helperName] const coverageOptions = { diff --git a/test/helper/webapi.js b/test/helper/webapi.js index 27cb816b6..da3be93e1 100644 --- a/test/helper/webapi.js +++ b/test/helper/webapi.js @@ -915,7 +915,6 @@ module.exports.tests = function () { it('should wait for cookie and throw error when cookie not found', async () => { if (isHelper('TestCafe')) return - if (process.env.DevTools) return await I.amOnPage('https://google.com') try { @@ -927,7 +926,6 @@ module.exports.tests = function () { it('should wait for cookie', async () => { if (isHelper('TestCafe')) return - if (process.env.DevTools) return await I.amOnPage('/') await I.setCookie({ @@ -1503,7 +1501,7 @@ module.exports.tests = function () { }) it('should check css property for several elements', async function () { - if (isHelper('TestCafe') || process.env.BROWSER === 'firefox' || process.env.DevTools === 'true') this.skip() + if (isHelper('TestCafe') || process.env.BROWSER === 'firefox') this.skip() try { await I.amOnPage('/') From 5bf1b631241ae6406857dc4642c05c09562b6665 Mon Sep 17 00:00:00 2001 From: Thomas Hohn Date: Wed, 13 Nov 2024 15:19:56 +0100 Subject: [PATCH 13/16] Leave changelog un-touched --- docs/changelog.md | 697 +++++++++++++++++++++++----------------------- 1 file changed, 349 insertions(+), 348 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index 8fb6ca31c..11305e7a9 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -35,10 +35,10 @@ I.flushSoftAssertions() // Throws an error if any soft assertions have failed. T ``` * feat(cli): print failed hooks ([#4476](https://github.com/codeceptjs/CodeceptJS/issues/4476)) - by **[kobenguyent](https://github.com/kobenguyent)** * run command - ![Screenshot 2024-09-02 at 15 25 20](https://github.com/user-attachments/assets/625c6b54-03f6-41c6-9d0c-cd699582404a) + ![Screenshot 2024-09-02 at 15 25 20](https://github.com/user-attachments/assets/625c6b54-03f6-41c6-9d0c-cd699582404a) * run workers command -![Screenshot 2024-09-02 at 15 24 53](https://github.com/user-attachments/assets/efff0312-1229-44b6-a94f-c9b9370b9a64) + ![Screenshot 2024-09-02 at 15 24 53](https://github.com/user-attachments/assets/efff0312-1229-44b6-a94f-c9b9370b9a64) 🐛 *Bug Fixes* * fix(AI): minor AI improvements - by **[DavertMik](https://github.com/DavertMik)** @@ -55,11 +55,11 @@ I.flushSoftAssertions() // Throws an error if any soft assertions have failed. T helpers: { REST: { endpoint: 'http://site.com/api', - prettyPrintJson: true, - httpAgent: { - ca: fs.readFileSync(__dirname + '/path/to/ca.pem'), - rejectUnauthorized: false, - keepAlive: true + prettyPrintJson: true, + httpAgent: { + ca: fs.readFileSync(__dirname + '/path/to/ca.pem'), + rejectUnauthorized: false, + keepAlive: true } } } @@ -222,7 +222,7 @@ locate('div').withClassAttr('text'); ``` * fix(playwright): set the record video resolution ([#4311](https://github.com/codeceptjs/CodeceptJS/issues/4311)) - by **[KobeNguyent](https://github.com/KobeNguyent)** -You could now set the recording video resolution + You could now set the recording video resolution ``` url: siteUrl, windowSize: '300x500', @@ -323,23 +323,23 @@ Examples: ```js // recording traffics and verify the traffic - I.startRecordingTraffic(); - I.amOnPage('https://codecept.io/'); - I.seeTraffic({ name: 'traffics', url: 'https://codecept.io/img/companies/BC_LogoScreen_C.jpg' }); +I.startRecordingTraffic(); +I.amOnPage('https://codecept.io/'); +I.seeTraffic({ name: 'traffics', url: 'https://codecept.io/img/companies/BC_LogoScreen_C.jpg' }); ``` ```js // check the traffic with advanced params - I.amOnPage('https://openai.com/blog/chatgpt'); - I.startRecordingTraffic(); - I.seeTraffic({ - name: 'sentry event', - url: 'https://images.openai.com/blob/cf717bdb-0c8c-428a-b82b-3c3add87a600', - parameters: { - width: '1919', - height: '1138', - }, - }); +I.amOnPage('https://openai.com/blog/chatgpt'); +I.startRecordingTraffic(); +I.seeTraffic({ + name: 'sentry event', + url: 'https://images.openai.com/blob/cf717bdb-0c8c-428a-b82b-3c3add87a600', + parameters: { + width: '1919', + height: '1138', + }, +}); ``` * Introduce the playwright locator: `_react`, `_vue`, `data-testid` attribute. See [#4255](https://github.com/codeceptjs/CodeceptJS/issues/4255) by **[KobeNguyenT](https://github.com/KobeNguyenT)** @@ -470,7 +470,7 @@ PUT tests -- /Users/tDesktop/projects/codeceptjs-rest-demo/src/PUT_test.ts -- 4 * feat: mock server helper ([#4155](https://github.com/codeceptjs/CodeceptJS/issues/4155)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** ![Screenshot 2024-01-25 at 13 47 59](https://github.com/codeceptjs/CodeceptJS/assets/7845001/8fe7aacf-f1c9-4d7e-89a6-3748b3ccb26c) * feat(webdriver): network traffics manipulation ([#4166](https://github.com/codeceptjs/CodeceptJS/issues/4166)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** - **[Webdriver]** Added commands to check network traffics - supported only with devtoolsProtocol + **[Webdriver]** Added commands to check network traffics - supported only with devtoolsProtocol * `startRecordingTraffic` * `grabRecordedNetworkTraffics` * `flushNetworkTraffics` @@ -482,23 +482,23 @@ Examples: ```js // recording traffics and verify the traffic - I.startRecordingTraffic(); - I.amOnPage('https://codecept.io/'); - I.seeTraffic({ name: 'traffics', url: 'https://codecept.io/img/companies/BC_LogoScreen_C.jpg' }); +I.startRecordingTraffic(); +I.amOnPage('https://codecept.io/'); +I.seeTraffic({ name: 'traffics', url: 'https://codecept.io/img/companies/BC_LogoScreen_C.jpg' }); ``` ```js // check the traffic with advanced params - I.amOnPage('https://openai.com/blog/chatgpt'); - I.startRecordingTraffic(); - I.seeTraffic({ - name: 'sentry event', - url: 'https://images.openai.com/blob/cf717bdb-0c8c-428a-b82b-3c3add87a600', - parameters: { - width: '1919', - height: '1138', - }, - }); +I.amOnPage('https://openai.com/blog/chatgpt'); +I.startRecordingTraffic(); +I.seeTraffic({ + name: 'sentry event', + url: 'https://images.openai.com/blob/cf717bdb-0c8c-428a-b82b-3c3add87a600', + parameters: { + width: '1919', + height: '1138', + }, +}); ``` * feat(webapi): add waitForCookie ([#4169](https://github.com/codeceptjs/CodeceptJS/issues/4169)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** Waits for the specified cookie in the cookies. @@ -546,18 +546,18 @@ Example: ```js { - helpers: { - WebDriver : { - smartWait: 5000, - browser: "chrome", - restart: false, - windowSize: "maximize", - timeouts: { - "script": 60000, - "page load": 10000 - } - } - } + helpers: { + WebDriver : { + smartWait: 5000, + browser: "chrome", + restart: false, + windowSize: "maximize", + timeouts: { + "script": 60000, + "page load": 10000 + } + } + } } ``` @@ -566,19 +566,19 @@ For example: ```js { - helpers: { - WebDriver : { - smartWait: 5000, - browser: "chrome", - browserVersion: '116.0.5793.0', // or 'stable', 'beta', 'dev' or 'canary' - restart: false, - windowSize: "maximize", - timeouts: { - "script": 60000, - "page load": 10000 - } - } - } + helpers: { + WebDriver : { + smartWait: 5000, + browser: "chrome", + browserVersion: '116.0.5793.0', // or 'stable', 'beta', 'dev' or 'canary' + restart: false, + windowSize: "maximize", + timeouts: { + "script": 60000, + "page load": 10000 + } + } + } } ``` * feat: wdio with devtools protocol ([#4105](https://github.com/codeceptjs/CodeceptJS/issues/4105)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** @@ -587,17 +587,18 @@ Running with devtools protocol ```js { - helpers: { - WebDriver : { - url: "http://localhost", - browser: "chrome", - desiredCapabilities: { - chromeOptions: { - args: [ "--headless", "--disable-gpu", "--no-sandbox" ] - } - } - } - } + helpers: { + WebDriver : { + url: "http://localhost", + browser: "chrome", + devtoolsProtocol: true, + desiredCapabilities: { + chromeOptions: { + args: [ "--headless", "--disable-gpu", "--no-sandbox" ] + } + } + } + } } ``` * feat: add a locator builder method withTextEquals() ([#4100](https://github.com/codeceptjs/CodeceptJS/issues/4100)) - by **[mirao](https://github.com/mirao)** @@ -658,9 +659,9 @@ Updated ```js Scenario('Verify getting list of users', async () => { -let res = await I.getUserPerPage(2); -res.data = []; // this line causes the issue -await I.expectEqual(res.data.data[0].id, 7); + let res = await I.getUserPerPage(2); + res.data = []; // this line causes the issue + await I.expectEqual(res.data.data[0].id, 7); }); ``` at this time, res.data.data[0].id would throw undefined error and somehow the test is missing all its steps. @@ -678,14 +679,14 @@ Plugins: screenshotOnFail, tryTo, retryFailedStep, retryTo, eachElement Repro -- **[1]** Starting recording promises Timeouts: -› **[Session]** Starting singleton browser session + › **[Session]** Starting singleton browser session Reproduce issue I am on page "https://example.com" › [Browser:Error] Failed to load resource: the server responded with a status of 404 () › [New Context] {} user1: I am on page "https://example.com" user1: I execute script () => { -return { width: window.screen.width, height: window.screen.height }; + return { width: window.screen.width, height: window.screen.height }; } sessionScreen is {"width":375,"height":667} ✔ OK in 1890ms @@ -705,7 +706,7 @@ OK | 1 passed // 4s deprecate some JSON Wire Protocol commands: `grabGeoLocation`, `setGeoLocation` * fix: cannot locate complicated locator ([#4101](https://github.com/codeceptjs/CodeceptJS/issues/4101)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** - + Locator issue due to the lib changes ``` @@ -830,7 +831,7 @@ Fixed this error: locator.isVisible: Unexpected token "s" while parsing selector ":has-text('Were you able to resolve the resident's issue?') >> nth=0" at Playwright.waitForText (node_modules\codeceptjs\lib\helper\Playwright.js:2584:79) ``` -* fix: move to sha256 ([#4038](https://github.com/codeceptjs/CodeceptJS/issues/4038)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** +* fix: move to sha256 ([#4038](https://github.com/codeceptjs/CodeceptJS/issues/4038)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** * fix: respect retries from retryfailedstep plugin in helpers ([#4028](https://github.com/codeceptjs/CodeceptJS/issues/4028)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** ``` Currently inside the _before() of helpers for example Playwright, the retries is set there, however, when retryFailedStep plugin is enabled, the retries of recorder is still using the value from _before() not the value from retryFailedStep plugin. @@ -1301,34 +1302,34 @@ await I.seeInField('checkbox[]', secret('see test three')); ## 3.5.4 🐛 Bug Fixes: - * **[Playwright]** When passing `userDataDir`, it throws error after test execution ([#3814](https://github.com/codeceptjs/CodeceptJS/issues/3814)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** - * [CodeceptJS-CLI] Improve command to generate types ([#3788](https://github.com/codeceptjs/CodeceptJS/issues/3788)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** - * Heal plugin fix ([#3820](https://github.com/codeceptjs/CodeceptJS/issues/3820)) - by **[davert](https://github.com/davert)** - * Fix for error in using `all` with `run-workers` ([#3805](https://github.com/codeceptjs/CodeceptJS/issues/3805)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** +* **[Playwright]** When passing `userDataDir`, it throws error after test execution ([#3814](https://github.com/codeceptjs/CodeceptJS/issues/3814)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** +* [CodeceptJS-CLI] Improve command to generate types ([#3788](https://github.com/codeceptjs/CodeceptJS/issues/3788)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** +* Heal plugin fix ([#3820](https://github.com/codeceptjs/CodeceptJS/issues/3820)) - by **[davert](https://github.com/davert)** +* Fix for error in using `all` with `run-workers` ([#3805](https://github.com/codeceptjs/CodeceptJS/issues/3805)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** ```js helpers: { - Playwright: { - url: 'https://github.com', + Playwright: { + url: 'https://github.com', show: false, browser: 'chromium', waitForNavigation: 'load', waitForTimeout: 30_000, trace: true, keepTraceForPassedTests: true - }, }, - multiple: { - profile1: { - browsers: [ - { - browser: "chromium", - } - ] - }, +}, +multiple: { + profile1: { + browsers: [ + { + browser: "chromium", + } + ] }, +}, ``` - * Highlight elements issues ([#3779](https://github.com/codeceptjs/CodeceptJS/issues/3779)) ([#3778](https://github.com/codeceptjs/CodeceptJS/issues/3778)) - by **[philkas](https://github.com/philkas)** - * Support ` ` symbol in `I.see` method ([#3815](https://github.com/codeceptjs/CodeceptJS/issues/3815)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** +* Highlight elements issues ([#3779](https://github.com/codeceptjs/CodeceptJS/issues/3779)) ([#3778](https://github.com/codeceptjs/CodeceptJS/issues/3778)) - by **[philkas](https://github.com/philkas)** +* Support ` ` symbol in `I.see` method ([#3815](https://github.com/codeceptjs/CodeceptJS/issues/3815)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** ```js // HTML code uses   instead of space @@ -1338,7 +1339,7 @@ I.see("My Text!") // this test would work with both   and space ``` 📖 Documentation - * Improve the configuration of electron testing when the app is build with electron-forge ([#3802](https://github.com/codeceptjs/CodeceptJS/issues/3802)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** +* Improve the configuration of electron testing when the app is build with electron-forge ([#3802](https://github.com/codeceptjs/CodeceptJS/issues/3802)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** ```js const path = require("path"); @@ -1360,19 +1361,19 @@ exports.config = { 🛩️ Features #### **[Playwright]** new features and improvements - * Parse the response in recording network steps ([#3771](https://github.com/codeceptjs/CodeceptJS/issues/3771)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** +* Parse the response in recording network steps ([#3771](https://github.com/codeceptjs/CodeceptJS/issues/3771)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** ```js const traffics = await I.grabRecordedNetworkTraffics(); - expect(traffics[0].url).to.equal('https://reqres.in/api/comments/1'); - expect(traffics[0].response.status).to.equal(200); - expect(traffics[0].response.body).to.contain({ name: 'this was mocked' }); +expect(traffics[0].url).to.equal('https://reqres.in/api/comments/1'); +expect(traffics[0].response.status).to.equal(200); +expect(traffics[0].response.body).to.contain({ name: 'this was mocked' }); - expect(traffics[1].url).to.equal('https://reqres.in/api/comments/1'); - expect(traffics[1].response.status).to.equal(200); - expect(traffics[1].response.body).to.contain({ name: 'this was another mocked' }); +expect(traffics[1].url).to.equal('https://reqres.in/api/comments/1'); +expect(traffics[1].response.status).to.equal(200); +expect(traffics[1].response.body).to.contain({ name: 'this was another mocked' }); ``` - * Grab metrics ([#3809](https://github.com/codeceptjs/CodeceptJS/issues/3809)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** +* Grab metrics ([#3809](https://github.com/codeceptjs/CodeceptJS/issues/3809)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** ```js const metrics = await I.grabMetrics(); @@ -1475,32 +1476,32 @@ Examples: ```js // recording traffics and verify the traffic - await I.startRecordingTraffic(); - I.amOnPage('https://codecept.io/'); - await I.seeTraffic({ name: 'traffics', url: 'https://codecept.io/img/companies/BC_LogoScreen_C.jpg' }); +await I.startRecordingTraffic(); +I.amOnPage('https://codecept.io/'); +await I.seeTraffic({ name: 'traffics', url: 'https://codecept.io/img/companies/BC_LogoScreen_C.jpg' }); ``` ```js // block the traffic - I.blockTraffic('https://reqres.in/api/comments/*'); - await I.amOnPage('/form/fetch_call'); - await I.startRecordingTraffic(); - await I.click('GET COMMENTS'); - await I.see('Can not load data!'); +I.blockTraffic('https://reqres.in/api/comments/*'); +await I.amOnPage('/form/fetch_call'); +await I.startRecordingTraffic(); +await I.click('GET COMMENTS'); +await I.see('Can not load data!'); ``` ```js // check the traffic with advanced params - I.amOnPage('https://openai.com/blog/chatgpt'); - await I.startRecordingTraffic(); - await I.seeTraffic({ - name: 'sentry event', - url: 'https://images.openai.com/blob/cf717bdb-0c8c-428a-b82b-3c3add87a600', - parameters: { - width: '1919', - height: '1138', - }, - }); +I.amOnPage('https://openai.com/blog/chatgpt'); +await I.startRecordingTraffic(); +await I.seeTraffic({ + name: 'sentry event', + url: 'https://images.openai.com/blob/cf717bdb-0c8c-428a-b82b-3c3add87a600', + parameters: { + width: '1919', + height: '1138', + }, +}); ``` 🐛 Bugfix @@ -1522,7 +1523,7 @@ Examples: 🛩️ Features -* [Puppeteer][WebDriver][TestCafe] Added methods by **[KobeNguyenT](https://github.com/KobeNguyenT)** in [#3737](https://github.com/codeceptjs/CodeceptJS/issues/3737) +* [Puppeteer][WebDriver][TestCafe] Added methods by **[KobeNguyenT](https://github.com/KobeNguyenT)** in [#3737](https://github.com/codeceptjs/CodeceptJS/issues/3737) * `blur` * `focus` * Improved BDD output to print steps without `I.` commands` by **[davertmik](https://github.com/davertmik)** [#3739](https://github.com/codeceptjs/CodeceptJS/issues/3739) @@ -1535,7 +1536,7 @@ Examples: 📖 Documentation * Fixed Playwright docs by **[Horsty80](https://github.com/Horsty80)** -* Fixed ai docs by **[ngraf](https://github.com/ngraf)** +* Fixed ai docs by **[ngraf](https://github.com/ngraf)** * Various fixes by **[KobeNguyenT](https://github.com/KobeNguyenT)** ## 3.5.0 @@ -1543,7 +1544,7 @@ Examples: 🛩️ Features - **🪄 [AI Powered Test Automation](/ai)** - use OpenAI as a copilot for test automation. [#3713](https://github.com/codeceptjs/CodeceptJS/issues/3713) By **[davertmik](https://github.com/davertmik)** -![](https://user-images.githubusercontent.com/220264/250418764-c382709a-3ccb-4eb5-b6bc-538f3b3b3d35.png) + ![](https://user-images.githubusercontent.com/220264/250418764-c382709a-3ccb-4eb5-b6bc-538f3b3b3d35.png) * [AI guide](/ai) added * added support for OpenAI in `pause()` * added [`heal` plugin](/plugins#heal) for self-healing tests @@ -1623,13 +1624,13 @@ Feature('flaky Before & BeforeSuite', { retryBefore: 2, retryBeforeSuite: 3 }) retry: [ { // enable this config only for flaky tests - grep: '@flaky', + grep: '@flaky', Before: 3 // retry Before 3 times Scenario: 3 // retry Scenario 3 times - }, + }, { // retry less when running slow tests - grep: '@slow' + grep: '@slow' Scenario: 1 Before: 1 }, { @@ -1651,7 +1652,7 @@ timeout: [ ``` * JsDoc: Removed promise from `I.say`. See [#3535](https://github.com/codeceptjs/CodeceptJS/issues/3535) by **[danielrentz](https://github.com/danielrentz)** -* **[Playwright]** `handleDownloads` requires now a filename param. See [#3511](https://github.com/codeceptjs/CodeceptJS/issues/3511) by **[PeterNgTr](https://github.com/PeterNgTr)** +* **[Playwright]** `handleDownloads` requires now a filename param. See [#3511](https://github.com/codeceptjs/CodeceptJS/issues/3511) by **[PeterNgTr](https://github.com/PeterNgTr)** * **[WebDriver]** Added support for v8, removed support for webdriverio v5 and lower. See [#3578](https://github.com/codeceptjs/CodeceptJS/issues/3578) by **[PeterNgTr](https://github.com/PeterNgTr)** @@ -1660,20 +1661,20 @@ timeout: [ 🛩️ Features * **Promise-based typings** for TypeScript definitions in [#3465](https://github.com/codeceptjs/CodeceptJS/issues/3465) by **[nlespiaucq](https://github.com/nlespiaucq)**. If you use TypeScript or use linters [check how it may be useful to you](https://bit.ly/3XIMq6n). -* **Translation** improved to use [custom vocabulary](https://codecept.io/translation/). +* **Translation** improved to use [custom vocabulary](https://codecept.io/translation/). * **[Playwright]** Added methods in [#3398](https://github.com/codeceptjs/CodeceptJS/issues/3398) by **[mirao](https://github.com/mirao)** * `restartBrowser` - to restart a browser (with different config) * `_createContextPage` - to create a new browser context with a page from a helper -* Added [Cucumber custom types](/bdd#custom-types) for BDD in [#3435](https://github.com/codeceptjs/CodeceptJS/issues/3435) by **[Likstern](https://github.com/Likstern)** -* Propose using JSONResponse helper when initializing project for API testing. [#3455](https://github.com/codeceptjs/CodeceptJS/issues/3455) by **[PeterNgTr](https://github.com/PeterNgTr)** +* Added [Cucumber custom types](/bdd#custom-types) for BDD in [#3435](https://github.com/codeceptjs/CodeceptJS/issues/3435) by **[Likstern](https://github.com/Likstern)** +* Propose using JSONResponse helper when initializing project for API testing. [#3455](https://github.com/codeceptjs/CodeceptJS/issues/3455) by **[PeterNgTr](https://github.com/PeterNgTr)** * When translation enabled, generate tests using localized aliases. By **[davertmik](https://github.com/davertmik)** -* **[Appium]** Added `checkIfAppIsInstalled` in [#3507](https://github.com/codeceptjs/CodeceptJS/issues/3507) by **[PeterNgTr](https://github.com/PeterNgTr)** +* **[Appium]** Added `checkIfAppIsInstalled` in [#3507](https://github.com/codeceptjs/CodeceptJS/issues/3507) by **[PeterNgTr](https://github.com/PeterNgTr)** 🐛 Bugfixes * Fixed [#3462](https://github.com/codeceptjs/CodeceptJS/issues/3462) `TypeError: Cannot read properties of undefined (reading 'setStatus')` by **[dwentland24](https://github.com/dwentland24)** in [#3438](https://github.com/codeceptjs/CodeceptJS/issues/3438) -* Fixed creating steps file for TypeScript setup [#3459](https://github.com/codeceptjs/CodeceptJS/issues/3459) by **[PeterNgTr](https://github.com/PeterNgTr)** -* Fixed issue of after all event in `run-rerun` command after complete execution [#3464](https://github.com/codeceptjs/CodeceptJS/issues/3464) by **[jain-neeeraj](https://github.com/jain-neeeraj)** +* Fixed creating steps file for TypeScript setup [#3459](https://github.com/codeceptjs/CodeceptJS/issues/3459) by **[PeterNgTr](https://github.com/PeterNgTr)** +* Fixed issue of after all event in `run-rerun` command after complete execution [#3464](https://github.com/codeceptjs/CodeceptJS/issues/3464) by **[jain-neeeraj](https://github.com/jain-neeeraj)** * [Playwright][WebDriver][Appium] Do not change `waitForTimeout` value on validation. See [#3478](https://github.com/codeceptjs/CodeceptJS/issues/3478) by **[pmajewski24](https://github.com/pmajewski24)**. Fixes [#2589](https://github.com/codeceptjs/CodeceptJS/issues/2589) * [Playwright][WebDriver][Protractor][Puppeteer][TestCafe] Fixes `Element "{null: undefined}" was not found` and `element ([object Object]) still not present` messages when using object locators. See [#3501](https://github.com/codeceptjs/CodeceptJS/issues/3501) and [#3502](https://github.com/codeceptjs/CodeceptJS/issues/3502) by **[pmajewski24](https://github.com/pmajewski24)** * **[Playwright]** Improved file names when downloading file in [#3449](https://github.com/codeceptjs/CodeceptJS/issues/3449) by **[PeterNgTr](https://github.com/PeterNgTr)**. Fixes [#3412](https://github.com/codeceptjs/CodeceptJS/issues/3412) and [#3409](https://github.com/codeceptjs/CodeceptJS/issues/3409) @@ -1681,7 +1682,7 @@ timeout: [ * **[Playwright]** Using system-native path separator when saving artifacts in [#3460](https://github.com/codeceptjs/CodeceptJS/issues/3460) by **[PeterNgTr](https://github.com/PeterNgTr)** * **[Playwright]** Saving videos and traces from multiple sessions in [#3505](https://github.com/codeceptjs/CodeceptJS/issues/3505) by **[davertmik](https://github.com/davertmik)** * **[Playwright]** Fixed `amOnPage` to navigate to `about:blank` by **[zaxoavoki](https://github.com/zaxoavoki)** in [#3470](https://github.com/codeceptjs/CodeceptJS/issues/3470) Fixes [#2311](https://github.com/codeceptjs/CodeceptJS/issues/2311) -* Various typing improvements by **[AWolf81](https://github.com/AWolf81)** **[PeterNgTr](https://github.com/PeterNgTr)** **[mirao](https://github.com/mirao)** +* Various typing improvements by **[AWolf81](https://github.com/AWolf81)** **[PeterNgTr](https://github.com/PeterNgTr)** **[mirao](https://github.com/mirao)** 📖 Documentation @@ -1714,7 +1715,7 @@ const response = await I.sendPostRequest('/user', secretData); * fix(playwright) - video name and missing type by **[PeterNgTr](https://github.com/PeterNgTr)** in [#3430](https://github.com/codeceptjs/CodeceptJS/issues/3430) * fix for expected type of "bootstrap", "teardown", "bootstrapAll" and "teardownAll" by **[ngraf](https://github.com/ngraf)** in [#3424](https://github.com/codeceptjs/CodeceptJS/issues/3424) * Improve generate pageobject `gpo` command to work with TypeScript by **[PeterNgTr](https://github.com/PeterNgTr)** in [#3411](https://github.com/codeceptjs/CodeceptJS/issues/3411) -* Fixed dry-run to always return 0 code and exit +* Fixed dry-run to always return 0 code and exit * Added minimal version notice for NodeJS >= 12 * fix(utils): remove . of test title to avoid confusion by **[PeterNgTr](https://github.com/PeterNgTr)** in [#3431](https://github.com/codeceptjs/CodeceptJS/issues/3431) @@ -1722,7 +1723,7 @@ const response = await I.sendPostRequest('/user', secretData); 🛩️ Features -* Added **TypeScript types for CodeceptJS config**. +* Added **TypeScript types for CodeceptJS config**. Update `codecept.conf.js` to get intellisense when writing config file: @@ -1743,17 +1744,17 @@ exports.config = { 🐛 Bugfixes -* **[Puppeteer]** Fixed support for Puppeteer > 14.4 by **[PeterNgTr](https://github.com/PeterNgTr)** +* **[Puppeteer]** Fixed support for Puppeteer > 14.4 by **[PeterNgTr](https://github.com/PeterNgTr)** * Don't report files as existing when non-directory is in path by **[jonathanperret](https://github.com/jonathanperret)**. See [#3374](https://github.com/codeceptjs/CodeceptJS/issues/3374) -* Fixed TS type for `secret` function by **[PeterNgTr](https://github.com/PeterNgTr)** +* Fixed TS type for `secret` function by **[PeterNgTr](https://github.com/PeterNgTr)** * Fixed wrong order for async MetaSteps by **[dwentland24](https://github.com/dwentland24)**. See [#3393](https://github.com/codeceptjs/CodeceptJS/issues/3393) -* Fixed same param substitution in BDD step. See [#3385](https://github.com/codeceptjs/CodeceptJS/issues/3385) by **[snehabhandge](https://github.com/snehabhandge)** +* Fixed same param substitution in BDD step. See [#3385](https://github.com/codeceptjs/CodeceptJS/issues/3385) by **[snehabhandge](https://github.com/snehabhandge)** 📖 Documentation * Updated [configuration options](https://codecept.io/configuration/) to match TypeScript types * Updated [TypeScript documentation](https://codecept.io/typescript/) on simplifying TS installation -* Added codecept-tesults plugin documentation by **[ajeetd](https://github.com/ajeetd)** +* Added codecept-tesults plugin documentation by **[ajeetd](https://github.com/ajeetd)** @@ -1766,21 +1767,21 @@ I.sendPostRequest('/auth', secret({ name: 'jon', password: '123456' }, 'password ``` * Added [a guide about using of `secret`](/secrets) function * **[Appium]** Use `touchClick` when interacting with elements in iOS. See [#3317](https://github.com/codeceptjs/CodeceptJS/issues/3317) by **[mikk150](https://github.com/mikk150)** -* **[Playwright]** Added `cdpConnection` option to connect over CDP. See [#3309](https://github.com/codeceptjs/CodeceptJS/issues/3309) by **[Hmihaly](https://github.com/Hmihaly)** +* **[Playwright]** Added `cdpConnection` option to connect over CDP. See [#3309](https://github.com/codeceptjs/CodeceptJS/issues/3309) by **[Hmihaly](https://github.com/Hmihaly)** * [customLocator plugin] Allowed to specify multiple attributes for custom locator. Thanks to **[aruiz-caritsqa](https://github.com/aruiz-caritsqa)** ```js plugins: { - customLocator: { - enabled: true, - prefix: '$', - attribute: ['data-qa', 'data-test'], - } + customLocator: { + enabled: true, + prefix: '$', + attribute: ['data-qa', 'data-test'], + } } ``` * [retryTo plugin] Fixed [#3147](https://github.com/codeceptjs/CodeceptJS/issues/3147) using `pollInterval` option. See [#3351](https://github.com/codeceptjs/CodeceptJS/issues/3351) by **[cyonkee](https://github.com/cyonkee)** * **[Playwright]** Fixed grabbing of browser console messages and window resize in new tab. Thanks to **[mirao](https://github.com/mirao)** -* **[REST]** Added `prettyPrintJson` option to print JSON in nice way by **[PeterNgTr](https://github.com/PeterNgTr)** +* **[REST]** Added `prettyPrintJson` option to print JSON in nice way by **[PeterNgTr](https://github.com/PeterNgTr)** * **[JSONResponse]** Updated response validation to iterate over array items if response is array. Thanks to **[PeterNgTr](https://github.com/PeterNgTr)** ```js @@ -1804,7 +1805,7 @@ I.dontSeeResponseContainsJson({ user: 2 }); ## 3.3.2 * **[REST]** Fixed override of headers/token in `haveRequestHeaders()` and `amBearerAuthenticated()`. See [#3304](https://github.com/codeceptjs/CodeceptJS/issues/3304) by **[mirao](https://github.com/mirao)** -* Reverted typings change introduced in [#3245](https://github.com/codeceptjs/CodeceptJS/issues/3245). [More details on this](https://twitter.com/CodeceptJS/status/1519725963856207873) +* Reverted typings change introduced in [#3245](https://github.com/codeceptjs/CodeceptJS/issues/3245). [More details on this](https://twitter.com/CodeceptJS/status/1519725963856207873) ## 3.3.1 @@ -1812,7 +1813,7 @@ I.dontSeeResponseContainsJson({ user: 2 }); * Add option to avoid duplicate gherkin step definitions ([#3257](https://github.com/codeceptjs/CodeceptJS/issues/3257)) - **[raywiis](https://github.com/raywiis)** * Added `step.*` for run-workers [#3272](https://github.com/codeceptjs/CodeceptJS/issues/3272). Thanks to **[abhimanyupandian](https://github.com/abhimanyupandian)** -* Fixed loading tests for `codecept run` using glob patterns. By **[jayudey-wf](https://github.com/jayudey-wf)** +* Fixed loading tests for `codecept run` using glob patterns. By **[jayudey-wf](https://github.com/jayudey-wf)** ``` npx codeceptjs run test-dir/*" @@ -1825,9 +1826,9 @@ npx codeceptjs run test-dir/*" helpers: { Playwright : { url: "http://localhost", - colorScheme: "dark", + colorScheme: "dark", } - } +} ``` @@ -1835,8 +1836,8 @@ npx codeceptjs run test-dir/*" * **[Playwright]** Fixed `Cannot read property 'video' of undefined` * Fixed haveRequestHeaders() and amBearerAuthenticated() of REST helper ([#3260](https://github.com/codeceptjs/CodeceptJS/issues/3260)) - **[mirao](https://github.com/mirao)** -* Fixed: allure attachment fails if screenshot failed [#3298](https://github.com/codeceptjs/CodeceptJS/issues/3298) by **[ruudvanderweijde](https://github.com/ruudvanderweijde)** -* Fixed [#3105](https://github.com/codeceptjs/CodeceptJS/issues/3105) using autoLogin() plugin with TypeScript. Fix [#3290](https://github.com/codeceptjs/CodeceptJS/issues/3290) by **[PeterNgTr](https://github.com/PeterNgTr)** +* Fixed: allure attachment fails if screenshot failed [#3298](https://github.com/codeceptjs/CodeceptJS/issues/3298) by **[ruudvanderweijde](https://github.com/ruudvanderweijde)** +* Fixed [#3105](https://github.com/codeceptjs/CodeceptJS/issues/3105) using autoLogin() plugin with TypeScript. Fix [#3290](https://github.com/codeceptjs/CodeceptJS/issues/3290) by **[PeterNgTr](https://github.com/PeterNgTr)** * **[Playwright]** Added extra params for click and dragAndDrop to type definitions by **[mirao](https://github.com/mirao)** @@ -1881,10 +1882,10 @@ await eachElement('click all links in .list', '.list a', (el) => { ``` * **[Playwright]** Added support to `playwright-core` package if `playwright` is not installed. See [#3190](https://github.com/codeceptjs/CodeceptJS/issues/3190), fixes [#2663](https://github.com/codeceptjs/CodeceptJS/issues/2663). * **[Playwright]** Added `makeApiRequest` action to perform API requests. Requires Playwright >= 1.18 -* Added support to `codecept.config.js` for name consistency across other JS tools. See motivation at [#3195](https://github.com/codeceptjs/CodeceptJS/issues/3195) by **[JiLiZART](https://github.com/JiLiZART)** +* Added support to `codecept.config.js` for name consistency across other JS tools. See motivation at [#3195](https://github.com/codeceptjs/CodeceptJS/issues/3195) by **[JiLiZART](https://github.com/JiLiZART)** * **[ApiDataFactory]** Added options arg to `have` method. See [#3197](https://github.com/codeceptjs/CodeceptJS/issues/3197) by **[JJlokidoki](https://github.com/JJlokidoki)** -* Improved pt-br translations to include keywords: 'Funcionalidade', 'Cenário', 'Antes', 'Depois', 'AntesDaSuite', 'DepoisDaSuite'. See [#3206](https://github.com/codeceptjs/CodeceptJS/issues/3206) by **[danilolutz](https://github.com/danilolutz)** -* [allure plugin] Introduced `addStep` method to add comments and attachments. See [#3104](https://github.com/codeceptjs/CodeceptJS/issues/3104) by **[EgorBodnar](https://github.com/EgorBodnar)** +* Improved pt-br translations to include keywords: 'Funcionalidade', 'Cenário', 'Antes', 'Depois', 'AntesDaSuite', 'DepoisDaSuite'. See [#3206](https://github.com/codeceptjs/CodeceptJS/issues/3206) by **[danilolutz](https://github.com/danilolutz)** +* [allure plugin] Introduced `addStep` method to add comments and attachments. See [#3104](https://github.com/codeceptjs/CodeceptJS/issues/3104) by **[EgorBodnar](https://github.com/EgorBodnar)** 🐛 Bugfixes: @@ -1896,14 +1897,14 @@ await eachElement('click all links in .list', '.list a', (el) => { * Added [api testing](/api) guides * Added [internal api](/internal-api) guides * **[Appium]** Fixed documentation for `performSwipe` -* **[Playwright]** update docs for `usePlaywrightTo` method by **[dbudzins](https://github.com/dbudzins)** +* **[Playwright]** update docs for `usePlaywrightTo` method by **[dbudzins](https://github.com/dbudzins)** ## 3.2.3 * Documentation improvements by **[maojunxyz](https://github.com/maojunxyz)** -* Guard mocha cli reporter from registering step logger multiple times [#3180](https://github.com/codeceptjs/CodeceptJS/issues/3180) by **[nikocanvacom](https://github.com/nikocanvacom)** +* Guard mocha cli reporter from registering step logger multiple times [#3180](https://github.com/codeceptjs/CodeceptJS/issues/3180) by **[nikocanvacom](https://github.com/nikocanvacom)** * **[Playwright]** Fixed "tracing.stop: tracing.stop: ENAMETOOLONG: name too long" by **[hatufacci](https://github.com/hatufacci)** -* Fixed [#2889](https://github.com/codeceptjs/CodeceptJS/issues/2889): return always the same error contract from simplifyTest. See [#3168](https://github.com/codeceptjs/CodeceptJS/issues/3168) by **[andremoah](https://github.com/andremoah)** +* Fixed [#2889](https://github.com/codeceptjs/CodeceptJS/issues/2889): return always the same error contract from simplifyTest. See [#3168](https://github.com/codeceptjs/CodeceptJS/issues/3168) by **[andremoah](https://github.com/andremoah)** ## 3.2.2 @@ -1929,10 +1930,10 @@ await eachElement('click all links in .list', '.list a', (el) => { 🛩️ Features: **[Timeouts](https://codecept.io/advanced/#timeout) implemented** - * global timeouts (via `timeout` config option). - * _Breaking change:_ timeout option expects **timeout in seconds**, not in milliseconds as it was previously. - * test timeouts (via `Scenario` and `Feature` options) - * _Breaking change:_ `Feature().timeout()` and `Scenario().timeout()` calls has no effect and are deprecated +* global timeouts (via `timeout` config option). + * _Breaking change:_ timeout option expects **timeout in seconds**, not in milliseconds as it was previously. +* test timeouts (via `Scenario` and `Feature` options) + * _Breaking change:_ `Feature().timeout()` and `Scenario().timeout()` calls has no effect and are deprecated ```js // set timeout for every test in suite to 10 secs @@ -1942,13 +1943,13 @@ Feature('tests with timeout', { timeout: 10 }); Scenario('a test with timeout', { timeout: 20 }, ({ I }) => {}); ``` - * step timeouts (See [#3059](https://github.com/codeceptjs/CodeceptJS/issues/3059) by **[nikocanvacom](https://github.com/nikocanvacom)**) +* step timeouts (See [#3059](https://github.com/codeceptjs/CodeceptJS/issues/3059) by **[nikocanvacom](https://github.com/nikocanvacom)**) ```js // set step timeout to 5 secs I.limitTime(5).click('Link'); ``` - * `stepTimeout` plugin introduced to automatically add timeouts for each step ([#3059](https://github.com/codeceptjs/CodeceptJS/issues/3059) by **[nikocanvacom](https://github.com/nikocanvacom)**). +* `stepTimeout` plugin introduced to automatically add timeouts for each step ([#3059](https://github.com/codeceptjs/CodeceptJS/issues/3059) by **[nikocanvacom](https://github.com/nikocanvacom)**). [**retryTo**](/plugins/#retryto) plugin introduced to rerun a set of steps on failure: @@ -1966,7 +1967,7 @@ await retryTo(() => { 🐛 Bugfixes: -* Fixed allure plugin "Unexpected endStep()" error in [#3098](https://github.com/codeceptjs/CodeceptJS/issues/3098) by **[abhimanyupandian](https://github.com/abhimanyupandian)** +* Fixed allure plugin "Unexpected endStep()" error in [#3098](https://github.com/codeceptjs/CodeceptJS/issues/3098) by **[abhimanyupandian](https://github.com/abhimanyupandian)** * **[Puppeteer]** always close remote browser on test end. See [#3054](https://github.com/codeceptjs/CodeceptJS/issues/3054) by **[mattonem](https://github.com/mattonem)** * stepbyStepReport Plugin: Disabled screenshots after test has failed. See [#3119](https://github.com/codeceptjs/CodeceptJS/issues/3119) by **[ioannisChalkias](https://github.com/ioannisChalkias)** @@ -1975,23 +1976,23 @@ await retryTo(() => { 🛩️ Features: -* BDD Improvement. Added `DataTableArgument` class to work with table data structures. +* BDD Improvement. Added `DataTableArgument` class to work with table data structures. ```js const { DataTableArgument } = require('codeceptjs'); //... Given('I have an employee card', (table) => { const dataTableArgument = new DataTableArgument(table); - const hashes = dataTableArgument.hashes(); + const hashes = dataTableArgument.hashes(); // hashes = [{ name: 'Harry', surname: 'Potter', position: 'Seeker' }]; const rows = dataTableArgument.rows(); // rows = [['Harry', 'Potter', Seeker]]; - } +} ``` See updated [BDD section](https://codecept.io/bdd/) for more API options. Thanks to **[EgorBodnar](https://github.com/EgorBodnar)** * Support `cjs` file extensions for config file: `codecept.conf.cjs`. See [#3052](https://github.com/codeceptjs/CodeceptJS/issues/3052) by **[kalvenschraut](https://github.com/kalvenschraut)** -* API updates: Added `test.file` and `suite.file` properties to `test` and `suite` objects to use in helpers and plugins. +* API updates: Added `test.file` and `suite.file` properties to `test` and `suite` objects to use in helpers and plugins. 🐛 Bugfixes: @@ -1999,9 +2000,9 @@ See updated [BDD section](https://codecept.io/bdd/) for more API options. Thanks * **[Playwright]** Apply `basicAuth` credentials to all opened browser contexts. See [#3036](https://github.com/codeceptjs/CodeceptJS/issues/3036) by **[nikocanvacom](https://github.com/nikocanvacom)**. Fixes [#3035](https://github.com/codeceptjs/CodeceptJS/issues/3035) * **[WebDriver]** Updated `webdriverio` default version to `^6.12.1`. See [#3043](https://github.com/codeceptjs/CodeceptJS/issues/3043) by **[sridhareaswaran](https://github.com/sridhareaswaran)** * **[Playwright]** `I.haveRequestHeaders` affects all tabs. See [#3049](https://github.com/codeceptjs/CodeceptJS/issues/3049) by **[jancorvus](https://github.com/jancorvus)** -* BDD: Fixed unhandled empty feature files. Fix [#3046](https://github.com/codeceptjs/CodeceptJS/issues/3046) by **[abhimanyupandian](https://github.com/abhimanyupandian)** -* Fixed `RangeError: Invalid string length` in `recorder.js` when running huge amount of tests. -* **[Appium]** Fixed definitions for `touchPerform`, `hideDeviceKeyboard`, `removeApp` by **[mirao](https://github.com/mirao)** +* BDD: Fixed unhandled empty feature files. Fix [#3046](https://github.com/codeceptjs/CodeceptJS/issues/3046) by **[abhimanyupandian](https://github.com/abhimanyupandian)** +* Fixed `RangeError: Invalid string length` in `recorder.js` when running huge amount of tests. +* **[Appium]** Fixed definitions for `touchPerform`, `hideDeviceKeyboard`, `removeApp` by **[mirao](https://github.com/mirao)** 📖 Documentation: @@ -2026,10 +2027,10 @@ exports.config = { 🐛 Bugfixes: -* **[Playwright]** Fixed [#2986](https://github.com/codeceptjs/CodeceptJS/issues/2986) error is thrown when deleting a missing video. Fix by **[hatufacci](https://github.com/hatufacci)** +* **[Playwright]** Fixed [#2986](https://github.com/codeceptjs/CodeceptJS/issues/2986) error is thrown when deleting a missing video. Fix by **[hatufacci](https://github.com/hatufacci)** * Fixed false positive result when invalid function is called in a helper. See [#2997](https://github.com/codeceptjs/CodeceptJS/issues/2997) by **[abhimanyupandian](https://github.com/abhimanyupandian)** * **[Appium]** Removed full page mode for `saveScreenshot`. See [#3002](https://github.com/codeceptjs/CodeceptJS/issues/3002) by **[nlespiaucq](https://github.com/nlespiaucq)** -* **[Playwright]** Fixed [#3003](https://github.com/codeceptjs/CodeceptJS/issues/3003) saving trace for a test with a long name. Fix by **[hatufacci](https://github.com/hatufacci)** +* **[Playwright]** Fixed [#3003](https://github.com/codeceptjs/CodeceptJS/issues/3003) saving trace for a test with a long name. Fix by **[hatufacci](https://github.com/hatufacci)** 🎱 Other: @@ -2038,7 +2039,7 @@ exports.config = { ## 3.1.1 * **[Appium]** Fixed [#2759](https://github.com/codeceptjs/CodeceptJS/issues/2759) - `grabNumberOfVisibleElements`, `grabAttributeFrom`, `grabAttributeFromAll` to allow id locators. + `grabNumberOfVisibleElements`, `grabAttributeFrom`, `grabAttributeFromAll` to allow id locators. ## 3.1.0 @@ -2056,11 +2057,11 @@ exports.config = { 🐛 Bugfixes: * **[Puppeteer]** Fixed [#2244](https://github.com/codeceptjs/CodeceptJS/issues/2244) `els[0]._clickablePoint is not a function` by **[karunandrii](https://github.com/karunandrii)**. -* **[Puppeteer]** Fixed `fillField` to check for invisible elements. See [#2916](https://github.com/codeceptjs/CodeceptJS/issues/2916) by **[anne-open-xchange](https://github.com/anne-open-xchange)** -* **[Playwright]** Reset of dialog event listener before registration of new one. [#2946](https://github.com/codeceptjs/CodeceptJS/issues/2946) by **[nikocanvacom](https://github.com/nikocanvacom)** +* **[Puppeteer]** Fixed `fillField` to check for invisible elements. See [#2916](https://github.com/codeceptjs/CodeceptJS/issues/2916) by **[anne-open-xchange](https://github.com/anne-open-xchange)** +* **[Playwright]** Reset of dialog event listener before registration of new one. [#2946](https://github.com/codeceptjs/CodeceptJS/issues/2946) by **[nikocanvacom](https://github.com/nikocanvacom)** * Fixed running Gherkin features with `run-multiple` using chunks. See [#2900](https://github.com/codeceptjs/CodeceptJS/issues/2900) by **[andrenoberto](https://github.com/andrenoberto)** * Fixed [#2937](https://github.com/codeceptjs/CodeceptJS/issues/2937) broken typings for subfolders on Windows by **[jancorvus](https://github.com/jancorvus)** -* Fixed issue where cucumberJsonReporter not working with fakerTransform plugin. See [#2942](https://github.com/codeceptjs/CodeceptJS/issues/2942) by **[ilangv](https://github.com/ilangv)** +* Fixed issue where cucumberJsonReporter not working with fakerTransform plugin. See [#2942](https://github.com/codeceptjs/CodeceptJS/issues/2942) by **[ilangv](https://github.com/ilangv)** * Fixed [#2952](https://github.com/codeceptjs/CodeceptJS/issues/2952) finished job with status code 0 when playwright cannot connect to remote wss url. By **[davertmik](https://github.com/davertmik)** @@ -2193,23 +2194,23 @@ Library updates: * **[Playwright]** Fix connection close with remote browser. See [#2629](https://github.com/codeceptjs/CodeceptJS/issues/2629) by **[dipiash](https://github.com/dipiash)** * **[REST]** set maxUploadFileSize when performing api calls. See [#2611](https://github.com/codeceptjs/CodeceptJS/issues/2611) by **[PeterNgTr](https://github.com/PeterNgTr)** * Duplicate Scenario names (combined with Feature name) are now detected via a warning message. -Duplicate test names can cause `codeceptjs run-workers` to not function. See [#2656](https://github.com/codeceptjs/CodeceptJS/issues/2656) by **[Georgegriff](https://github.com/Georgegriff)** + Duplicate test names can cause `codeceptjs run-workers` to not function. See [#2656](https://github.com/codeceptjs/CodeceptJS/issues/2656) by **[Georgegriff](https://github.com/Georgegriff)** * Documentation fixes Bug Fixes: - * --suites flag now should function correctly for `codeceptjs run-workers`. See [#2655](https://github.com/codeceptjs/CodeceptJS/issues/2655) by **[Georgegriff](https://github.com/Georgegriff)** - * [autoLogin plugin] Login methods should now function as expected with `codeceptjs run-workers`. See [#2658](https://github.com/codeceptjs/CodeceptJS/issues/2658) by **[Georgegriff](https://github.com/Georgegriff)**, resolves [#2620](https://github.com/codeceptjs/CodeceptJS/issues/2620) +* --suites flag now should function correctly for `codeceptjs run-workers`. See [#2655](https://github.com/codeceptjs/CodeceptJS/issues/2655) by **[Georgegriff](https://github.com/Georgegriff)** +* [autoLogin plugin] Login methods should now function as expected with `codeceptjs run-workers`. See [#2658](https://github.com/codeceptjs/CodeceptJS/issues/2658) by **[Georgegriff](https://github.com/Georgegriff)**, resolves [#2620](https://github.com/codeceptjs/CodeceptJS/issues/2620) ## 3.0.1 ♨️ Hot fix: - * Lock the mocha version to avoid the errors. See [#2624](https://github.com/codeceptjs/CodeceptJS/issues/2624) by PeterNgTr +* Lock the mocha version to avoid the errors. See [#2624](https://github.com/codeceptjs/CodeceptJS/issues/2624) by PeterNgTr 🐛 Bug Fix: - * Fixed error handling in Scenario.js. See [#2607](https://github.com/codeceptjs/CodeceptJS/issues/2607) by haveac1gar - * Changing type definition in order to allow the use of functions with any number of any arguments. See [#2616](https://github.com/codeceptjs/CodeceptJS/issues/2616) by akoltun +* Fixed error handling in Scenario.js. See [#2607](https://github.com/codeceptjs/CodeceptJS/issues/2607) by haveac1gar +* Changing type definition in order to allow the use of functions with any number of any arguments. See [#2616](https://github.com/codeceptjs/CodeceptJS/issues/2616) by akoltun * Some updates/changes on documentations @@ -2255,23 +2256,23 @@ Read changelog to learn more about version 👇 ## 3.0.0-beta.4 🐛 Bug Fix: - * PageObject was broken when using "this" inside a simple object. - * The typings for all WebDriver methods work correctly. - * The typings for "this.helper" and helper constructor work correctly, too. +* PageObject was broken when using "this" inside a simple object. +* The typings for all WebDriver methods work correctly. +* The typings for "this.helper" and helper constructor work correctly, too. 🧤 Internal: - * Our TS Typings will be tested now! We strarted using [dtslint](https://github.com/microsoft/dtslint) to check all typings and all rules for linter. - Example: +* Our TS Typings will be tested now! We strarted using [dtslint](https://github.com/microsoft/dtslint) to check all typings and all rules for linter. + Example: ```ts const psp = wd.grabPageScrollPosition() // $ExpectType Promise - psp.then( - result => { - result.x // $ExpectType number - result.y // $ExpectType number - } - ) +psp.then( + result => { + result.x // $ExpectType number + result.y // $ExpectType number + } +) ``` - * And last: Reducing package size from 3.3Mb to 2.0Mb +* And last: Reducing package size from 3.3Mb to 2.0Mb ## 3.0.0-beta-3 @@ -2293,8 +2294,8 @@ MyPage.hasFiles('first arg', 'second arg'); // OUTPUT: MyPage: hasFile "First arg", "Second arg" - I see file "codecept.js" - I see file "codecept.po.json" +I see file "codecept.js" +I see file "codecept.po.json" ``` * Introduced official [TypeScript boilerplate](https://github.com/codeceptjs/typescript-boilerplate). Started by **[Vorobeyko](https://github.com/Vorobeyko)**. @@ -2444,22 +2445,22 @@ npm i playwright@^0.12 --save ``` [Notable changes](https://github.com/microsoft/playwright/releases/tag/v0.12.0): - * Fixed opening two browsers on start - * `executeScript` - passed function now accepts only one argument. Pass in objects or arrays if you need multtple arguments: +* Fixed opening two browsers on start +* `executeScript` - passed function now accepts only one argument. Pass in objects or arrays if you need multtple arguments: ```js // Old style, does not work anymore: I.executeScript((x, y) => x + y, x, y); // New style, passing an object: I.executeScript(({x, y}) => x + y, {x, y}); ``` - * `click` - automatically waits for element to become clickable (visible, not animated) and waits for navigation. - * `clickLink` - deprecated - * `waitForClickable` - deprecated - * `forceClick` - added - * Added support for custom locators. See [#2277](https://github.com/codeceptjs/CodeceptJS/issues/2277) - * Introduced [device emulation](/playwright/#device-emulation): - * globally via `emulate` config option - * per session +* `click` - automatically waits for element to become clickable (visible, not animated) and waits for navigation. +* `clickLink` - deprecated +* `waitForClickable` - deprecated +* `forceClick` - added +* Added support for custom locators. See [#2277](https://github.com/codeceptjs/CodeceptJS/issues/2277) +* Introduced [device emulation](/playwright/#device-emulation): + * globally via `emulate` config option + * per session **[WebDriver] Updated to webdriverio v6** by **[PeterNgTr](https://github.com/PeterNgTr)**. @@ -2470,7 +2471,7 @@ upgrade webdriverio to ^6.0: npm i webdriverio@^6.0 --save ``` *(webdriverio v5 support is deprecated and will be removed in CodeceptJS 3.0)* - **[WebDriver]** Introduced [Shadow DOM support](/shadow) by **[gkushang](https://github.com/gkushang)** +**[WebDriver]** Introduced [Shadow DOM support](/shadow) by **[gkushang](https://github.com/gkushang)** ```js I.click({ shadow: ['my-app', 'recipe-hello', 'button'] }); @@ -2628,7 +2629,7 @@ I.click({ css: '[data-test-id=register_button]'); I.click('$register_button'); ``` * [Puppeteer][WebDriver] `pressKey` improvements by **[martomo](https://github.com/martomo)**: -Changed pressKey method to resolve issues and extend functionality. + Changed pressKey method to resolve issues and extend functionality. * Did not properly recognize 'Meta' (or 'Command') as modifier key. * Right modifier keys did not work in WebDriver using JsonWireProtocol. * 'Shift' + 'key' combination would not reflect actual keyboard behavior. @@ -2684,8 +2685,8 @@ npx codeceptjs dry-run * **[Appium]** Optimization when clicking, searching for fields by accessibility id. See [#1777](https://github.com/codeceptjs/CodeceptJS/issues/1777) by **[gagandeepsingh26](https://github.com/gagandeepsingh26)** * **[TestCafe]** Fixed `switchTo` by **[KadoBOT](https://github.com/KadoBOT)** * **[WebDriver]** Added geolocation actions by **[PeterNgTr](https://github.com/PeterNgTr)** - * `grabGeoLocation()` - * `setGeoLocation()` + * `grabGeoLocation()` + * `setGeoLocation()` * **[Polly]** Check typeof arguments for mock requests by **[VikalpP](https://github.com/VikalpP)**. Fixes [#1815](https://github.com/codeceptjs/CodeceptJS/issues/1815) * CLI improvements by **[jamesgeorge007](https://github.com/jamesgeorge007)** * `codeceptjs` command prints list of all available commands @@ -2853,8 +2854,8 @@ Do you want to improve this project? [Learn more about sponsorin CodeceptJS Use it with `FileSystem` helper to test availability of a file: ```js const fileName = await I.downloadFile('a.file-link'); - I.amInPath('output'); - I.seeFile(fileName); +I.amInPath('output'); +I.seeFile(fileName); ``` > Actions `amInPath` and `seeFile` are taken from [FileSystem](https://codecept.io/helpers/FileSystem) helper @@ -3010,8 +3011,8 @@ I.say('This is by default'); //cyan is used ## 1.4.5 * Add **require** param to main config. Allows to require Node modules before executing tests. By **[LukoyanovE](https://github.com/LukoyanovE)**. For example: - * Use `ts-node/register` to register TypeScript parser - * Use `should` to register should-style assertions + * Use `ts-node/register` to register TypeScript parser + * Use `should` to register should-style assertions ```js "require": ["ts-node/register", "should"] @@ -3067,10 +3068,10 @@ Scenario('update user profile', () => { * [**Allure Reporter Integration**](https://codecept.io/reports/#allure). Full inegration with Allure Server. Get nicely looking UI for tests,including steps, nested steps, and screenshots. Thanks **Natarajan Krishnamurthy **[krish](https://github.com/krish)**** for sponsoring this feature. * [Plugins API introduced](https://codecept.io/hooks/#plugins). Create custom plugins for CodeceptJS by hooking into event dispatcher, and using promise recorder. * **Official [CodeceptJS plugins](https://codecept.io/plugins) added**: - * **`stepByStepReport` - creates nicely looking report to see test execution as a slideshow**. Use this plugin to debug tests in headless environment without recording a video. - * `allure` - Allure reporter added as plugin. - * `screenshotOnFail` - saves screenshot on fail. Replaces similar functionality from helpers. - * `retryFailedStep` - to rerun each failed step. + * **`stepByStepReport` - creates nicely looking report to see test execution as a slideshow**. Use this plugin to debug tests in headless environment without recording a video. + * `allure` - Allure reporter added as plugin. + * `screenshotOnFail` - saves screenshot on fail. Replaces similar functionality from helpers. + * `retryFailedStep` - to rerun each failed step. * **[Puppeteer]** Fix `executeAsyncScript` unexpected token by **[jonathanz](https://github.com/jonathanz)** * Added `override` option to `run-multiple` command by **[svarlet](https://github.com/svarlet)** @@ -3081,11 +3082,11 @@ Scenario('update user profile', () => { ## 1.3.2 * Interactve Shell improvements for `pause()` - * Added `next` command for **step-by-step debug** when using `pause()`. - * Use `After(pause);` in a to start interactive console after last step. + * Added `next` command for **step-by-step debug** when using `pause()`. + * Use `After(pause);` in a to start interactive console after last step. * **[Puppeteer]** Updated to Puppeteer 1.6.0 - * Added `waitForRequest` to wait for network request. - * Added `waitForResponse` to wait for network response. + * Added `waitForRequest` to wait for network request. + * Added `waitForResponse` to wait for network response. * Improved TypeScript definitions to support custom steps and page objects. By **[xt1](https://github.com/xt1)** * Fixed XPath detection to accept XPath which starts with `./` by **[BenoitZugmeyer](https://github.com/BenoitZugmeyer)** @@ -3150,14 +3151,14 @@ This change allows using auto-completion when running a specific test. --- * Nested steps output enabled for page objects. - * to see high-level steps only run tests with `--steps` flag. - * to see PageObjects implementation run tests with `--debug`. + * to see high-level steps only run tests with `--steps` flag. + * to see PageObjects implementation run tests with `--debug`. * PageObjects simplified to remove `_init()` extra method. Try updated generators and see [updated guide](https://codecept.io/pageobjects/#pageobject). * **[Puppeteer]** [Multiple sessions](https://codecept.io/acceptance/#multiple-sessions) enabled. Requires Puppeteer >= 1.5 * **[Puppeteer]** Stability improvement. Waits for for `load` event on page load. This strategy can be changed in config: - * `waitForNavigation` config option introduced. Possible options: `load`, `domcontentloaded`, `networkidle0`, `networkidle2`. See [Puppeteer API](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagewaitfornavigationoptions) - * `getPageTimeout` config option to set maximum navigation time in milliseconds. Default is 30 seconds. - * `waitForNavigation` method added. Explicitly waits for navigation to be finished. + * `waitForNavigation` config option introduced. Possible options: `load`, `domcontentloaded`, `networkidle0`, `networkidle2`. See [Puppeteer API](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagewaitfornavigationoptions) + * `getPageTimeout` config option to set maximum navigation time in milliseconds. Default is 30 seconds. + * `waitForNavigation` method added. Explicitly waits for navigation to be finished. * [WebDriverIO][Protractor][Puppeteer][Nightmare] **Possible BC** `grabTextFrom` unified. Return a text for single matched element and an array of texts for multiple elements. * [Puppeteer]Fixed `resizeWindow` by **[sergejkaravajnij](https://github.com/sergejkaravajnij)** * [WebDriverIO][Protractor][Puppeteer][Nightmare] `waitForFunction` added. Waits for client-side JavaScript function to return true by **[GREENpoint](https://github.com/GREENpoint)**. @@ -3200,8 +3201,8 @@ Scenario('run in different browsers', (I) => { "parallel": { // run in 2 processes "chunks": 2, - // run all tests in chrome - "browsers": ["chrome"] + // run all tests in chrome + "browsers": ["chrome"] }, } ``` @@ -3251,45 +3252,45 @@ Scenario('this test should throw error', (I) => { ## 1.1.7 * Docker Image updateed. [See updated reference](https://codecept.io/docker/): - * codeceptjs package is mounted as `/codecept` insde container - * tests directory is expected to be mounted as `/tests` - * `codeceptjs` global runner added (symlink to `/codecept/bin/codecept.js`) + * codeceptjs package is mounted as `/codecept` insde container + * tests directory is expected to be mounted as `/tests` + * `codeceptjs` global runner added (symlink to `/codecept/bin/codecept.js`) * **[Protractor]** Functions added by **[reubenmiller](https://github.com/reubenmiller)**: - * `_locateCheckable (only available from other helpers)` - * `_locateClickable (only available from other helpers)` - * `_locateFields (only available from other helpers)` - * `acceptPopup` - * `cancelPopup` - * `dragAndDrop` - * `grabBrowserLogs` - * `grabCssPropertyFrom` - * `grabHTMLFrom` - * `grabNumberOfVisibleElements` - * `grabPageScrollPosition (new)` - * `rightClick` - * `scrollPageToBottom` - * `scrollPageToTop` - * `scrollTo` - * `seeAttributesOnElements` - * `seeCssPropertiesOnElements` - * `seeInPopup` - * `seeNumberOfVisibleElements` - * `switchTo` - * `waitForEnabled` - * `waitForValue` - * `waitInUrl` - * `waitNumberOfVisibleElements` - * `waitToHide` - * `waitUntil` - * `waitUrlEquals` + * `_locateCheckable (only available from other helpers)` + * `_locateClickable (only available from other helpers)` + * `_locateFields (only available from other helpers)` + * `acceptPopup` + * `cancelPopup` + * `dragAndDrop` + * `grabBrowserLogs` + * `grabCssPropertyFrom` + * `grabHTMLFrom` + * `grabNumberOfVisibleElements` + * `grabPageScrollPosition (new)` + * `rightClick` + * `scrollPageToBottom` + * `scrollPageToTop` + * `scrollTo` + * `seeAttributesOnElements` + * `seeCssPropertiesOnElements` + * `seeInPopup` + * `seeNumberOfVisibleElements` + * `switchTo` + * `waitForEnabled` + * `waitForValue` + * `waitInUrl` + * `waitNumberOfVisibleElements` + * `waitToHide` + * `waitUntil` + * `waitUrlEquals` * **[Nightmare]** added: - * `grabPageScrollPosition` (new) - * `seeNumberOfVisibleElements` - * `waitToHide` + * `grabPageScrollPosition` (new) + * `seeNumberOfVisibleElements` + * `waitToHide` * **[Puppeteer]** added: - * `grabPageScrollPosition` (new) + * `grabPageScrollPosition` (new) * **[WebDriverIO]** added" - * `grabPageScrollPosition` (new) + * `grabPageScrollPosition` (new) * **[Puppeteer]** Fixed running wait* functions without setting `sec` parameter. * [Puppeteer][Protractor] Fixed bug with I.click when using an object selector with the xpath property. By **[reubenmiller](https://github.com/reubenmiller)** * [WebDriverIO][Protractor][Nightmare][Puppeteer] Fixed I.switchTo(0) and I.scrollTo(100, 100) api inconsistencies between helpers. @@ -3311,13 +3312,13 @@ Scenario('this test should throw error', (I) => { * **[Puppeteer]** Added `waitForEnabled`, `waitForValue` and `waitNumberOfVisibleElements` methods by **[reubenmiller](https://github.com/reubenmiller)** * **[WebDriverIO]** Fixed `grabNumberOfVisibleElements` to return 0 when no visible elements are on page. By **[michaltrunek](https://github.com/michaltrunek)** * Helpers API improvements (by **[reubenmiller](https://github.com/reubenmiller)**) - * `_passed` hook runs after a test passed successfully - * `_failed` hook runs on a failed test + * `_passed` hook runs after a test passed successfully + * `_failed` hook runs on a failed test * Hooks API. New events added by **[reubenmiller](https://github.com/reubenmiller)**: - * `event.all.before` - executed before all tests - * `event.all.after` - executed after all tests - * `event.multiple.before` - executed before all processes in run-multiple - * `event.multiple.after` - executed after all processes in run-multiple + * `event.all.before` - executed before all tests + * `event.all.after` - executed after all tests + * `event.multiple.before` - executed before all processes in run-multiple + * `event.multiple.after` - executed after all processes in run-multiple * Multiple execution * Allow `AfterSuite` and `After` test hooks to be defined after the first Scenario. By **[reubenmiller](https://github.com/reubenmiller)** * **[Nightmare]** Prevent `I.amOnpage` navigation if the browser is already at the given url @@ -3381,46 +3382,46 @@ I.runOnAndroid(caps => caps.platformVersion >= 7, () => { ## 1.1.3 * **[Puppeteer]** +25 Functions added by **[reubenmiller](https://github.com/reubenmiller)** - * `_locateCheckable` - * `_locateClickable` - * `_locateFields` - * `closeOtherTabs` - * `dragAndDrop` - * `grabBrowserLogs` - * `grabCssPropertyFrom` - * `grabHTMLFrom` - * `grabNumberOfVisibleElements` - * `grabSource` - * `rightClick` - * `scrollPageToBottom` - * `scrollPageToTop` - * `scrollTo` - * `seeAttributesOnElements` - * `seeCssPropertiesOnElements` - * `seeInField` - * `seeNumberOfElements` - * `seeNumberOfVisibleElements` - * `seeTextEquals` - * `seeTitleEquals` - * `switchTo` - * `waitForInvisible` - * `waitInUrl` - * `waitUrlEquals` + * `_locateCheckable` + * `_locateClickable` + * `_locateFields` + * `closeOtherTabs` + * `dragAndDrop` + * `grabBrowserLogs` + * `grabCssPropertyFrom` + * `grabHTMLFrom` + * `grabNumberOfVisibleElements` + * `grabSource` + * `rightClick` + * `scrollPageToBottom` + * `scrollPageToTop` + * `scrollTo` + * `seeAttributesOnElements` + * `seeCssPropertiesOnElements` + * `seeInField` + * `seeNumberOfElements` + * `seeNumberOfVisibleElements` + * `seeTextEquals` + * `seeTitleEquals` + * `switchTo` + * `waitForInvisible` + * `waitInUrl` + * `waitUrlEquals` * **[Protractor]** +8 functions added by **[reubenmiller](https://github.com/reubenmiller)** - * `closeCurrentTab` - * `grabSource` - * `openNewTab` - * `seeNumberOfElements` - * `seeTextEquals` - * `seeTitleEquals` - * `switchToNextTab` - * `switchToPreviousTab` + * `closeCurrentTab` + * `grabSource` + * `openNewTab` + * `seeNumberOfElements` + * `seeTextEquals` + * `seeTitleEquals` + * `switchToNextTab` + * `switchToPreviousTab` * **[Nightmare]** `waitForInvisible` added by **[reubenmiller](https://github.com/reubenmiller)** * **[Puppeteer]** Printing console.log information in debug mode. * **[Nightmare]** Integrated with `nightmare-har-plugin` by mingfang. Added `enableHAR` option. Added HAR functions: - * `grabHAR` - * `saveHAR` - * `resetHAR` + * `grabHAR` + * `saveHAR` + * `resetHAR` * **[WebDriverIO]** Fixed execution stability for parallel requests with Chromedriver * **[WebDriverIO]** Fixed resizeWindow when resizing to 'maximize' by **[reubenmiller](https://github.com/reubenmiller)** * **[WebDriverIO]** Fixing resizing window to full screen when taking a screenshot by **[reubenmiller](https://github.com/reubenmiller)** @@ -3479,7 +3480,7 @@ I.dontSee('Email Address'); ```html - CodeceptJS is awesome + CodeceptJS is awesome ``` ↑ This element can be located with `~foobar` in WebDriverIO and Appium helpers. Thanks to **[flyskywhy](https://github.com/flyskywhy)** @@ -3599,35 +3600,35 @@ Next notable feature is **[SmartWait](http://codecept.io/acceptance/#smartwait)* * [WebDriverIO][SeleniumWebdriver] Fixed "windowSize": "maximize" for Chrome 59+ version [#560](https://github.com/codeceptjs/CodeceptJS/issues/560) by **[APshenkin](https://github.com/APshenkin)** * **[Nightmare]** Fixed restarting by **[APshenkin](https://github.com/APshenkin)** [#581](https://github.com/codeceptjs/CodeceptJS/issues/581) * **[WebDriverIO]** Methods added by **[APshenkin](https://github.com/APshenkin)**: - * [grabCssPropertyFrom](http://codecept.io/helpers/WebDriverIO/#grabcsspropertyfrom) - * [seeTitleEquals](http://codecept.io/helpers/WebDriverIO/#seetitleequals) - * [seeTextEquals](http://codecept.io/helpers/WebDriverIO/#seetextequals) - * [seeCssPropertiesOnElements](http://codecept.io/helpers/WebDriverIO/#seecsspropertiesonelements) - * [seeAttributesOnElements](http://codecept.io/helpers/WebDriverIO/#seeattributesonelements) - * [grabNumberOfVisibleElements](http://codecept.io/helpers/WebDriverIO/#grabnumberofvisibleelements) - * [waitInUrl](http://codecept.io/helpers/WebDriverIO/#waitinurl) - * [waitUrlEquals](http://codecept.io/helpers/WebDriverIO/#waiturlequals) - * [waitForValue](http://codecept.io/helpers/WebDriverIO/#waitforvalue) - * [waitNumberOfVisibleElements](http://codecept.io/helpers/WebDriverIO/#waitnumberofvisibleelements) - * [switchToNextTab](http://codecept.io/helpers/WebDriverIO/#switchtonexttab) - * [switchToPreviousTab](http://codecept.io/helpers/WebDriverIO/#switchtoprevioustab) - * [closeCurrentTab](http://codecept.io/helpers/WebDriverIO/#closecurrenttab) - * [openNewTab](http://codecept.io/helpers/WebDriverIO/#opennewtab) - * [refreshPage](http://codecept.io/helpers/WebDriverIO/#refreshpage) - * [scrollPageToBottom](http://codecept.io/helpers/WebDriverIO/#scrollpagetobottom) - * [scrollPageToTop](http://codecept.io/helpers/WebDriverIO/#scrollpagetotop) - * [grabBrowserLogs](http://codecept.io/helpers/WebDriverIO/#grabbrowserlogs) + * [grabCssPropertyFrom](http://codecept.io/helpers/WebDriverIO/#grabcsspropertyfrom) + * [seeTitleEquals](http://codecept.io/helpers/WebDriverIO/#seetitleequals) + * [seeTextEquals](http://codecept.io/helpers/WebDriverIO/#seetextequals) + * [seeCssPropertiesOnElements](http://codecept.io/helpers/WebDriverIO/#seecsspropertiesonelements) + * [seeAttributesOnElements](http://codecept.io/helpers/WebDriverIO/#seeattributesonelements) + * [grabNumberOfVisibleElements](http://codecept.io/helpers/WebDriverIO/#grabnumberofvisibleelements) + * [waitInUrl](http://codecept.io/helpers/WebDriverIO/#waitinurl) + * [waitUrlEquals](http://codecept.io/helpers/WebDriverIO/#waiturlequals) + * [waitForValue](http://codecept.io/helpers/WebDriverIO/#waitforvalue) + * [waitNumberOfVisibleElements](http://codecept.io/helpers/WebDriverIO/#waitnumberofvisibleelements) + * [switchToNextTab](http://codecept.io/helpers/WebDriverIO/#switchtonexttab) + * [switchToPreviousTab](http://codecept.io/helpers/WebDriverIO/#switchtoprevioustab) + * [closeCurrentTab](http://codecept.io/helpers/WebDriverIO/#closecurrenttab) + * [openNewTab](http://codecept.io/helpers/WebDriverIO/#opennewtab) + * [refreshPage](http://codecept.io/helpers/WebDriverIO/#refreshpage) + * [scrollPageToBottom](http://codecept.io/helpers/WebDriverIO/#scrollpagetobottom) + * [scrollPageToTop](http://codecept.io/helpers/WebDriverIO/#scrollpagetotop) + * [grabBrowserLogs](http://codecept.io/helpers/WebDriverIO/#grabbrowserlogs) * Use mkdirp to create output directory. [#592](https://github.com/codeceptjs/CodeceptJS/issues/592) by **[vkramskikh](https://github.com/vkramskikh)** * **[WebDriverIO]** Fixed `seeNumberOfVisibleElements` by **[BorisOsipov](https://github.com/BorisOsipov)** [#574](https://github.com/codeceptjs/CodeceptJS/issues/574) * Lots of fixes for promise chain by **[APshenkin](https://github.com/APshenkin)** [#568](https://github.com/codeceptjs/CodeceptJS/issues/568) - * Fix [#543](https://github.com/codeceptjs/CodeceptJS/issues/543)- After block not properly executed if Scenario fails - * Expected behavior in promise chains: `_beforeSuite` hooks from helpers -> `BeforeSuite` from test -> `_before` hooks from helpers -> `Before` from test - > Test steps -> `_failed` hooks from helpers (if test failed) -> `After` from test -> `_after` hooks from helpers -> `AfterSuite` from test -> `_afterSuite` hook from helpers. - * if during test we got errors from any hook (in test or in helper) - stop complete this suite and go to another - * if during test we got error from Selenium server - stop complete this suite and go to another - * [WebDriverIO][Protractor] if `restart` option is false - close all tabs expect one in `_after`. - * Complete `_after`, `_afterSuite` hooks even After/AfterSuite from test was failed - * Don't close browser between suites, when `restart` option is false. We should start browser only one time and close it only after all tests. - * Close tabs and clear local storage, if `keepCookies` flag is enabled + * Fix [#543](https://github.com/codeceptjs/CodeceptJS/issues/543)- After block not properly executed if Scenario fails + * Expected behavior in promise chains: `_beforeSuite` hooks from helpers -> `BeforeSuite` from test -> `_before` hooks from helpers -> `Before` from test - > Test steps -> `_failed` hooks from helpers (if test failed) -> `After` from test -> `_after` hooks from helpers -> `AfterSuite` from test -> `_afterSuite` hook from helpers. + * if during test we got errors from any hook (in test or in helper) - stop complete this suite and go to another + * if during test we got error from Selenium server - stop complete this suite and go to another + * [WebDriverIO][Protractor] if `restart` option is false - close all tabs expect one in `_after`. + * Complete `_after`, `_afterSuite` hooks even After/AfterSuite from test was failed + * Don't close browser between suites, when `restart` option is false. We should start browser only one time and close it only after all tests. + * Close tabs and clear local storage, if `keepCookies` flag is enabled * Fix TypeError when using babel-node or ts-node on node.js 7+ [#586](https://github.com/codeceptjs/CodeceptJS/issues/586) by **[vkramskikh](https://github.com/vkramskikh)** * **[Nightmare]** fixed usage of `_locate` @@ -3661,8 +3662,8 @@ const actor = require('codeceptjs').actor; * run command to create `output` directory if it doesn't exist * **[Protractor]** fixed loading globally installed Protractor * run-multiple command improvements: - * create output directories for each process - * print process ids in output + * create output directories for each process + * print process ids in output ## 0.6.1 @@ -3695,13 +3696,13 @@ codeceptjs run users_test.js -c tests * **[WebDriverIO]** added `seeNumberOfVisibleElements` method by **[elarouche](https://github.com/elarouche)**. * Exit with non-zero code if init throws an error by **[rincedd](https://github.com/rincedd)** * New guides published: - * [Installation](http://codecept.io/installation/) - * [Hooks](http://codecept.io/hooks/) - * [Advanced Usage](http://codecept.io/advanced/) + * [Installation](http://codecept.io/installation/) + * [Hooks](http://codecept.io/hooks/) + * [Advanced Usage](http://codecept.io/advanced/) * Meta packages published: - * [codecept-webdriverio](https://www.npmjs.com/package/codecept-webdriverio) - * [codecept-protractor](https://www.npmjs.com/package/codecept-protractor) - * [codecept-nightmare](https://www.npmjs.com/package/codecept-nightmare) + * [codecept-webdriverio](https://www.npmjs.com/package/codecept-webdriverio) + * [codecept-protractor](https://www.npmjs.com/package/codecept-protractor) + * [codecept-nightmare](https://www.npmjs.com/package/codecept-nightmare) ## 0.5.1 @@ -3742,7 +3743,7 @@ _before() { } _afterStep() { - if (this.err) throw new Error('Browser JS error '+this.err); + if (this.err) throw new Error('Browser JS error '+this.err); } ``` @@ -3757,7 +3758,7 @@ _before() { } _afterStep() { - if (this.err) throw new Error('Browser JS error '+this.err); + if (this.err) throw new Error('Browser JS error '+this.err); } ``` From 12a8e4d68455ed71565d79db7ff623af1251acb6 Mon Sep 17 00:00:00 2001 From: Thomas Hohn Date: Wed, 13 Nov 2024 15:27:37 +0100 Subject: [PATCH 14/16] Second attempt --- docs/changelog.md | 268 +++++++++++++++++++++++----------------------- 1 file changed, 134 insertions(+), 134 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index 11305e7a9..d53d259f8 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -55,11 +55,11 @@ I.flushSoftAssertions() // Throws an error if any soft assertions have failed. T helpers: { REST: { endpoint: 'http://site.com/api', - prettyPrintJson: true, - httpAgent: { - ca: fs.readFileSync(__dirname + '/path/to/ca.pem'), - rejectUnauthorized: false, - keepAlive: true + prettyPrintJson: true, + httpAgent: { + ca: fs.readFileSync(__dirname + '/path/to/ca.pem'), + rejectUnauthorized: false, + keepAlive: true } } } @@ -323,23 +323,23 @@ Examples: ```js // recording traffics and verify the traffic -I.startRecordingTraffic(); -I.amOnPage('https://codecept.io/'); -I.seeTraffic({ name: 'traffics', url: 'https://codecept.io/img/companies/BC_LogoScreen_C.jpg' }); + I.startRecordingTraffic(); + I.amOnPage('https://codecept.io/'); + I.seeTraffic({ name: 'traffics', url: 'https://codecept.io/img/companies/BC_LogoScreen_C.jpg' }); ``` ```js // check the traffic with advanced params -I.amOnPage('https://openai.com/blog/chatgpt'); -I.startRecordingTraffic(); -I.seeTraffic({ - name: 'sentry event', - url: 'https://images.openai.com/blob/cf717bdb-0c8c-428a-b82b-3c3add87a600', - parameters: { - width: '1919', - height: '1138', - }, -}); + I.amOnPage('https://openai.com/blog/chatgpt'); + I.startRecordingTraffic(); + I.seeTraffic({ + name: 'sentry event', + url: 'https://images.openai.com/blob/cf717bdb-0c8c-428a-b82b-3c3add87a600', + parameters: { + width: '1919', + height: '1138', + }, + }); ``` * Introduce the playwright locator: `_react`, `_vue`, `data-testid` attribute. See [#4255](https://github.com/codeceptjs/CodeceptJS/issues/4255) by **[KobeNguyenT](https://github.com/KobeNguyenT)** @@ -482,23 +482,23 @@ Examples: ```js // recording traffics and verify the traffic -I.startRecordingTraffic(); -I.amOnPage('https://codecept.io/'); -I.seeTraffic({ name: 'traffics', url: 'https://codecept.io/img/companies/BC_LogoScreen_C.jpg' }); + I.startRecordingTraffic(); + I.amOnPage('https://codecept.io/'); + I.seeTraffic({ name: 'traffics', url: 'https://codecept.io/img/companies/BC_LogoScreen_C.jpg' }); ``` ```js // check the traffic with advanced params -I.amOnPage('https://openai.com/blog/chatgpt'); -I.startRecordingTraffic(); -I.seeTraffic({ - name: 'sentry event', - url: 'https://images.openai.com/blob/cf717bdb-0c8c-428a-b82b-3c3add87a600', - parameters: { - width: '1919', - height: '1138', - }, -}); + I.amOnPage('https://openai.com/blog/chatgpt'); + I.startRecordingTraffic(); + I.seeTraffic({ + name: 'sentry event', + url: 'https://images.openai.com/blob/cf717bdb-0c8c-428a-b82b-3c3add87a600', + parameters: { + width: '1919', + height: '1138', + }, + }); ``` * feat(webapi): add waitForCookie ([#4169](https://github.com/codeceptjs/CodeceptJS/issues/4169)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** Waits for the specified cookie in the cookies. @@ -546,18 +546,18 @@ Example: ```js { - helpers: { - WebDriver : { - smartWait: 5000, - browser: "chrome", - restart: false, - windowSize: "maximize", - timeouts: { - "script": 60000, - "page load": 10000 - } - } - } + helpers: { + WebDriver : { + smartWait: 5000, + browser: "chrome", + restart: false, + windowSize: "maximize", + timeouts: { + "script": 60000, + "page load": 10000 + } + } + } } ``` @@ -566,19 +566,19 @@ For example: ```js { - helpers: { - WebDriver : { - smartWait: 5000, - browser: "chrome", - browserVersion: '116.0.5793.0', // or 'stable', 'beta', 'dev' or 'canary' - restart: false, - windowSize: "maximize", - timeouts: { - "script": 60000, - "page load": 10000 - } - } - } + helpers: { + WebDriver : { + smartWait: 5000, + browser: "chrome", + browserVersion: '116.0.5793.0', // or 'stable', 'beta', 'dev' or 'canary' + restart: false, + windowSize: "maximize", + timeouts: { + "script": 60000, + "page load": 10000 + } + } + } } ``` * feat: wdio with devtools protocol ([#4105](https://github.com/codeceptjs/CodeceptJS/issues/4105)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** @@ -587,18 +587,18 @@ Running with devtools protocol ```js { - helpers: { - WebDriver : { - url: "http://localhost", - browser: "chrome", - devtoolsProtocol: true, - desiredCapabilities: { - chromeOptions: { - args: [ "--headless", "--disable-gpu", "--no-sandbox" ] - } - } - } - } + helpers: { + WebDriver : { + url: "http://localhost", + browser: "chrome", + devtoolsProtocol: true, + desiredCapabilities: { + chromeOptions: { + args: [ "--headless", "--disable-gpu", "--no-sandbox" ] + } + } + } + } } ``` * feat: add a locator builder method withTextEquals() ([#4100](https://github.com/codeceptjs/CodeceptJS/issues/4100)) - by **[mirao](https://github.com/mirao)** @@ -659,9 +659,9 @@ Updated ```js Scenario('Verify getting list of users', async () => { - let res = await I.getUserPerPage(2); - res.data = []; // this line causes the issue - await I.expectEqual(res.data.data[0].id, 7); +let res = await I.getUserPerPage(2); +res.data = []; // this line causes the issue +await I.expectEqual(res.data.data[0].id, 7); }); ``` at this time, res.data.data[0].id would throw undefined error and somehow the test is missing all its steps. @@ -679,14 +679,14 @@ Plugins: screenshotOnFail, tryTo, retryFailedStep, retryTo, eachElement Repro -- **[1]** Starting recording promises Timeouts: - › **[Session]** Starting singleton browser session +› **[Session]** Starting singleton browser session Reproduce issue I am on page "https://example.com" › [Browser:Error] Failed to load resource: the server responded with a status of 404 () › [New Context] {} user1: I am on page "https://example.com" user1: I execute script () => { - return { width: window.screen.width, height: window.screen.height }; +return { width: window.screen.width, height: window.screen.height }; } sessionScreen is {"width":375,"height":667} ✔ OK in 1890ms @@ -1308,25 +1308,25 @@ await I.seeInField('checkbox[]', secret('see test three')); * Fix for error in using `all` with `run-workers` ([#3805](https://github.com/codeceptjs/CodeceptJS/issues/3805)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** ```js helpers: { - Playwright: { - url: 'https://github.com', + Playwright: { + url: 'https://github.com', show: false, browser: 'chromium', waitForNavigation: 'load', waitForTimeout: 30_000, trace: true, keepTraceForPassedTests: true + }, }, -}, -multiple: { - profile1: { - browsers: [ - { - browser: "chromium", - } - ] + multiple: { + profile1: { + browsers: [ + { + browser: "chromium", + } + ] + }, }, -}, ``` * Highlight elements issues ([#3779](https://github.com/codeceptjs/CodeceptJS/issues/3779)) ([#3778](https://github.com/codeceptjs/CodeceptJS/issues/3778)) - by **[philkas](https://github.com/philkas)** * Support ` ` symbol in `I.see` method ([#3815](https://github.com/codeceptjs/CodeceptJS/issues/3815)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** @@ -1365,13 +1365,13 @@ exports.config = { ```js const traffics = await I.grabRecordedNetworkTraffics(); -expect(traffics[0].url).to.equal('https://reqres.in/api/comments/1'); -expect(traffics[0].response.status).to.equal(200); -expect(traffics[0].response.body).to.contain({ name: 'this was mocked' }); + expect(traffics[0].url).to.equal('https://reqres.in/api/comments/1'); + expect(traffics[0].response.status).to.equal(200); + expect(traffics[0].response.body).to.contain({ name: 'this was mocked' }); -expect(traffics[1].url).to.equal('https://reqres.in/api/comments/1'); -expect(traffics[1].response.status).to.equal(200); -expect(traffics[1].response.body).to.contain({ name: 'this was another mocked' }); + expect(traffics[1].url).to.equal('https://reqres.in/api/comments/1'); + expect(traffics[1].response.status).to.equal(200); + expect(traffics[1].response.body).to.contain({ name: 'this was another mocked' }); ``` * Grab metrics ([#3809](https://github.com/codeceptjs/CodeceptJS/issues/3809)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** @@ -1476,32 +1476,32 @@ Examples: ```js // recording traffics and verify the traffic -await I.startRecordingTraffic(); -I.amOnPage('https://codecept.io/'); -await I.seeTraffic({ name: 'traffics', url: 'https://codecept.io/img/companies/BC_LogoScreen_C.jpg' }); + await I.startRecordingTraffic(); + I.amOnPage('https://codecept.io/'); + await I.seeTraffic({ name: 'traffics', url: 'https://codecept.io/img/companies/BC_LogoScreen_C.jpg' }); ``` ```js // block the traffic -I.blockTraffic('https://reqres.in/api/comments/*'); -await I.amOnPage('/form/fetch_call'); -await I.startRecordingTraffic(); -await I.click('GET COMMENTS'); -await I.see('Can not load data!'); + I.blockTraffic('https://reqres.in/api/comments/*'); + await I.amOnPage('/form/fetch_call'); + await I.startRecordingTraffic(); + await I.click('GET COMMENTS'); + await I.see('Can not load data!'); ``` ```js // check the traffic with advanced params -I.amOnPage('https://openai.com/blog/chatgpt'); -await I.startRecordingTraffic(); -await I.seeTraffic({ - name: 'sentry event', - url: 'https://images.openai.com/blob/cf717bdb-0c8c-428a-b82b-3c3add87a600', - parameters: { - width: '1919', - height: '1138', - }, -}); + I.amOnPage('https://openai.com/blog/chatgpt'); + await I.startRecordingTraffic(); + await I.seeTraffic({ + name: 'sentry event', + url: 'https://images.openai.com/blob/cf717bdb-0c8c-428a-b82b-3c3add87a600', + parameters: { + width: '1919', + height: '1138', + }, + }); ``` 🐛 Bugfix @@ -1624,13 +1624,13 @@ Feature('flaky Before & BeforeSuite', { retryBefore: 2, retryBeforeSuite: 3 }) retry: [ { // enable this config only for flaky tests - grep: '@flaky', + grep: '@flaky', Before: 3 // retry Before 3 times Scenario: 3 // retry Scenario 3 times - }, + }, { // retry less when running slow tests - grep: '@slow' + grep: '@slow' Scenario: 1 Before: 1 }, { @@ -1772,11 +1772,11 @@ I.sendPostRequest('/auth', secret({ name: 'jon', password: '123456' }, 'password ```js plugins: { - customLocator: { - enabled: true, - prefix: '$', - attribute: ['data-qa', 'data-test'], - } + customLocator: { + enabled: true, + prefix: '$', + attribute: ['data-qa', 'data-test'], + } } ``` * [retryTo plugin] Fixed [#3147](https://github.com/codeceptjs/CodeceptJS/issues/3147) using `pollInterval` option. See [#3351](https://github.com/codeceptjs/CodeceptJS/issues/3351) by **[cyonkee](https://github.com/cyonkee)** @@ -1826,9 +1826,9 @@ npx codeceptjs run test-dir/*" helpers: { Playwright : { url: "http://localhost", - colorScheme: "dark", + colorScheme: "dark", } -} + } ``` @@ -1983,11 +1983,11 @@ const { DataTableArgument } = require('codeceptjs'); //... Given('I have an employee card', (table) => { const dataTableArgument = new DataTableArgument(table); - const hashes = dataTableArgument.hashes(); + const hashes = dataTableArgument.hashes(); // hashes = [{ name: 'Harry', surname: 'Potter', position: 'Seeker' }]; const rows = dataTableArgument.rows(); // rows = [['Harry', 'Potter', Seeker]]; -} + } ``` See updated [BDD section](https://codecept.io/bdd/) for more API options. Thanks to **[EgorBodnar](https://github.com/EgorBodnar)** @@ -2265,12 +2265,12 @@ Read changelog to learn more about version 👇 Example: ```ts const psp = wd.grabPageScrollPosition() // $ExpectType Promise -psp.then( - result => { - result.x // $ExpectType number - result.y // $ExpectType number - } -) + psp.then( + result => { + result.x // $ExpectType number + result.y // $ExpectType number + } + ) ``` * And last: Reducing package size from 3.3Mb to 2.0Mb @@ -2294,8 +2294,8 @@ MyPage.hasFiles('first arg', 'second arg'); // OUTPUT: MyPage: hasFile "First arg", "Second arg" -I see file "codecept.js" -I see file "codecept.po.json" + I see file "codecept.js" + I see file "codecept.po.json" ``` * Introduced official [TypeScript boilerplate](https://github.com/codeceptjs/typescript-boilerplate). Started by **[Vorobeyko](https://github.com/Vorobeyko)**. @@ -2854,8 +2854,8 @@ Do you want to improve this project? [Learn more about sponsorin CodeceptJS Use it with `FileSystem` helper to test availability of a file: ```js const fileName = await I.downloadFile('a.file-link'); -I.amInPath('output'); -I.seeFile(fileName); + I.amInPath('output'); + I.seeFile(fileName); ``` > Actions `amInPath` and `seeFile` are taken from [FileSystem](https://codecept.io/helpers/FileSystem) helper @@ -3201,8 +3201,8 @@ Scenario('run in different browsers', (I) => { "parallel": { // run in 2 processes "chunks": 2, - // run all tests in chrome - "browsers": ["chrome"] + // run all tests in chrome + "browsers": ["chrome"] }, } ``` @@ -3480,7 +3480,7 @@ I.dontSee('Email Address'); ```html - CodeceptJS is awesome + CodeceptJS is awesome ``` ↑ This element can be located with `~foobar` in WebDriverIO and Appium helpers. Thanks to **[flyskywhy](https://github.com/flyskywhy)** @@ -3743,7 +3743,7 @@ _before() { } _afterStep() { - if (this.err) throw new Error('Browser JS error '+this.err); + if (this.err) throw new Error('Browser JS error '+this.err); } ``` From e7dd9ae0eafe7475fa13d262d20f60c10b01ce4c Mon Sep 17 00:00:00 2001 From: Thomas Hohn Date: Wed, 13 Nov 2024 15:31:33 +0100 Subject: [PATCH 15/16] Use correct hash --- docs/changelog.md | 488 ++++++++++++++++++++-------------------------- 1 file changed, 213 insertions(+), 275 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index d53d259f8..d028f8a18 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -7,68 +7,6 @@ layout: Section # Releases -## 3.6.6 - -❤️ Thanks all to those who contributed to make this release! ❤️ - -🛩️ *Features* -* feat(locator): add withAttrEndsWith, withAttrStartsWith, withAttrContains ([#4334](https://github.com/codeceptjs/CodeceptJS/issues/4334)) - by **[Maksym-Artemenko](https://github.com/Maksym-Artemenko)** -* feat: soft assert ([#4473](https://github.com/codeceptjs/CodeceptJS/issues/4473)) - by **[kobenguyent](https://github.com/kobenguyent)** - * Soft assert - -Zero-configuration when paired with other helpers like REST, Playwright: - -```js -// inside codecept.conf.js -{ - helpers: { - Playwright: {...}, - SoftExpectHelper: {}, - } -} -``` - -```js -// in scenario -I.softExpectEqual('a', 'b') -I.flushSoftAssertions() // Throws an error if any soft assertions have failed. The error message contains all the accumulated failures. -``` -* feat(cli): print failed hooks ([#4476](https://github.com/codeceptjs/CodeceptJS/issues/4476)) - by **[kobenguyent](https://github.com/kobenguyent)** - * run command - ![Screenshot 2024-09-02 at 15 25 20](https://github.com/user-attachments/assets/625c6b54-03f6-41c6-9d0c-cd699582404a) - - * run workers command - ![Screenshot 2024-09-02 at 15 24 53](https://github.com/user-attachments/assets/efff0312-1229-44b6-a94f-c9b9370b9a64) - -🐛 *Bug Fixes* -* fix(AI): minor AI improvements - by **[DavertMik](https://github.com/DavertMik)** -* fix(AI): add missing await in AI.js ([#4486](https://github.com/codeceptjs/CodeceptJS/issues/4486)) - by **[tomaculum](https://github.com/tomaculum)** -* fix(playwright): no async save video page ([#4472](https://github.com/codeceptjs/CodeceptJS/issues/4472)) - by **[kobenguyent](https://github.com/kobenguyent)** -* fix(rest): httpAgent condition ([#4484](https://github.com/codeceptjs/CodeceptJS/issues/4484)) - by **[kobenguyent](https://github.com/kobenguyent)** -* fix: DataCloneError error when `I.executeScript` command is used with `run-workers` ([#4483](https://github.com/codeceptjs/CodeceptJS/issues/4483)) - by **[code4muktesh](https://github.com/code4muktesh)** -* fix: no error thrown from rerun script ([#4494](https://github.com/codeceptjs/CodeceptJS/issues/4494)) - by **[lin-brian-l](https://github.com/lin-brian-l)** - - -```js -// fix the validation of httpAgent config. we could now pass ca, instead of key/cert. -{ - helpers: { - REST: { - endpoint: 'http://site.com/api', - prettyPrintJson: true, - httpAgent: { - ca: fs.readFileSync(__dirname + '/path/to/ca.pem'), - rejectUnauthorized: false, - keepAlive: true - } - } - } -} -``` - -📖 *Documentation* -* doc(AI): minor AI improvements - by **[DavertMik](https://github.com/DavertMik)** - ## 3.6.5 ❤️ Thanks all to those who contributed to make this release! ❤️ @@ -222,7 +160,7 @@ locate('div').withClassAttr('text'); ``` * fix(playwright): set the record video resolution ([#4311](https://github.com/codeceptjs/CodeceptJS/issues/4311)) - by **[KobeNguyent](https://github.com/KobeNguyent)** - You could now set the recording video resolution +You could now set the recording video resolution ``` url: siteUrl, windowSize: '300x500', @@ -470,7 +408,7 @@ PUT tests -- /Users/tDesktop/projects/codeceptjs-rest-demo/src/PUT_test.ts -- 4 * feat: mock server helper ([#4155](https://github.com/codeceptjs/CodeceptJS/issues/4155)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** ![Screenshot 2024-01-25 at 13 47 59](https://github.com/codeceptjs/CodeceptJS/assets/7845001/8fe7aacf-f1c9-4d7e-89a6-3748b3ccb26c) * feat(webdriver): network traffics manipulation ([#4166](https://github.com/codeceptjs/CodeceptJS/issues/4166)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** - **[Webdriver]** Added commands to check network traffics - supported only with devtoolsProtocol + **[Webdriver]** Added commands to check network traffics - supported only with devtoolsProtocol * `startRecordingTraffic` * `grabRecordedNetworkTraffics` * `flushNetworkTraffics` @@ -706,7 +644,7 @@ OK | 1 passed // 4s deprecate some JSON Wire Protocol commands: `grabGeoLocation`, `setGeoLocation` * fix: cannot locate complicated locator ([#4101](https://github.com/codeceptjs/CodeceptJS/issues/4101)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** - + Locator issue due to the lib changes ``` @@ -831,7 +769,7 @@ Fixed this error: locator.isVisible: Unexpected token "s" while parsing selector ":has-text('Were you able to resolve the resident's issue?') >> nth=0" at Playwright.waitForText (node_modules\codeceptjs\lib\helper\Playwright.js:2584:79) ``` -* fix: move to sha256 ([#4038](https://github.com/codeceptjs/CodeceptJS/issues/4038)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** +* fix: move to sha256 ([#4038](https://github.com/codeceptjs/CodeceptJS/issues/4038)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** * fix: respect retries from retryfailedstep plugin in helpers ([#4028](https://github.com/codeceptjs/CodeceptJS/issues/4028)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** ``` Currently inside the _before() of helpers for example Playwright, the retries is set there, however, when retryFailedStep plugin is enabled, the retries of recorder is still using the value from _before() not the value from retryFailedStep plugin. @@ -1302,10 +1240,10 @@ await I.seeInField('checkbox[]', secret('see test three')); ## 3.5.4 🐛 Bug Fixes: -* **[Playwright]** When passing `userDataDir`, it throws error after test execution ([#3814](https://github.com/codeceptjs/CodeceptJS/issues/3814)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** -* [CodeceptJS-CLI] Improve command to generate types ([#3788](https://github.com/codeceptjs/CodeceptJS/issues/3788)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** -* Heal plugin fix ([#3820](https://github.com/codeceptjs/CodeceptJS/issues/3820)) - by **[davert](https://github.com/davert)** -* Fix for error in using `all` with `run-workers` ([#3805](https://github.com/codeceptjs/CodeceptJS/issues/3805)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** + * **[Playwright]** When passing `userDataDir`, it throws error after test execution ([#3814](https://github.com/codeceptjs/CodeceptJS/issues/3814)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** + * [CodeceptJS-CLI] Improve command to generate types ([#3788](https://github.com/codeceptjs/CodeceptJS/issues/3788)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** + * Heal plugin fix ([#3820](https://github.com/codeceptjs/CodeceptJS/issues/3820)) - by **[davert](https://github.com/davert)** + * Fix for error in using `all` with `run-workers` ([#3805](https://github.com/codeceptjs/CodeceptJS/issues/3805)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** ```js helpers: { Playwright: { @@ -1328,8 +1266,8 @@ await I.seeInField('checkbox[]', secret('see test three')); }, }, ``` -* Highlight elements issues ([#3779](https://github.com/codeceptjs/CodeceptJS/issues/3779)) ([#3778](https://github.com/codeceptjs/CodeceptJS/issues/3778)) - by **[philkas](https://github.com/philkas)** -* Support ` ` symbol in `I.see` method ([#3815](https://github.com/codeceptjs/CodeceptJS/issues/3815)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** + * Highlight elements issues ([#3779](https://github.com/codeceptjs/CodeceptJS/issues/3779)) ([#3778](https://github.com/codeceptjs/CodeceptJS/issues/3778)) - by **[philkas](https://github.com/philkas)** + * Support ` ` symbol in `I.see` method ([#3815](https://github.com/codeceptjs/CodeceptJS/issues/3815)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** ```js // HTML code uses   instead of space @@ -1339,7 +1277,7 @@ I.see("My Text!") // this test would work with both   and space ``` 📖 Documentation -* Improve the configuration of electron testing when the app is build with electron-forge ([#3802](https://github.com/codeceptjs/CodeceptJS/issues/3802)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** + * Improve the configuration of electron testing when the app is build with electron-forge ([#3802](https://github.com/codeceptjs/CodeceptJS/issues/3802)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** ```js const path = require("path"); @@ -1361,7 +1299,7 @@ exports.config = { 🛩️ Features #### **[Playwright]** new features and improvements -* Parse the response in recording network steps ([#3771](https://github.com/codeceptjs/CodeceptJS/issues/3771)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** + * Parse the response in recording network steps ([#3771](https://github.com/codeceptjs/CodeceptJS/issues/3771)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** ```js const traffics = await I.grabRecordedNetworkTraffics(); @@ -1373,7 +1311,7 @@ exports.config = { expect(traffics[1].response.status).to.equal(200); expect(traffics[1].response.body).to.contain({ name: 'this was another mocked' }); ``` -* Grab metrics ([#3809](https://github.com/codeceptjs/CodeceptJS/issues/3809)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** + * Grab metrics ([#3809](https://github.com/codeceptjs/CodeceptJS/issues/3809)) - by **[KobeNguyenT](https://github.com/KobeNguyenT)** ```js const metrics = await I.grabMetrics(); @@ -1523,7 +1461,7 @@ Examples: 🛩️ Features -* [Puppeteer][WebDriver][TestCafe] Added methods by **[KobeNguyenT](https://github.com/KobeNguyenT)** in [#3737](https://github.com/codeceptjs/CodeceptJS/issues/3737) +* [Puppeteer][WebDriver][TestCafe] Added methods by **[KobeNguyenT](https://github.com/KobeNguyenT)** in [#3737](https://github.com/codeceptjs/CodeceptJS/issues/3737) * `blur` * `focus` * Improved BDD output to print steps without `I.` commands` by **[davertmik](https://github.com/davertmik)** [#3739](https://github.com/codeceptjs/CodeceptJS/issues/3739) @@ -1536,7 +1474,7 @@ Examples: 📖 Documentation * Fixed Playwright docs by **[Horsty80](https://github.com/Horsty80)** -* Fixed ai docs by **[ngraf](https://github.com/ngraf)** +* Fixed ai docs by **[ngraf](https://github.com/ngraf)** * Various fixes by **[KobeNguyenT](https://github.com/KobeNguyenT)** ## 3.5.0 @@ -1544,7 +1482,7 @@ Examples: 🛩️ Features - **🪄 [AI Powered Test Automation](/ai)** - use OpenAI as a copilot for test automation. [#3713](https://github.com/codeceptjs/CodeceptJS/issues/3713) By **[davertmik](https://github.com/davertmik)** - ![](https://user-images.githubusercontent.com/220264/250418764-c382709a-3ccb-4eb5-b6bc-538f3b3b3d35.png) +![](https://user-images.githubusercontent.com/220264/250418764-c382709a-3ccb-4eb5-b6bc-538f3b3b3d35.png) * [AI guide](/ai) added * added support for OpenAI in `pause()` * added [`heal` plugin](/plugins#heal) for self-healing tests @@ -1652,7 +1590,7 @@ timeout: [ ``` * JsDoc: Removed promise from `I.say`. See [#3535](https://github.com/codeceptjs/CodeceptJS/issues/3535) by **[danielrentz](https://github.com/danielrentz)** -* **[Playwright]** `handleDownloads` requires now a filename param. See [#3511](https://github.com/codeceptjs/CodeceptJS/issues/3511) by **[PeterNgTr](https://github.com/PeterNgTr)** +* **[Playwright]** `handleDownloads` requires now a filename param. See [#3511](https://github.com/codeceptjs/CodeceptJS/issues/3511) by **[PeterNgTr](https://github.com/PeterNgTr)** * **[WebDriver]** Added support for v8, removed support for webdriverio v5 and lower. See [#3578](https://github.com/codeceptjs/CodeceptJS/issues/3578) by **[PeterNgTr](https://github.com/PeterNgTr)** @@ -1661,20 +1599,20 @@ timeout: [ 🛩️ Features * **Promise-based typings** for TypeScript definitions in [#3465](https://github.com/codeceptjs/CodeceptJS/issues/3465) by **[nlespiaucq](https://github.com/nlespiaucq)**. If you use TypeScript or use linters [check how it may be useful to you](https://bit.ly/3XIMq6n). -* **Translation** improved to use [custom vocabulary](https://codecept.io/translation/). +* **Translation** improved to use [custom vocabulary](https://codecept.io/translation/). * **[Playwright]** Added methods in [#3398](https://github.com/codeceptjs/CodeceptJS/issues/3398) by **[mirao](https://github.com/mirao)** * `restartBrowser` - to restart a browser (with different config) * `_createContextPage` - to create a new browser context with a page from a helper -* Added [Cucumber custom types](/bdd#custom-types) for BDD in [#3435](https://github.com/codeceptjs/CodeceptJS/issues/3435) by **[Likstern](https://github.com/Likstern)** -* Propose using JSONResponse helper when initializing project for API testing. [#3455](https://github.com/codeceptjs/CodeceptJS/issues/3455) by **[PeterNgTr](https://github.com/PeterNgTr)** +* Added [Cucumber custom types](/bdd#custom-types) for BDD in [#3435](https://github.com/codeceptjs/CodeceptJS/issues/3435) by **[Likstern](https://github.com/Likstern)** +* Propose using JSONResponse helper when initializing project for API testing. [#3455](https://github.com/codeceptjs/CodeceptJS/issues/3455) by **[PeterNgTr](https://github.com/PeterNgTr)** * When translation enabled, generate tests using localized aliases. By **[davertmik](https://github.com/davertmik)** -* **[Appium]** Added `checkIfAppIsInstalled` in [#3507](https://github.com/codeceptjs/CodeceptJS/issues/3507) by **[PeterNgTr](https://github.com/PeterNgTr)** +* **[Appium]** Added `checkIfAppIsInstalled` in [#3507](https://github.com/codeceptjs/CodeceptJS/issues/3507) by **[PeterNgTr](https://github.com/PeterNgTr)** 🐛 Bugfixes * Fixed [#3462](https://github.com/codeceptjs/CodeceptJS/issues/3462) `TypeError: Cannot read properties of undefined (reading 'setStatus')` by **[dwentland24](https://github.com/dwentland24)** in [#3438](https://github.com/codeceptjs/CodeceptJS/issues/3438) -* Fixed creating steps file for TypeScript setup [#3459](https://github.com/codeceptjs/CodeceptJS/issues/3459) by **[PeterNgTr](https://github.com/PeterNgTr)** -* Fixed issue of after all event in `run-rerun` command after complete execution [#3464](https://github.com/codeceptjs/CodeceptJS/issues/3464) by **[jain-neeeraj](https://github.com/jain-neeeraj)** +* Fixed creating steps file for TypeScript setup [#3459](https://github.com/codeceptjs/CodeceptJS/issues/3459) by **[PeterNgTr](https://github.com/PeterNgTr)** +* Fixed issue of after all event in `run-rerun` command after complete execution [#3464](https://github.com/codeceptjs/CodeceptJS/issues/3464) by **[jain-neeeraj](https://github.com/jain-neeeraj)** * [Playwright][WebDriver][Appium] Do not change `waitForTimeout` value on validation. See [#3478](https://github.com/codeceptjs/CodeceptJS/issues/3478) by **[pmajewski24](https://github.com/pmajewski24)**. Fixes [#2589](https://github.com/codeceptjs/CodeceptJS/issues/2589) * [Playwright][WebDriver][Protractor][Puppeteer][TestCafe] Fixes `Element "{null: undefined}" was not found` and `element ([object Object]) still not present` messages when using object locators. See [#3501](https://github.com/codeceptjs/CodeceptJS/issues/3501) and [#3502](https://github.com/codeceptjs/CodeceptJS/issues/3502) by **[pmajewski24](https://github.com/pmajewski24)** * **[Playwright]** Improved file names when downloading file in [#3449](https://github.com/codeceptjs/CodeceptJS/issues/3449) by **[PeterNgTr](https://github.com/PeterNgTr)**. Fixes [#3412](https://github.com/codeceptjs/CodeceptJS/issues/3412) and [#3409](https://github.com/codeceptjs/CodeceptJS/issues/3409) @@ -1682,7 +1620,7 @@ timeout: [ * **[Playwright]** Using system-native path separator when saving artifacts in [#3460](https://github.com/codeceptjs/CodeceptJS/issues/3460) by **[PeterNgTr](https://github.com/PeterNgTr)** * **[Playwright]** Saving videos and traces from multiple sessions in [#3505](https://github.com/codeceptjs/CodeceptJS/issues/3505) by **[davertmik](https://github.com/davertmik)** * **[Playwright]** Fixed `amOnPage` to navigate to `about:blank` by **[zaxoavoki](https://github.com/zaxoavoki)** in [#3470](https://github.com/codeceptjs/CodeceptJS/issues/3470) Fixes [#2311](https://github.com/codeceptjs/CodeceptJS/issues/2311) -* Various typing improvements by **[AWolf81](https://github.com/AWolf81)** **[PeterNgTr](https://github.com/PeterNgTr)** **[mirao](https://github.com/mirao)** +* Various typing improvements by **[AWolf81](https://github.com/AWolf81)** **[PeterNgTr](https://github.com/PeterNgTr)** **[mirao](https://github.com/mirao)** 📖 Documentation @@ -1715,7 +1653,7 @@ const response = await I.sendPostRequest('/user', secretData); * fix(playwright) - video name and missing type by **[PeterNgTr](https://github.com/PeterNgTr)** in [#3430](https://github.com/codeceptjs/CodeceptJS/issues/3430) * fix for expected type of "bootstrap", "teardown", "bootstrapAll" and "teardownAll" by **[ngraf](https://github.com/ngraf)** in [#3424](https://github.com/codeceptjs/CodeceptJS/issues/3424) * Improve generate pageobject `gpo` command to work with TypeScript by **[PeterNgTr](https://github.com/PeterNgTr)** in [#3411](https://github.com/codeceptjs/CodeceptJS/issues/3411) -* Fixed dry-run to always return 0 code and exit +* Fixed dry-run to always return 0 code and exit * Added minimal version notice for NodeJS >= 12 * fix(utils): remove . of test title to avoid confusion by **[PeterNgTr](https://github.com/PeterNgTr)** in [#3431](https://github.com/codeceptjs/CodeceptJS/issues/3431) @@ -1723,7 +1661,7 @@ const response = await I.sendPostRequest('/user', secretData); 🛩️ Features -* Added **TypeScript types for CodeceptJS config**. +* Added **TypeScript types for CodeceptJS config**. Update `codecept.conf.js` to get intellisense when writing config file: @@ -1744,17 +1682,17 @@ exports.config = { 🐛 Bugfixes -* **[Puppeteer]** Fixed support for Puppeteer > 14.4 by **[PeterNgTr](https://github.com/PeterNgTr)** +* **[Puppeteer]** Fixed support for Puppeteer > 14.4 by **[PeterNgTr](https://github.com/PeterNgTr)** * Don't report files as existing when non-directory is in path by **[jonathanperret](https://github.com/jonathanperret)**. See [#3374](https://github.com/codeceptjs/CodeceptJS/issues/3374) -* Fixed TS type for `secret` function by **[PeterNgTr](https://github.com/PeterNgTr)** +* Fixed TS type for `secret` function by **[PeterNgTr](https://github.com/PeterNgTr)** * Fixed wrong order for async MetaSteps by **[dwentland24](https://github.com/dwentland24)**. See [#3393](https://github.com/codeceptjs/CodeceptJS/issues/3393) -* Fixed same param substitution in BDD step. See [#3385](https://github.com/codeceptjs/CodeceptJS/issues/3385) by **[snehabhandge](https://github.com/snehabhandge)** +* Fixed same param substitution in BDD step. See [#3385](https://github.com/codeceptjs/CodeceptJS/issues/3385) by **[snehabhandge](https://github.com/snehabhandge)** 📖 Documentation * Updated [configuration options](https://codecept.io/configuration/) to match TypeScript types * Updated [TypeScript documentation](https://codecept.io/typescript/) on simplifying TS installation -* Added codecept-tesults plugin documentation by **[ajeetd](https://github.com/ajeetd)** +* Added codecept-tesults plugin documentation by **[ajeetd](https://github.com/ajeetd)** @@ -1767,7 +1705,7 @@ I.sendPostRequest('/auth', secret({ name: 'jon', password: '123456' }, 'password ``` * Added [a guide about using of `secret`](/secrets) function * **[Appium]** Use `touchClick` when interacting with elements in iOS. See [#3317](https://github.com/codeceptjs/CodeceptJS/issues/3317) by **[mikk150](https://github.com/mikk150)** -* **[Playwright]** Added `cdpConnection` option to connect over CDP. See [#3309](https://github.com/codeceptjs/CodeceptJS/issues/3309) by **[Hmihaly](https://github.com/Hmihaly)** +* **[Playwright]** Added `cdpConnection` option to connect over CDP. See [#3309](https://github.com/codeceptjs/CodeceptJS/issues/3309) by **[Hmihaly](https://github.com/Hmihaly)** * [customLocator plugin] Allowed to specify multiple attributes for custom locator. Thanks to **[aruiz-caritsqa](https://github.com/aruiz-caritsqa)** ```js @@ -1781,7 +1719,7 @@ plugins: { ``` * [retryTo plugin] Fixed [#3147](https://github.com/codeceptjs/CodeceptJS/issues/3147) using `pollInterval` option. See [#3351](https://github.com/codeceptjs/CodeceptJS/issues/3351) by **[cyonkee](https://github.com/cyonkee)** * **[Playwright]** Fixed grabbing of browser console messages and window resize in new tab. Thanks to **[mirao](https://github.com/mirao)** -* **[REST]** Added `prettyPrintJson` option to print JSON in nice way by **[PeterNgTr](https://github.com/PeterNgTr)** +* **[REST]** Added `prettyPrintJson` option to print JSON in nice way by **[PeterNgTr](https://github.com/PeterNgTr)** * **[JSONResponse]** Updated response validation to iterate over array items if response is array. Thanks to **[PeterNgTr](https://github.com/PeterNgTr)** ```js @@ -1805,7 +1743,7 @@ I.dontSeeResponseContainsJson({ user: 2 }); ## 3.3.2 * **[REST]** Fixed override of headers/token in `haveRequestHeaders()` and `amBearerAuthenticated()`. See [#3304](https://github.com/codeceptjs/CodeceptJS/issues/3304) by **[mirao](https://github.com/mirao)** -* Reverted typings change introduced in [#3245](https://github.com/codeceptjs/CodeceptJS/issues/3245). [More details on this](https://twitter.com/CodeceptJS/status/1519725963856207873) +* Reverted typings change introduced in [#3245](https://github.com/codeceptjs/CodeceptJS/issues/3245). [More details on this](https://twitter.com/CodeceptJS/status/1519725963856207873) ## 3.3.1 @@ -1813,7 +1751,7 @@ I.dontSeeResponseContainsJson({ user: 2 }); * Add option to avoid duplicate gherkin step definitions ([#3257](https://github.com/codeceptjs/CodeceptJS/issues/3257)) - **[raywiis](https://github.com/raywiis)** * Added `step.*` for run-workers [#3272](https://github.com/codeceptjs/CodeceptJS/issues/3272). Thanks to **[abhimanyupandian](https://github.com/abhimanyupandian)** -* Fixed loading tests for `codecept run` using glob patterns. By **[jayudey-wf](https://github.com/jayudey-wf)** +* Fixed loading tests for `codecept run` using glob patterns. By **[jayudey-wf](https://github.com/jayudey-wf)** ``` npx codeceptjs run test-dir/*" @@ -1836,8 +1774,8 @@ npx codeceptjs run test-dir/*" * **[Playwright]** Fixed `Cannot read property 'video' of undefined` * Fixed haveRequestHeaders() and amBearerAuthenticated() of REST helper ([#3260](https://github.com/codeceptjs/CodeceptJS/issues/3260)) - **[mirao](https://github.com/mirao)** -* Fixed: allure attachment fails if screenshot failed [#3298](https://github.com/codeceptjs/CodeceptJS/issues/3298) by **[ruudvanderweijde](https://github.com/ruudvanderweijde)** -* Fixed [#3105](https://github.com/codeceptjs/CodeceptJS/issues/3105) using autoLogin() plugin with TypeScript. Fix [#3290](https://github.com/codeceptjs/CodeceptJS/issues/3290) by **[PeterNgTr](https://github.com/PeterNgTr)** +* Fixed: allure attachment fails if screenshot failed [#3298](https://github.com/codeceptjs/CodeceptJS/issues/3298) by **[ruudvanderweijde](https://github.com/ruudvanderweijde)** +* Fixed [#3105](https://github.com/codeceptjs/CodeceptJS/issues/3105) using autoLogin() plugin with TypeScript. Fix [#3290](https://github.com/codeceptjs/CodeceptJS/issues/3290) by **[PeterNgTr](https://github.com/PeterNgTr)** * **[Playwright]** Added extra params for click and dragAndDrop to type definitions by **[mirao](https://github.com/mirao)** @@ -1882,10 +1820,10 @@ await eachElement('click all links in .list', '.list a', (el) => { ``` * **[Playwright]** Added support to `playwright-core` package if `playwright` is not installed. See [#3190](https://github.com/codeceptjs/CodeceptJS/issues/3190), fixes [#2663](https://github.com/codeceptjs/CodeceptJS/issues/2663). * **[Playwright]** Added `makeApiRequest` action to perform API requests. Requires Playwright >= 1.18 -* Added support to `codecept.config.js` for name consistency across other JS tools. See motivation at [#3195](https://github.com/codeceptjs/CodeceptJS/issues/3195) by **[JiLiZART](https://github.com/JiLiZART)** +* Added support to `codecept.config.js` for name consistency across other JS tools. See motivation at [#3195](https://github.com/codeceptjs/CodeceptJS/issues/3195) by **[JiLiZART](https://github.com/JiLiZART)** * **[ApiDataFactory]** Added options arg to `have` method. See [#3197](https://github.com/codeceptjs/CodeceptJS/issues/3197) by **[JJlokidoki](https://github.com/JJlokidoki)** -* Improved pt-br translations to include keywords: 'Funcionalidade', 'Cenário', 'Antes', 'Depois', 'AntesDaSuite', 'DepoisDaSuite'. See [#3206](https://github.com/codeceptjs/CodeceptJS/issues/3206) by **[danilolutz](https://github.com/danilolutz)** -* [allure plugin] Introduced `addStep` method to add comments and attachments. See [#3104](https://github.com/codeceptjs/CodeceptJS/issues/3104) by **[EgorBodnar](https://github.com/EgorBodnar)** +* Improved pt-br translations to include keywords: 'Funcionalidade', 'Cenário', 'Antes', 'Depois', 'AntesDaSuite', 'DepoisDaSuite'. See [#3206](https://github.com/codeceptjs/CodeceptJS/issues/3206) by **[danilolutz](https://github.com/danilolutz)** +* [allure plugin] Introduced `addStep` method to add comments and attachments. See [#3104](https://github.com/codeceptjs/CodeceptJS/issues/3104) by **[EgorBodnar](https://github.com/EgorBodnar)** 🐛 Bugfixes: @@ -1897,14 +1835,14 @@ await eachElement('click all links in .list', '.list a', (el) => { * Added [api testing](/api) guides * Added [internal api](/internal-api) guides * **[Appium]** Fixed documentation for `performSwipe` -* **[Playwright]** update docs for `usePlaywrightTo` method by **[dbudzins](https://github.com/dbudzins)** +* **[Playwright]** update docs for `usePlaywrightTo` method by **[dbudzins](https://github.com/dbudzins)** ## 3.2.3 * Documentation improvements by **[maojunxyz](https://github.com/maojunxyz)** -* Guard mocha cli reporter from registering step logger multiple times [#3180](https://github.com/codeceptjs/CodeceptJS/issues/3180) by **[nikocanvacom](https://github.com/nikocanvacom)** +* Guard mocha cli reporter from registering step logger multiple times [#3180](https://github.com/codeceptjs/CodeceptJS/issues/3180) by **[nikocanvacom](https://github.com/nikocanvacom)** * **[Playwright]** Fixed "tracing.stop: tracing.stop: ENAMETOOLONG: name too long" by **[hatufacci](https://github.com/hatufacci)** -* Fixed [#2889](https://github.com/codeceptjs/CodeceptJS/issues/2889): return always the same error contract from simplifyTest. See [#3168](https://github.com/codeceptjs/CodeceptJS/issues/3168) by **[andremoah](https://github.com/andremoah)** +* Fixed [#2889](https://github.com/codeceptjs/CodeceptJS/issues/2889): return always the same error contract from simplifyTest. See [#3168](https://github.com/codeceptjs/CodeceptJS/issues/3168) by **[andremoah](https://github.com/andremoah)** ## 3.2.2 @@ -1930,10 +1868,10 @@ await eachElement('click all links in .list', '.list a', (el) => { 🛩️ Features: **[Timeouts](https://codecept.io/advanced/#timeout) implemented** -* global timeouts (via `timeout` config option). - * _Breaking change:_ timeout option expects **timeout in seconds**, not in milliseconds as it was previously. -* test timeouts (via `Scenario` and `Feature` options) - * _Breaking change:_ `Feature().timeout()` and `Scenario().timeout()` calls has no effect and are deprecated + * global timeouts (via `timeout` config option). + * _Breaking change:_ timeout option expects **timeout in seconds**, not in milliseconds as it was previously. + * test timeouts (via `Scenario` and `Feature` options) + * _Breaking change:_ `Feature().timeout()` and `Scenario().timeout()` calls has no effect and are deprecated ```js // set timeout for every test in suite to 10 secs @@ -1943,13 +1881,13 @@ Feature('tests with timeout', { timeout: 10 }); Scenario('a test with timeout', { timeout: 20 }, ({ I }) => {}); ``` -* step timeouts (See [#3059](https://github.com/codeceptjs/CodeceptJS/issues/3059) by **[nikocanvacom](https://github.com/nikocanvacom)**) + * step timeouts (See [#3059](https://github.com/codeceptjs/CodeceptJS/issues/3059) by **[nikocanvacom](https://github.com/nikocanvacom)**) ```js // set step timeout to 5 secs I.limitTime(5).click('Link'); ``` -* `stepTimeout` plugin introduced to automatically add timeouts for each step ([#3059](https://github.com/codeceptjs/CodeceptJS/issues/3059) by **[nikocanvacom](https://github.com/nikocanvacom)**). + * `stepTimeout` plugin introduced to automatically add timeouts for each step ([#3059](https://github.com/codeceptjs/CodeceptJS/issues/3059) by **[nikocanvacom](https://github.com/nikocanvacom)**). [**retryTo**](/plugins/#retryto) plugin introduced to rerun a set of steps on failure: @@ -1967,7 +1905,7 @@ await retryTo(() => { 🐛 Bugfixes: -* Fixed allure plugin "Unexpected endStep()" error in [#3098](https://github.com/codeceptjs/CodeceptJS/issues/3098) by **[abhimanyupandian](https://github.com/abhimanyupandian)** +* Fixed allure plugin "Unexpected endStep()" error in [#3098](https://github.com/codeceptjs/CodeceptJS/issues/3098) by **[abhimanyupandian](https://github.com/abhimanyupandian)** * **[Puppeteer]** always close remote browser on test end. See [#3054](https://github.com/codeceptjs/CodeceptJS/issues/3054) by **[mattonem](https://github.com/mattonem)** * stepbyStepReport Plugin: Disabled screenshots after test has failed. See [#3119](https://github.com/codeceptjs/CodeceptJS/issues/3119) by **[ioannisChalkias](https://github.com/ioannisChalkias)** @@ -1976,7 +1914,7 @@ await retryTo(() => { 🛩️ Features: -* BDD Improvement. Added `DataTableArgument` class to work with table data structures. +* BDD Improvement. Added `DataTableArgument` class to work with table data structures. ```js const { DataTableArgument } = require('codeceptjs'); @@ -1992,7 +1930,7 @@ Given('I have an employee card', (table) => { See updated [BDD section](https://codecept.io/bdd/) for more API options. Thanks to **[EgorBodnar](https://github.com/EgorBodnar)** * Support `cjs` file extensions for config file: `codecept.conf.cjs`. See [#3052](https://github.com/codeceptjs/CodeceptJS/issues/3052) by **[kalvenschraut](https://github.com/kalvenschraut)** -* API updates: Added `test.file` and `suite.file` properties to `test` and `suite` objects to use in helpers and plugins. +* API updates: Added `test.file` and `suite.file` properties to `test` and `suite` objects to use in helpers and plugins. 🐛 Bugfixes: @@ -2000,9 +1938,9 @@ See updated [BDD section](https://codecept.io/bdd/) for more API options. Thanks * **[Playwright]** Apply `basicAuth` credentials to all opened browser contexts. See [#3036](https://github.com/codeceptjs/CodeceptJS/issues/3036) by **[nikocanvacom](https://github.com/nikocanvacom)**. Fixes [#3035](https://github.com/codeceptjs/CodeceptJS/issues/3035) * **[WebDriver]** Updated `webdriverio` default version to `^6.12.1`. See [#3043](https://github.com/codeceptjs/CodeceptJS/issues/3043) by **[sridhareaswaran](https://github.com/sridhareaswaran)** * **[Playwright]** `I.haveRequestHeaders` affects all tabs. See [#3049](https://github.com/codeceptjs/CodeceptJS/issues/3049) by **[jancorvus](https://github.com/jancorvus)** -* BDD: Fixed unhandled empty feature files. Fix [#3046](https://github.com/codeceptjs/CodeceptJS/issues/3046) by **[abhimanyupandian](https://github.com/abhimanyupandian)** -* Fixed `RangeError: Invalid string length` in `recorder.js` when running huge amount of tests. -* **[Appium]** Fixed definitions for `touchPerform`, `hideDeviceKeyboard`, `removeApp` by **[mirao](https://github.com/mirao)** +* BDD: Fixed unhandled empty feature files. Fix [#3046](https://github.com/codeceptjs/CodeceptJS/issues/3046) by **[abhimanyupandian](https://github.com/abhimanyupandian)** +* Fixed `RangeError: Invalid string length` in `recorder.js` when running huge amount of tests. +* **[Appium]** Fixed definitions for `touchPerform`, `hideDeviceKeyboard`, `removeApp` by **[mirao](https://github.com/mirao)** 📖 Documentation: @@ -2027,10 +1965,10 @@ exports.config = { 🐛 Bugfixes: -* **[Playwright]** Fixed [#2986](https://github.com/codeceptjs/CodeceptJS/issues/2986) error is thrown when deleting a missing video. Fix by **[hatufacci](https://github.com/hatufacci)** +* **[Playwright]** Fixed [#2986](https://github.com/codeceptjs/CodeceptJS/issues/2986) error is thrown when deleting a missing video. Fix by **[hatufacci](https://github.com/hatufacci)** * Fixed false positive result when invalid function is called in a helper. See [#2997](https://github.com/codeceptjs/CodeceptJS/issues/2997) by **[abhimanyupandian](https://github.com/abhimanyupandian)** * **[Appium]** Removed full page mode for `saveScreenshot`. See [#3002](https://github.com/codeceptjs/CodeceptJS/issues/3002) by **[nlespiaucq](https://github.com/nlespiaucq)** -* **[Playwright]** Fixed [#3003](https://github.com/codeceptjs/CodeceptJS/issues/3003) saving trace for a test with a long name. Fix by **[hatufacci](https://github.com/hatufacci)** +* **[Playwright]** Fixed [#3003](https://github.com/codeceptjs/CodeceptJS/issues/3003) saving trace for a test with a long name. Fix by **[hatufacci](https://github.com/hatufacci)** 🎱 Other: @@ -2039,7 +1977,7 @@ exports.config = { ## 3.1.1 * **[Appium]** Fixed [#2759](https://github.com/codeceptjs/CodeceptJS/issues/2759) - `grabNumberOfVisibleElements`, `grabAttributeFrom`, `grabAttributeFromAll` to allow id locators. + `grabNumberOfVisibleElements`, `grabAttributeFrom`, `grabAttributeFromAll` to allow id locators. ## 3.1.0 @@ -2057,11 +1995,11 @@ exports.config = { 🐛 Bugfixes: * **[Puppeteer]** Fixed [#2244](https://github.com/codeceptjs/CodeceptJS/issues/2244) `els[0]._clickablePoint is not a function` by **[karunandrii](https://github.com/karunandrii)**. -* **[Puppeteer]** Fixed `fillField` to check for invisible elements. See [#2916](https://github.com/codeceptjs/CodeceptJS/issues/2916) by **[anne-open-xchange](https://github.com/anne-open-xchange)** -* **[Playwright]** Reset of dialog event listener before registration of new one. [#2946](https://github.com/codeceptjs/CodeceptJS/issues/2946) by **[nikocanvacom](https://github.com/nikocanvacom)** +* **[Puppeteer]** Fixed `fillField` to check for invisible elements. See [#2916](https://github.com/codeceptjs/CodeceptJS/issues/2916) by **[anne-open-xchange](https://github.com/anne-open-xchange)** +* **[Playwright]** Reset of dialog event listener before registration of new one. [#2946](https://github.com/codeceptjs/CodeceptJS/issues/2946) by **[nikocanvacom](https://github.com/nikocanvacom)** * Fixed running Gherkin features with `run-multiple` using chunks. See [#2900](https://github.com/codeceptjs/CodeceptJS/issues/2900) by **[andrenoberto](https://github.com/andrenoberto)** * Fixed [#2937](https://github.com/codeceptjs/CodeceptJS/issues/2937) broken typings for subfolders on Windows by **[jancorvus](https://github.com/jancorvus)** -* Fixed issue where cucumberJsonReporter not working with fakerTransform plugin. See [#2942](https://github.com/codeceptjs/CodeceptJS/issues/2942) by **[ilangv](https://github.com/ilangv)** +* Fixed issue where cucumberJsonReporter not working with fakerTransform plugin. See [#2942](https://github.com/codeceptjs/CodeceptJS/issues/2942) by **[ilangv](https://github.com/ilangv)** * Fixed [#2952](https://github.com/codeceptjs/CodeceptJS/issues/2952) finished job with status code 0 when playwright cannot connect to remote wss url. By **[davertmik](https://github.com/davertmik)** @@ -2194,23 +2132,23 @@ Library updates: * **[Playwright]** Fix connection close with remote browser. See [#2629](https://github.com/codeceptjs/CodeceptJS/issues/2629) by **[dipiash](https://github.com/dipiash)** * **[REST]** set maxUploadFileSize when performing api calls. See [#2611](https://github.com/codeceptjs/CodeceptJS/issues/2611) by **[PeterNgTr](https://github.com/PeterNgTr)** * Duplicate Scenario names (combined with Feature name) are now detected via a warning message. - Duplicate test names can cause `codeceptjs run-workers` to not function. See [#2656](https://github.com/codeceptjs/CodeceptJS/issues/2656) by **[Georgegriff](https://github.com/Georgegriff)** +Duplicate test names can cause `codeceptjs run-workers` to not function. See [#2656](https://github.com/codeceptjs/CodeceptJS/issues/2656) by **[Georgegriff](https://github.com/Georgegriff)** * Documentation fixes Bug Fixes: -* --suites flag now should function correctly for `codeceptjs run-workers`. See [#2655](https://github.com/codeceptjs/CodeceptJS/issues/2655) by **[Georgegriff](https://github.com/Georgegriff)** -* [autoLogin plugin] Login methods should now function as expected with `codeceptjs run-workers`. See [#2658](https://github.com/codeceptjs/CodeceptJS/issues/2658) by **[Georgegriff](https://github.com/Georgegriff)**, resolves [#2620](https://github.com/codeceptjs/CodeceptJS/issues/2620) + * --suites flag now should function correctly for `codeceptjs run-workers`. See [#2655](https://github.com/codeceptjs/CodeceptJS/issues/2655) by **[Georgegriff](https://github.com/Georgegriff)** + * [autoLogin plugin] Login methods should now function as expected with `codeceptjs run-workers`. See [#2658](https://github.com/codeceptjs/CodeceptJS/issues/2658) by **[Georgegriff](https://github.com/Georgegriff)**, resolves [#2620](https://github.com/codeceptjs/CodeceptJS/issues/2620) ## 3.0.1 ♨️ Hot fix: -* Lock the mocha version to avoid the errors. See [#2624](https://github.com/codeceptjs/CodeceptJS/issues/2624) by PeterNgTr + * Lock the mocha version to avoid the errors. See [#2624](https://github.com/codeceptjs/CodeceptJS/issues/2624) by PeterNgTr 🐛 Bug Fix: -* Fixed error handling in Scenario.js. See [#2607](https://github.com/codeceptjs/CodeceptJS/issues/2607) by haveac1gar -* Changing type definition in order to allow the use of functions with any number of any arguments. See [#2616](https://github.com/codeceptjs/CodeceptJS/issues/2616) by akoltun + * Fixed error handling in Scenario.js. See [#2607](https://github.com/codeceptjs/CodeceptJS/issues/2607) by haveac1gar + * Changing type definition in order to allow the use of functions with any number of any arguments. See [#2616](https://github.com/codeceptjs/CodeceptJS/issues/2616) by akoltun * Some updates/changes on documentations @@ -2256,13 +2194,13 @@ Read changelog to learn more about version 👇 ## 3.0.0-beta.4 🐛 Bug Fix: -* PageObject was broken when using "this" inside a simple object. -* The typings for all WebDriver methods work correctly. -* The typings for "this.helper" and helper constructor work correctly, too. + * PageObject was broken when using "this" inside a simple object. + * The typings for all WebDriver methods work correctly. + * The typings for "this.helper" and helper constructor work correctly, too. 🧤 Internal: -* Our TS Typings will be tested now! We strarted using [dtslint](https://github.com/microsoft/dtslint) to check all typings and all rules for linter. - Example: + * Our TS Typings will be tested now! We strarted using [dtslint](https://github.com/microsoft/dtslint) to check all typings and all rules for linter. + Example: ```ts const psp = wd.grabPageScrollPosition() // $ExpectType Promise psp.then( @@ -2272,7 +2210,7 @@ Read changelog to learn more about version 👇 } ) ``` -* And last: Reducing package size from 3.3Mb to 2.0Mb + * And last: Reducing package size from 3.3Mb to 2.0Mb ## 3.0.0-beta-3 @@ -2445,22 +2383,22 @@ npm i playwright@^0.12 --save ``` [Notable changes](https://github.com/microsoft/playwright/releases/tag/v0.12.0): -* Fixed opening two browsers on start -* `executeScript` - passed function now accepts only one argument. Pass in objects or arrays if you need multtple arguments: + * Fixed opening two browsers on start + * `executeScript` - passed function now accepts only one argument. Pass in objects or arrays if you need multtple arguments: ```js // Old style, does not work anymore: I.executeScript((x, y) => x + y, x, y); // New style, passing an object: I.executeScript(({x, y}) => x + y, {x, y}); ``` -* `click` - automatically waits for element to become clickable (visible, not animated) and waits for navigation. -* `clickLink` - deprecated -* `waitForClickable` - deprecated -* `forceClick` - added -* Added support for custom locators. See [#2277](https://github.com/codeceptjs/CodeceptJS/issues/2277) -* Introduced [device emulation](/playwright/#device-emulation): - * globally via `emulate` config option - * per session + * `click` - automatically waits for element to become clickable (visible, not animated) and waits for navigation. + * `clickLink` - deprecated + * `waitForClickable` - deprecated + * `forceClick` - added + * Added support for custom locators. See [#2277](https://github.com/codeceptjs/CodeceptJS/issues/2277) + * Introduced [device emulation](/playwright/#device-emulation): + * globally via `emulate` config option + * per session **[WebDriver] Updated to webdriverio v6** by **[PeterNgTr](https://github.com/PeterNgTr)**. @@ -2471,7 +2409,7 @@ upgrade webdriverio to ^6.0: npm i webdriverio@^6.0 --save ``` *(webdriverio v5 support is deprecated and will be removed in CodeceptJS 3.0)* -**[WebDriver]** Introduced [Shadow DOM support](/shadow) by **[gkushang](https://github.com/gkushang)** + **[WebDriver]** Introduced [Shadow DOM support](/shadow) by **[gkushang](https://github.com/gkushang)** ```js I.click({ shadow: ['my-app', 'recipe-hello', 'button'] }); @@ -2629,7 +2567,7 @@ I.click({ css: '[data-test-id=register_button]'); I.click('$register_button'); ``` * [Puppeteer][WebDriver] `pressKey` improvements by **[martomo](https://github.com/martomo)**: - Changed pressKey method to resolve issues and extend functionality. +Changed pressKey method to resolve issues and extend functionality. * Did not properly recognize 'Meta' (or 'Command') as modifier key. * Right modifier keys did not work in WebDriver using JsonWireProtocol. * 'Shift' + 'key' combination would not reflect actual keyboard behavior. @@ -2685,8 +2623,8 @@ npx codeceptjs dry-run * **[Appium]** Optimization when clicking, searching for fields by accessibility id. See [#1777](https://github.com/codeceptjs/CodeceptJS/issues/1777) by **[gagandeepsingh26](https://github.com/gagandeepsingh26)** * **[TestCafe]** Fixed `switchTo` by **[KadoBOT](https://github.com/KadoBOT)** * **[WebDriver]** Added geolocation actions by **[PeterNgTr](https://github.com/PeterNgTr)** - * `grabGeoLocation()` - * `setGeoLocation()` + * `grabGeoLocation()` + * `setGeoLocation()` * **[Polly]** Check typeof arguments for mock requests by **[VikalpP](https://github.com/VikalpP)**. Fixes [#1815](https://github.com/codeceptjs/CodeceptJS/issues/1815) * CLI improvements by **[jamesgeorge007](https://github.com/jamesgeorge007)** * `codeceptjs` command prints list of all available commands @@ -3011,8 +2949,8 @@ I.say('This is by default'); //cyan is used ## 1.4.5 * Add **require** param to main config. Allows to require Node modules before executing tests. By **[LukoyanovE](https://github.com/LukoyanovE)**. For example: - * Use `ts-node/register` to register TypeScript parser - * Use `should` to register should-style assertions + * Use `ts-node/register` to register TypeScript parser + * Use `should` to register should-style assertions ```js "require": ["ts-node/register", "should"] @@ -3068,10 +3006,10 @@ Scenario('update user profile', () => { * [**Allure Reporter Integration**](https://codecept.io/reports/#allure). Full inegration with Allure Server. Get nicely looking UI for tests,including steps, nested steps, and screenshots. Thanks **Natarajan Krishnamurthy **[krish](https://github.com/krish)**** for sponsoring this feature. * [Plugins API introduced](https://codecept.io/hooks/#plugins). Create custom plugins for CodeceptJS by hooking into event dispatcher, and using promise recorder. * **Official [CodeceptJS plugins](https://codecept.io/plugins) added**: - * **`stepByStepReport` - creates nicely looking report to see test execution as a slideshow**. Use this plugin to debug tests in headless environment without recording a video. - * `allure` - Allure reporter added as plugin. - * `screenshotOnFail` - saves screenshot on fail. Replaces similar functionality from helpers. - * `retryFailedStep` - to rerun each failed step. + * **`stepByStepReport` - creates nicely looking report to see test execution as a slideshow**. Use this plugin to debug tests in headless environment without recording a video. + * `allure` - Allure reporter added as plugin. + * `screenshotOnFail` - saves screenshot on fail. Replaces similar functionality from helpers. + * `retryFailedStep` - to rerun each failed step. * **[Puppeteer]** Fix `executeAsyncScript` unexpected token by **[jonathanz](https://github.com/jonathanz)** * Added `override` option to `run-multiple` command by **[svarlet](https://github.com/svarlet)** @@ -3082,11 +3020,11 @@ Scenario('update user profile', () => { ## 1.3.2 * Interactve Shell improvements for `pause()` - * Added `next` command for **step-by-step debug** when using `pause()`. - * Use `After(pause);` in a to start interactive console after last step. + * Added `next` command for **step-by-step debug** when using `pause()`. + * Use `After(pause);` in a to start interactive console after last step. * **[Puppeteer]** Updated to Puppeteer 1.6.0 - * Added `waitForRequest` to wait for network request. - * Added `waitForResponse` to wait for network response. + * Added `waitForRequest` to wait for network request. + * Added `waitForResponse` to wait for network response. * Improved TypeScript definitions to support custom steps and page objects. By **[xt1](https://github.com/xt1)** * Fixed XPath detection to accept XPath which starts with `./` by **[BenoitZugmeyer](https://github.com/BenoitZugmeyer)** @@ -3151,14 +3089,14 @@ This change allows using auto-completion when running a specific test. --- * Nested steps output enabled for page objects. - * to see high-level steps only run tests with `--steps` flag. - * to see PageObjects implementation run tests with `--debug`. + * to see high-level steps only run tests with `--steps` flag. + * to see PageObjects implementation run tests with `--debug`. * PageObjects simplified to remove `_init()` extra method. Try updated generators and see [updated guide](https://codecept.io/pageobjects/#pageobject). * **[Puppeteer]** [Multiple sessions](https://codecept.io/acceptance/#multiple-sessions) enabled. Requires Puppeteer >= 1.5 * **[Puppeteer]** Stability improvement. Waits for for `load` event on page load. This strategy can be changed in config: - * `waitForNavigation` config option introduced. Possible options: `load`, `domcontentloaded`, `networkidle0`, `networkidle2`. See [Puppeteer API](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagewaitfornavigationoptions) - * `getPageTimeout` config option to set maximum navigation time in milliseconds. Default is 30 seconds. - * `waitForNavigation` method added. Explicitly waits for navigation to be finished. + * `waitForNavigation` config option introduced. Possible options: `load`, `domcontentloaded`, `networkidle0`, `networkidle2`. See [Puppeteer API](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagewaitfornavigationoptions) + * `getPageTimeout` config option to set maximum navigation time in milliseconds. Default is 30 seconds. + * `waitForNavigation` method added. Explicitly waits for navigation to be finished. * [WebDriverIO][Protractor][Puppeteer][Nightmare] **Possible BC** `grabTextFrom` unified. Return a text for single matched element and an array of texts for multiple elements. * [Puppeteer]Fixed `resizeWindow` by **[sergejkaravajnij](https://github.com/sergejkaravajnij)** * [WebDriverIO][Protractor][Puppeteer][Nightmare] `waitForFunction` added. Waits for client-side JavaScript function to return true by **[GREENpoint](https://github.com/GREENpoint)**. @@ -3252,45 +3190,45 @@ Scenario('this test should throw error', (I) => { ## 1.1.7 * Docker Image updateed. [See updated reference](https://codecept.io/docker/): - * codeceptjs package is mounted as `/codecept` insde container - * tests directory is expected to be mounted as `/tests` - * `codeceptjs` global runner added (symlink to `/codecept/bin/codecept.js`) + * codeceptjs package is mounted as `/codecept` insde container + * tests directory is expected to be mounted as `/tests` + * `codeceptjs` global runner added (symlink to `/codecept/bin/codecept.js`) * **[Protractor]** Functions added by **[reubenmiller](https://github.com/reubenmiller)**: - * `_locateCheckable (only available from other helpers)` - * `_locateClickable (only available from other helpers)` - * `_locateFields (only available from other helpers)` - * `acceptPopup` - * `cancelPopup` - * `dragAndDrop` - * `grabBrowserLogs` - * `grabCssPropertyFrom` - * `grabHTMLFrom` - * `grabNumberOfVisibleElements` - * `grabPageScrollPosition (new)` - * `rightClick` - * `scrollPageToBottom` - * `scrollPageToTop` - * `scrollTo` - * `seeAttributesOnElements` - * `seeCssPropertiesOnElements` - * `seeInPopup` - * `seeNumberOfVisibleElements` - * `switchTo` - * `waitForEnabled` - * `waitForValue` - * `waitInUrl` - * `waitNumberOfVisibleElements` - * `waitToHide` - * `waitUntil` - * `waitUrlEquals` + * `_locateCheckable (only available from other helpers)` + * `_locateClickable (only available from other helpers)` + * `_locateFields (only available from other helpers)` + * `acceptPopup` + * `cancelPopup` + * `dragAndDrop` + * `grabBrowserLogs` + * `grabCssPropertyFrom` + * `grabHTMLFrom` + * `grabNumberOfVisibleElements` + * `grabPageScrollPosition (new)` + * `rightClick` + * `scrollPageToBottom` + * `scrollPageToTop` + * `scrollTo` + * `seeAttributesOnElements` + * `seeCssPropertiesOnElements` + * `seeInPopup` + * `seeNumberOfVisibleElements` + * `switchTo` + * `waitForEnabled` + * `waitForValue` + * `waitInUrl` + * `waitNumberOfVisibleElements` + * `waitToHide` + * `waitUntil` + * `waitUrlEquals` * **[Nightmare]** added: - * `grabPageScrollPosition` (new) - * `seeNumberOfVisibleElements` - * `waitToHide` + * `grabPageScrollPosition` (new) + * `seeNumberOfVisibleElements` + * `waitToHide` * **[Puppeteer]** added: - * `grabPageScrollPosition` (new) + * `grabPageScrollPosition` (new) * **[WebDriverIO]** added" - * `grabPageScrollPosition` (new) + * `grabPageScrollPosition` (new) * **[Puppeteer]** Fixed running wait* functions without setting `sec` parameter. * [Puppeteer][Protractor] Fixed bug with I.click when using an object selector with the xpath property. By **[reubenmiller](https://github.com/reubenmiller)** * [WebDriverIO][Protractor][Nightmare][Puppeteer] Fixed I.switchTo(0) and I.scrollTo(100, 100) api inconsistencies between helpers. @@ -3312,13 +3250,13 @@ Scenario('this test should throw error', (I) => { * **[Puppeteer]** Added `waitForEnabled`, `waitForValue` and `waitNumberOfVisibleElements` methods by **[reubenmiller](https://github.com/reubenmiller)** * **[WebDriverIO]** Fixed `grabNumberOfVisibleElements` to return 0 when no visible elements are on page. By **[michaltrunek](https://github.com/michaltrunek)** * Helpers API improvements (by **[reubenmiller](https://github.com/reubenmiller)**) - * `_passed` hook runs after a test passed successfully - * `_failed` hook runs on a failed test + * `_passed` hook runs after a test passed successfully + * `_failed` hook runs on a failed test * Hooks API. New events added by **[reubenmiller](https://github.com/reubenmiller)**: - * `event.all.before` - executed before all tests - * `event.all.after` - executed after all tests - * `event.multiple.before` - executed before all processes in run-multiple - * `event.multiple.after` - executed after all processes in run-multiple + * `event.all.before` - executed before all tests + * `event.all.after` - executed after all tests + * `event.multiple.before` - executed before all processes in run-multiple + * `event.multiple.after` - executed after all processes in run-multiple * Multiple execution * Allow `AfterSuite` and `After` test hooks to be defined after the first Scenario. By **[reubenmiller](https://github.com/reubenmiller)** * **[Nightmare]** Prevent `I.amOnpage` navigation if the browser is already at the given url @@ -3382,46 +3320,46 @@ I.runOnAndroid(caps => caps.platformVersion >= 7, () => { ## 1.1.3 * **[Puppeteer]** +25 Functions added by **[reubenmiller](https://github.com/reubenmiller)** - * `_locateCheckable` - * `_locateClickable` - * `_locateFields` - * `closeOtherTabs` - * `dragAndDrop` - * `grabBrowserLogs` - * `grabCssPropertyFrom` - * `grabHTMLFrom` - * `grabNumberOfVisibleElements` - * `grabSource` - * `rightClick` - * `scrollPageToBottom` - * `scrollPageToTop` - * `scrollTo` - * `seeAttributesOnElements` - * `seeCssPropertiesOnElements` - * `seeInField` - * `seeNumberOfElements` - * `seeNumberOfVisibleElements` - * `seeTextEquals` - * `seeTitleEquals` - * `switchTo` - * `waitForInvisible` - * `waitInUrl` - * `waitUrlEquals` + * `_locateCheckable` + * `_locateClickable` + * `_locateFields` + * `closeOtherTabs` + * `dragAndDrop` + * `grabBrowserLogs` + * `grabCssPropertyFrom` + * `grabHTMLFrom` + * `grabNumberOfVisibleElements` + * `grabSource` + * `rightClick` + * `scrollPageToBottom` + * `scrollPageToTop` + * `scrollTo` + * `seeAttributesOnElements` + * `seeCssPropertiesOnElements` + * `seeInField` + * `seeNumberOfElements` + * `seeNumberOfVisibleElements` + * `seeTextEquals` + * `seeTitleEquals` + * `switchTo` + * `waitForInvisible` + * `waitInUrl` + * `waitUrlEquals` * **[Protractor]** +8 functions added by **[reubenmiller](https://github.com/reubenmiller)** - * `closeCurrentTab` - * `grabSource` - * `openNewTab` - * `seeNumberOfElements` - * `seeTextEquals` - * `seeTitleEquals` - * `switchToNextTab` - * `switchToPreviousTab` + * `closeCurrentTab` + * `grabSource` + * `openNewTab` + * `seeNumberOfElements` + * `seeTextEquals` + * `seeTitleEquals` + * `switchToNextTab` + * `switchToPreviousTab` * **[Nightmare]** `waitForInvisible` added by **[reubenmiller](https://github.com/reubenmiller)** * **[Puppeteer]** Printing console.log information in debug mode. * **[Nightmare]** Integrated with `nightmare-har-plugin` by mingfang. Added `enableHAR` option. Added HAR functions: - * `grabHAR` - * `saveHAR` - * `resetHAR` + * `grabHAR` + * `saveHAR` + * `resetHAR` * **[WebDriverIO]** Fixed execution stability for parallel requests with Chromedriver * **[WebDriverIO]** Fixed resizeWindow when resizing to 'maximize' by **[reubenmiller](https://github.com/reubenmiller)** * **[WebDriverIO]** Fixing resizing window to full screen when taking a screenshot by **[reubenmiller](https://github.com/reubenmiller)** @@ -3600,35 +3538,35 @@ Next notable feature is **[SmartWait](http://codecept.io/acceptance/#smartwait)* * [WebDriverIO][SeleniumWebdriver] Fixed "windowSize": "maximize" for Chrome 59+ version [#560](https://github.com/codeceptjs/CodeceptJS/issues/560) by **[APshenkin](https://github.com/APshenkin)** * **[Nightmare]** Fixed restarting by **[APshenkin](https://github.com/APshenkin)** [#581](https://github.com/codeceptjs/CodeceptJS/issues/581) * **[WebDriverIO]** Methods added by **[APshenkin](https://github.com/APshenkin)**: - * [grabCssPropertyFrom](http://codecept.io/helpers/WebDriverIO/#grabcsspropertyfrom) - * [seeTitleEquals](http://codecept.io/helpers/WebDriverIO/#seetitleequals) - * [seeTextEquals](http://codecept.io/helpers/WebDriverIO/#seetextequals) - * [seeCssPropertiesOnElements](http://codecept.io/helpers/WebDriverIO/#seecsspropertiesonelements) - * [seeAttributesOnElements](http://codecept.io/helpers/WebDriverIO/#seeattributesonelements) - * [grabNumberOfVisibleElements](http://codecept.io/helpers/WebDriverIO/#grabnumberofvisibleelements) - * [waitInUrl](http://codecept.io/helpers/WebDriverIO/#waitinurl) - * [waitUrlEquals](http://codecept.io/helpers/WebDriverIO/#waiturlequals) - * [waitForValue](http://codecept.io/helpers/WebDriverIO/#waitforvalue) - * [waitNumberOfVisibleElements](http://codecept.io/helpers/WebDriverIO/#waitnumberofvisibleelements) - * [switchToNextTab](http://codecept.io/helpers/WebDriverIO/#switchtonexttab) - * [switchToPreviousTab](http://codecept.io/helpers/WebDriverIO/#switchtoprevioustab) - * [closeCurrentTab](http://codecept.io/helpers/WebDriverIO/#closecurrenttab) - * [openNewTab](http://codecept.io/helpers/WebDriverIO/#opennewtab) - * [refreshPage](http://codecept.io/helpers/WebDriverIO/#refreshpage) - * [scrollPageToBottom](http://codecept.io/helpers/WebDriverIO/#scrollpagetobottom) - * [scrollPageToTop](http://codecept.io/helpers/WebDriverIO/#scrollpagetotop) - * [grabBrowserLogs](http://codecept.io/helpers/WebDriverIO/#grabbrowserlogs) + * [grabCssPropertyFrom](http://codecept.io/helpers/WebDriverIO/#grabcsspropertyfrom) + * [seeTitleEquals](http://codecept.io/helpers/WebDriverIO/#seetitleequals) + * [seeTextEquals](http://codecept.io/helpers/WebDriverIO/#seetextequals) + * [seeCssPropertiesOnElements](http://codecept.io/helpers/WebDriverIO/#seecsspropertiesonelements) + * [seeAttributesOnElements](http://codecept.io/helpers/WebDriverIO/#seeattributesonelements) + * [grabNumberOfVisibleElements](http://codecept.io/helpers/WebDriverIO/#grabnumberofvisibleelements) + * [waitInUrl](http://codecept.io/helpers/WebDriverIO/#waitinurl) + * [waitUrlEquals](http://codecept.io/helpers/WebDriverIO/#waiturlequals) + * [waitForValue](http://codecept.io/helpers/WebDriverIO/#waitforvalue) + * [waitNumberOfVisibleElements](http://codecept.io/helpers/WebDriverIO/#waitnumberofvisibleelements) + * [switchToNextTab](http://codecept.io/helpers/WebDriverIO/#switchtonexttab) + * [switchToPreviousTab](http://codecept.io/helpers/WebDriverIO/#switchtoprevioustab) + * [closeCurrentTab](http://codecept.io/helpers/WebDriverIO/#closecurrenttab) + * [openNewTab](http://codecept.io/helpers/WebDriverIO/#opennewtab) + * [refreshPage](http://codecept.io/helpers/WebDriverIO/#refreshpage) + * [scrollPageToBottom](http://codecept.io/helpers/WebDriverIO/#scrollpagetobottom) + * [scrollPageToTop](http://codecept.io/helpers/WebDriverIO/#scrollpagetotop) + * [grabBrowserLogs](http://codecept.io/helpers/WebDriverIO/#grabbrowserlogs) * Use mkdirp to create output directory. [#592](https://github.com/codeceptjs/CodeceptJS/issues/592) by **[vkramskikh](https://github.com/vkramskikh)** * **[WebDriverIO]** Fixed `seeNumberOfVisibleElements` by **[BorisOsipov](https://github.com/BorisOsipov)** [#574](https://github.com/codeceptjs/CodeceptJS/issues/574) * Lots of fixes for promise chain by **[APshenkin](https://github.com/APshenkin)** [#568](https://github.com/codeceptjs/CodeceptJS/issues/568) - * Fix [#543](https://github.com/codeceptjs/CodeceptJS/issues/543)- After block not properly executed if Scenario fails - * Expected behavior in promise chains: `_beforeSuite` hooks from helpers -> `BeforeSuite` from test -> `_before` hooks from helpers -> `Before` from test - > Test steps -> `_failed` hooks from helpers (if test failed) -> `After` from test -> `_after` hooks from helpers -> `AfterSuite` from test -> `_afterSuite` hook from helpers. - * if during test we got errors from any hook (in test or in helper) - stop complete this suite and go to another - * if during test we got error from Selenium server - stop complete this suite and go to another - * [WebDriverIO][Protractor] if `restart` option is false - close all tabs expect one in `_after`. - * Complete `_after`, `_afterSuite` hooks even After/AfterSuite from test was failed - * Don't close browser between suites, when `restart` option is false. We should start browser only one time and close it only after all tests. - * Close tabs and clear local storage, if `keepCookies` flag is enabled + * Fix [#543](https://github.com/codeceptjs/CodeceptJS/issues/543)- After block not properly executed if Scenario fails + * Expected behavior in promise chains: `_beforeSuite` hooks from helpers -> `BeforeSuite` from test -> `_before` hooks from helpers -> `Before` from test - > Test steps -> `_failed` hooks from helpers (if test failed) -> `After` from test -> `_after` hooks from helpers -> `AfterSuite` from test -> `_afterSuite` hook from helpers. + * if during test we got errors from any hook (in test or in helper) - stop complete this suite and go to another + * if during test we got error from Selenium server - stop complete this suite and go to another + * [WebDriverIO][Protractor] if `restart` option is false - close all tabs expect one in `_after`. + * Complete `_after`, `_afterSuite` hooks even After/AfterSuite from test was failed + * Don't close browser between suites, when `restart` option is false. We should start browser only one time and close it only after all tests. + * Close tabs and clear local storage, if `keepCookies` flag is enabled * Fix TypeError when using babel-node or ts-node on node.js 7+ [#586](https://github.com/codeceptjs/CodeceptJS/issues/586) by **[vkramskikh](https://github.com/vkramskikh)** * **[Nightmare]** fixed usage of `_locate` @@ -3662,8 +3600,8 @@ const actor = require('codeceptjs').actor; * run command to create `output` directory if it doesn't exist * **[Protractor]** fixed loading globally installed Protractor * run-multiple command improvements: - * create output directories for each process - * print process ids in output + * create output directories for each process + * print process ids in output ## 0.6.1 @@ -3696,13 +3634,13 @@ codeceptjs run users_test.js -c tests * **[WebDriverIO]** added `seeNumberOfVisibleElements` method by **[elarouche](https://github.com/elarouche)**. * Exit with non-zero code if init throws an error by **[rincedd](https://github.com/rincedd)** * New guides published: - * [Installation](http://codecept.io/installation/) - * [Hooks](http://codecept.io/hooks/) - * [Advanced Usage](http://codecept.io/advanced/) + * [Installation](http://codecept.io/installation/) + * [Hooks](http://codecept.io/hooks/) + * [Advanced Usage](http://codecept.io/advanced/) * Meta packages published: - * [codecept-webdriverio](https://www.npmjs.com/package/codecept-webdriverio) - * [codecept-protractor](https://www.npmjs.com/package/codecept-protractor) - * [codecept-nightmare](https://www.npmjs.com/package/codecept-nightmare) + * [codecept-webdriverio](https://www.npmjs.com/package/codecept-webdriverio) + * [codecept-protractor](https://www.npmjs.com/package/codecept-protractor) + * [codecept-nightmare](https://www.npmjs.com/package/codecept-nightmare) ## 0.5.1 @@ -3758,7 +3696,7 @@ _before() { } _afterStep() { - if (this.err) throw new Error('Browser JS error '+this.err); + if (this.err) throw new Error('Browser JS error '+this.err); } ``` From 34a6e4f598d17a4da525a82f2d8990a79402f516 Mon Sep 17 00:00:00 2001 From: Thomas Hohn Date: Wed, 13 Nov 2024 15:40:00 +0100 Subject: [PATCH 16/16] Correct revert --- docs/changelog.md | 62 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/docs/changelog.md b/docs/changelog.md index d028f8a18..bd22e1210 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -7,6 +7,68 @@ layout: Section # Releases +## 3.6.6 + +❤️ Thanks all to those who contributed to make this release! ❤️ + +🛩️ *Features* +* feat(locator): add withAttrEndsWith, withAttrStartsWith, withAttrContains ([#4334](https://github.com/codeceptjs/CodeceptJS/issues/4334)) - by **[Maksym-Artemenko](https://github.com/Maksym-Artemenko)** +* feat: soft assert ([#4473](https://github.com/codeceptjs/CodeceptJS/issues/4473)) - by **[kobenguyent](https://github.com/kobenguyent)** + * Soft assert + +Zero-configuration when paired with other helpers like REST, Playwright: + +```js +// inside codecept.conf.js +{ + helpers: { + Playwright: {...}, + SoftExpectHelper: {}, + } +} +``` + +```js +// in scenario +I.softExpectEqual('a', 'b') +I.flushSoftAssertions() // Throws an error if any soft assertions have failed. The error message contains all the accumulated failures. +``` +* feat(cli): print failed hooks ([#4476](https://github.com/codeceptjs/CodeceptJS/issues/4476)) - by **[kobenguyent](https://github.com/kobenguyent)** + * run command + ![Screenshot 2024-09-02 at 15 25 20](https://github.com/user-attachments/assets/625c6b54-03f6-41c6-9d0c-cd699582404a) + + * run workers command +![Screenshot 2024-09-02 at 15 24 53](https://github.com/user-attachments/assets/efff0312-1229-44b6-a94f-c9b9370b9a64) + +🐛 *Bug Fixes* +* fix(AI): minor AI improvements - by **[DavertMik](https://github.com/DavertMik)** +* fix(AI): add missing await in AI.js ([#4486](https://github.com/codeceptjs/CodeceptJS/issues/4486)) - by **[tomaculum](https://github.com/tomaculum)** +* fix(playwright): no async save video page ([#4472](https://github.com/codeceptjs/CodeceptJS/issues/4472)) - by **[kobenguyent](https://github.com/kobenguyent)** +* fix(rest): httpAgent condition ([#4484](https://github.com/codeceptjs/CodeceptJS/issues/4484)) - by **[kobenguyent](https://github.com/kobenguyent)** +* fix: DataCloneError error when `I.executeScript` command is used with `run-workers` ([#4483](https://github.com/codeceptjs/CodeceptJS/issues/4483)) - by **[code4muktesh](https://github.com/code4muktesh)** +* fix: no error thrown from rerun script ([#4494](https://github.com/codeceptjs/CodeceptJS/issues/4494)) - by **[lin-brian-l](https://github.com/lin-brian-l)** + + +```js +// fix the validation of httpAgent config. we could now pass ca, instead of key/cert. +{ + helpers: { + REST: { + endpoint: 'http://site.com/api', + prettyPrintJson: true, + httpAgent: { + ca: fs.readFileSync(__dirname + '/path/to/ca.pem'), + rejectUnauthorized: false, + keepAlive: true + } + } + } +} +``` + +📖 *Documentation* +* doc(AI): minor AI improvements - by **[DavertMik](https://github.com/DavertMik)** + ## 3.6.5 ❤️ Thanks all to those who contributed to make this release! ❤️