带有反应和 google API 服务的赛普拉斯 - 如何存根自动完成

Cypress with react and google API services - how to stub autocomplete

我正在尝试测试一个反应 web 应用程序(在一个单独的项目中创建),它包含一个弹出窗口,其中有一个包含 google 城市自动完成的输入:

(因为语言原因我改了文字)

我在“搜索城市”中有一个文本输入,如果插入数据,google 搜索城市和 returns 结果(例如我搜索意大利罗马):

当我按下“保存数据”时,有一个功能会检查 google 结果,然后关闭弹出窗口:

在文件中:

export const useGoogleApiDesktop = () => {
    
    let autocompleteService
    
    if (window.google && window.google.maps) {
        autocompleteService = new window.google.maps.places.AutocompleteService()
    }
}

在另一个文件中(名为的文件):

const googleApi = useGoogleApiDesktop()

const onSubmitClick = useCallback(async () => {
        [...]
        const res: GoogleApiPlacesResponse = await googleApi.autocompleteService.getPlacePredictions({
            input: addressComputed,
            types: ['(cities)'],
            componentRestrictions: { country: 'it' }
        })
    }, [])

当我在普通浏览器中使用它时,一切正常; 但是如果我尝试用 cypress 启动它来测试它,它 returns 我这个错误:

我试图避免这个错误,只是继续并关闭弹出窗口,因为在我的测试期间,我不需要在该行上写任何东西;我只需要在其他文本区域上写点东西并关闭弹出窗口。

因为我做不到,所以我试图打断那个电话,但我完全不熟悉 cy.stub() 并且不起作用:

function selectAddress(bookingConfig) {
  // opens the popup  
  cy.get('.reservationsWhereAdd').click()

 
  // trying to add the google library
  const win = cy.state('window')
  const document = win.document
  const script = document.createElement('script')
  script.src = `https://maps.googleapis.com/maps/api/js?key=[myApiKey]&libraries=places&language=it`
  script.async = true

  // this is commented since I don't think I need it
  // window.initMap = function () {
  //   // JS API is loaded and available
  //   console.log('lanciato')
  // }

  // Append the ‘script’ element to ‘head’
  document.head.appendChild(script)

  // type something in some fields
  cy.get('#street').type(bookingConfig.street)
  cy.get('#streetNumber').type(bookingConfig.streetNum)
  cy.get('#nameOnTheDoorbell').type(bookingConfig.nameOnTheDoorbell)
  cy.get('#addressAlias').type(bookingConfig.addressAlias)

  // this correctly finds and prints the object
  console.log('--->', win.google.maps.places)


  cy.stub(googleApi.autocompleteService, 'getPlacePredictions')

  // this closes the popup
  cy.get('.flex-1 > .btn').click()

}

这个 cy.stub 但是不起作用,我不明白为什么:它说 googleApi is not defined

知道如何解决这个问题吗?谢谢!

更新:

错误后,使用cypress window,我手动关闭弹出窗口,重新打开,填写字段,然后点击保存数据。它起作用了,所以我在打开弹出窗口后添加了一个 cy.wait(1000),它在 95% 的时间里都起作用(9 次对 10 次)。关于如何“等待加载 google api,然后填写字段”的任何想法?

正如更新块所说,我发现问题在于加载 google API 的时间非常长,因为它不是本地的,需要时间来检索。

所以一开始我只是在执行我的代码之前放了一个cy.wait(2000);但这不是答案:如果我 运行 代码在慢速网络上会怎样?或者如果我的应用程序需要更多时间来加载?

所以,我创建了一个命令,首先等待 google API 加载;如果在 5 次尝试后加载失败,则测试失败。 然后,在那之后,我的代码正在执行。这样我的测试就不会轻易失败。

代码如下:

cypress/support/command.js

Cypress.Commands.add('waitForGoogleApi', () => {
  let mapWaitCount = 0
  const mapWaitMax = 5

  cyMapLoad()

  function cyMapLoad() {
    mapWaitCount++

    cy.window().then(win => {
      if (typeof win.google != 'undefined') {
        console.log(`Done at attempt #${mapWaitCount}:`, win)
        return true
      } else if (mapWaitCount <= mapWaitMax) {
        console.log('Waiting attempt #' + mapWaitCount) // just log
        cy.wait(2000)
        cyMapLoad()
      } else if (mapWaitCount > mapWaitMax) {
        console.log('Failed to load google api')
        return false
      }
    })
  }
})

在您要使用的文件中:

cy.waitForGoogleApi().then(() => {
    // here comes the code to execute after loading the google Apis
})