mirror of
https://github.com/utopia-os/utopia-ui.git
synced 2026-01-13 16:34:31 +00:00
fix(other): improve e2e test reliability with API mocking and race condition fixes (#621)
This commit is contained in:
parent
a4d8bbeae8
commit
b9bab44274
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,3 +5,4 @@ cypress/node_modules/
|
||||
cypress/results/
|
||||
cypress/runner-results/
|
||||
cypress/screenshots/
|
||||
|
||||
|
||||
99
backend/prepare-seed.js
Normal file
99
backend/prepare-seed.js
Normal 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()
|
||||
|
||||
@ -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 \
|
||||
|
||||
@ -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')
|
||||
})
|
||||
|
||||
|
||||
@ -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)
|
||||
})
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user