diff --git a/e2e/USER_STORIES.md b/e2e/USER_STORIES.md index a6ed3766..9e55059a 100644 --- a/e2e/USER_STORIES.md +++ b/e2e/USER_STORIES.md @@ -1560,14 +1560,14 @@ Acceptance: ### US-131 — Say where you are and find members on a map -As a member, I want to give a town, state or country on my profile and see where +As a member, I want to give a city, state or country on my profile and see where the rest of a space is, so that I can find the people near me. Acceptance: -- The location field on the profile form searches places by name, leaves out - towns of under a thousand people, and publishes what was picked to kind 0. -- Choosing a town publishes a geohash with it; choosing a state or a country +- The location field on the profile form searches places by name, offers cities, + states and countries, and publishes what was picked to kind 0. +- Choosing a city publishes a geohash with it; choosing a state or a country publishes the name alone, so nothing finer than the answer given goes out. - The directory offers a map whenever a member has a geohash, pins each of them with their avatar, and opens a pin's profile when it is clicked. diff --git a/e2e/harness/net/http.ts b/e2e/harness/net/http.ts index 89d3e07c..ecfa9b55 100644 --- a/e2e/harness/net/http.ts +++ b/e2e/harness/net/http.ts @@ -19,9 +19,6 @@ const PLAUSIBLE_ORIGIN = "https://plausible.coracle.social" // Transcription and speech both go here, against whichever key the user has saved. const OPENROUTER_ORIGIN = "https://openrouter.ai" -// The place search behind the profile's location field, in src/app/location.ts. -const GEOCODING_ORIGIN = "https://geocoding-api.open-meteo.com" - // .test resolves nowhere and the block-all aborts the navigation, so a spec sees the redirect. const CHECKOUT_ORIGIN = "https://checkout.test" @@ -618,20 +615,28 @@ export const mockLivekit = (context: BrowserContext, {serverUrl, token}: Livekit }, ) -// One row of Open-Meteo's answer. `feature_code` is PCLI for a country and PPL* for a town. +// One row of Photon's answer. Anything but a city, state or country is left out of the results. export type GeocodedPlace = { + type: string name: string - admin1?: string + state?: string country?: string - feature_code: string - population?: number latitude: number longitude: number } -/** The place search, answering every term with the same places. */ -export const mockGeocoding = (context: BrowserContext, results: GeocodedPlace[]) => - context.route(`${GEOCODING_ORIGIN}/**`, route => route.fulfill({json: {results}})) +/** The place search behind the profile's location field, answering every term with the same places. */ +export const mockGeocoding = (context: BrowserContext, places: GeocodedPlace[]) => + context.route("https://photon.komoot.io/**", route => + route.fulfill({ + json: { + features: places.map(({type, name, state, country, latitude, longitude}) => ({ + geometry: {coordinates: [longitude, latitude]}, + properties: {type, name, state, country}, + })), + }, + }), + ) /** Serves a png for anything loaded as an image, so a fixture's avatar and blob urls are never fetched. */ export const mockImages = (context: BrowserContext) => diff --git a/e2e/specs/people.spec.ts b/e2e/specs/people.spec.ts index faadf8dd..6b9323a2 100644 --- a/e2e/specs/people.spec.ts +++ b/e2e/specs/people.spec.ts @@ -652,22 +652,27 @@ test("US-131 say where you are and find members on a map", async ({seed, as}) => await mockGeocoding(page.context(), [ { + type: "city", name: "Portland", - admin1: "Oregon", + state: "Oregon", country: "United States", - feature_code: "PPLA2", - population: 652503, latitude: 45.52345, longitude: -122.67621, }, { - name: "Portlaw", - admin1: "Munster", - country: "Ireland", - feature_code: "PPL", - population: 900, - latitude: 52.28833, - longitude: -7.32056, + type: "state", + name: "Oregon", + country: "United States", + latitude: 43.93179, + longitude: -120.76562, + }, + { + type: "street", + name: "Portland Avenue", + state: "Oregon", + country: "United States", + latitude: 45.51, + longitude: -122.65, }, ]) @@ -679,10 +684,13 @@ test("US-131 say where you are and find members on a map", async ({seed, as}) => const form = await openEditForm() - await form.getByPlaceholder("Search for a town").fill("portl") + await form.getByPlaceholder("Search for a city").fill("portl") - // A town of under a thousand people is not somewhere to be from. - await expect(form.getByRole("button", {name: "Portlaw, Munster, Ireland"})).toHaveCount(0) + // A state is a place to be from; a street is not. + await expect(form.getByRole("button", {name: "Oregon, United States"})).toBeVisible() + await expect( + form.getByRole("button", {name: "Portland Avenue, Oregon, United States"}), + ).toHaveCount(0) await form.getByRole("button", {name: "Portland, Oregon, United States"}).click() await form.getByRole("button", {name: "Save Changes"}).click() @@ -725,7 +733,7 @@ test("US-131 say where you are and find members on a map", async ({seed, as}) => await expect(pins).toHaveCount(0) - // A country is not a pin, so choosing one takes alice off the map. + // A state is not a pin, so choosing one takes alice off the map. await page.goto(profilePath(users.alice.pubkey)) const secondForm = await openEditForm() @@ -733,18 +741,14 @@ test("US-131 say where you are and find members on a map", async ({seed, as}) => await expect(secondForm.getByText("Portland, Oregon, United States")).toBeVisible() await secondForm.getByRole("button", {name: "Clear location"}).click() - await secondForm.getByPlaceholder("Search for a town").fill("portl") - await secondForm.getByRole("button", {name: "Portland, Oregon, United States"}).click() - await secondForm.getByLabel("How much of your location to show").selectOption({label: "Country"}) - - await expect(secondForm.getByText("United States", {exact: true})).toBeVisible() - + await secondForm.getByPlaceholder("Search for a city").fill("oreg") + await secondForm.getByRole("button", {name: "Oregon, United States"}).click() await secondForm.getByRole("button", {name: "Save Changes"}).click() await expect(page.getByRole("alert")).toContainText("Your profile has been updated!") const republished = getPublishedEvents(page.context(), PROFILE) - expect(JSON.parse(republished[1].content).location).toBe("United States") + expect(JSON.parse(republished[1].content).location).toBe("Oregon, United States") expect(republished[1].tags.map(tag => tag[0])).not.toContain("g") }) diff --git a/src/app/components/InputLocation.svelte b/src/app/components/InputLocation.svelte index e0031520..1876f104 100644 --- a/src/app/components/InputLocation.svelte +++ b/src/app/components/InputLocation.svelte @@ -1,19 +1,12 @@ {#if location} -
-
- - {location} - -
- {#if place} - - {/if} +
+ + {location} +
{:else}
{#if failed}

Location search is unavailable right now.

{:else if results.length > 0}