fix(other): improve e2e test reliability with API mocking and race condition fixes (#621)

This commit is contained in:
mahula 2025-12-16 21:12:08 +01:00 committed by GitHub
parent a4d8bbeae8
commit b9bab44274
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 175 additions and 1 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@ cypress/node_modules/
cypress/results/
cypress/runner-results/
cypress/screenshots/

99
backend/prepare-seed.js Normal file
View File

@ -0,0 +1,99 @@
#!/usr/bin/env node
/**
* Prepares seed data by updating event dates relative to the current date.
*
* This script modifies items.json in-place, updating all items with
* layer "layer-events" to have realistic start/end dates that ensure
* events are visible in the app (end dates in the future).
*
* Date strategy:
* - Event 1 (item-event-1): Long-running, started 30 days ago, ends in 365 days
* - Event 2 (item-event-2): Upcoming single-day event in 7 days
* - Event 3 (item-event-3): Ongoing event, started yesterday, ends tomorrow
* - Event 4 (item-event-4): Upcoming multi-day conference in 30 days
*/
const fs = require('fs')
const path = require('path')
const seedPath = path.join(__dirname, 'directus-config/development/seed/items.json')
function addDays(date, days) {
const result = new Date(date)
result.setDate(result.getDate() + days)
return result
}
function addHours(date, hours) {
const result = new Date(date)
result.setHours(result.getHours() + hours)
return result
}
function formatDateTime(date) {
return date.toISOString().slice(0, 19)
}
/**
* Calculate dynamic dates for each event based on current time
*/
function getEventDates(syncId, now) {
const dateConfigs = {
// "Some Event" - long-running, started in past, ends far in future
'item-event-1': {
start: addDays(now, -30),
end: addDays(now, 365)
},
// "Tech Meetup Munich" - upcoming single-day event (the one used in search tests)
'item-event-2': {
start: addHours(addDays(now, 7), 18),
end: addHours(addDays(now, 7), 21)
},
// "Sustainability Workshop NYC" - ongoing event (started yesterday, ends tomorrow)
'item-event-3': {
start: addHours(addDays(now, -1), 14),
end: addHours(addDays(now, 1), 17)
},
// "Open Source Conference" - upcoming multi-day conference
'item-event-4': {
start: addHours(addDays(now, 30), 9),
end: addHours(addDays(now, 32), 18)
}
}
return dateConfigs[syncId] || null
}
function prepareSeedData() {
// Read the current items.json
const content = fs.readFileSync(seedPath, 'utf8')
const seedData = JSON.parse(content)
const now = new Date()
let updatedCount = 0
// Update event items with dynamic dates
for (const item of seedData.data) {
if (item.layer === 'layer-events' && item._sync_id) {
const dates = getEventDates(item._sync_id, now)
if (dates) {
item.start = formatDateTime(dates.start)
item.end = formatDateTime(dates.end)
console.log(` ${item._sync_id} (${item.name}):`)
console.log(` start: ${item.start}`)
console.log(` end: ${item.end}`)
updatedCount++
}
}
}
// Write back to items.json
fs.writeFileSync(seedPath, JSON.stringify(seedData, null, 4))
console.log(`\nUpdated ${updatedCount} event(s) with dynamic dates.`)
}
console.log('Preparing seed data with dynamic dates...\n')
prepareSeedData()

View File

@ -15,6 +15,9 @@ PGDATABASE="${PGDATABASE:-'directus'}"
PROJECT_NAME="${PROJECT:-development}"
PROJECT_FOLDER=$SCRIPT_DIR/directus-config/$PROJECT_NAME
echo "Preparing seed data with dynamic dates"
node $SCRIPT_DIR/prepare-seed.js || exit 1
echo "Seed data"
npx directus-sync@3.4.0 seed push \
--seed-path $PROJECT_FOLDER/seed \

View File

@ -74,7 +74,7 @@ describe('Utopia Map Search', () => {
cy.contains('Wat Arun').first().click()
})
cy.get('.leaflet-popup').should('be.visible')
cy.get('.leaflet-popup', { timeout: 15000 }).should('exist')
cy.get('.leaflet-popup-content').should('contain', 'Wat Arun')
})

View File

@ -76,6 +76,12 @@ Cypress.Commands.add('searchFor', (query: string) => {
Cypress.Commands.add('waitForMapReady', () => {
cy.get('[data-cy="search-input"]', { timeout: 10000 }).should('be.visible')
cy.get('.leaflet-container', { timeout: 10000 }).should('be.visible')
cy.wait('@getLayers', { timeout: 15000 }).then((interception) => {
const layerCount = interception.response?.body?.data?.length || 3
for (let i = 0; i < layerCount; i++) {
cy.wait('@getLayerItems', { timeout: 15000 })
}
})
cy.get('.leaflet-marker-icon', { timeout: 15000 }).should('have.length.at.least', 1)
})

View File

@ -5,6 +5,71 @@ import './commands'
// for screenshot embedding
import addContext from 'mochawesome/addContext'
const photonMockData: Record<string, object> = {
berlin: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {
osm_type: 'R',
osm_id: 62422,
osm_key: 'place',
osm_value: 'city',
type: 'city',
countrycode: 'DE',
name: 'Berlin',
country: 'Germany',
state: 'Berlin',
extent: [13.088345, 52.6755087, 13.7611609, 52.3382448],
},
geometry: { type: 'Point', coordinates: [13.3951309, 52.5173885] },
},
],
},
'wat arun': {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {
osm_type: 'W',
osm_id: 25867629,
osm_key: 'tourism',
osm_value: 'attraction',
type: 'attraction',
countrycode: 'TH',
name: 'Wat Arun',
country: 'Thailand',
city: 'Bangkok',
extent: [100.4882, 13.7437, 100.4912, 13.7407],
},
geometry: { type: 'Point', coordinates: [100.4897, 13.7437] },
},
],
},
}
beforeEach(() => {
cy.intercept('GET', 'https://photon.komoot.io/api/*', (req) => {
const url = new URL(req.url)
const query = (url.searchParams.get('q') || '').toLowerCase()
const mockKey = Object.keys(photonMockData).find((key) =>
query.includes(key.toLowerCase()),
)
if (mockKey) {
req.reply(photonMockData[mockKey])
} else {
req.reply({ type: 'FeatureCollection', features: [] })
}
}).as('photonApi')
cy.intercept('GET', '**/items/layers*').as('getLayers')
cy.intercept('GET', '**/items/items*').as('getLayerItems')
})
// Global exception handler
Cypress.on('uncaught:exception', (err) => {
// eslint-disable-next-line no-console