All Versions
156
Latest Version
Avg Release Cycle
18 days
Latest Release
10 days ago

Changelog History
Page 15

  • v0.18.0 Changes

    October 10, 2017

    ✨ Enhancements

    ✅ :gear: Testing in headless Firefox

    ✅ We have added support for headless testing in Firefox (version 56+) and Chrome.

    testcafe firefox:headless tests/sample-fixture.js
    
    runner
        .src('tests/sample-fixture.js')
        .browsers('firefox:headless')
        .run()
        .then(failedCount => {
            // ...
        });
    

    ✅ :gear: Outputting test results to multiple channels (#1412)

    ✅ You can now print a report in the console and saved it to a .json file by specifying multiple reporters when running tests.

    testcafe all tests/sample-fixture.js -r spec,json:report.json
    
    const stream = fs.createWriteStream('report.json');
    
    runner
        .src('tests/sample-fixture.js')
        .browsers('chrome')
        .reporter('spec')
        .reporter('json', stream)
        .run()
        .then(failedCount => {
            stream.end();
        });
    

    ✅ :gear: Entering the debug mode when a test fails (#1608)

    ✅ TestCafe can now automatically switch to the debug mode when a test fails. Test execution is paused so that you can explore the tested page to determine the failure's cause.

    💻 To enable this behavior, use the --debug-on-fail flag in the command line or the debugOnFail option in the API.

    testcafe chrome tests/fixture.js --debug-on-fail
    
    runner.run({ debugOnFail: true });
    

    ✅ :gear: Interacting with the tested page in debug mode (#1848)

    When debugging your tests, you can now interact with the tested page. Click the Unlock page button in the page footer to enable interaction.

    📄 [Unlock page button](docs/articles/images/unlock-page-button.png)

    Click Resume to continue running the test or click Next Step to skip to the next step.

    ✅ :gear: Chrome and Firefox are opened with clean profiles by default (#1623)

    ✅ TestCafe now opens Chrome and Firefox with empty profiles to eliminate profile settings' and extensions' influence on tests.

    However, you can return to the previous behavior using the :userProfile browser option.

    testcafe firefox:userProfile tests/test.js
    
    runner
        .src('tests/fixture1.js')
        .browsers('firefox:userProfile')
        .run();
    

    ✅ :gear: Customizable timeout to wait for the window.load event (#1645)

    💅 Previously, TestCafe started a test when the DOMContentLoaded event was raised. However, there are many pages that execute initialization code on the window.load event (which is raised after DOMContentLoaded because it waits for all stylesheets, images and subframes to load). In this case, you need to wait for the window.load event to fire before running tests.

    🚀 With this release, TestCafe waits 3 seconds for the window.load event. We have also added a pageLoadTimeout setting that allows you to customize this interval. You can set it to 0 to skip waiting for window.load.

    💻 The following examples show how to use the pageLoadTimeout setting from the command line and API:

    testcafe chrome test.js --page-load-timeout 0
    
    runner.run({
        pageLoadTimeout: 0
    });
    

    ✅ You can also use the setPageLoadTimeout method in the test API to set the timeout for an individual test.

    fixture `Page load timeout`
        .page `http://devexpress.github.io/testcafe/example/`;
    
    test(`Page load timeout`, async t => {
        await t
            .setPageLoadTimeout(0)
            .navigateTo('http://devexpress.github.io/testcafe/');
    });
    

    ✅ :gear: Access messages output by the tested app to the browser console (#1738)

    ✅ You can now obtain messages that the tested app outputs to the browser console. This is useful if your application or the framework it uses posts errors, warnings or other informative messages to the console.

    💻 Use the t.getBrowserConsoleMessages method that returns the following object:

    {
        error: ["Cannot access the 'db' database. Wrong credentials.", '...'], // error messages
        warn: ['The setTimeout property is deprecated', '...'],                // warning messages
        log: ['[09:12:08] Logged in', '[09:25:43] Changes saved', '...'],      // log messages
        info: ['The application was updated since your last visit.', '...']    // info messages
    }
    

    💻 Note that this method returns only messages posted via the console.error, console.warn, console.log and console.info methods. Messages the browser outputs (like when an unhandled exception occurs on the page) are not returned.

    📄 For instance, you can use React's typechecking feature, PropTypes, to check that you assigned valid values to the component's props. If a PropTypes rule is violated, React posts an error to the JavaScript console.

    💻 The following example shows how to check the React prop types for errors using the t.getBrowserConsoleMessages method:

    // check-prop-types.js
    import { t } from 'testcafe';
    
    export default async function () {
        const { error } = await t.getBrowserConsoleMessages();
    
        await t.expect(error[0]).notOk();
    }
    
    // test.js
    import { Selector } from 'testcafe';
    import checkPropTypes from './check-prop-types';
    
    fixture `react example`
        .page `http://localhost:8080/`  // https://github.com/mzabriskie/react-example
        .afterEach(() => checkPropTypes());
    
    test('test', async t => {
        await t
            .typeText(Selector('.form-control'), 'devexpress')
            .click(Selector('button').withText('Go'))
            .click(Selector('h4').withText('Organizations'));
    });
    

    ✅ :gear: Defining drag end point on the destination element (#982)

    The t.dragToElement action can now drop a dragged element at any point inside the destination element. You can specify the target point using the destinationOffsetX and destinationOffsetY options.

    import { Selector } from 'testcafe';
    
    const fileIcon      = Selector('.file-icon');
    const directoryPane = Selector('.directory');
    
    fixture `My Fixture`
        .page `https://example.com/`;
    
    test('My Test', async t => {
        await t
            .dragToElement(fileIcon, directoryPane, {
                offsetX: 10,
                offsetY: 10,
                destinationOffsetX: 100,
                destinationOffsetY: 50,
                modifiers: {
                    shift: true
                }
            });
    });
    

    ✅ :gear: TestCafe exits gracefully when the process is interrupted (#1378)

    ✅ Previously, TestCafe left browsers open when you exited the process by pressing Ctrl+C in the terminal. ✅ Now TestCafe exits gracefully closing all browsers opened for testing.

    🐛 Bug Fixes

    • ✅ Tests no longer hang in Nightmare (#1493)
    • ✅ The focus event is raised when clicking links with tabIndex="0" (#1803)
    • ✅ Headless Chrome processes no longer hang after test runs (#1826)
    • setFilesToUpload no longer throws a RangeError on websites that use Angular (#1731)
    • 🛠 Fixed a bug where an iframe got a wrong origin (#1753)
    • document.open does not throw an error if document.defaultView is null (testcafe-hammerhead/#1272)
    • ✅ No error is thrown when the handler passed to addEventListener is undefined (testcafe-hammerhead/#1251)
    • ✅ An error is no longer raised if the processed element is not extendible (testcafe-hammerhead/#1300)
    • 🛠 Fixed a bug where an onclick handler did not work after click on a Submit button (testcafe-hammerhead/#1291)
    • 💅 Images with style = background-image: url("img.png"); are loaded correctly (testcafe-hammerhead/#1212)
    • ✅ Documents can contain two ShadowUI roots (testcafe-hammerhead/#1246)
    • ✅ HTML in an overridden document.write function is processed correctly (testcafe-hammerhead/#1311)
    • ✅ Elements processing works for a documentFragment as it is added to the DOM (testcafe-hammerhead/#1334)
  • v0.17.2 Changes

    🐛 Bug Fixes

    • ✅ Taking a screenshot on teamcity agent works correctly (#1625)
    • 🐳 It is possible to run tests on remote devices from a docker container (#1728)
    • ✅ TestCafe compiles TypeScript tests correctly if Mocha or Jest typedefs are included in the project (#1537)
    • 🍎 Running on remote devices works correctly on MacOS (#1732)
    • ✅ A target directory is checked before creating a screenshot (#1551)
    • ✅ TypeScript definitions allow you to send any objects as dependencies for ClientFunctions (#1713)
    • ✅ The second MutationObserver callback argument is not missed (testcafe-hammerhead/#1268)
    • 🔗 Link's href property with an unsupported protocol is set correctly (testcafe-hammerhead/#1276)
    • ✅ The document.documentURI property is processed correctly in IE (testcafe-hammerhead/#1270)
    • JSON.stringify and Object.keys functions work properly for a MessageEvent instance (testcafe-hammerhead/#1277)
  • v0.17.1 Changes

    🐛 Bug Fixes

    • ✅ The hover action no longer fails for elements that hide on mouseover (#1679)
    • 📚 SelectText and SelectTextAreaContent TypeScript definitions match the documentation (#1697)
    • 🏁 TestCafe finds browsers installed for the current user on Windows (#1688)
    • ✅ TestCafe can resize MS Edge 15 window (#1517)
    • ✅ Google Chrome Canary has a dedicated chrome-canary alias (#1711)
    • 🏁 Test no longer hangs when takeScreenshot is called in headless Chrome Canary on Windows (#1685)
    • ✅ Tests fail if the uncaughtRejection exception is raised (#1473)
    • 🍎 TypeScript tests run on macOS with no errors (#1696)
    • ✅ The test duration is reported accurately (#1674)
    • ✅ XHR requests with an overridden setRequestHeader function returned by the XhrSandbox.openNativeXhr method are now handled properly (testcafe-hammerhead/#1252)
    • ✅ HTML in an overridden document.write function is now processed correctly (testcafe-hammerhead/#1218)
    • Object.assign is overridden (testcafe-hammerhead/#1208)
    • ✅ Scripts with async functions are processed correctly (testcafe-hammerhead/#1260)
  • v0.17.0 Changes

    ✨ Enhancements

    ✅ :gear: Testing Electron applications (testcafe-browser-provider-electron)

    ✅ We have created a browser provider that allows you to test Electron applications with TestCafe.

    🔌 To do this, install the browser provider plugin from npm:

    npm install testcafe-browser-provider-electron
    

    🔧 Create a .testcafe-electron-rc file that contains the Electron plugin's configurations. The only required setting here is mainWindowUrl. It is a URL (or path) to the main window page that relates to the application's directory.

    {
        "mainWindowUrl": "./index.html"
    }
    

    Place this file in the application root directory.

    Next, install the Electron module.

    npm install [email protected]
    

    ✅ You can now run tests. Specify the electron browser name and the application path ✅ when the test launches.

    testcafe "electron:/home/user/electron-app" "path/to/test/file.js"
    
    testCafe
        .createRunner()
        .src('path/to/test/file.js')
        .browsers('electron:/home/user/electron-app')
        .run();
    

    👀 Nota that you can also test the Electron app's executable files. See the plugin readme to learn more about the Electron browser provider.

    ✅ :gear: Concurrent test execution (#1165)

    ✅ We have added concurrent test launch. This makes a test batch complete faster.

    ✅ TestCafe launches one instance of each specified browser by default. Tests are run one by one in each of them.

    Enable concurrency and TestCafe launches multiple instances of each browser. It distributes the test batch among them. The tests are run in parallel.

    💻 To enable concurrency, add -cin the command line or use the runner.concurrency() API method. 💻 Specify the number of instances for each browser.

    testcafe -c 3 chrome tests/test.js
    
    var testRunPromise = runner
        .src('tests/test.js')
        .browsers('chrome')
        .concurrency(3)
        .run();
    

    📚 See Concurrent Test Execution for more details.

    ✅ :gear: Further improvements in automatic waiting mechanism (#1521)

    We have enhanced the waiting mechanism behavior in certain scenarios which required wait actions.

    ✅ :gear: User roles preserve the local storage (#1454)

    ✅ TestCafe now saves the local storage state when switching between roles. You get the same local storage content you left when you switch back.

    ✅ This is useful for testing websites that perform authentication via local storage instead of cookies.

    🐛 Bug Fixes

    • ✅ Selector's withAttribute method supports searching by strict match (#1548)
    • ✅ Description for the path parameter of the t.takeScreenshot action has been corrected (#1515)
    • ✅ Local storage is now cleaned appropriately after the test run.(#1546)
    • 💅 TestCafe now checks element visibility with a timeout when the target element's style.top is negative (#1185)
    • ✅ Fetching an absolute CORS URL now works correctly. (#1629)
    • ➕ Add partial support for proxying live node collections (the GetElementsByTagName method) (#1442)
    • 🐎 TypeScript performance has been enhanced. (#1591)
    • ✅ The right port is now applied to a cross-domain iframe location after redirect. (testcafe-hammerhead/#1191)
    • ✅ All internal properties are marked as non-enumerable. (testcafe-hammerhead/#1182)
    • 👌 Support proxying pages with defined referrer policy. (testcafe-hammerhead/#1195)
    • ✅ WebWorker content is now correctly proxied in FireFox 54. (testcafe-hammerhead/#1216)
    • ✅ Code instrumentation for the document.activeElement property works properly if it is null. (testcafe-hammerhead/#1226)
    • length, item and namedItem are no longer own properties of LiveNodeListWrapper. (testcafe-hammerhead/#1222)
    • ✅ The scope option in the serviceWorker.register function is processed correctly. (testcafe-hammerhead/#1233)
    • ✅ Promises from a fetch request are now processed correctly. (testcafe-hammerhead/#1234)
    • 🛠 Fix transpiling for the for..of loop to support browsers without window.Iterator. (testcafe-hammerhead/#1231)
  • v0.16.2 Changes

    🐛 Bug Fixes

    • ✅ Typing text now raises the onChange event in latest React versions. (#1558)
    • 🐳 Screenshots can now be taken when TestCafe runs from the Docker image. (#1540)
    • ✅ The native value property setters of HTMLInputElement and HTMLTextAreaElement prototypes are now saved. (testcafe-hammerhead/#1185)
    • ✅ The name and namedItem methods of an HTMLCollection are now marked as non-enumerable. (testcafe-hammerhead/#1172)
    • ✅ Code instrumentation of the length property runs faster. (testcafe-hammerhead/#979)
  • v0.16.1 Changes

    🐛 Bug Fixes

  • v0.16.0 Changes

    ✅ TypeScript support, seamless testing in headless Chrome and device emulator, and numerous bug fixes.

    ✨ Enhancements

    ✅ :gear: TypeScript support (#408)

    🚀 In this release, we have added the capability to write tests in TypeScript. By using TypeScript to write your TestCafe tests, you get the advantages of strongly-typed languages such as: rich coding assistance, painless scalability, check-as-you-type code verification, and much more.

    📦 TestCafe bundles TypeScript declaration file with the npm package, so you have no need to install any additional packages.

    Just create a .ts file with the

    <!-- Use js instead of ts for this code block for proper code highlighting -->

    import { Selector } from 'testcafe';
    

    ✅ and write your test.

    📚 For details, see TypeScript Support

    ✅ :gear: Support running in Chrome in headless mode and in device emulator (#1417)

    ✅ Now TestCafe allows you to run your tests in Google Chrome in headless and device emulation modes.

    ⚡️ Headless mode allows you to run tests in Chrome without any visible UI shell. To run tests in headless mode, use the :headless postfix:

    testcafe "chrome:headless" tests/sample-fixture.js
    

    📚 Device emulation mode allows you to check how your tests works on mobile devices via Chrome's built-in device emulator. To run tests in device emulation mode, specify emulation: and device parameters:

    testcafe "chrome:emulation:device=iphone 6" tests/sample-fixture.js
    

    📚 For details, see Using Chrome-specific Features.

    ✅ :gear: Support HTML5 Drag and Drop (#897)

    🚀 Starting with this release, TestCafe supports HTML5 drag and drop, so you can test elements with the draggable attribute.

    ✅ :gear: Fixed URL for opening remote browsers (#1476)

    📚 We have simplified the format of links that TestCafe generates when you run tests on remote browsers.

    ✅ Now, you have no need to type a unique link for each test run, all the links became constant. So, it is easier now to run tests on a remote device repeatedly: you can run them by navigating a link from your browser history.

    🐛 Bug Fixes

    • ✅ No TestCafe UI on screenshots created during testing (#1357)
    • 👀 mouseenter and mouseleave events are not triggered during cursor moving (#1426)
    • ✅ The runner's speed option affects the speed of doubleClick action (#1486)
    • ✅ Press action shortcuts work wrong if input's value ends with '.' or starts with '-.' (#1499)
    • ✅ A test report has too small line length on Travis (#1469)
    • ✅ Service messages with cookies do not have enough time to come to server before a new page is loaded (testcafe-hammerhead/#1086)
    • ✅ The window.history.replaceState function is overridden incorrectly (testcafe-hammerhead/#1146)
    • ✅ Hammerhead crashes if a script file contains a sourcemap comment (testcafe-hammerhead/#1052)
    • ✅ The proxy should override the DOMParser.parseFromString method (testcafe-hammerhead/#1133)
    • 🔀 The fetch method should emulate the native behaviour on merging headers (testcafe-hammerhead/#1116)
    • ✅ The EventSource requests are broken when used via proxy (testcafe-hammerhead/#1106)
    • ✅ The code processing may cause syntax errors in some cases because of wrong location property wrapping (testcafe-hammerhead/#1101)
    • ✅ When calling the fetch function without parameters, we should return its native result instead of window.Promise.reject (testcafe-hammerhead/#1099)
    • ✅ The querySelector function is overridden incorrectly (testcafe-hammerhead/#1131)
  • v0.15.0 Changes

    🔌 Plugins for React and Vue.js, TestCafe Docker image, support for Internet access proxies and lots of bug fixes.

    💥 Breaking Changes

    🆕 New calls to selector's withText method no longer override previous calls

    📚 We have changed the way the withText method behaves when it is called in a chain.

    const el = Selector('div').withText('This is').withText('my element');
    

    In previous versions, this selector searched for a div with text my element because the second call to withText overrode the first one.

    Now this code returns an element whose text contains both This is and my element as the second call compounds with the first one.

    ✨ Enhancements

    ✅ :gear: Plugin for testing React apps

    🚀 In this release cycle, we have created a plugin for testing React applications. 🔌 This plugin allows you to select React components by their names.

    import ReactSelector from 'testcafe-react-selector';
    
    const TodoList         = ReactSelector('TodoApp TodoList');
    const itemsCountStatus = ReactSelector('TodoApp div');
    const itemsCount       = ReactSelector('TodoApp div span');
    

    And it enables you to get React component's state and props.

    import ReactSelector from 'testcafe-react-selector';
    
    fixture `TODO list test`
        .page('http://localhost:1337');
    
    test('Check list item', async t => {
        const el = ReactSelector('TodoList');
    
        await t.expect(el.getReact().props.priority).eql('High');
        await t.expect(el.getReact().state.isActive).eql(false);
    });
    

    👀 To learn more, see the testcafe-react-selectors repository.

    ✅ :gear: Plugin for testing Vue.js apps

    🚀 In addition to the React plugin, we have released a plugin that facilitates testing Vue.js applications.

    In the same manner, it allows you to select Vue.js components with VueSelector selectors.

    import VueSelector from 'testcafe-vue-selectors';
    
    const rootVue   = VueSelector();
    const todoInput = VueSelector('todo-input');
    const todoItem  = VueSelector('todo-list todo-item');
    

    These selectors allow you to get Vue component's props, state and computed properties.

    import VueSelector from 'testcafe-vue-selector';
    
    fixture `TODO list test`
        .page('http://localhost:1337');
    
    test('Check list item', async t => {
        const todoItem = VueSelector('todo-item');
    
        await t
            .expect(todoItem.getVue().props.priority).eql('High')
            .expect(todoItem.getVue().state.isActive).eql(false)
            .expect(todoItem.getVue().computed.text).eql('Item 1');
    });
    

    👀 To learn more, see the testcafe-vue-selectors repository.

    🐳 :gear: TestCafe Docker image (#1141)

    🐳 We have created a Docker image with TestCafe, Chromium and Firefox preinstalled.

    ✅ You no longer need to manually install browsers or the testing framework on your server. 🐳 Pull the Docker image from the repository and run TestCafe immediately.

    docker pull testcafe/testcafe
    docker run -v //user/tests:/tests -it testcafe/testcafe firefox tests/**/*.js
    

    📚 To learn more, see Using TestCafe Docker Image

    ✅ :gear: Support for Internet access proxies (#1206)

    ✅ If your local network uses a proxy server to access the Internet, TestCafe can use it reach the external webpages.

    💻 To specify the proxy server, use a command line option

    testcafe chrome my-tests/**/*.js --proxy 172.0.10.10:8080
    

    or a method in the API.

    runner.useProxy('username:[email protected]');
    

    Note that you can pass the credentials with the proxy server host.

    ✅ :gear: Debugging mode option (#1347)

    📚 As an alternative to calling the t.debug method ✅ in test code, you can now specify the --debug-mode command line option to pause the test before the first action or assertion. ✅ When the test is paused, you can debug in the browser developer tools as well as continue test execution step by step.

    testcafe chrome my-tests/**/*.js --debug-mode
    

    ✅ If you use TestCafe API, provide the debugMode option to the runner.run method.

    runner.run({ debugMode: true });
    

    ✅ :gear: Filtering selector's matching set by attribute (#1346)

    You can now use the withAttribute method to select elements that have a particular attribute set to a specific value. You can omit the attribute value to select elements that simply have the specified attribute.

    const el = Selector('div').withAttribute('attributeName', 'value').nth(2);
    

    ✅ :gear: hasAttribute method added to DOM node state (#1045)

    For you convenience, the DOM node state object now provides the hasAttribute method that allows you to determine if an element has a particular attribute.

    const el = Selector('div.button');
    
    t.expect(el.hasAttribute('disabled')).ok();
    

    ✅ :gear: Redirection when switching between roles (#1339)

    📚 User roles now provide a preserveUrl option 💻 that allows you to save the webpage URL to which the browser was redirected after logging in. If you enable this option when creating a role, 💻 the browser will be redirected to the saved URL every time you switch to this role.

    const regularUser = Role(url, async t => {
        /* authentication code */
    }, { preserveUrl: true })
    

    🐛 Bug Fixes

    • 🛠 Fixed a bug where incorrect call site and callstack were generated for an assertion that failed in a class method (#1267)
    • ✅ Incorrect validation result no longer appears when a test controller is used inside an async function (#1285)
    • ✅ Click on the status panel no longer affects the page state (#1389)
    • ✅ The input event is now raised with a correct selection value when input value was changed (#1388)
    • ✅ Inline source maps are now placed in transpiled files so that breakpoints work correctly (#1375)
    • value and selectedIndex in the input event handler for the dropdown element are now valid (#1366)
    • ✅ A presskey('enter') call now raises the click event on a button element (#1424)
    • ✅ The cursor position in Monaco editor is now set correctly on the click action (#1385)
    • hasScroll now works correctly if the body has absolute positioning (#1353)
    • ✅ Text can now be typed into HTML5 input elements (#1327)
    • focusin and focusout events are now raised when the browser window is in the background (testcafe-hammerhead/#1044)
    • caretPositionFromPoint and caretRangeFromPoint now ignore TestCafe UI elements on the page (testcafe-hammerhead/#1084)
    • ✅ Images created with the Image constructor are now loaded through the proxy (testcafe-hammerhead/#1087)
    • 💅 The innerText return value is now clear of script and style code (testcafe-hammerhead/#1079)
    • ✅ Non-string values for element's text properties are now converted to String (testcafe-hammerhead/#1091)
    • ✅ SVG elements are now processed correctly in IE (testcafe-hammerhead/#1083)
  • v0.14.0 Changes

    🛠 Authentication via user roles, client-side debugging and numerous bug fixes.

    ✨ Enhancements

    ✅ :gear: Authentication via user roles (#243)

    ✅ Many test scenarios involve the activity of more than one user. TestCafe addresses these scenarios by providing a convenient way ✅ to isolate authentication test actions and apply them easily whenever you need to switch the user account.

    A piece of logic that logs in a particular user is called a role. It is a good practice to create a role for each user account participating in your test.

    Create roles via the Role constructor. You can keep them in a separate helper file.

    helper.js

    import { Role } from 'testcafe';
    
    export var regularAccUser = Role('http://example.com/login', async t => {
        await t
            .typeText('#login', 'TestUser')
            .typeText('#password', 'testpass')
            .click('#sign-in');
    });
    
    export var facebookAccUser = Role('http://example.com/login', async t => {
        await t
            .click('#sign-in-with-facebook')
            .typeText('#email', '[email protected]')
            .typeText('#pass', 'testpass')
            .click('#submit');
    });
    
    export var admin = Role('http://example.com/login', async t => {
        await t
            .typeText('#login', 'Admin')
            .typeText('#password', 'adminpass')
            .click('#sign-in');
    });
    

    ✅ In test code, use the t.useRole method to switch between roles.

    test.js

    import { regularAccUser, admin } from './helper';
    import { Selector } from 'testcafe';
    
    const entry        = Selector('#entry');
    const removeButton = Selector('#remove-entry');
    
    fixture `My Fixture`
        .page `http://example.com`;
    
    test('test that involves two users', async t => {
        await t
            .useRole(regularAccUser)
            .expect(entry.exists).ok()
            .expect(removeButton.visible).notOk()
            .useRole(admin)
            .expect(removeButton.visible).ok()
            .click(removeButton)
            .expect(entry.exists).notOk()
    });
    

    📚 To learn more, see User Roles.

    💻 :gear: BrowserStack support

    🚀 We have released the BrowserStack browser provider plugin.

    🔌 Install this plugin from npm.

    npm install testcafe-browser-provider-browserstack
    

    💻 And save the BrowserStack username and access key to environment variables BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY.

    ✅ Now you can run tests on any virtual machine available on BrowserStack.

    testcafe "browserstack:[email protected]:Windows 10" "path/to/test/file.js"
    

    ✅ :gear: Client-side debugging (#918)

    ✅ We have added a new t.debug method to debug test behavior on the client.

    ✅ When test execution reaches t.debug, it pauses so that you can open browser's developer tools 💅 and check the web page state, DOM elements location, their CSS styles.

    fixture `My fixture`
        .page `https://devexpress.github.io/testcafe/example`;
    
    test('My test', async t => {
        await t
            .debug()
            .setNativeDialogHandler(() => true)
            .click('#populate')
            .click('#submit-button');
    });
    

    ✅ In the footer, you'll find buttons that allow you to continue test execution or step to the next test action.

    [Page Footer in the Debug Mode](media/client-debugging-footer.png)

    ✅ TestCafe logs points in code where the debugger stopped.

    🌲 [Logging Debugger Breakpoints](media/log-debugger.png)

    ✅ :gear: Testing local webpages (#1286)

    📚 You can now run tests against local webpages. To do this, specify a URL with the file:// scheme or a relative path when calling the page function.

    fixture `MyFixture`
        .page `file:///user/my-website/index.html`;
    
    fixture `MyFixture`
        .page `../my-project/index.html`;
    

    📚 You can also navigate to local pages with the t.navigateTo action.

    fixture `My fixture`
        .page `http://www.example.com/`;
    
    test('Navigate to local pages', async t => {
        await t
            .navigateTo('file:///user/my-website/index.html')
            .navigateTo('../my-project/index.html');
    });
    

    ✅ :gear: Adding custom methods to the selector (#1212)

    📚 You can now extend selectors with custom methods executed on the client. Use the addCustomMethods method to provide custom methods.

    const myTable = Selector('.my-table').addCustomMethods({
        getCellText: (table, rowIndex, columnIndex) =>
            table.rows[rowIndex].cells[columnIndex].innerText
    });
    
    await t.expect(myTable.getCellText(1, 1)).contains('hey!');
    

    🏗 Use this feature to build selectors that reflect the specifics of your web app.

    ✅ :gear: Removing the native dialog handler (#243)

    📚 We have added the capability to remove a native dialog handler by passing null to the t.setNativeDialogHandler method.

    fixture `My fixture`
        .page `https://devexpress.github.io/testcafe/example`;
    
    test('My test', async t => {
        await t
            .setNativeDialogHandler(() => true)
            .click('#populate')
            .setNativeDialogHandler(null)
            .click('#submit-button');
    });
    

    🐛 Bug Fixes

    • 🛠 Fixed a bug that led to an incorrect callstack in test run report (#1226)
    • ✅ Cursor is now hidden on screenshots created using the t.takeScreenshot action (#1245)
    • ✅ Error no longer appears when selecting a non-existent child by index (#1240)
    • ✅ The blur event is now raised on time when an input is hidden in IE (#1275)
    • ✅ TestCafe no longer fails if a client function argument contains ES6 class method syntax (#1279)
    • ✅ TestCafe now reports errors that occur during browser provider initialization (#1282)
    • ✅ Click on the debugger panel no longer affects the tested page (#1200)
    • ✅ An unhandled error no longer occurs when running a fixture without tests (#1302)
    • ✅ The input event is now raised when the value of a select element is changed (#1311)
    • ✅ You can now perform actions with ShadowDOM elements (#1312)
    • ✅ Server no longer responds with status 222 when window.fetch() is called in Chrome (#1134)
    • ✅ The JSON reporter no longer returns screenshotPath: null if a screenshot path is not specified (#1269)
    • The navigateTo action no longer fails silently with schemes like http*string*:// (#965)
    • ✅ The SVG use tag is no longer broken when the parent page has a file:// URL (testcafe-hammerhead/#1051)
    • 🛠 Fixed a bug where toString was used instead of instanceToString from DOM utils (testcafe-hammerhead/#1055)
    • ✅ File download is no longer raised if the resource is fetched by setting the script src (testcafe-hammerhead/#1062)
    • 🛠 Fixed wrong CORS emulation for fetch requests (testcafe-hammerhead/#1059)
    • Navigator.sendBeacon function is now overridden (testcafe-hammerhead/#1035)
  • v0.13.0 Changes

    ✅ IDE plugins, fixture hooks, speed option for test actions, a couple of API enhancements and lots of bug fixes.

    ✨ Enhancements

    🔌 :gear: IDE Plugins

    🚀 With this release, we have prepared test runner plugins for ✅ VSCode and SublimeText. 🔌 These plugins allow you to

    • ✅ Run a particular test, fixture, all tests in a file or directory via the context menu or built-in commands,
    • 💻 Automatically detect browsers installed on the local machine,
    • ✅ Repeat last test run,
    • ✅ Debug tests,
    • ✅ View test results in the Debug Console panel.

    ✅ :gear: Fixture hooks (#903)

    ✅ You can now specify fixture hooks that will be executed before the first test in a fixture is started and after the last test is finished.

    fixture `My fixture`
        .page `http://example.com`
        .before( async ctx => {
            /* fixture initialization code */
        })
        .after( async ctx => {
            /* fixture finalization code */
        });
    

    ✅ Unlike test hooks, fixture hooks are executed between test runs and do not have access to the tested page. ✅ Use them to perform server-side operations like preparing the server that hosts the tested app.

    ✅ Sharing variables between fixture hooks and test code

    🛠 Use the ctx parameter passed to fixture.before and fixture.after methods (fixture context) to share values and objects with test code. You can assign to ctx parameter's properties or add new properties.

    ✅ In test code, use the t.fixtureCtx property to access the fixture context.

    fixture `Fixture1`
        .before(async ctx  => {
            ctx.someProp = 123;
        })
        .after(async ctx  => {
            console.log(ctx.newProp); // > abc
        });
    
    test('Test1', async t => {
        console.log(t.fixtureCtx.someProp); // > 123
    });
    
    test('Test2', async t => {
        t.fixtureCtx.newProp = 'abc';
    });
    

    ✅ :gear: Speed option for test actions (#865)

    ✅ You can now specify speed for individual test actions using the speed option.

    import { Selector } from 'testcafe';
    
    const nameInput = Selector('#developer-name');
    
    fixture `My Fixture`
        .page `http://devexpress.github.io/testcafe/example/`
    
    test('My Test', async t => {
        await t
            .typeText(nameInput, 'Peter')
            .typeText(nameInput, ' Parker', { speed: 0.1 });
    });
    

    ✅ If speed is also specified for the whole test, the action speed setting overrides test speed.

    ✅ :gear: Setting test speed from test code (#865)

    ✅ You can now specify test speed from code using the t.setTestSpeed method.

    import { Selector } from 'testcafe';
    
    fixture `Test Speed`
        .page `http://devexpress.github.io/testcafe/example/`;
    
    const nameInput = Selector('#developer-name');
    
    test(`Test Speed`, async t => {
        await t
            .typeText(nameInput, 'Peter')
            .setTestSpeed(0.1)
            .typeText(nameInput, ' Parker');
    });
    

    ✅ :gear: Using test controller outside of test code (#1166)

    📚 You may sometimes need to call test API from outside of test code. For instance, your page model ✅ can contain methods that perform common operations used in many tests, like authentication.

    import { Selector } from 'testcafe';
    
    export default class Page {
        constructor () {
            this.loginInput    = Selector('#login');
            this.passwordInput = Selector('#password');
            this.signInButton  = Selector('#sign-in-button');
        }
        async login (t) {
            await t
                .typeText(this.loginInput, 'MyLogin')
                .typeText(this.passwordInput, 'Pa$$word')
                .click(this.signInButton);
        }
    }
    

    ✅ In this instance, you need to access the test controller from the page model's login method.

    ✅ TestCafe allows you to avoid passing the test controller to the method explicitly. Instead, you can simply import t to the page model file.

    import { Selector, t } from 'testcafe';
    
    export default class Page {
        constructor () {
            this.loginInput    = Selector('#login');
            this.passwordInput = Selector('#password');
            this.signInButton  = Selector('#sign-in-button');
        }
        async login () {
            await t
                .typeText(this.loginInput, 'MyLogin')
                .typeText(this.passwordInput, 'Pa$$word')
                .click(this.signInButton);
        }
    }
    

    ✅ TestCafe will implicitly resolve test context and provide the right test controller.

    ✅ :gear: Inserting text with one keystroke with t.typeText action (by @ericyd) (#1230)

    The new paste option allows you to insert a portion of text with one keystroke, similar to the paste operation.

    import { Selector } from 'testcafe';
    
    fixture `My fixture`
        .page `http://devexpress.github.io/testcafe/example/`;
    
    const nameInput = Selector('#developer-name');
    
    test(`My test`, async t => {
        await t
            .typeText(nameInput, 'Peter')
            .typeText(nameInput, ' Parker', { paste: true });
    });
    

    ✅ :gear: prevSibling and nextSibling selector's DOM search methods (#1218)

    The new prevSibling and nextSibling methods allow you to search among sibling elements that reside before and after the selector's matching elements in the DOM tree.

    Selector('li .active').prevSibling(2);
    Selector('li').nextSibling('.checked');
    

    🚚 :gear: Deprecated functionality removed (#1167)

    🚚 The following deprecated members have been removed from the API.

    • t.select method - use Selector instead:
    const id = await t.select('.someClass').id;
    
    // can be replaced with
    
    const id = await Selector('.someClass').id;
    

    🐛 Bug Fixes

    • 🛠 Fixed a bug where tests failed with a script error (#1188)
    • ✅ Text can now be typed to an input field with type "email" in Firefox (#1187)
    • npm install no longer displays warnings (#769)
    • 🍎 Dev Tools can now be opened with a keyboard shortcut or right click on macOS (#1193)
    • ✅ A warning no longer appears when using ClientFunction with dependencies (#1168)
    • ✅ Tests can now run against React Storybook (#1147)
    • ✅ Script error is no longer thrown in iOS webviews (Firefox, Chrome of iOS) (#1189)
    • ✅ XhrSandbox.createNativeXHR now works correctly (testcafe-hammerhead/#1042)
    • ✅ Window.prototype is no longer used for NativeMethods initialization (testcafe-hammerhead/#1040)
    • ✅ Functions from the 'vm' module are now overridden on the client (testcafe-hammerhead/#1029)
    • ✅ Input type is now changed while setting the selection range in Firefox (testcafe-hammerhead/#1025)
    • ✅ An iframe with the about:blank src can now send postMessage (testcafe-hammerhead/#1026)
    • ✅ The formaction attribute is now overridden correctly after it is appended in DOM (testcafe-hammerhead/#1021)
    • 🛠 Fixed a bug where the Authorization Header was wrongly removed (testcafe-hammerhead/#1016)
    • ✅ The file:// protocol is now supported (testcafe-hammerhead/#908)