Testcafe: Error: 'replace' is not a function 2 hammerhead.js:6:2882

Created on 16 Mar 2020  路  6Comments  路  Source: DevExpress/testcafe


I'm getting "Error: 'replace' is not a function" after hitting a button inside a div that suppose to close it and proceed with the next step.

What is your Test Scenario?

I'm using testcafe version ^1.8.0.
I also tried with version v1.8.3-alpha.3.
Both have the same behavior.

The site is www.gap.com, I'm testing the checkout page, following steps (we are not really placing the order here, so don't worry with real data):

  1. Open www.gap.com
  2. Add any product to bag and proceed to checkout page;
  3. On checkout bag, do a guest checkout (enter any valid email);
  4. Proceed to shipping address and enter the following information (the street name is wrong intentionally, do not use auto fill or google address suggestion)
    Full name: test test
    street address: 2 Foolsom
    city: San Francisco
    state: California
    zip: 94105
  5. Hit the button "Continue to Payment" (I'm using Selector('#shippingAddress__button--add');)
  6. Hit the button "Accept Suggestion" (I'm using Selector('#addressConfirm').find('button').withText('ACCEPT SUGGESTION');)

Executing the steps manually it works fine.

Here is the code:

import { t, Selector } from 'testcafe';

const fldFullName = Selector('#addressForm__fullName');
const fldStreet = Selector('#addressForm__address');
const fldAptUnit = Selector('#addressForm__apt');
const fldTownCity = Selector('#addressForm__town');
const slcState = Selector('#addressForm__state');
const lblStateOption = slcState.find('option');
const fldZip = Selector('#addressForm__zip');
const fldPhone = Selector('#addressForm__phone');
const btnContinueToPayment = Selector('#shippingAddress__button--add');
const btnReviewOrder = Selector('#payment__savePayment--button');
const btnUseThisAddress = Selector('#addressConfirm__confirm--button');
const btnEditAddress = Selector('#addressConfirm__edit--button');
const btnAcceptSuggestion = Selector('#addressConfirm').find('button').withText('ACCEPT SUGGESTION');
const btnAddNewAddress = Selector('#shippingAddress__button--addnew');
const ckbAddress1 = Selector('#addressItem0');
const ckbAddressGroup = Selector('#shippingAddress__scrollContainer');

const ShippingAddressPanel = {
    fillNewAddress: async address => {
        await t
            .typeText(fldFullName, address.name)
            .typeText(fldStreet, address.street)
            .typeText(fldAptUnit, address.aptUnit)
            .typeText(fldTownCity, address.townCity)
            .click(slcState)
            .click(lblStateOption.withText(address.state))
            .typeText(fldZip, address.zip)
            .typeText(fldPhone, address.phone);

  await ShippingAddressPanel.clickContinueToPayment();
        await ShippingAddressPanel.clickReviewOrder();
    },

    fillNewAddressWithAvs: async address => {
        await t.typeText(fldFullName, address.name);
        await t.typeText(fldStreet, address.partialStreet, { speed: 0.1 });
        await t.pressKey('down');
        await t.pressKey('enter');
        await t.typeText(fldPhone, address.phone);
    },

    checkAvs: async address => {
        await t.expect(fldStreet.value).eql(address.street);
        await t.expect(fldTownCity.value).eql(address.townCity);
        await t.expect(slcState.value).eql(address.stateValue);
        await t.expect(fldZip.value).eql(address.zip);
    },

    selectExistingAddress: async () => await t.click(ckbAddress1),

    selectExistingAddressRandomly: async () => {
        await t.click(ckbAddressGroup.child(1));
        await t.click(ckbAddressGroup.child(2));
        await t.click(ckbAddressGroup.child(0));
    },

    clickAddNewAddress: async () => await t.click(btnAddNewAddress),

    clickReviewOrder: async () => {
        if (await btnReviewOrder.exists) {
            await t.click(btnReviewOrder);
        }
    },

    clickContinueToPayment: async () => {
        if (await btnContinueToPayment.exists) {
            await t.click(btnContinueToPayment);
        }
    },

    clickUseThisAddress: async () => {
        if (await btnUseThisAddress.exists) {
            await t.click(btnUseThisAddress);
        }
    },

    clickEditAddress: async () => {
        if (await btnEditAddress.exists) {
            await t.click(btnEditAddress);
        }
    },

    clickAcceptSuggestion: async () => {
        if (await btnAcceptSuggestion.exists) {
            await t.click(btnAcceptSuggestion);
        }
    }

};
module.exports = ShippingAddressPanel;

I'm calling the methods from another file in the following order:
fillNewAddress
clickAcceptSuggestion

What is the Current behavior?

On step 6, I'm getting the error message: Error: 'replace' is not a function 2 hammerhead.js:6:2882
with the following stacktrace:
Error: 'replace' is not a function 2 hammerhead.js:6:2882 _error http://192.168.0.13:51031/hammerhead.js:6 value http://192.168.0.13:51031/hammerhead.js:6 toTitleCase http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/main.chunk.js:9579 handleSubmit http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/main.chunk.js:29938 handleSubmit self-hosted:880 doSubmit http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:98523 handleSubmit http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:98598 submit http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:97170 submitIfNeeded http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:97270 componentWillReceiveProps http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:97395 callComponentWillReceiveProps http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:60605 updateClassInstance http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:60819 updateClassComponent http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:64673 beginWork$1 http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:66411 callCallback http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:46619 dispatchEvent http://192.168.0.13:51031/hammerhead.js:7 invokeGuardedCallbackDev http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:46668 invokeGuardedCallback http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:46721 beginWork$$1 http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:72006 performUnitOfWork http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:70923 workLoopSync http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:70896 performSyncWorkOnRoot http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:70485 performSyncWorkOnRoot self-hosted:920 flushSyncCallbackQueueImpl http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:58525 unstable_runWithPriority http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:102929 runWithPriority$2 http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:58471 flushSyncCallbackQueueImpl http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:58520 flushSyncCallbackQueue http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:58508 discreteUpdates$1 http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:70639 discreteUpdates http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:47719 dispatchDiscreteEvent http://192.168.0.13:51031/x0axw_dWK!s!utf-8/https://local.secure-www.gap.com/static/js/1.chunk.js:52156 dispatchDiscreteEvent self-hosted:977 l http://192.168.0.13:51031/hammerhead.js:14 _getEventListenerWrapper http://192.168.0.13:51031/hammerhead.js:7 dispatchEvent http://192.168.0.13:51031/hammerhead.js:7 _raiseDispatchEvent http://192.168.0.13:51031/hammerhead.js:8 _dispatchMouseEvent http://192.168.0.13:51031/hammerhead.js:8 _dispatchMouseRelatedEvents http://192.168.0.13:51031/hammerhead.js:8 l http://192.168.0.13:51031/hammerhead.js:8 _simulateEvent http://192.168.0.13:51031/hammerhead.js:8 click http://192.168.0.13:51031/hammerhead.js:8 run http://192.168.0.13:51031/testcafe-automation.js:1 _click http://192.168.0.13:51031/testcafe-automation.js:1 run http://192.168.0.13:51031/testcafe-automation.js:1 a http://192.168.0.13:51031/hammerhead.js:17 forEach self-hosted:235 d http://192.168.0.13:51031/hammerhead.js:17 p http://192.168.0.13:51031/hammerhead.js:17 n http://192.168.0.13:51031/hammerhead.js:17

What is the Expected behavior?

The modal should close and display the page normally.
Same behavior as we do manually.

What is聽your web application and聽your TestCafe聽test code?

www.gap.com

code included above.
I'm happy on providing more information and help debugging the issue. Just let me know what you need :)
Thanks a lot guys <3

Website screenshot:
Screen Shot 2020-03-16 at 8 49 46 AM

Video with the issue:
replaceErrorMessage

Steps to Reproduce:

described above.

Your Environment details:

  • testcafe version: 1.8.2
  • node.js version: v10.16.3
  • command-line arguments: testcafe firefox --selector-timeout 19000 --page-load-timeout 10000 ./e2etest/testCafe/specs/*.test.js --skip-js-errors --ignore-certificate-errors -e -S -s ./e2etest/testCafe/screenshots
  • browser name and version: Firefox 74.0 (64-bit)
  • platform and version: macOS Catalina 10.15.1 (19B88)
Auto-locked question

Most helpful comment

Thank you for provided codebase. Now I can see the error. We will research it and notify you as soon as we have any result.

All 6 comments

I followed these steps but was unable to reproduce the issue. Could you please clarify if you got the error with this website or with locally published debug scripts? Also, attach a full test sample where we could reproduce the issue.

Hi @Dmitry-Ostashev ,

Here is the complete codebase: https://github.com/raptatinha/testcafeSample

You can do:

  1. git clone https://github.com/raptatinha/testcafeSample.git
  2. cd testcafeSample
  3. npm install
  4. npm run test:testcafe-dev

The test will fail with: "The specified selector does not match any element in the DOM tree.
聽> | Selector('#payment__field--cc')"

This is because the error mentioned (Error: 'replace' is not a function 2 hammerhead.js:6:2882) is thrown right after executing "await ShippingAddressPanel.clickAcceptSuggestion();" file commons.page.js line 123 (I left a comment there).

If you debug , add 2 breakpoints on file commons.page.js line 123 and 124, open the browse console before executing line 123 and you should see the error mentioned (Error: 'replace' is not a function 2 hammerhead.js:6:2882)
For debugging, open avs.test.js and hit the debug start button on VS Code. I already added the debug settings there.

Thanks and let me know if anything else is needed.

Thank you for provided codebase. Now I can see the error. We will research it and notify you as soon as we have any result.

This error is reproduced on the origin site:

err

The place, where the error occurs:

code

e.apt is a number and equal to 1 and has not the replace method.

Thank you guys!
Sorry for making you spend time with it.

This thread has been automatically locked since it is closed and there has not been any recent activity. Please open a new issue for related bugs or feature requests. We recommend you ask TestCafe API, usage and configuration inquiries on StackOverflow.

Was this page helpful?
0 / 5 - 0 ratings