mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2026-03-01 12:44:17 +00:00
add itemsearch tests to cypress search testing
This commit is contained in:
parent
81349e299b
commit
eeee4b9d01
50
cypress/e2e/search/item-search.cy.ts
Normal file
50
cypress/e2e/search/item-search.cy.ts
Normal file
@ -0,0 +1,50 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
describe('Utopia Map Item Search', () => {
|
||||
beforeEach(() => {
|
||||
cy.clearCookies()
|
||||
cy.clearLocalStorage()
|
||||
cy.window().then((win) => {
|
||||
win.sessionStorage.clear()
|
||||
})
|
||||
|
||||
cy.visit('/')
|
||||
cy.waitForMapReady()
|
||||
})
|
||||
|
||||
it('should find items by exact name match', () => {
|
||||
cy.searchFor('Tech Meetup Munich')
|
||||
cy.get('[data-cy="search-suggestions"]').should('contain', 'Tech Meetup Munich')
|
||||
})
|
||||
|
||||
it('should find items by partial name match (case insensitive)', () => {
|
||||
cy.searchFor('café collaboration')
|
||||
cy.get('[data-cy="search-suggestions"]').should('contain', 'Café Collaboration London')
|
||||
})
|
||||
|
||||
it('should find items by text content', () => {
|
||||
cy.searchFor('sustainability')
|
||||
cy.get('[data-cy="search-suggestions"]').should('contain', 'Alex Entrepreneur')
|
||||
})
|
||||
|
||||
it('should navigate to item profile when clicking search result', () => {
|
||||
cy.intercept('GET', '**/items*').as('getItems')
|
||||
|
||||
cy.visit('/')
|
||||
cy.waitForMapReady()
|
||||
|
||||
cy.searchFor('makerspace')
|
||||
cy.get('[data-cy="search-suggestions"]').within(() => {
|
||||
cy.get('[data-cy="search-item-result"]').contains('Makerspace Tokyo').click()
|
||||
})
|
||||
|
||||
cy.url().should('match', /\/(item\/|[a-f0-9-]+)/)
|
||||
cy.get('body').should('contain', 'Makerspace Tokyo')
|
||||
|
||||
// Verify search uses local filtering (items already loaded)
|
||||
cy.get('@getItems.all').then((calls) => {
|
||||
expect(calls.length).to.be.greaterThan(0)
|
||||
})
|
||||
})
|
||||
|
||||
})
|
||||
@ -87,6 +87,7 @@ export default tseslint.config(
|
||||
'cypress/downloads/**',
|
||||
'cypress/screenshots/**',
|
||||
'cypress/videos/**',
|
||||
'results/**',
|
||||
'dist/**',
|
||||
'build/**',
|
||||
'*.min.js'
|
||||
|
||||
@ -22,6 +22,43 @@ declare global {
|
||||
* @example cy.waitForMapReady()
|
||||
*/
|
||||
waitForMapReady(): Chainable<Element>
|
||||
|
||||
/**
|
||||
* Click on a map marker
|
||||
* @example cy.clickMarker() // clicks first marker
|
||||
*/
|
||||
clickMarker(): Chainable<Element>
|
||||
|
||||
/**
|
||||
* Wait for a popup to appear on the map
|
||||
* @example cy.waitForPopup()
|
||||
*/
|
||||
waitForPopup(): Chainable<Element>
|
||||
|
||||
/**
|
||||
* Close the currently open popup
|
||||
* @example cy.closePopup()
|
||||
*/
|
||||
closePopup(): Chainable<Element>
|
||||
|
||||
/**
|
||||
* Toggle a layer's visibility in the layer control
|
||||
* @param layerName - Name of the layer to toggle
|
||||
* @example cy.toggleLayer('places')
|
||||
*/
|
||||
toggleLayer(layerName: string): Chainable<Element>
|
||||
|
||||
/**
|
||||
* Open the layer control panel
|
||||
* @example cy.openLayerControl()
|
||||
*/
|
||||
openLayerControl(): Chainable<Element>
|
||||
|
||||
/**
|
||||
* Close the layer control panel
|
||||
* @example cy.closeLayerControl()
|
||||
*/
|
||||
closeLayerControl(): Chainable<Element>
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -42,4 +79,30 @@ Cypress.Commands.add('waitForMapReady', () => {
|
||||
cy.get('.leaflet-marker-icon', { timeout: 15000 }).should('have.length.at.least', 1)
|
||||
})
|
||||
|
||||
Cypress.Commands.add('clickMarker', () => {
|
||||
// For now, always use force click since markers might be clustered or outside viewport
|
||||
cy.get('.leaflet-marker-icon').first().click({ force: true })
|
||||
})
|
||||
|
||||
Cypress.Commands.add('waitForPopup', () => {
|
||||
cy.get('[data-cy="item-popup"]', { timeout: 10000 }).should('be.visible')
|
||||
})
|
||||
|
||||
Cypress.Commands.add('closePopup', () => {
|
||||
cy.get('.leaflet-popup-close-button').click()
|
||||
})
|
||||
|
||||
Cypress.Commands.add('toggleLayer', (layerName: string) => {
|
||||
cy.get(`[data-cy="layer-checkbox-${layerName}"]`).click()
|
||||
})
|
||||
|
||||
Cypress.Commands.add('openLayerControl', () => {
|
||||
cy.get('[data-cy="layer-control-button"]').click()
|
||||
cy.get('[data-cy="layer-control-panel"]', { timeout: 5000 }).should('be.visible')
|
||||
})
|
||||
|
||||
Cypress.Commands.add('closeLayerControl', () => {
|
||||
cy.get('[data-cy="layer-control-close"]').click()
|
||||
})
|
||||
|
||||
export {}
|
||||
|
||||
@ -113,6 +113,7 @@ export const SearchControl = () => {
|
||||
autoComplete='off'
|
||||
value={value}
|
||||
className='tw:input tw:input-bordered tw:h-12 tw:grow tw:shadow-xl tw:rounded-box tw:pr-12 tw:w-full'
|
||||
data-cy='search-input'
|
||||
ref={searchInput}
|
||||
onChange={(e) => setValue(e.target.value)}
|
||||
onFocus={() => {
|
||||
@ -124,6 +125,7 @@ export const SearchControl = () => {
|
||||
{value.length > 0 && (
|
||||
<button
|
||||
className='tw:btn tw:btn-sm tw:btn-circle tw:absolute tw:right-2 tw:top-2'
|
||||
data-cy='search-clear-button'
|
||||
onClick={() => setValue('')}
|
||||
>
|
||||
✕
|
||||
@ -140,13 +142,14 @@ export const SearchControl = () => {
|
||||
value.length === 0 ? (
|
||||
''
|
||||
) : (
|
||||
<div className='tw:card tw:card-body tw:bg-base-100 tw:p-4 tw:mt-2 tw:shadow-xl tw:overflow-y-auto tw:max-h-[calc(100dvh-152px)] tw:absolute tw:z-3000 tw:w-83'>
|
||||
<div className='tw:card tw:card-body tw:bg-base-100 tw:p-4 tw:mt-2 tw:shadow-xl tw:overflow-y-auto tw:max-h-[calc(100dvh-152px)] tw:absolute tw:z-3000 tw:w-83' data-cy='search-suggestions'>
|
||||
{tagsResults.length > 0 && (
|
||||
<div className='tw:flex tw:flex-wrap'>
|
||||
{tagsResults.slice(0, 3).map((tag) => (
|
||||
<div
|
||||
key={tag.name}
|
||||
className='tw:rounded-2xl tw:text-white tw:p-1 tw:px-4 tw:shadow-md tw:card tw:mr-2 tw:mb-2 tw:cursor-pointer'
|
||||
data-cy='search-tag-result'
|
||||
style={{ backgroundColor: tag.color }}
|
||||
onClick={() => {
|
||||
addFilterTag(tag)
|
||||
@ -165,6 +168,7 @@ export const SearchControl = () => {
|
||||
<div
|
||||
key={item.id}
|
||||
className='tw:cursor-pointer tw:hover:font-bold tw:flex tw:flex-row'
|
||||
data-cy='search-item-result'
|
||||
onClick={() => {
|
||||
const marker = Object.entries(leafletRefs).find((r) => r[1].item === item)?.[1]
|
||||
.marker
|
||||
@ -178,7 +182,7 @@ export const SearchControl = () => {
|
||||
}}
|
||||
>
|
||||
{item.layer?.markerIcon.image ? (
|
||||
<div className='tw:w-7 tw:h-full tw:flex tw:justify-center tw:items-center'>
|
||||
<div className='tw:w-7 tw:h-full tw:flex tw:justify-center tw:items-center' data-cy='search-item-icon'>
|
||||
<SVG
|
||||
src={appState.assetsApi.url + item.layer.markerIcon.image}
|
||||
className='tw:text-current tw:mr-2 tw:mt-0'
|
||||
@ -191,7 +195,7 @@ export const SearchControl = () => {
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className='tw:w-7' />
|
||||
<div className='tw:w-7' data-cy='search-item-icon-placeholder' />
|
||||
)}
|
||||
<div>
|
||||
<div className='tw:text-sm tw:overflow-hidden tw:text-ellipsis tw:whitespace-nowrap tw:max-w-[17rem]'>
|
||||
@ -207,6 +211,7 @@ export const SearchControl = () => {
|
||||
{Array.from(geoResults).map((geo) => (
|
||||
<div
|
||||
className='tw:flex tw:flex-row tw:hover:font-bold tw:cursor-pointer'
|
||||
data-cy='search-geo-result'
|
||||
key={Math.random()}
|
||||
onClick={() => {
|
||||
searchInput.current?.blur()
|
||||
@ -262,6 +267,7 @@ export const SearchControl = () => {
|
||||
{isGeoCoordinate(value) && (
|
||||
<div
|
||||
className='tw:flex tw:flex-row tw:hover:font-bold tw:cursor-pointer'
|
||||
data-cy='search-coordinate-result'
|
||||
onClick={() => {
|
||||
marker(
|
||||
new LatLng(extractCoordinates(value)![0], extractCoordinates(value)![1]),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user