From 6102985d757ead0e4cde9e075956a56c8914599e Mon Sep 17 00:00:00 2001 From: Olga Bulat Date: Tue, 5 Dec 2023 18:07:39 +0300 Subject: [PATCH] Add additional search view pages to the Nuxt app (#3140) * Add and update unit tests * Add collections to the search&media stores & service Signed-off-by: Olga Bulat * Add collection page Signed-off-by: Olga Bulat * Add POC media fetching and collection header Signed-off-by: Olga Bulat * Make page matching more strict and set up page Signed-off-by: Olga Bulat * Add a test to validate-collection-params Signed-off-by: Olga Bulat * Do not show "0 results found" before fetch finished Signed-off-by: Olga Bulat * Use getCollectionPath from search store Signed-off-by: Olga Bulat * Simplify pages Signed-off-by: Olga Bulat * Fix load more Signed-off-by: Olga Bulat * Reset search state Signed-off-by: Olga Bulat * Set back to results path in single-result middleware Signed-off-by: Olga Bulat * Fix paddings Signed-off-by: Olga Bulat * Use Results type Signed-off-by: Olga Bulat * Remove page query param Signed-off-by: Olga Bulat * Refactor creatorHref Signed-off-by: Olga Bulat * Add requested changes Signed-off-by: Olga Bulat * Fix server rendering Signed-off-by: Olga Bulat * Add e2e tests Signed-off-by: Olga Bulat * Update bottom margin of the collection header Signed-off-by: Olga Bulat * Fix e2e tests Signed-off-by: Olga Bulat --------- Signed-off-by: Olga Bulat --- .../VCollectionHeader/VCollectionHeader.vue | 6 +- frontend/src/components/VCollectionPage.vue | 106 ++ frontend/src/components/VLoadMore.vue | 21 +- .../components/VMediaInfo/VByLine/VByLine.vue | 45 +- frontend/src/data/api-service.ts | 8 +- frontend/src/data/media-service.ts | 10 +- frontend/src/locales/scripts/en.json5 | 14 + frontend/src/middleware/collection.ts | 15 + frontend/src/middleware/single-result.ts | 18 +- frontend/src/pages/audio/source/_.vue | 37 + frontend/src/pages/audio/tag/_tag.vue | 37 + frontend/src/pages/image/source/_.vue | 36 + frontend/src/pages/image/tag/_tag.vue | 37 + frontend/src/stores/media/index.ts | 13 +- frontend/src/stores/provider.ts | 19 + frontend/src/stores/search.ts | 65 +- frontend/src/types/result.ts | 12 + frontend/src/types/search.ts | 5 + frontend/src/utils/parse-collection-path.ts | 24 + .../test/playwright/e2e/collections.spec.ts | 55 + .../playwright/e2e/external-sources.spec.ts | 8 +- .../test/playwright/e2e/global-audio.spec.ts | 9 +- .../test/playwright/e2e/image-detail.spec.ts | 11 +- frontend/test/playwright/utils/navigation.ts | 7 +- frontend/test/tapes/response-293.json5 | 1191 +++++++++++++++++ frontend/test/tapes/response-314.json5 | 972 ++++++++++++++ frontend/test/tapes/response-333.json5 | 745 +++++++++++ .../unit/specs/stores/search-store.spec.js | 15 + .../utils/validate-collection-params.spec.js | 48 + 29 files changed, 3533 insertions(+), 56 deletions(-) create mode 100644 frontend/src/components/VCollectionPage.vue create mode 100644 frontend/src/middleware/collection.ts create mode 100644 frontend/src/pages/audio/source/_.vue create mode 100644 frontend/src/pages/audio/tag/_tag.vue create mode 100644 frontend/src/pages/image/source/_.vue create mode 100644 frontend/src/pages/image/tag/_tag.vue create mode 100644 frontend/src/utils/parse-collection-path.ts create mode 100644 frontend/test/playwright/e2e/collections.spec.ts create mode 100644 frontend/test/tapes/response-293.json5 create mode 100644 frontend/test/tapes/response-314.json5 create mode 100644 frontend/test/tapes/response-333.json5 create mode 100644 frontend/test/unit/specs/utils/validate-collection-params.spec.js diff --git a/frontend/src/components/VCollectionHeader/VCollectionHeader.vue b/frontend/src/components/VCollectionHeader/VCollectionHeader.vue index b7d99e3864..1edca9bd32 100644 --- a/frontend/src/components/VCollectionHeader/VCollectionHeader.vue +++ b/frontend/src/components/VCollectionHeader/VCollectionHeader.vue @@ -75,6 +75,7 @@ export default defineComponent({ }, }, setup(props) { + const mediaStore = useMediaStore() const providerStore = useProviderStore() const uiStore = useUiStore() @@ -114,7 +115,10 @@ export default defineComponent({ const { getI18nCollectionResultCountLabel } = useI18nResultsCount() const resultsLabel = computed(() => { - const resultsCount = useMediaStore().results[props.mediaType].count + if (mediaStore.resultCount === 0 && mediaStore.fetchState.isFetching) { + return "" + } + const resultsCount = mediaStore.results[props.mediaType].count if (props.collectionParams.collection === "creator") { return getI18nCollectionResultCountLabel( resultsCount, diff --git a/frontend/src/components/VCollectionPage.vue b/frontend/src/components/VCollectionPage.vue new file mode 100644 index 0000000000..3fff6d953d --- /dev/null +++ b/frontend/src/components/VCollectionPage.vue @@ -0,0 +1,106 @@ + + diff --git a/frontend/src/components/VLoadMore.vue b/frontend/src/components/VLoadMore.vue index 1c702083c8..da9cadce49 100644 --- a/frontend/src/components/VLoadMore.vue +++ b/frontend/src/components/VLoadMore.vue @@ -46,19 +46,26 @@ export default defineComponent({ storeToRefs(mediaStore) const { searchTerm } = storeToRefs(searchStore) + const searchStarted = computed(() => { + return searchStore.strategy === "default" + ? searchTerm.value !== "" + : searchStore.collectionParams !== null + }) + /** * Whether we should show the "Load more" button. * If the user has entered a search term, there is at least 1 page of results, * there has been no fetching error, and there are more results to fetch, * we show the button. */ - const canLoadMore = computed( - () => - searchTerm.value !== "" && - !fetchState.value.fetchingError && - !fetchState.value.isFinished && - resultCount.value > 0 - ) + const canLoadMore = computed(() => { + return Boolean( + searchStarted.value && + !fetchState.value.fetchingError && + !fetchState.value.isFinished && + resultCount.value > 0 + ) + }) const reachResultEndEventSent = ref(false) /** diff --git a/frontend/src/components/VMediaInfo/VByLine/VByLine.vue b/frontend/src/components/VMediaInfo/VByLine/VByLine.vue index 30de95ec58..cb5c7709f8 100644 --- a/frontend/src/components/VMediaInfo/VByLine/VByLine.vue +++ b/frontend/src/components/VMediaInfo/VByLine/VByLine.vue @@ -59,6 +59,7 @@ import { import { useElementSize, useScroll, watchDebounced } from "@vueuse/core" import { useI18n } from "~/composables/use-i18n" +import { useSearchStore } from "~/stores/search" import type { SupportedMediaType } from "~/constants/media" import VSourceCreatorButton from "~/components/VMediaInfo/VByLine/VSourceCreatorButton.vue" @@ -95,7 +96,9 @@ export default defineComponent({ const buttonsRef = ref(null) const showCreator = computed(() => { - return props.creator && props.creator.toLowerCase() !== "unidentified" + return Boolean( + props.creator && props.creator.toLowerCase() !== "unidentified" + ) }) const i18n = useI18n() @@ -213,33 +216,27 @@ export default defineComponent({ { debounce: 100 } ) - // TODO: implement this function in the search store. - const getCollectionPath = ({ - type, - source, - creator, - }: { - type: SupportedMediaType - source: string - creator?: string - }) => { - let path = `/${type}/source/${source}/` - if (creator) path += `creator/${encodeURIComponent(creator)}/` - return path - } + const searchStore = useSearchStore() + const creatorHref = computed(() => { - return showCreator.value - ? getCollectionPath({ - type: props.mediaType, - source: props.sourceSlug, - creator: props.creator, - }) - : undefined + if (!props.creator) return undefined + return searchStore.getCollectionPath({ + type: props.mediaType, + collectionParams: { + collection: "creator", + source: props.sourceSlug, + creator: props.creator, + }, + }) }) + const sourceHref = computed(() => { - return getCollectionPath({ + return searchStore.getCollectionPath({ type: props.mediaType, - source: props.sourceSlug, + collectionParams: { + collection: "source", + source: props.sourceSlug, + }, }) }) diff --git a/frontend/src/data/api-service.ts b/frontend/src/data/api-service.ts index 699a40fa58..f9cdbcbc09 100644 --- a/frontend/src/data/api-service.ts +++ b/frontend/src/data/api-service.ts @@ -63,6 +63,7 @@ export interface ApiService { client: AxiosInstance query( resource: string, + slug: string, params: Record ): Promise> get( @@ -138,19 +139,22 @@ export const createApiService = ({ /** * @param resource - The endpoint of the resource + * @param slug - the optional additional endpoint, used for collections. * @param params - Url parameter object * @returns response The API response object */ query( resource: string, - params: Record + slug: string = "", + params: Record = {} ): Promise> { - return client.get(`${getResourceSlug(resource)}`, { params }) + return client.get(`${getResourceSlug(resource)}${slug}`, { params }) }, /** * @param resource - The endpoint of the resource * @param slug - The sub-endpoint of the resource + * @param params - Url query parameter object * @returns Response The API response object */ get( diff --git a/frontend/src/data/media-service.ts b/frontend/src/data/media-service.ts index e6b7b99d74..e377e15233 100644 --- a/frontend/src/data/media-service.ts +++ b/frontend/src/data/media-service.ts @@ -1,5 +1,8 @@ import { decodeMediaData } from "~/utils/decode-media-data" -import type { PaginatedSearchQuery } from "~/types/search" +import type { + PaginatedCollectionQuery, + PaginatedSearchQuery, +} from "~/types/search" import type { ApiService } from "~/data/api-service" import type { DetailFromMediaType, Media } from "~/types/media" import { AUDIO, type SupportedMediaType } from "~/constants/media" @@ -45,9 +48,11 @@ class MediaService { /** * Search for media items by keyword. * @param params - API search query parameters + * @param slug - optional slug to get a collection */ async search( - params: PaginatedSearchQuery + params: PaginatedSearchQuery | PaginatedCollectionQuery, + slug: string = "" ): Promise>> { // Add the `peaks` param to all audio searches automatically if (this.mediaType === AUDIO) { @@ -56,6 +61,7 @@ class MediaService { const res = await this.apiService.query>( this.mediaType, + slug, params as unknown as Record ) return this.transformResults(res.data) diff --git a/frontend/src/locales/scripts/en.json5 b/frontend/src/locales/scripts/en.json5 index 494d33b9f9..0fabb7a102 100644 --- a/frontend/src/locales/scripts/en.json5 +++ b/frontend/src/locales/scripts/en.json5 @@ -774,6 +774,20 @@ source: "Open source site", creator: "Open creator page", }, + ariaLabel: { + creator: { + audio: "Audio files by {creator} in {source}", + image: "Images by {creator} in {source}", + }, + source: { + audio: "Audio files from {source}", + image: "Images from {source}", + }, + tag: { + audio: "Audio files with the tag {tag}", + image: "Images with the tag {tag}", + }, + }, resultCountLabel: { creator: { audio: { diff --git a/frontend/src/middleware/collection.ts b/frontend/src/middleware/collection.ts new file mode 100644 index 0000000000..8441199e59 --- /dev/null +++ b/frontend/src/middleware/collection.ts @@ -0,0 +1,15 @@ +import { useFeatureFlagStore } from "~/stores/feature-flag" + +import type { Middleware } from "@nuxt/types" + +export const collectionMiddleware: Middleware = async ({ + $pinia, + error: nuxtError, +}) => { + if (!useFeatureFlagStore($pinia).isOn("additional_search_views")) { + nuxtError({ + statusCode: 404, + message: "Additional search views are not enabled", + }) + } +} diff --git a/frontend/src/middleware/single-result.ts b/frontend/src/middleware/single-result.ts index 83babf0218..e9a2a6d476 100644 --- a/frontend/src/middleware/single-result.ts +++ b/frontend/src/middleware/single-result.ts @@ -7,6 +7,10 @@ import { AUDIO, IMAGE } from "~/constants/media" import type { Middleware } from "@nuxt/types" +const isSearchPath = (path: string) => path.includes("/search/") +const isSearchOrCollectionPath = (path: string) => + isSearchPath(path) || path.includes("/source/") || path.includes("/tag/") + export const singleResultMiddleware: Middleware = async ({ route, from, @@ -31,16 +35,18 @@ export const singleResultMiddleware: Middleware = async ({ // Client-side rendering singleResultStore.setMediaById(mediaType, route.params.id) - if (from && from.path.includes("/search/")) { + if (from && isSearchOrCollectionPath(from.path)) { const searchStore = useSearchStore($pinia) searchStore.setBackToSearchPath(from.fullPath) - const searchTerm = Array.isArray(route.query.q) - ? route.query.q[0] - : route.query.q + if (isSearchPath(from.path)) { + const searchTerm = Array.isArray(route.query.q) + ? route.query.q[0] + : route.query.q - if (searchTerm) { - searchStore.setSearchTerm(searchTerm) + if (searchTerm) { + searchStore.setSearchTerm(searchTerm) + } } } } diff --git a/frontend/src/pages/audio/source/_.vue b/frontend/src/pages/audio/source/_.vue new file mode 100644 index 0000000000..490680007c --- /dev/null +++ b/frontend/src/pages/audio/source/_.vue @@ -0,0 +1,37 @@ + + + diff --git a/frontend/src/pages/audio/tag/_tag.vue b/frontend/src/pages/audio/tag/_tag.vue new file mode 100644 index 0000000000..d2fde05282 --- /dev/null +++ b/frontend/src/pages/audio/tag/_tag.vue @@ -0,0 +1,37 @@ + + + diff --git a/frontend/src/pages/image/source/_.vue b/frontend/src/pages/image/source/_.vue new file mode 100644 index 0000000000..e5799ea3cc --- /dev/null +++ b/frontend/src/pages/image/source/_.vue @@ -0,0 +1,36 @@ + + + diff --git a/frontend/src/pages/image/tag/_tag.vue b/frontend/src/pages/image/tag/_tag.vue new file mode 100644 index 0000000000..b834814d8d --- /dev/null +++ b/frontend/src/pages/image/tag/_tag.vue @@ -0,0 +1,37 @@ + + + diff --git a/frontend/src/stores/media/index.ts b/frontend/src/stores/media/index.ts index 4b43350e5e..4e9ba59a2d 100644 --- a/frontend/src/stores/media/index.ts +++ b/frontend/src/stores/media/index.ts @@ -24,8 +24,6 @@ import { isSearchTypeSupported, useSearchStore } from "~/stores/search" import { useRelatedMediaStore } from "~/stores/media/related-media" import { deepFreeze } from "~/utils/deep-freeze" -import { PaginatedSearchQuery } from "~/types/search" - export type MediaStoreResult = { count: number pageCount: number @@ -443,18 +441,19 @@ export const useMediaStore = defineStore("media", { mediaType: SupportedMediaType shouldPersistMedia: boolean }) { + const searchStore = useSearchStore() + const { pathSlug, query: queryParams } = + searchStore.getSearchUrlParts(mediaType) let page = this.results[mediaType].page + 1 - const queryParams: PaginatedSearchQuery = { - ...useSearchStore().apiSearchQueryParams, - // Don't need to set `page` parameter for the first page. - page: shouldPersistMedia ? `${page}` : undefined, + if (shouldPersistMedia) { + queryParams.page = `${page}` } this._updateFetchState(mediaType, "start") try { const accessToken = this.$nuxt.$openverseApiToken const service = initServices[mediaType](accessToken) - const data = await service.search(queryParams) + const data = await service.search(queryParams, pathSlug) const mediaCount = data.result_count let errorData: FetchingError | undefined /** diff --git a/frontend/src/stores/provider.ts b/frontend/src/stores/provider.ts index 520f25c52a..f077c45c38 100644 --- a/frontend/src/stores/provider.ts +++ b/frontend/src/stores/provider.ts @@ -26,6 +26,10 @@ export interface ProviderState { audio: FetchState image: FetchState } + sourceNames: { + audio: string[] + image: string[] + } } /** @@ -56,6 +60,10 @@ export const useProviderStore = defineStore("provider", { [AUDIO]: { isFetching: false, hasStarted: false, fetchingError: null }, [IMAGE]: { isFetching: false, hasStarted: false, fetchingError: null }, }, + sourceNames: { + [AUDIO]: [], + [IMAGE]: [], + }, }), actions: { @@ -153,8 +161,19 @@ export const useProviderStore = defineStore("provider", { this.$nuxt.$sentry.captureException(error, { extra: { errorData } }) } finally { this.providers[mediaType] = sortedProviders + this.sourceNames[mediaType] = sortedProviders.map((p) => p.source_name) } }, + + /** + * Returns true if the given source name exists in the given media type sources list. + */ + isSourceNameValid( + mediaType: SupportedMediaType, + sourceName: string + ): boolean { + return this.sourceNames[mediaType].includes(sourceName) + }, }, getters: { diff --git a/frontend/src/stores/search.ts b/frontend/src/stores/search.ts index b39011189f..301daeb82f 100644 --- a/frontend/src/stores/search.ts +++ b/frontend/src/stores/search.ts @@ -38,7 +38,13 @@ import { useProviderStore } from "~/stores/provider" import { useFeatureFlagStore } from "~/stores/feature-flag" import { useMediaStore } from "~/stores/media" -import { SearchQuery, PaginatedSearchQuery } from "~/types/search" +import { + SearchQuery, + SearchStrategy, + PaginatedSearchQuery, + CollectionParams, + PaginatedCollectionQuery, +} from "~/types/search" import type { Ref } from "vue" @@ -53,6 +59,8 @@ export const isSearchTypeSupported = ( export interface SearchState { searchType: SearchType + strategy: SearchStrategy + collectionParams: CollectionParams | null recentSearches: Ref backToSearchPath: string searchTerm: string @@ -98,10 +106,26 @@ export function computeQueryParams( return searchQuery } +export function collectionToPath(collectionParams: CollectionParams) { + switch (collectionParams.collection) { + case "tag": { + return `tag/${collectionParams.tag}/` + } + case "creator": { + return `source/${collectionParams.source}/creator/${collectionParams.creator}/` + } + case "source": { + return `source/${collectionParams.source}/` + } + } +} + export const useSearchStore = defineStore("search", { state: (): SearchState => ({ searchType: ALL_MEDIA, searchTerm: "", + strategy: "default", + collectionParams: null, backToSearchPath: "", localSearchTerm: "", recentSearches: useStorage("recent-searches", []), @@ -173,6 +197,17 @@ export const useSearchStore = defineStore("search", { }, }, actions: { + getSearchUrlParts(mediaType: SupportedMediaType) { + const query: PaginatedSearchQuery | PaginatedCollectionQuery = + this.strategy === "default" + ? computeQueryParams(mediaType, this.filters, this.searchTerm, "API") + : {} + const pathSlug = + this.collectionParams === null + ? "" + : collectionToPath(this.collectionParams) + return { query, pathSlug } + }, setBackToSearchPath(path: string) { this.backToSearchPath = path }, @@ -220,6 +255,21 @@ export const useSearchStore = defineStore("search", { }) }, + /** + * Returns localized frontend path for the given collection. + * Does not support query parameters for now. + */ + getCollectionPath({ + type, + collectionParams, + }: { + type: SupportedMediaType + collectionParams: CollectionParams + }) { + const path = `/${type}/${collectionToPath(collectionParams)}` + return this.$nuxt.localePath(path) + }, + setSearchType(type: SearchType) { const featureFlagStore = useFeatureFlagStore() if ( @@ -244,6 +294,8 @@ export const useSearchStore = defineStore("search", { if (this.searchTerm === formattedTerm) return this.searchTerm = formattedTerm this.localSearchTerm = formattedTerm + this.collectionParams = null + this.strategy = "default" this.addRecentSearch(formattedTerm) @@ -431,6 +483,15 @@ export const useSearchStore = defineStore("search", { this.filters[filterCategory] = newFilterData[filterCategory] }) }, + setCollectionState( + collectionParams: CollectionParams, + mediaType: SupportedMediaType + ) { + this.collectionParams = collectionParams + this.strategy = collectionParams?.collection + this.setSearchType(mediaType) + this.clearFilters() + }, /** * Called when a /search path is server-rendered. */ @@ -451,6 +512,8 @@ export const useSearchStore = defineStore("search", { : {}), }) + this.strategy = "default" + this.setSearchTerm(query.q) this.searchType = pathToSearchType(path) if (!isSearchTypeSupported(this.searchType)) return diff --git a/frontend/src/types/result.ts b/frontend/src/types/result.ts index 39abaa161c..994521957a 100644 --- a/frontend/src/types/result.ts +++ b/frontend/src/types/result.ts @@ -1 +1,13 @@ +import { AUDIO, IMAGE } from "~/constants/media" +import { AudioDetail, ImageDetail } from "~/types/media" + export type ResultKind = "search" | "related" | "collection" +export type Results = + | { + type: typeof AUDIO + items: AudioDetail[] + } + | { + type: typeof IMAGE + items: ImageDetail[] + } diff --git a/frontend/src/types/search.ts b/frontend/src/types/search.ts index b74f90c6a0..a7d4c87390 100644 --- a/frontend/src/types/search.ts +++ b/frontend/src/types/search.ts @@ -1,6 +1,7 @@ import { INCLUDE_SENSITIVE_QUERY_PARAM } from "~/constants/content-safety" export type Collection = "tag" | "creator" | "source" +export type SearchStrategy = "default" | Collection /** * The filter query parameters. @@ -40,6 +41,10 @@ export type PaginatedSearchQuery = SearchRequestQuery & PaginatedParams & SearchFilterQuery +export type PaginatedCollectionQuery = PaginatedParams & { + [key: string]: string +} + export type TagCollection = { collection: "tag"; tag: string } export type CreatorCollection = { collection: "creator" diff --git a/frontend/src/utils/parse-collection-path.ts b/frontend/src/utils/parse-collection-path.ts new file mode 100644 index 0000000000..0c3cd19e19 --- /dev/null +++ b/frontend/src/utils/parse-collection-path.ts @@ -0,0 +1,24 @@ +import { CreatorCollection, SourceCollection } from "~/types/search" + +export function parseCollectionPath( + pathMatch: string +): SourceCollection | CreatorCollection | null { + // Build collection params. + // pathMatch is the part of the path after the collection name: + //`/sourceName` or `/sourceName/creator/creatorName`. + const pathMatchParts = pathMatch + .split("/") + .map((part) => part.trim()) + .filter((part) => part !== "") + + if (pathMatchParts.length === 1) { + return { collection: "source", source: pathMatchParts[0] } + } else if (pathMatchParts.length === 3 && pathMatchParts[1] === "creator") { + return { + collection: "creator", + creator: pathMatchParts[2], + source: pathMatchParts[0], + } + } + return null +} diff --git a/frontend/test/playwright/e2e/collections.spec.ts b/frontend/test/playwright/e2e/collections.spec.ts new file mode 100644 index 0000000000..9b12c4676e --- /dev/null +++ b/frontend/test/playwright/e2e/collections.spec.ts @@ -0,0 +1,55 @@ +import { test, expect } from "@playwright/test" + +import { setCookies, t } from "~~/test/playwright/utils/navigation" + +test.describe.configure({ mode: "parallel" }) + +test.beforeEach(async ({ context, page }) => { + await setCookies(context, { + features: { additional_search_views: "on", analytics: "off" }, + }) + await page.goto("/image/f9384235-b72e-4f1e-9b05-e1b116262a29?q=cat") +}) +test("can open tags collection page from image page", async ({ page }) => { + // Using the href because there are multiple links with the same text. + await page.click('[href*="/tag/cat"]') + + await expect( + page.getByRole("button", { name: t("browsePage.load") }) + ).toBeEnabled() + + await expect(page.getByRole("heading", { name: /cat/i })).toBeVisible() + expect(await page.locator("figure").count()).toEqual(20) + expect(page.url()).toMatch(/image\/tag\/cat/) +}) +test("can open source collection page from image page", async ({ page }) => { + const sourcePattern = /flickr/i + + await page.getByRole("link", { name: sourcePattern }).first().click() + + await expect( + page.getByRole("button", { name: t("browsePage.load") }) + ).toBeEnabled() + + await expect(page.getByRole("heading", { name: sourcePattern })).toBeVisible() + + expect(await page.locator("figure").count()).toEqual(20) + + expect(page.url()).toMatch(/image\/source\/flickr\/$/) +}) +test("can open creator collection page from image page", async ({ page }) => { + const creatorPattern = /strogoscope/i + await page.getByRole("link", { name: creatorPattern }).first().click() + + await expect( + page.getByRole("button", { name: t("browsePage.load") }) + ).toBeEnabled() + + await expect( + page.getByRole("heading", { name: creatorPattern }) + ).toBeVisible() + + expect(await page.locator("figure").count()).toEqual(20) + + expect(page.url()).toMatch(/image\/source\/flickr\/creator\/strogoscope\//) +}) diff --git a/frontend/test/playwright/e2e/external-sources.spec.ts b/frontend/test/playwright/e2e/external-sources.spec.ts index 44ff86cad4..11c0557de3 100644 --- a/frontend/test/playwright/e2e/external-sources.spec.ts +++ b/frontend/test/playwright/e2e/external-sources.spec.ts @@ -1,6 +1,10 @@ import { test } from "@playwright/test" -import { goToSearchTerm, t } from "~~/test/playwright/utils/navigation" +import { + goToSearchTerm, + t, + turnOnAnalytics, +} from "~~/test/playwright/utils/navigation" import { collectAnalyticsEvents, @@ -11,6 +15,7 @@ test("sends VIEW_EXTERNAL_SOURCES analytics events", async ({ page, context, }) => { + await turnOnAnalytics(page) const events = collectAnalyticsEvents(context) await goToSearchTerm(page, "cat", { searchType: "image", mode: "SSR" }) @@ -33,6 +38,7 @@ test("sends SELECT_EXTERNAL_SOURCE analytics events", async ({ page, context, }) => { + await turnOnAnalytics(page) const pagePromise = page.context().waitForEvent("page") const events = collectAnalyticsEvents(context) diff --git a/frontend/test/playwright/e2e/global-audio.spec.ts b/frontend/test/playwright/e2e/global-audio.spec.ts index 3dfb0d8da1..404d9a6595 100644 --- a/frontend/test/playwright/e2e/global-audio.spec.ts +++ b/frontend/test/playwright/e2e/global-audio.spec.ts @@ -16,7 +16,7 @@ test.describe("Global Audio", () => { // Navigate to the details page of the playing audio track await firstAudioRow.click() // and confirm is still playing (or loading to play) - const mainPlayerButton = page.locator(".main-track >> button") + const mainPlayerButton = page.locator(".main-track >> button").first() await sleep(600) // Doesn't seem to make a difference for the status await expect(mainPlayerButton).toHaveAttribute( "aria-label", @@ -53,8 +53,11 @@ test.describe("Global Audio", () => { const secondAudioRow = await audio.getNthAudioRow(page, 1) await secondAudioRow.click() // and confirm is not playing - const mainPlayerButton = page.locator(".main-track >> button") - await expect(mainPlayerButton).toHaveAttribute("aria-label", "Play") + await expect( + page + .locator(".main-track") + .getByRole("button", { name: t("playPause.play") }) + ).toBeVisible() }) }) }) diff --git a/frontend/test/playwright/e2e/image-detail.spec.ts b/frontend/test/playwright/e2e/image-detail.spec.ts index d84c116ba6..a218645402 100644 --- a/frontend/test/playwright/e2e/image-detail.spec.ts +++ b/frontend/test/playwright/e2e/image-detail.spec.ts @@ -1,7 +1,11 @@ import { test, expect, Page } from "@playwright/test" import { mockProviderApis } from "~~/test/playwright/utils/route" -import { t } from "~~/test/playwright/utils/navigation" +import { + setCookies, + t, + turnOnAnalytics, +} from "~~/test/playwright/utils/navigation" import { collectAnalyticsEvents, expectEventPayloadToMatch, @@ -26,6 +30,9 @@ test.beforeEach(async ({ context }) => { }) test("shows the author and title of the image", async ({ page }) => { + await setCookies(page.context(), { + features: { additional_search_views: "off" }, + }) await goToCustomImagePage(page) const author = page.locator('a[aria-label^="author"]') await expect(author).toBeVisible() @@ -69,6 +76,7 @@ test.describe("analytics", () => { context, page, }) => { + await turnOnAnalytics(page) const analyticsEvents = collectAnalyticsEvents(context) await goToCustomImagePage(page) @@ -90,6 +98,7 @@ test.describe("analytics", () => { context, page, }) => { + await turnOnAnalytics(page) const analyticsEvents = collectAnalyticsEvents(context) await goToCustomImagePage(page) diff --git a/frontend/test/playwright/utils/navigation.ts b/frontend/test/playwright/utils/navigation.ts index 04ce549c50..f430841ee7 100644 --- a/frontend/test/playwright/utils/navigation.ts +++ b/frontend/test/playwright/utils/navigation.ts @@ -443,5 +443,10 @@ export const setBreakpointCookie = async (page: Page, breakpoint: string) => { export const turnOnAnalytics = async (page: Page) => { await page.goto("/preferences") - await page.getByLabel("Record custom events and page views.").click() + const analyticsCheckbox = page.getByLabel( + "Record custom events and page views." + ) + if (!(await analyticsCheckbox.isChecked())) { + await analyticsCheckbox.click() + } } diff --git a/frontend/test/tapes/response-293.json5 b/frontend/test/tapes/response-293.json5 new file mode 100644 index 0000000000..712b80abcb --- /dev/null +++ b/frontend/test/tapes/response-293.json5 @@ -0,0 +1,1191 @@ +{ + meta: { + createdAt: '2023-12-02T08:40:28.824Z', + host: 'https://api.openverse.engineering', + resHumanReadable: true, + resUncompressed: true, + }, + req: { + headers: { + connection: 'keep-alive', + }, + url: '/v1/images/tag/cat/', + method: 'GET', + body: '', + }, + res: { + status: 200, + headers: { + date: [ + 'Sat, 02 Dec 2023 08:40:29 GMT', + ], + 'content-type': [ + 'application/json', + ], + 'transfer-encoding': [ + 'chunked', + ], + connection: [ + 'keep-alive', + ], + vary: [ + 'Accept-Encoding, Accept, Authorization, origin', + ], + allow: [ + 'GET, HEAD, OPTIONS', + ], + 'x-ratelimit-limit-anon_burst': [ + '5/hour', + ], + 'x-ratelimit-available-anon_burst': [ + '3', + ], + 'x-ratelimit-limit-anon_sustained': [ + '100/day', + ], + 'x-ratelimit-available-anon_sustained': [ + '97', + ], + 'x-ratelimit-limit-anon_thumbnail': [ + '150/minute', + ], + 'x-ratelimit-available-anon_thumbnail': [ + '149', + ], + 'x-frame-options': [ + 'DENY', + ], + 'x-content-type-options': [ + 'nosniff', + ], + 'referrer-policy': [ + 'same-origin', + ], + 'cross-origin-opener-policy': [ + 'same-origin', + ], + 'access-control-allow-origin': [ + '*', + ], + 'x-request-id': [ + 'd52e31a98a49496e85b5457518e2d576', + ], + 'cache-control': [ + 'max-age=14400', + ], + 'cf-cache-status': [ + 'MISS', + ], + 'last-modified': [ + 'Sat, 02 Dec 2023 08:40:29 GMT', + ], + 'strict-transport-security': [ + 'max-age=15552000; includeSubDomains; preload', + ], + server: [ + 'cloudflare', + ], + 'cf-ray': [ + '82f243edbc31c1c1-BUD', + ], + 'content-encoding': [ + 'br', + ], + 'alt-svc': [ + 'h3=":443"; ma=86400', + ], + }, + body: { + result_count: 10000, + page_count: 20, + page_size: 20, + page: 1, + results: [ + { + id: '233c95f5-7c4f-40c1-83ca-f12d5b116fea', + title: 'Luhtiaitta', + indexed_on: '2023-11-07T00:22:47.888277Z', + foreign_landing_url: 'https://www.finna.fi/Record/satakunnanmuseo.6B319E19-14CC-4F72-9DAE-64F01AFD5679', + url: 'https://api.finna.fi/Cover/Show?source=Solr&id=satakunnanmuseo.6B319E19-14CC-4F72-9DAE-64F01AFD5679&index=0&size=large', + creator: 'Salminen, Emil, valokuvaaja', + creator_url: null, + license: 'by', + license_version: '4.0', + license_url: 'https://creativecommons.org/licenses/by/4.0/', + provider: 'finnishmuseums', + source: 'finnish_satakunnan_museum', + category: null, + filesize: null, + filetype: null, + tags: [ + { + name: '16.05.1931, 1931', + accuracy: null, + }, + { + name: 'aidat', + accuracy: null, + }, + { + name: 'architectural tradition', + accuracy: null, + }, + { + name: 'building culture', + accuracy: null, + }, + { + name: 'buildings', + accuracy: null, + }, + { + name: 'cat', + accuracy: null, + }, + { + name: 'farm buildings', + accuracy: null, + }, + { + name: 'fences', + accuracy: null, + }, + { + name: 'fishermen', + accuracy: null, + }, + { + name: 'fiskare', + accuracy: null, + }, + { + name: 'hirsirakennukset', + accuracy: null, + }, + { + name: 'human being', + accuracy: null, + }, + { + name: 'ihminen', + accuracy: null, + }, + { + name: 'kalastajat', + accuracy: null, + }, + { + name: 'katt', + accuracy: null, + }, + { + name: 'kissa', + accuracy: null, + }, + { + name: 'log buildings', + accuracy: null, + }, + { + name: 'luhdit', + accuracy: null, + }, + { + name: 'luhtiaitat', + accuracy: null, + }, + { + name: 'maatalousrakennukset', + accuracy: null, + }, + { + name: 'män', + accuracy: null, + }, + { + name: 'människan', + accuracy: null, + }, + { + name: 'men', + accuracy: null, + }, + { + name: 'miehet', + accuracy: null, + }, + { + name: 'outbuildings', + accuracy: null, + }, + { + name: 'puurakennukset', + accuracy: null, + }, + { + name: 'rakennukset', + accuracy: null, + }, + { + name: 'rakennuskulttuuri', + accuracy: null, + }, + { + name: 'rakennusperinne', + accuracy: null, + }, + { + name: 'riukuaidat', + accuracy: null, + }, + { + name: 'staket', + accuracy: null, + }, + { + name: 'stockhus', + accuracy: null, + }, + { + name: 'talousrakennukset', + accuracy: null, + }, + { + name: 'ulkorakennukset', + accuracy: null, + }, + { + name: 'wooden buildings', + accuracy: null, + }, + ], + attribution: '"Luhtiaitta" by Salminen, Emil, valokuvaaja is licensed under CC BY 4.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/4.0/.', + fields_matched: [], + mature: false, + height: null, + width: null, + thumbnail: 'http://localhost:49153/v1/images/233c95f5-7c4f-40c1-83ca-f12d5b116fea/thumb/', + detail_url: 'http://localhost:49153/v1/images/233c95f5-7c4f-40c1-83ca-f12d5b116fea/', + related_url: 'http://localhost:49153/v1/images/233c95f5-7c4f-40c1-83ca-f12d5b116fea/related/', + unstable__sensitivity: [], + }, + { + id: 'ba1c1605-e52a-482f-950d-a26a29e30ed6', + title: 'Fluffy feline striking a pose with playful charm', + indexed_on: '2023-11-01T00:50:15.230245Z', + foreign_landing_url: 'https://wordpress.org/photos/photo/541652feb6/', + url: 'https://pd.w.org/2023/10/541652feb67370d92.20947704-1365x2048.jpg', + creator: 'Shahana', + creator_url: 'https://wordpress.org/photos/author/shahanac/', + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'wordpress', + source: 'wordpress', + category: null, + filesize: 203753, + filetype: 'jpg', + tags: [ + { + name: 'cat', + accuracy: null, + }, + { + name: 'grass', + accuracy: null, + }, + ], + attribution: '"Fluffy feline striking a pose with playful charm" by Shahana is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 2048, + width: 1365, + thumbnail: 'http://localhost:49153/v1/images/ba1c1605-e52a-482f-950d-a26a29e30ed6/thumb/', + detail_url: 'http://localhost:49153/v1/images/ba1c1605-e52a-482f-950d-a26a29e30ed6/', + related_url: 'http://localhost:49153/v1/images/ba1c1605-e52a-482f-950d-a26a29e30ed6/related/', + unstable__sensitivity: [], + }, + { + id: 'fa4cf9c9-d0eb-4b6b-9d51-d8e55ffc8d2c', + title: 'Cat walk', + indexed_on: '2023-11-01T00:50:15.230245Z', + foreign_landing_url: 'https://wordpress.org/photos/photo/698654040b/', + url: 'https://pd.w.org/2023/10/698654040b1071258.37328411-1638x2048.jpg', + creator: 'sharankrishna', + creator_url: 'https://wordpress.org/photos/author/sharankrishna/', + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'wordpress', + source: 'wordpress', + category: null, + filesize: 251484, + filetype: 'jpg', + tags: [ + { + name: 'cat', + accuracy: null, + }, + { + name: 'grass', + accuracy: null, + }, + { + name: 'kitten', + accuracy: null, + }, + ], + attribution: '"Cat walk" by sharankrishna is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 2048, + width: 1638, + thumbnail: 'http://localhost:49153/v1/images/fa4cf9c9-d0eb-4b6b-9d51-d8e55ffc8d2c/thumb/', + detail_url: 'http://localhost:49153/v1/images/fa4cf9c9-d0eb-4b6b-9d51-d8e55ffc8d2c/', + related_url: 'http://localhost:49153/v1/images/fa4cf9c9-d0eb-4b6b-9d51-d8e55ffc8d2c/related/', + unstable__sensitivity: [], + }, + { + id: '5c973dee-d29f-4961-8341-6afe3bf2be28', + title: 'white cat behind a flower pot #WPPhotoFestival', + indexed_on: '2023-11-01T00:50:15.230245Z', + foreign_landing_url: 'https://wordpress.org/photos/photo/725653a547/', + url: 'https://pd.w.org/2023/10/725653a547e44e848.00441797-1638x2048.jpg', + creator: 'sharankrishna', + creator_url: 'https://wordpress.org/photos/author/sharankrishna/', + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'wordpress', + source: 'wordpress', + category: null, + filesize: 427826, + filetype: 'jpg', + tags: [ + { + name: 'cat', + accuracy: null, + }, + { + name: 'kitten', + accuracy: null, + }, + { + name: 'plants', + accuracy: null, + }, + ], + attribution: '"white cat behind a flower pot #WPPhotoFestival" by sharankrishna is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 2048, + width: 1638, + thumbnail: 'http://localhost:49153/v1/images/5c973dee-d29f-4961-8341-6afe3bf2be28/thumb/', + detail_url: 'http://localhost:49153/v1/images/5c973dee-d29f-4961-8341-6afe3bf2be28/', + related_url: 'http://localhost:49153/v1/images/5c973dee-d29f-4961-8341-6afe3bf2be28/related/', + unstable__sensitivity: [], + }, + { + id: '7710ba3b-fa96-4da3-8109-07bfe81451f8', + title: 'Close-up of a light-colored cat with blue eyes and distinct facial markings. The cat is looking to the side, and its background includes a portion of a pavement and a white structure.', + indexed_on: '2023-11-01T00:50:15.230245Z', + foreign_landing_url: 'https://wordpress.org/photos/photo/485652f6a7/', + url: 'https://pd.w.org/2023/10/485652f6a70847853.72840966-2048x2048.jpg', + creator: 'Javier Casares', + creator_url: 'https://www.javiercasares.com/', + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'wordpress', + source: 'wordpress', + category: null, + filesize: 406627, + filetype: 'jpg', + tags: [ + { + name: 'animal', + accuracy: null, + }, + { + name: 'cat', + accuracy: null, + }, + { + name: 'fawn', + accuracy: null, + }, + ], + attribution: '"Close-up of a light-colored cat with blue eyes and distinct facial markings. The cat is looking to the side, and its background includes a portion of a pavement and a white structure." by Javier Casares is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 2048, + width: 2048, + thumbnail: 'http://localhost:49153/v1/images/7710ba3b-fa96-4da3-8109-07bfe81451f8/thumb/', + detail_url: 'http://localhost:49153/v1/images/7710ba3b-fa96-4da3-8109-07bfe81451f8/', + related_url: 'http://localhost:49153/v1/images/7710ba3b-fa96-4da3-8109-07bfe81451f8/related/', + unstable__sensitivity: [], + }, + { + id: '844d517e-0404-49ec-871e-1e77c81c3291', + title: 'White color cat sitting on road #WPPhotoFestival', + indexed_on: '2023-11-01T00:50:15.230245Z', + foreign_landing_url: 'https://wordpress.org/photos/photo/673653a011/', + url: 'https://pd.w.org/2023/10/673653a01189b72b6.97587115-2048x1203.jpg', + creator: 'sharankrishna', + creator_url: 'https://wordpress.org/photos/author/sharankrishna/', + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'wordpress', + source: 'wordpress', + category: null, + filesize: 304394, + filetype: 'jpg', + tags: [ + { + name: 'cat', + accuracy: null, + }, + { + name: 'road', + accuracy: null, + }, + { + name: 'wpphotofestival', + accuracy: null, + }, + ], + attribution: '"White color cat sitting on road #WPPhotoFestival" by sharankrishna is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 1203, + width: 2048, + thumbnail: 'http://localhost:49153/v1/images/844d517e-0404-49ec-871e-1e77c81c3291/thumb/', + detail_url: 'http://localhost:49153/v1/images/844d517e-0404-49ec-871e-1e77c81c3291/', + related_url: 'http://localhost:49153/v1/images/844d517e-0404-49ec-871e-1e77c81c3291/related/', + unstable__sensitivity: [], + }, + { + id: '2c267e9d-0202-4677-8b05-c3224757feba', + title: 'Two brown striped cats sleeping together on a wooden chair', + indexed_on: '2023-11-01T00:50:15.230245Z', + foreign_landing_url: 'https://wordpress.org/photos/photo/8636531357/', + url: 'https://pd.w.org/2023/10/86365313577aa0474.96371257-2048x1536.jpg', + creator: 'benimub', + creator_url: 'https://wordpress.org/photos/author/benimub/', + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'wordpress', + source: 'wordpress', + category: null, + filesize: 529393, + filetype: 'jpg', + tags: [ + { + name: 'cat', + accuracy: null, + }, + { + name: 'chair', + accuracy: null, + }, + ], + attribution: '"Two brown striped cats sleeping together on a wooden chair" by benimub is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 1536, + width: 2048, + thumbnail: 'http://localhost:49153/v1/images/2c267e9d-0202-4677-8b05-c3224757feba/thumb/', + detail_url: 'http://localhost:49153/v1/images/2c267e9d-0202-4677-8b05-c3224757feba/', + related_url: 'http://localhost:49153/v1/images/2c267e9d-0202-4677-8b05-c3224757feba/related/', + unstable__sensitivity: [], + }, + { + id: 'a948dee1-9823-45dd-b9d7-d08f93a0cabe', + title: 'A cat lying on top of a wall', + indexed_on: '2023-11-01T00:50:15.230245Z', + foreign_landing_url: 'https://wordpress.org/photos/photo/50165398ce/', + url: 'https://pd.w.org/2023/10/50165398ceacb03b8.19676903-2048x1774.jpg', + creator: 'ajithrn', + creator_url: 'https://ajithrn.com', + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'wordpress', + source: 'wordpress', + category: null, + filesize: 460152, + filetype: 'jpg', + tags: [ + { + name: 'cat', + accuracy: null, + }, + { + name: 'ears', + accuracy: null, + }, + { + name: 'eye', + accuracy: null, + }, + { + name: 'nose', + accuracy: null, + }, + { + name: 'tree', + accuracy: null, + }, + ], + attribution: '"A cat lying on top of a wall" by ajithrn is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 1774, + width: 2048, + thumbnail: 'http://localhost:49153/v1/images/a948dee1-9823-45dd-b9d7-d08f93a0cabe/thumb/', + detail_url: 'http://localhost:49153/v1/images/a948dee1-9823-45dd-b9d7-d08f93a0cabe/', + related_url: 'http://localhost:49153/v1/images/a948dee1-9823-45dd-b9d7-d08f93a0cabe/related/', + unstable__sensitivity: [], + }, + { + id: 'bec291a1-d752-427d-bbc8-74d92188bb8a', + title: 'A white cat with captivating dual-color eyes, one brown and one blue, gracefully walking.(#WCBhopal)', + indexed_on: '2023-11-01T00:50:15.230245Z', + foreign_landing_url: 'https://wordpress.org/photos/photo/334652111c/', + url: 'https://pd.w.org/2023/10/334652111c3c10b99.55159798-1536x2048.jpeg', + creator: 'Ayush Kavia', + creator_url: 'https://wordpress.org/photos/author/wpayushkavia/', + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'wordpress', + source: 'wordpress', + category: null, + filesize: 538970, + filetype: 'jpg', + tags: [ + { + name: 'cat', + accuracy: null, + }, + { + name: 'eyes', + accuracy: null, + }, + ], + attribution: '"A white cat with captivating dual-color eyes, one brown and one blue, gracefully walking.(#WCBhopal)" by Ayush Kavia is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 2048, + width: 1536, + thumbnail: 'http://localhost:49153/v1/images/bec291a1-d752-427d-bbc8-74d92188bb8a/thumb/', + detail_url: 'http://localhost:49153/v1/images/bec291a1-d752-427d-bbc8-74d92188bb8a/', + related_url: 'http://localhost:49153/v1/images/bec291a1-d752-427d-bbc8-74d92188bb8a/related/', + unstable__sensitivity: [], + }, + { + id: '01673a27-46ee-4181-947e-50a4fb97cd30', + title: 'Adorable tabby cat', + indexed_on: '2023-11-01T00:50:15.230245Z', + foreign_landing_url: 'https://wordpress.org/photos/photo/526652feb0/', + url: 'https://pd.w.org/2023/10/526652feb0e7a21c1.35709336-1365x2048.jpg', + creator: 'Shahana', + creator_url: 'https://wordpress.org/photos/author/shahanac/', + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'wordpress', + source: 'wordpress', + category: null, + filesize: 261575, + filetype: 'jpg', + tags: [ + { + name: 'cat', + accuracy: null, + }, + { + name: 'grass', + accuracy: null, + }, + ], + attribution: '"Adorable tabby cat" by Shahana is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 2048, + width: 1365, + thumbnail: 'http://localhost:49153/v1/images/01673a27-46ee-4181-947e-50a4fb97cd30/thumb/', + detail_url: 'http://localhost:49153/v1/images/01673a27-46ee-4181-947e-50a4fb97cd30/', + related_url: 'http://localhost:49153/v1/images/01673a27-46ee-4181-947e-50a4fb97cd30/related/', + unstable__sensitivity: [], + }, + { + id: 'b0824a5a-605c-422c-b256-4c815682ab8c', + title: 'A light orange kitten lies on a tiled floor, reaching out to a crumpled shiny object with its paw. The kitten has green eyes and is looking towards the camera.', + indexed_on: '2023-11-01T00:50:15.230245Z', + foreign_landing_url: 'https://wordpress.org/photos/photo/38652f6ada/', + url: 'https://pd.w.org/2023/10/38652f6ada3eb936.88875394-2048x1540.jpg', + creator: 'Javier Casares', + creator_url: 'https://www.javiercasares.com/', + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'wordpress', + source: 'wordpress', + category: null, + filesize: 681693, + filetype: 'jpg', + tags: [ + { + name: 'cat', + accuracy: null, + }, + { + name: 'floor', + accuracy: null, + }, + { + name: 'kitten', + accuracy: null, + }, + ], + attribution: '"A light orange kitten lies on a tiled floor, reaching out to a crumpled shiny object with its paw. The kitten has green eyes and is looking towards the camera." by Javier Casares is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 1540, + width: 2048, + thumbnail: 'http://localhost:49153/v1/images/b0824a5a-605c-422c-b256-4c815682ab8c/thumb/', + detail_url: 'http://localhost:49153/v1/images/b0824a5a-605c-422c-b256-4c815682ab8c/', + related_url: 'http://localhost:49153/v1/images/b0824a5a-605c-422c-b256-4c815682ab8c/related/', + unstable__sensitivity: [], + }, + { + id: '50902853-7051-4b48-b280-53124128c33a', + title: 'A close-up of a light-colored cat with distinct markings on its face, resting on the ground. The cat has its eyes partially closed. Surrounding the cat are dried leaves, rocks, and some greenery.', + indexed_on: '2023-11-01T00:50:15.230245Z', + foreign_landing_url: 'https://wordpress.org/photos/photo/59365380b9/', + url: 'https://pd.w.org/2023/10/59365380b9406d0a1.28560800-2048x1536.jpg', + creator: 'Javier Casares', + creator_url: 'https://www.javiercasares.com/', + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'wordpress', + source: 'wordpress', + category: null, + filesize: 529910, + filetype: 'jpg', + tags: [ + { + name: 'cat', + accuracy: null, + }, + { + name: 'nature', + accuracy: null, + }, + ], + attribution: '"A close-up of a light-colored cat with distinct markings on its face, resting on the ground. The cat has its eyes partially closed. Surrounding the cat are dried leaves, rocks, and some greenery." by Javier Casares is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 1536, + width: 2048, + thumbnail: 'http://localhost:49153/v1/images/50902853-7051-4b48-b280-53124128c33a/thumb/', + detail_url: 'http://localhost:49153/v1/images/50902853-7051-4b48-b280-53124128c33a/', + related_url: 'http://localhost:49153/v1/images/50902853-7051-4b48-b280-53124128c33a/related/', + unstable__sensitivity: [], + }, + { + id: '70725c7f-7303-4883-9dbb-eae841df5477', + title: 'A surprised cat, lying on stone floor.', + indexed_on: '2023-11-01T00:50:15.230245Z', + foreign_landing_url: 'https://wordpress.org/photos/photo/215652ac58/', + url: 'https://pd.w.org/2023/10/215652ac58b81d496.28438337-2048x2048.jpg', + creator: 'Javier Casares', + creator_url: 'https://www.javiercasares.com/', + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'wordpress', + source: 'wordpress', + category: null, + filesize: 820782, + filetype: 'jpg', + tags: [ + { + name: 'cat', + accuracy: null, + }, + { + name: 'flooring', + accuracy: null, + }, + { + name: 'flowerpot', + accuracy: null, + }, + ], + attribution: '"A surprised cat, lying on stone floor." by Javier Casares is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 2048, + width: 2048, + thumbnail: 'http://localhost:49153/v1/images/70725c7f-7303-4883-9dbb-eae841df5477/thumb/', + detail_url: 'http://localhost:49153/v1/images/70725c7f-7303-4883-9dbb-eae841df5477/', + related_url: 'http://localhost:49153/v1/images/70725c7f-7303-4883-9dbb-eae841df5477/related/', + unstable__sensitivity: [], + }, + { + id: 'ef98bf78-d0ac-41da-8667-3925e01580f4', + title: 'A white kitten resting its head on a larger gray-striped cat. Both cats are on a concrete surface with a weathered wall in the background. The kitten’s black tail is visible.', + indexed_on: '2023-11-01T00:50:15.230245Z', + foreign_landing_url: 'https://wordpress.org/photos/photo/9786530e16/', + url: 'https://pd.w.org/2023/10/9786530e169795e64.06474618-2048x1540.jpg', + creator: 'Javier Casares', + creator_url: 'https://www.javiercasares.com/', + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'wordpress', + source: 'wordpress', + category: null, + filesize: 781357, + filetype: 'jpg', + tags: [ + { + name: 'cat', + accuracy: null, + }, + { + name: 'comfort', + accuracy: null, + }, + { + name: 'fawn', + accuracy: null, + }, + { + name: 'siamese', + accuracy: null, + }, + { + name: 'sleeping', + accuracy: null, + }, + ], + attribution: '"A white kitten resting its head on a larger gray-striped cat. Both cats are on a concrete surface with a weathered wall in the background. The kitten’s black tail is visible." by Javier Casares is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 1540, + width: 2048, + thumbnail: 'http://localhost:49153/v1/images/ef98bf78-d0ac-41da-8667-3925e01580f4/thumb/', + detail_url: 'http://localhost:49153/v1/images/ef98bf78-d0ac-41da-8667-3925e01580f4/', + related_url: 'http://localhost:49153/v1/images/ef98bf78-d0ac-41da-8667-3925e01580f4/related/', + unstable__sensitivity: [], + }, + { + id: '5eee0ca3-b0ef-477f-ac42-b9f7a3f88be1', + title: 'Cat sitting on a wall', + indexed_on: '2023-11-01T00:50:15.230245Z', + foreign_landing_url: 'https://wordpress.org/photos/photo/24965403f6/', + url: 'https://pd.w.org/2023/10/24965403f6ce9a666.25245069-2048x1365.jpg', + creator: 'sharankrishna', + creator_url: 'https://wordpress.org/photos/author/sharankrishna/', + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'wordpress', + source: 'wordpress', + category: null, + filesize: 202593, + filetype: 'jpg', + tags: [ + { + name: 'branch', + accuracy: null, + }, + { + name: 'cat', + accuracy: null, + }, + { + name: 'eye', + accuracy: null, + }, + ], + attribution: '"Cat sitting on a wall" by sharankrishna is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 1365, + width: 2048, + thumbnail: 'http://localhost:49153/v1/images/5eee0ca3-b0ef-477f-ac42-b9f7a3f88be1/thumb/', + detail_url: 'http://localhost:49153/v1/images/5eee0ca3-b0ef-477f-ac42-b9f7a3f88be1/', + related_url: 'http://localhost:49153/v1/images/5eee0ca3-b0ef-477f-ac42-b9f7a3f88be1/related/', + unstable__sensitivity: [], + }, + { + id: '974c464a-a1e8-46a8-9045-705aef1ba034', + title: "Politicians - Vanity Fair. 'He", + indexed_on: '2023-11-01T00:17:13.436828Z', + foreign_landing_url: 'https://www.rawpixel.com/image/12554198/image-cat-face-person', + url: 'https://images.rawpixel.com/image_1300/cHJpdmF0ZS9sci9pbWFnZXMvd2Vic2l0ZS8yMDIzLTAxL3ljYmF0bXM0NDEzOS1pbWFnZS5qcGc.jpg', + creator: null, + creator_url: null, + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'rawpixel', + source: 'rawpixel', + category: null, + filesize: null, + filetype: 'tiff', + tags: [ + { + name: 'cat', + accuracy: null, + }, + { + name: 'face', + accuracy: null, + }, + { + name: 'person', + accuracy: null, + }, + { + name: 'cartoon', + accuracy: null, + }, + { + name: 'art', + accuracy: null, + }, + { + name: 'vintage', + accuracy: null, + }, + { + name: 'man', + accuracy: null, + }, + { + name: 'painting', + accuracy: null, + }, + { + name: 'fashion', + accuracy: null, + }, + { + name: 'drawing', + accuracy: null, + }, + { + name: 'history', + accuracy: null, + }, + ], + attribution: '"Politicians - Vanity Fair. \'He" is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 4096, + width: 2350, + thumbnail: 'http://localhost:49153/v1/images/974c464a-a1e8-46a8-9045-705aef1ba034/thumb/', + detail_url: 'http://localhost:49153/v1/images/974c464a-a1e8-46a8-9045-705aef1ba034/', + related_url: 'http://localhost:49153/v1/images/974c464a-a1e8-46a8-9045-705aef1ba034/related/', + unstable__sensitivity: [], + }, + { + id: 'e39f05c5-c586-482d-af68-ff13a790fd75', + title: 'Opening the Sluices or the Secret', + indexed_on: '2023-11-01T00:17:13.436828Z', + foreign_landing_url: 'https://www.rawpixel.com/image/12553789/opening-the-sluices-the-secret-expedition', + url: 'https://images.rawpixel.com/image_1300/cHJpdmF0ZS9sci9pbWFnZXMvd2Vic2l0ZS8yMDIzLTAxL3ljYmF0bXM0MjU2NC1pbWFnZS5qcGc.jpg', + creator: null, + creator_url: null, + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'rawpixel', + source: 'rawpixel', + category: null, + filesize: null, + filetype: 'tiff', + tags: [ + { + name: 'cat', + accuracy: null, + }, + { + name: 'face', + accuracy: null, + }, + { + name: 'person', + accuracy: null, + }, + { + name: 'cartoon', + accuracy: null, + }, + { + name: 'art', + accuracy: null, + }, + { + name: 'vintage', + accuracy: null, + }, + { + name: 'animal', + accuracy: null, + }, + { + name: 'woman', + accuracy: null, + }, + { + name: 'painting', + accuracy: null, + }, + { + name: 'wedding', + accuracy: null, + }, + ], + attribution: '"Opening the Sluices or the Secret" is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 4096, + width: 2525, + thumbnail: 'http://localhost:49153/v1/images/e39f05c5-c586-482d-af68-ff13a790fd75/thumb/', + detail_url: 'http://localhost:49153/v1/images/e39f05c5-c586-482d-af68-ff13a790fd75/', + related_url: 'http://localhost:49153/v1/images/e39f05c5-c586-482d-af68-ff13a790fd75/related/', + unstable__sensitivity: [], + }, + { + id: 'dc552962-a2de-45b6-91c8-711eb35d9ddb', + title: 'Design for the New Gallery', + indexed_on: '2023-11-01T00:17:13.436828Z', + foreign_landing_url: 'https://www.rawpixel.com/image/12554145/design-for-the-new-gallery-busts-and-pictures', + url: 'https://images.rawpixel.com/image_1300/cHJpdmF0ZS9sci9pbWFnZXMvd2Vic2l0ZS8yMDIzLTAxL3ljYmF0bXM0NDExOS1pbWFnZS5qcGc.jpg', + creator: null, + creator_url: null, + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'rawpixel', + source: 'rawpixel', + category: null, + filesize: null, + filetype: 'tiff', + tags: [ + { + name: 'cat', + accuracy: null, + }, + { + name: 'face', + accuracy: null, + }, + { + name: 'person', + accuracy: null, + }, + { + name: 'cartoon', + accuracy: null, + }, + { + name: 'book', + accuracy: null, + }, + { + name: 'art', + accuracy: null, + }, + { + name: 'vintage', + accuracy: null, + }, + { + name: 'animal', + accuracy: null, + }, + { + name: 'man', + accuracy: null, + }, + { + name: 'woman', + accuracy: null, + }, + { + name: 'painting', + accuracy: null, + }, + ], + attribution: '"Design for the New Gallery" is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 3750, + width: 4096, + thumbnail: 'http://localhost:49153/v1/images/dc552962-a2de-45b6-91c8-711eb35d9ddb/thumb/', + detail_url: 'http://localhost:49153/v1/images/dc552962-a2de-45b6-91c8-711eb35d9ddb/', + related_url: 'http://localhost:49153/v1/images/dc552962-a2de-45b6-91c8-711eb35d9ddb/related/', + unstable__sensitivity: [], + }, + { + id: '7b29b605-4352-48dd-9ccf-f247e794d0dc', + title: 'Head of a Tiger', + indexed_on: '2023-11-01T00:17:13.436828Z', + foreign_landing_url: 'https://www.rawpixel.com/image/12555432/head-tiger', + url: 'https://images.rawpixel.com/image_1300/cHJpdmF0ZS9sci9pbWFnZXMvd2Vic2l0ZS8yMDIzLTA5L3ljYmF0bXM0NzEwMy1pbWFnZS5qcGc.jpg', + creator: null, + creator_url: null, + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'rawpixel', + source: 'rawpixel', + category: null, + filesize: null, + filetype: 'tiff', + tags: [ + { + name: 'cat', + accuracy: null, + }, + { + name: 'face', + accuracy: null, + }, + { + name: 'paper', + accuracy: null, + }, + { + name: 'tiger', + accuracy: null, + }, + { + name: 'person', + accuracy: null, + }, + { + name: 'art', + accuracy: null, + }, + { + name: 'watercolors', + accuracy: null, + }, + { + name: 'pattern', + accuracy: null, + }, + { + name: 'vintage', + accuracy: null, + }, + { + name: 'animal', + accuracy: null, + }, + { + name: 'painting', + accuracy: null, + }, + { + name: 'nature', + accuracy: null, + }, + ], + attribution: '"Head of a Tiger" is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 3396, + width: 3540, + thumbnail: 'http://localhost:49153/v1/images/7b29b605-4352-48dd-9ccf-f247e794d0dc/thumb/', + detail_url: 'http://localhost:49153/v1/images/7b29b605-4352-48dd-9ccf-f247e794d0dc/', + related_url: 'http://localhost:49153/v1/images/7b29b605-4352-48dd-9ccf-f247e794d0dc/related/', + unstable__sensitivity: [], + }, + { + id: '43d69782-b475-4154-b1d2-66cc07a83f3b', + title: "[Shooting] Enamour'd Sportsman", + indexed_on: '2023-11-01T00:17:13.436828Z', + foreign_landing_url: 'https://www.rawpixel.com/image/12555065/shooting-enamourd-sportsman', + url: 'https://images.rawpixel.com/image_1300/cHJpdmF0ZS9sci9pbWFnZXMvd2Vic2l0ZS8yMDIzLTAxL3ljYmF0bXM0NDk2MS1pbWFnZS5qcGc.jpg', + creator: null, + creator_url: null, + license: 'cc0', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/zero/1.0/', + provider: 'rawpixel', + source: 'rawpixel', + category: null, + filesize: null, + filetype: 'tiff', + tags: [ + { + name: 'retro color', + accuracy: null, + }, + { + name: '1801', + accuracy: null, + }, + { + name: 'adult', + accuracy: null, + }, + { + name: 'after john raphael smith', + accuracy: null, + }, + { + name: 'animal', + accuracy: null, + }, + { + name: 'apparel', + accuracy: null, + }, + { + name: 'architecture', + accuracy: null, + }, + { + name: 'art', + accuracy: null, + }, + { + name: 'artwork', + accuracy: null, + }, + { + name: 'canine', + accuracy: null, + }, + { + name: 'cat', + accuracy: null, + }, + ], + attribution: '"[Shooting] Enamour\'d Sportsman" is marked with CC0 1.0. To view the terms, visit https://creativecommons.org/publicdomain/zero/1.0/.', + fields_matched: [], + mature: false, + height: 3345, + width: 4096, + thumbnail: 'http://localhost:49153/v1/images/43d69782-b475-4154-b1d2-66cc07a83f3b/thumb/', + detail_url: 'http://localhost:49153/v1/images/43d69782-b475-4154-b1d2-66cc07a83f3b/', + related_url: 'http://localhost:49153/v1/images/43d69782-b475-4154-b1d2-66cc07a83f3b/related/', + unstable__sensitivity: [], + }, + ], + }, + }, +} \ No newline at end of file diff --git a/frontend/test/tapes/response-314.json5 b/frontend/test/tapes/response-314.json5 new file mode 100644 index 0000000000..fdd7da82bf --- /dev/null +++ b/frontend/test/tapes/response-314.json5 @@ -0,0 +1,972 @@ +{ + meta: { + createdAt: '2023-12-02T10:16:13.309Z', + host: 'https://api.openverse.engineering', + resHumanReadable: true, + resUncompressed: true, + }, + req: { + headers: { + connection: 'keep-alive', + }, + url: '/v1/images/source/flickr/creator/strogoscope/', + method: 'GET', + body: '', + }, + res: { + status: 200, + headers: { + date: [ + 'Sat, 02 Dec 2023 10:16:14 GMT', + ], + 'content-type': [ + 'application/json', + ], + 'transfer-encoding': [ + 'chunked', + ], + connection: [ + 'keep-alive', + ], + vary: [ + 'Accept-Encoding, Accept, Authorization, origin', + ], + allow: [ + 'GET, HEAD, OPTIONS', + ], + 'x-ratelimit-limit-anon_burst': [ + '5/hour', + ], + 'x-ratelimit-available-anon_burst': [ + '4', + ], + 'x-ratelimit-limit-anon_sustained': [ + '100/day', + ], + 'x-ratelimit-available-anon_sustained': [ + '98', + ], + 'x-ratelimit-limit-anon_thumbnail': [ + '150/minute', + ], + 'x-ratelimit-available-anon_thumbnail': [ + '149', + ], + 'x-frame-options': [ + 'DENY', + ], + 'x-content-type-options': [ + 'nosniff', + ], + 'referrer-policy': [ + 'same-origin', + ], + 'cross-origin-opener-policy': [ + 'same-origin', + ], + 'access-control-allow-origin': [ + '*', + ], + 'x-request-id': [ + 'f8563cdebae9442fa4ed5f9870745680', + ], + 'cache-control': [ + 'max-age=14400', + ], + 'cf-cache-status': [ + 'MISS', + ], + 'last-modified': [ + 'Sat, 02 Dec 2023 10:16:14 GMT', + ], + 'strict-transport-security': [ + 'max-age=15552000; includeSubDomains; preload', + ], + server: [ + 'cloudflare', + ], + 'cf-ray': [ + '82f2d02c9f8c6852-BUD', + ], + 'content-encoding': [ + 'br', + ], + 'alt-svc': [ + 'h3=":443"; ma=86400', + ], + }, + body: { + result_count: 691, + page_count: 20, + page_size: 20, + page: 1, + results: [ + { + id: 'a4eb2425-fed1-4a3c-9b71-ccbcfe197232', + title: 'First snow 2020', + indexed_on: '2020-12-14T00:19:16.319987Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50712093816', + url: 'https://live.staticflickr.com/65535/50712093816_1cf7e6b9b7_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [ + { + name: 'korea', + accuracy: null, + }, + { + name: 'night', + accuracy: null, + }, + { + name: 'seoul', + accuracy: null, + }, + { + name: 'sigmafp', + accuracy: null, + }, + { + name: 'snow', + accuracy: null, + }, + { + name: 'voigtlaendercolorskopar21mmf35', + accuracy: null, + }, + ], + attribution: '"First snow 2020" by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 683, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/a4eb2425-fed1-4a3c-9b71-ccbcfe197232/thumb/', + detail_url: 'http://localhost:49153/v1/images/a4eb2425-fed1-4a3c-9b71-ccbcfe197232/', + related_url: 'http://localhost:49153/v1/images/a4eb2425-fed1-4a3c-9b71-ccbcfe197232/related/', + unstable__sensitivity: [], + }, + { + id: '3b4a8d0d-ca0f-4da8-8934-79bcd6dfdc10', + title: 'First snow 2020', + indexed_on: '2020-12-14T00:19:16.319987Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50712094026', + url: 'https://live.staticflickr.com/65535/50712094026_05c8c82a1e_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [ + { + name: 'korea', + accuracy: null, + }, + { + name: 'night', + accuracy: null, + }, + { + name: 'seoul', + accuracy: null, + }, + { + name: 'sigmafp', + accuracy: null, + }, + { + name: 'snow', + accuracy: null, + }, + ], + attribution: '"First snow 2020" by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 683, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/3b4a8d0d-ca0f-4da8-8934-79bcd6dfdc10/thumb/', + detail_url: 'http://localhost:49153/v1/images/3b4a8d0d-ca0f-4da8-8934-79bcd6dfdc10/', + related_url: 'http://localhost:49153/v1/images/3b4a8d0d-ca0f-4da8-8934-79bcd6dfdc10/related/', + unstable__sensitivity: [], + }, + { + id: 'ad9c85a0-c1e6-43b3-9252-672788d362c8', + title: 'First snow 2020', + indexed_on: '2020-12-14T00:19:16.319987Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50712178162', + url: 'https://live.staticflickr.com/65535/50712178162_e4c77c1ba2_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [ + { + name: 'korea', + accuracy: null, + }, + { + name: 'night', + accuracy: null, + }, + { + name: 'seoul', + accuracy: null, + }, + { + name: 'sigmafp', + accuracy: null, + }, + { + name: 'snow', + accuracy: null, + }, + { + name: 'voigtlaendercolorskopar21mmf35', + accuracy: null, + }, + ], + attribution: '"First snow 2020" by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 683, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/ad9c85a0-c1e6-43b3-9252-672788d362c8/thumb/', + detail_url: 'http://localhost:49153/v1/images/ad9c85a0-c1e6-43b3-9252-672788d362c8/', + related_url: 'http://localhost:49153/v1/images/ad9c85a0-c1e6-43b3-9252-672788d362c8/related/', + unstable__sensitivity: [], + }, + { + id: '8a717d49-5bf2-4c2c-b633-8aa6b5ad7e9a', + title: 'A portrait of an excited puppy', + indexed_on: '2020-12-09T00:19:22.193888Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50695225456', + url: 'https://live.staticflickr.com/65535/50695225456_a07fe43679_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [ + { + name: 'dog', + accuracy: null, + }, + { + name: 'monochrome', + accuracy: null, + }, + { + name: 'sigmafp', + accuracy: null, + }, + { + name: 'voigtlaendercolorskopar21mmf35', + accuracy: null, + }, + ], + attribution: '"A portrait of an excited puppy" by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 682, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/8a717d49-5bf2-4c2c-b633-8aa6b5ad7e9a/thumb/', + detail_url: 'http://localhost:49153/v1/images/8a717d49-5bf2-4c2c-b633-8aa6b5ad7e9a/', + related_url: 'http://localhost:49153/v1/images/8a717d49-5bf2-4c2c-b633-8aa6b5ad7e9a/related/', + unstable__sensitivity: [], + }, + { + id: '940ac4fb-cbe3-4804-96b2-0e401ee17d8d', + title: "autumn is already here, it's just not evenly distributed", + indexed_on: '2020-10-24T00:19:13.822693Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50520774936', + url: 'https://live.staticflickr.com/65535/50520774936_8b5b184f09_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [ + { + name: 'autumn', + accuracy: null, + }, + { + name: 'korea', + accuracy: null, + }, + { + name: 'seoul', + accuracy: null, + }, + { + name: 'voigtlaendercolorskopar21mmf35', + accuracy: null, + }, + ], + attribution: '"autumn is already here, it\'s just not evenly distributed" by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 574, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/940ac4fb-cbe3-4804-96b2-0e401ee17d8d/thumb/', + detail_url: 'http://localhost:49153/v1/images/940ac4fb-cbe3-4804-96b2-0e401ee17d8d/', + related_url: 'http://localhost:49153/v1/images/940ac4fb-cbe3-4804-96b2-0e401ee17d8d/related/', + unstable__sensitivity: [], + }, + { + id: 'f0c663c9-25a9-4cc9-b3c3-232f52aa71fa', + title: "autumn is already here, it's just not evenly distributed", + indexed_on: '2020-10-24T00:19:13.822693Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50520954772', + url: 'https://live.staticflickr.com/65535/50520954772_8b3bf7b94c_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [ + { + name: 'autumn', + accuracy: null, + }, + { + name: 'korea', + accuracy: null, + }, + { + name: 'seoul', + accuracy: null, + }, + { + name: 'sigmafp', + accuracy: null, + }, + { + name: 'voigtlaendercolorskopar21mmf35', + accuracy: null, + }, + ], + attribution: '"autumn is already here, it\'s just not evenly distributed" by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 576, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/f0c663c9-25a9-4cc9-b3c3-232f52aa71fa/thumb/', + detail_url: 'http://localhost:49153/v1/images/f0c663c9-25a9-4cc9-b3c3-232f52aa71fa/', + related_url: 'http://localhost:49153/v1/images/f0c663c9-25a9-4cc9-b3c3-232f52aa71fa/related/', + unstable__sensitivity: [], + }, + { + id: '7cc6a3ef-e17d-4457-959e-a9a214aa5f39', + title: 'A portrait of a giant puppy near a cafe in Seoul', + indexed_on: '2020-10-22T00:18:53.112103Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50512852028', + url: 'https://live.staticflickr.com/65535/50512852028_90925de3fd_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [], + attribution: '"A portrait of a giant puppy near a cafe in Seoul" by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 682, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/7cc6a3ef-e17d-4457-959e-a9a214aa5f39/thumb/', + detail_url: 'http://localhost:49153/v1/images/7cc6a3ef-e17d-4457-959e-a9a214aa5f39/', + related_url: 'http://localhost:49153/v1/images/7cc6a3ef-e17d-4457-959e-a9a214aa5f39/related/', + unstable__sensitivity: [], + }, + { + id: '9c5c085c-0500-4403-b5d2-4392bdd575a3', + title: 'shadows are getting longer', + indexed_on: '2020-10-19T00:18:50.201811Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50501825726', + url: 'https://live.staticflickr.com/65535/50501825726_dd8ceebb59_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [ + { + name: 'korea', + accuracy: null, + }, + { + name: 'seoul', + accuracy: null, + }, + { + name: 'sigmafp', + accuracy: null, + }, + ], + attribution: '"shadows are getting longer" by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 576, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/9c5c085c-0500-4403-b5d2-4392bdd575a3/thumb/', + detail_url: 'http://localhost:49153/v1/images/9c5c085c-0500-4403-b5d2-4392bdd575a3/', + related_url: 'http://localhost:49153/v1/images/9c5c085c-0500-4403-b5d2-4392bdd575a3/related/', + unstable__sensitivity: [], + }, + { + id: '182d3deb-69d1-4168-bcc2-82b886ff38e9', + title: 'waiting', + indexed_on: '2020-10-18T00:19:01.019669Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50497754371', + url: 'https://live.staticflickr.com/65535/50497754371_fe1647cbcb_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [], + attribution: '"waiting" by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 682, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/182d3deb-69d1-4168-bcc2-82b886ff38e9/thumb/', + detail_url: 'http://localhost:49153/v1/images/182d3deb-69d1-4168-bcc2-82b886ff38e9/', + related_url: 'http://localhost:49153/v1/images/182d3deb-69d1-4168-bcc2-82b886ff38e9/related/', + unstable__sensitivity: [], + }, + { + id: 'f65ce029-d3ad-44e5-bb1c-ec3a0f8d53fa', + title: 'City hall subway station', + indexed_on: '2020-10-11T00:18:43.843272Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50447535007', + url: 'https://live.staticflickr.com/65535/50447535007_3861053778_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [], + attribution: '"City hall subway station" by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 681, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/f65ce029-d3ad-44e5-bb1c-ec3a0f8d53fa/thumb/', + detail_url: 'http://localhost:49153/v1/images/f65ce029-d3ad-44e5-bb1c-ec3a0f8d53fa/', + related_url: 'http://localhost:49153/v1/images/f65ce029-d3ad-44e5-bb1c-ec3a0f8d53fa/related/', + unstable__sensitivity: [], + }, + { + id: '83e3cadd-26d7-47e4-a0dd-1454d9c6447c', + title: 'subway entrance', + indexed_on: '2020-09-20T00:18:37.397884Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50359447743', + url: 'https://live.staticflickr.com/65535/50359447743_83db57e42a_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [ + { + name: 'multipleexposures', + accuracy: null, + }, + { + name: 'seoul', + accuracy: null, + }, + { + name: 'sigmafp', + accuracy: null, + }, + { + name: 'voigtlaendercolorskopar21mmf35', + accuracy: null, + }, + ], + attribution: '"subway entrance" by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 683, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/83e3cadd-26d7-47e4-a0dd-1454d9c6447c/thumb/', + detail_url: 'http://localhost:49153/v1/images/83e3cadd-26d7-47e4-a0dd-1454d9c6447c/', + related_url: 'http://localhost:49153/v1/images/83e3cadd-26d7-47e4-a0dd-1454d9c6447c/related/', + unstable__sensitivity: [], + }, + { + id: 'd7bf7178-e791-44c6-8006-5853b40b82b7', + title: '', + indexed_on: '2020-09-13T00:18:36.006127Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50333297818', + url: 'https://live.staticflickr.com/65535/50333297818_42b6a0e358_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [ + { + name: 'abstract', + accuracy: null, + }, + { + name: 'multipleexposures', + accuracy: null, + }, + { + name: 'sigmafp', + accuracy: null, + }, + { + name: 'voigtlaendercolorskopar21mmf35', + accuracy: null, + }, + ], + attribution: 'This work by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 683, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/d7bf7178-e791-44c6-8006-5853b40b82b7/thumb/', + detail_url: 'http://localhost:49153/v1/images/d7bf7178-e791-44c6-8006-5853b40b82b7/', + related_url: 'http://localhost:49153/v1/images/d7bf7178-e791-44c6-8006-5853b40b82b7/related/', + unstable__sensitivity: [], + }, + { + id: 'a9a07d18-42bd-4048-9004-cc4cd663ae3d', + title: '', + indexed_on: '2020-09-13T00:18:36.006127Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50334163092', + url: 'https://live.staticflickr.com/65535/50334163092_420e6e9290_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [ + { + name: 'abstract', + accuracy: null, + }, + { + name: 'multipleexposures', + accuracy: null, + }, + { + name: 'sigmafp', + accuracy: null, + }, + { + name: 'voigtlaendercolorskopar21mmf35', + accuracy: null, + }, + ], + attribution: 'This work by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 683, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/a9a07d18-42bd-4048-9004-cc4cd663ae3d/thumb/', + detail_url: 'http://localhost:49153/v1/images/a9a07d18-42bd-4048-9004-cc4cd663ae3d/', + related_url: 'http://localhost:49153/v1/images/a9a07d18-42bd-4048-9004-cc4cd663ae3d/related/', + unstable__sensitivity: [], + }, + { + id: 'c283df51-6755-42c3-bf2d-42567bcff0c9', + title: '', + indexed_on: '2020-09-11T00:17:45.905344Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50326565447', + url: 'https://live.staticflickr.com/65535/50326565447_92bfd26192_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [ + { + name: 'sigmafp', + accuracy: null, + }, + { + name: 'sky', + accuracy: null, + }, + { + name: 'twoexposures', + accuracy: null, + }, + { + name: 'voigtlaendercolorskopar21mmf35', + accuracy: null, + }, + ], + attribution: 'This work by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 683, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/c283df51-6755-42c3-bf2d-42567bcff0c9/thumb/', + detail_url: 'http://localhost:49153/v1/images/c283df51-6755-42c3-bf2d-42567bcff0c9/', + related_url: 'http://localhost:49153/v1/images/c283df51-6755-42c3-bf2d-42567bcff0c9/related/', + unstable__sensitivity: [], + }, + { + id: '17e663e5-ce85-4812-a323-1a9f907f1376', + title: 'Mapo night', + indexed_on: '2020-08-27T00:18:45.443673Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50272054627', + url: 'https://live.staticflickr.com/65535/50272054627_c475c49518_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [ + { + name: 'korea', + accuracy: null, + }, + { + name: 'monochrome', + accuracy: null, + }, + { + name: 'night', + accuracy: null, + }, + { + name: 'seoul', + accuracy: null, + }, + { + name: 'street', + accuracy: null, + }, + ], + attribution: '"Mapo night" by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 682, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/17e663e5-ce85-4812-a323-1a9f907f1376/thumb/', + detail_url: 'http://localhost:49153/v1/images/17e663e5-ce85-4812-a323-1a9f907f1376/', + related_url: 'http://localhost:49153/v1/images/17e663e5-ce85-4812-a323-1a9f907f1376/related/', + unstable__sensitivity: [], + }, + { + id: '55d7b1b9-f2f1-4eb9-bd4b-435b891e129b', + title: 'Mapo night', + indexed_on: '2020-08-27T00:18:45.443673Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50271781367', + url: 'https://live.staticflickr.com/65535/50271781367_588b0a6472_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [ + { + name: 'korea', + accuracy: null, + }, + { + name: 'monochrome', + accuracy: null, + }, + { + name: 'night', + accuracy: null, + }, + { + name: 'seoul', + accuracy: null, + }, + { + name: 'street', + accuracy: null, + }, + ], + attribution: '"Mapo night" by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 682, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/55d7b1b9-f2f1-4eb9-bd4b-435b891e129b/thumb/', + detail_url: 'http://localhost:49153/v1/images/55d7b1b9-f2f1-4eb9-bd4b-435b891e129b/', + related_url: 'http://localhost:49153/v1/images/55d7b1b9-f2f1-4eb9-bd4b-435b891e129b/related/', + unstable__sensitivity: [], + }, + { + id: 'c5068bd6-969a-4d26-901e-a6928ad88f03', + title: 'Mapo night', + indexed_on: '2020-08-27T00:18:45.443673Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50271216348', + url: 'https://live.staticflickr.com/65535/50271216348_51f10430a0_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [ + { + name: 'korea', + accuracy: null, + }, + { + name: 'monochrome', + accuracy: null, + }, + { + name: 'night', + accuracy: null, + }, + { + name: 'seoul', + accuracy: null, + }, + { + name: 'street', + accuracy: null, + }, + ], + attribution: '"Mapo night" by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 682, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/c5068bd6-969a-4d26-901e-a6928ad88f03/thumb/', + detail_url: 'http://localhost:49153/v1/images/c5068bd6-969a-4d26-901e-a6928ad88f03/', + related_url: 'http://localhost:49153/v1/images/c5068bd6-969a-4d26-901e-a6928ad88f03/related/', + unstable__sensitivity: [], + }, + { + id: 'ff68bf12-1e39-4304-8cee-d79ebf66873f', + title: '', + indexed_on: '2020-08-20T00:18:39.037141Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50243759443', + url: 'https://live.staticflickr.com/65535/50243759443_7ceb4cf8db_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [ + { + name: 'evening', + accuracy: null, + }, + { + name: 'korea', + accuracy: null, + }, + { + name: 'seoul', + accuracy: null, + }, + { + name: 'street', + accuracy: null, + }, + { + name: 'voigtlaendercolorskopar21mmf35', + accuracy: null, + }, + ], + attribution: 'This work by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 682, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/ff68bf12-1e39-4304-8cee-d79ebf66873f/thumb/', + detail_url: 'http://localhost:49153/v1/images/ff68bf12-1e39-4304-8cee-d79ebf66873f/', + related_url: 'http://localhost:49153/v1/images/ff68bf12-1e39-4304-8cee-d79ebf66873f/related/', + unstable__sensitivity: [], + }, + { + id: '890c0e0b-2147-4790-8bef-babde53cf0f4', + title: 'Sunstars and flares', + indexed_on: '2020-08-19T00:18:36.958800Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50240275561', + url: 'https://live.staticflickr.com/65535/50240275561_4455072550_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [ + { + name: 'colorskopar21mmf35', + accuracy: null, + }, + { + name: 'korea', + accuracy: null, + }, + { + name: 'seoul', + accuracy: null, + }, + { + name: 'voigtlaender', + accuracy: null, + }, + { + name: 'voigtlaendercolorskopar21mmf35', + accuracy: null, + }, + ], + attribution: '"Sunstars and flares" by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 575, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/890c0e0b-2147-4790-8bef-babde53cf0f4/thumb/', + detail_url: 'http://localhost:49153/v1/images/890c0e0b-2147-4790-8bef-babde53cf0f4/', + related_url: 'http://localhost:49153/v1/images/890c0e0b-2147-4790-8bef-babde53cf0f4/related/', + unstable__sensitivity: [], + }, + { + id: '851269f3-0cfc-45e4-a549-241e2a97cf34', + title: 'morning', + indexed_on: '2020-08-14T00:19:06.315502Z', + foreign_landing_url: 'https://www.flickr.com/photos/7788419@N05/50221995402', + url: 'https://live.staticflickr.com/65535/50221995402_6300e390b8_b.jpg', + creator: 'strogoscope', + creator_url: 'https://www.flickr.com/photos/7788419@N05', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: null, + filesize: null, + filetype: null, + tags: [ + { + name: 'korea', + accuracy: null, + }, + { + name: 'seoul', + accuracy: null, + }, + { + name: 'sigmafp', + accuracy: null, + }, + ], + attribution: '"morning" by strogoscope is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 682, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/851269f3-0cfc-45e4-a549-241e2a97cf34/thumb/', + detail_url: 'http://localhost:49153/v1/images/851269f3-0cfc-45e4-a549-241e2a97cf34/', + related_url: 'http://localhost:49153/v1/images/851269f3-0cfc-45e4-a549-241e2a97cf34/related/', + unstable__sensitivity: [], + }, + ], + }, + }, +} \ No newline at end of file diff --git a/frontend/test/tapes/response-333.json5 b/frontend/test/tapes/response-333.json5 new file mode 100644 index 0000000000..27840b25d3 --- /dev/null +++ b/frontend/test/tapes/response-333.json5 @@ -0,0 +1,745 @@ +{ + meta: { + createdAt: '2023-12-02T10:30:26.278Z', + host: 'https://api.openverse.engineering', + resHumanReadable: true, + resUncompressed: true, + }, + req: { + headers: { + connection: 'keep-alive', + }, + url: '/v1/images/source/flickr/', + method: 'GET', + body: '', + }, + res: { + status: 200, + headers: { + date: [ + 'Sat, 02 Dec 2023 10:30:26 GMT', + ], + 'content-type': [ + 'application/json', + ], + 'transfer-encoding': [ + 'chunked', + ], + connection: [ + 'keep-alive', + ], + vary: [ + 'Accept-Encoding, Accept, Authorization, origin', + ], + allow: [ + 'GET, HEAD, OPTIONS', + ], + 'x-ratelimit-limit-anon_burst': [ + '5/hour', + ], + 'x-ratelimit-available-anon_burst': [ + '4', + ], + 'x-ratelimit-limit-anon_sustained': [ + '100/day', + ], + 'x-ratelimit-available-anon_sustained': [ + '99', + ], + 'x-ratelimit-limit-anon_thumbnail': [ + '150/minute', + ], + 'x-ratelimit-available-anon_thumbnail': [ + '149', + ], + 'x-frame-options': [ + 'DENY', + ], + 'x-content-type-options': [ + 'nosniff', + ], + 'referrer-policy': [ + 'same-origin', + ], + 'cross-origin-opener-policy': [ + 'same-origin', + ], + 'access-control-allow-origin': [ + '*', + ], + 'x-request-id': [ + 'bc562ee96539435d84d3579c41a0fd33', + ], + 'cache-control': [ + 'max-age=14400', + ], + 'cf-cache-status': [ + 'HIT', + ], + age: [ + '76367', + ], + 'last-modified': [ + 'Fri, 01 Dec 2023 13:17:39 GMT', + ], + 'strict-transport-security': [ + 'max-age=15552000; includeSubDomains; preload', + ], + server: [ + 'cloudflare', + ], + 'cf-ray': [ + '82f2e4ff3b42c1b4-BUD', + ], + 'content-encoding': [ + 'br', + ], + 'alt-svc': [ + 'h3=":443"; ma=86400', + ], + }, + body: { + result_count: 10000, + page_count: 20, + page_size: 20, + page: 1, + results: [ + { + id: '9a2f8d07-99da-45b4-a596-3913d755bb29', + title: '', + indexed_on: '2023-11-27T00:00:52.143934Z', + foreign_landing_url: 'https://www.flickr.com/photos/75012450@N00/53356265534', + url: 'https://live.staticflickr.com/65535/53356265534_5fd061ef72_b.jpg', + creator: 'Mikel Agirregabiria Agirre', + creator_url: 'https://www.flickr.com/photos/75012450@N00', + license: 'by-nc-sa', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by-nc-sa/2.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [], + attribution: 'This work by Mikel Agirregabiria Agirre is licensed under CC BY-NC-SA 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/2.0/.', + fields_matched: [], + mature: false, + height: 768, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/9a2f8d07-99da-45b4-a596-3913d755bb29/thumb/', + detail_url: 'http://localhost:49153/v1/images/9a2f8d07-99da-45b4-a596-3913d755bb29/', + related_url: 'http://localhost:49153/v1/images/9a2f8d07-99da-45b4-a596-3913d755bb29/related/', + unstable__sensitivity: [], + }, + { + id: '977dea49-d072-4bd8-a74d-6e208721f4a7', + title: 'Premio GetxoBlog Ur para Amaia Agirre, Alcaldesa de Getxo', + indexed_on: '2023-11-27T00:00:52.143934Z', + foreign_landing_url: 'https://www.flickr.com/photos/75012450@N00/53355061902', + url: 'https://live.staticflickr.com/65535/53355061902_8072652935_b.jpg', + creator: 'Mikel Agirregabiria Agirre', + creator_url: 'https://www.flickr.com/photos/75012450@N00', + license: 'by-nc-sa', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by-nc-sa/2.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [], + attribution: '"Premio GetxoBlog Ur para Amaia Agirre, Alcaldesa de Getxo" by Mikel Agirregabiria Agirre is licensed under CC BY-NC-SA 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/2.0/.', + fields_matched: [], + mature: false, + height: 768, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/977dea49-d072-4bd8-a74d-6e208721f4a7/thumb/', + detail_url: 'http://localhost:49153/v1/images/977dea49-d072-4bd8-a74d-6e208721f4a7/', + related_url: 'http://localhost:49153/v1/images/977dea49-d072-4bd8-a74d-6e208721f4a7/related/', + unstable__sensitivity: [], + }, + { + id: '439b2c4e-36b4-4e10-b3a9-2b7fa0ddbef4', + title: 'Premio GetxoBlog Ur para Amaia Agirre, Alcaldesa de Getxo', + indexed_on: '2023-11-27T00:00:52.143934Z', + foreign_landing_url: 'https://www.flickr.com/photos/75012450@N00/53355935361', + url: 'https://live.staticflickr.com/65535/53355935361_9cef275e8d_b.jpg', + creator: 'Mikel Agirregabiria Agirre', + creator_url: 'https://www.flickr.com/photos/75012450@N00', + license: 'by-nc-sa', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by-nc-sa/2.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [], + attribution: '"Premio GetxoBlog Ur para Amaia Agirre, Alcaldesa de Getxo" by Mikel Agirregabiria Agirre is licensed under CC BY-NC-SA 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/2.0/.', + fields_matched: [], + mature: false, + height: 768, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/439b2c4e-36b4-4e10-b3a9-2b7fa0ddbef4/thumb/', + detail_url: 'http://localhost:49153/v1/images/439b2c4e-36b4-4e10-b3a9-2b7fa0ddbef4/', + related_url: 'http://localhost:49153/v1/images/439b2c4e-36b4-4e10-b3a9-2b7fa0ddbef4/related/', + unstable__sensitivity: [], + }, + { + id: 'd27c6913-2dad-4775-a085-65e9091f738c', + title: 'Premio GetxoBlog Ur para Amaia Agirre, Alcaldesa de Getxo', + indexed_on: '2023-11-27T00:00:52.143934Z', + foreign_landing_url: 'https://www.flickr.com/photos/75012450@N00/53355061907', + url: 'https://live.staticflickr.com/65535/53355061907_d159038b3c_b.jpg', + creator: 'Mikel Agirregabiria Agirre', + creator_url: 'https://www.flickr.com/photos/75012450@N00', + license: 'by-nc-sa', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by-nc-sa/2.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [], + attribution: '"Premio GetxoBlog Ur para Amaia Agirre, Alcaldesa de Getxo" by Mikel Agirregabiria Agirre is licensed under CC BY-NC-SA 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/2.0/.', + fields_matched: [], + mature: false, + height: 768, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/d27c6913-2dad-4775-a085-65e9091f738c/thumb/', + detail_url: 'http://localhost:49153/v1/images/d27c6913-2dad-4775-a085-65e9091f738c/', + related_url: 'http://localhost:49153/v1/images/d27c6913-2dad-4775-a085-65e9091f738c/related/', + unstable__sensitivity: [], + }, + { + id: 'e7687b92-08d5-414a-a8a0-45411fe2f915', + title: 'ENTRAR Y SALIR ASI SEA POR LAS VENTANAS', + indexed_on: '2023-11-26T00:00:59.659756Z', + foreign_landing_url: 'https://www.flickr.com/photos/130050005@N06/53354155153', + url: 'https://live.staticflickr.com/65535/53354155153_6af7465f60_b.jpg', + creator: 'El77CCA', + creator_url: 'https://www.flickr.com/photos/130050005@N06', + license: 'by-nc-sa', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by-nc-sa/2.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [], + attribution: '"ENTRAR Y SALIR ASI SEA POR LAS VENTANAS" by El77CCA is licensed under CC BY-NC-SA 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/2.0/.', + fields_matched: [], + mature: false, + height: 683, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/e7687b92-08d5-414a-a8a0-45411fe2f915/thumb/', + detail_url: 'http://localhost:49153/v1/images/e7687b92-08d5-414a-a8a0-45411fe2f915/', + related_url: 'http://localhost:49153/v1/images/e7687b92-08d5-414a-a8a0-45411fe2f915/related/', + unstable__sensitivity: [], + }, + { + id: '256d1c8e-fadf-4b33-be6e-a379e1b29e5b', + title: 'fire-2023-sat-32', + indexed_on: '2023-11-26T00:00:59.659756Z', + foreign_landing_url: 'https://www.flickr.com/photos/49503002894@N01/53354247419', + url: 'https://live.staticflickr.com/65535/53354247419_549a46f307_b.jpg', + creator: 'Kris Krug', + creator_url: 'https://www.flickr.com/photos/49503002894@N01', + license: 'by-nc-sa', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by-nc-sa/2.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [], + attribution: '"fire-2023-sat-32" by Kris Krug is licensed under CC BY-NC-SA 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/2.0/.', + fields_matched: [], + mature: false, + height: 606, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/256d1c8e-fadf-4b33-be6e-a379e1b29e5b/thumb/', + detail_url: 'http://localhost:49153/v1/images/256d1c8e-fadf-4b33-be6e-a379e1b29e5b/', + related_url: 'http://localhost:49153/v1/images/256d1c8e-fadf-4b33-be6e-a379e1b29e5b/related/', + unstable__sensitivity: [], + }, + { + id: '6e5401a7-2433-409b-bbde-e9bb8fff926c', + title: 'ENTRAR Y SALIR ASI SEA POR LAS VENTANAS', + indexed_on: '2023-11-26T00:00:59.659756Z', + foreign_landing_url: 'https://www.flickr.com/photos/130050005@N06/53354257354', + url: 'https://live.staticflickr.com/65535/53354257354_aba5cc7313_b.jpg', + creator: 'El77CCA', + creator_url: 'https://www.flickr.com/photos/130050005@N06', + license: 'by-nc-sa', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by-nc-sa/2.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [], + attribution: '"ENTRAR Y SALIR ASI SEA POR LAS VENTANAS" by El77CCA is licensed under CC BY-NC-SA 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/2.0/.', + fields_matched: [], + mature: false, + height: 683, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/6e5401a7-2433-409b-bbde-e9bb8fff926c/thumb/', + detail_url: 'http://localhost:49153/v1/images/6e5401a7-2433-409b-bbde-e9bb8fff926c/', + related_url: 'http://localhost:49153/v1/images/6e5401a7-2433-409b-bbde-e9bb8fff926c/related/', + unstable__sensitivity: [], + }, + { + id: '27d6d5b1-33f5-4724-b53e-889a24410c9e', + title: 'alex002', + indexed_on: '2023-11-26T00:00:59.659756Z', + foreign_landing_url: 'https://www.flickr.com/photos/157252539@N04/53354370875', + url: 'https://live.staticflickr.com/65535/53354370875_699e2afe8a_b.jpg', + creator: 'biwith', + creator_url: 'https://www.flickr.com/photos/157252539@N04', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [], + attribution: '"alex002" by biwith is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 1024, + width: 679, + thumbnail: 'http://localhost:49153/v1/images/27d6d5b1-33f5-4724-b53e-889a24410c9e/thumb/', + detail_url: 'http://localhost:49153/v1/images/27d6d5b1-33f5-4724-b53e-889a24410c9e/', + related_url: 'http://localhost:49153/v1/images/27d6d5b1-33f5-4724-b53e-889a24410c9e/related/', + unstable__sensitivity: [], + }, + { + id: '5f733de4-65fa-4a44-a1a7-5030a6eca2e3', + title: 'fire-2023-sat-62', + indexed_on: '2023-11-26T00:00:59.659756Z', + foreign_landing_url: 'https://www.flickr.com/photos/49503002894@N01/53354370940', + url: 'https://live.staticflickr.com/65535/53354370940_9247b08493_b.jpg', + creator: 'Kris Krug', + creator_url: 'https://www.flickr.com/photos/49503002894@N01', + license: 'by-nc-sa', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by-nc-sa/2.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [], + attribution: '"fire-2023-sat-62" by Kris Krug is licensed under CC BY-NC-SA 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/2.0/.', + fields_matched: [], + mature: false, + height: 683, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/5f733de4-65fa-4a44-a1a7-5030a6eca2e3/thumb/', + detail_url: 'http://localhost:49153/v1/images/5f733de4-65fa-4a44-a1a7-5030a6eca2e3/', + related_url: 'http://localhost:49153/v1/images/5f733de4-65fa-4a44-a1a7-5030a6eca2e3/related/', + unstable__sensitivity: [], + }, + { + id: 'b72bf27e-006c-40af-966f-f8eb91db71ab', + title: 'IMG_0393', + indexed_on: '2023-11-26T00:00:59.659756Z', + foreign_landing_url: 'https://www.flickr.com/photos/131961022@N07/53354373835', + url: 'https://live.staticflickr.com/65535/53354373835_11818ffb3c_b.jpg', + creator: 'sudesb', + creator_url: 'https://www.flickr.com/photos/131961022@N07', + license: 'pdm', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/mark/1.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [], + attribution: '"IMG_0393" by sudesb is marked with Public Domain Mark 1.0. To view the terms, visit https://creativecommons.org/publicdomain/mark/1.0/.', + fields_matched: [], + mature: false, + height: 683, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/b72bf27e-006c-40af-966f-f8eb91db71ab/thumb/', + detail_url: 'http://localhost:49153/v1/images/b72bf27e-006c-40af-966f-f8eb91db71ab/', + related_url: 'http://localhost:49153/v1/images/b72bf27e-006c-40af-966f-f8eb91db71ab/related/', + unstable__sensitivity: [], + }, + { + id: '445e3098-9c05-426d-b946-f9d44bebdfc6', + title: 'ENTRAR Y SALIR ASI SEA POR LAS VENTANAS', + indexed_on: '2023-11-26T00:00:59.659756Z', + foreign_landing_url: 'https://www.flickr.com/photos/130050005@N06/53354379800', + url: 'https://live.staticflickr.com/65535/53354379800_321296b5ca_b.jpg', + creator: 'El77CCA', + creator_url: 'https://www.flickr.com/photos/130050005@N06', + license: 'by-nc-sa', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by-nc-sa/2.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [], + attribution: '"ENTRAR Y SALIR ASI SEA POR LAS VENTANAS" by El77CCA is licensed under CC BY-NC-SA 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/2.0/.', + fields_matched: [], + mature: false, + height: 1024, + width: 683, + thumbnail: 'http://localhost:49153/v1/images/445e3098-9c05-426d-b946-f9d44bebdfc6/thumb/', + detail_url: 'http://localhost:49153/v1/images/445e3098-9c05-426d-b946-f9d44bebdfc6/', + related_url: 'http://localhost:49153/v1/images/445e3098-9c05-426d-b946-f9d44bebdfc6/related/', + unstable__sensitivity: [], + }, + { + id: 'c58a78d2-706d-4475-bffb-ef70d24e2c13', + title: 'ENTRAR Y SALIR ASI SEA POR LAS VENTANAS', + indexed_on: '2023-11-26T00:00:59.659756Z', + foreign_landing_url: 'https://www.flickr.com/photos/130050005@N06/53354380290', + url: 'https://live.staticflickr.com/65535/53354380290_09ba8bd2d4_b.jpg', + creator: 'El77CCA', + creator_url: 'https://www.flickr.com/photos/130050005@N06', + license: 'by-nc-sa', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by-nc-sa/2.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [], + attribution: '"ENTRAR Y SALIR ASI SEA POR LAS VENTANAS" by El77CCA is licensed under CC BY-NC-SA 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/2.0/.', + fields_matched: [], + mature: false, + height: 1024, + width: 683, + thumbnail: 'http://localhost:49153/v1/images/c58a78d2-706d-4475-bffb-ef70d24e2c13/thumb/', + detail_url: 'http://localhost:49153/v1/images/c58a78d2-706d-4475-bffb-ef70d24e2c13/', + related_url: 'http://localhost:49153/v1/images/c58a78d2-706d-4475-bffb-ef70d24e2c13/related/', + unstable__sensitivity: [], + }, + { + id: 'c42d0d2e-7f2d-4e3e-a138-a6aa5abf8cf5', + title: 'Atlantic Ghost Crab (Ocypode quadrata)', + indexed_on: '2023-11-26T00:00:59.659756Z', + foreign_landing_url: 'https://www.flickr.com/photos/38514062@N03/53353038127', + url: 'https://live.staticflickr.com/65535/53353038127_5119a98379_b.jpg', + creator: 'Mary Keim', + creator_url: 'https://www.flickr.com/photos/38514062@N03', + license: 'by-nc-sa', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by-nc-sa/2.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [ + { + name: 'canaveralnationalseashore', + accuracy: null, + }, + { + name: 'centralflorida', + accuracy: null, + }, + { + name: 'marykeim', + accuracy: null, + }, + ], + attribution: '"Atlantic Ghost Crab (Ocypode quadrata)" by Mary Keim is licensed under CC BY-NC-SA 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/2.0/.', + fields_matched: [], + mature: false, + height: 614, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/c42d0d2e-7f2d-4e3e-a138-a6aa5abf8cf5/thumb/', + detail_url: 'http://localhost:49153/v1/images/c42d0d2e-7f2d-4e3e-a138-a6aa5abf8cf5/', + related_url: 'http://localhost:49153/v1/images/c42d0d2e-7f2d-4e3e-a138-a6aa5abf8cf5/related/', + unstable__sensitivity: [], + }, + { + id: '0b401705-1618-42cd-9f95-a42d35af566a', + title: 'Thanksgiving Visit to Charlotte Hall', + indexed_on: '2023-11-26T00:00:59.659756Z', + foreign_landing_url: 'https://www.flickr.com/photos/64018555@N03/53353047557', + url: 'https://live.staticflickr.com/65535/53353047557_fa0603a7cc_b.jpg', + creator: 'MDGovpics', + creator_url: 'https://www.flickr.com/photos/64018555@N03', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [ + { + name: 'arunamiller', + accuracy: null, + }, + { + name: 'governor', + accuracy: null, + }, + { + name: 'governormoore', + accuracy: null, + }, + { + name: 'governorwesmoore', + accuracy: null, + }, + { + name: 'governorwmoore', + accuracy: null, + }, + { + name: 'ltgovernorarunamiller', + accuracy: null, + }, + { + name: 'ltgovernormiller', + accuracy: null, + }, + { + name: 'thanksgivingvisittocharlottehall', + accuracy: null, + }, + { + name: 'westleymoore', + accuracy: null, + }, + { + name: 'westleywatendeomarimoore', + accuracy: null, + }, + ], + attribution: '"Thanksgiving Visit to Charlotte Hall" by MDGovpics is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 819, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/0b401705-1618-42cd-9f95-a42d35af566a/thumb/', + detail_url: 'http://localhost:49153/v1/images/0b401705-1618-42cd-9f95-a42d35af566a/', + related_url: 'http://localhost:49153/v1/images/0b401705-1618-42cd-9f95-a42d35af566a/related/', + unstable__sensitivity: [], + }, + { + id: '04bbf6ec-ffbc-40c3-b872-dbf4f1047ab7', + title: 'alex004', + indexed_on: '2023-11-26T00:00:59.659756Z', + foreign_landing_url: 'https://www.flickr.com/photos/157252539@N04/53353049417', + url: 'https://live.staticflickr.com/65535/53353049417_fa224128aa_b.jpg', + creator: 'biwith', + creator_url: 'https://www.flickr.com/photos/157252539@N04', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [], + attribution: '"alex004" by biwith is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 683, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/04bbf6ec-ffbc-40c3-b872-dbf4f1047ab7/thumb/', + detail_url: 'http://localhost:49153/v1/images/04bbf6ec-ffbc-40c3-b872-dbf4f1047ab7/', + related_url: 'http://localhost:49153/v1/images/04bbf6ec-ffbc-40c3-b872-dbf4f1047ab7/related/', + unstable__sensitivity: [], + }, + { + id: '87e9b112-e663-42a2-9480-b1deb170ab8c', + title: 'IMG_0410', + indexed_on: '2023-11-26T00:00:59.659756Z', + foreign_landing_url: 'https://www.flickr.com/photos/131961022@N07/53353050707', + url: 'https://live.staticflickr.com/65535/53353050707_457de00f41_b.jpg', + creator: 'sudesb', + creator_url: 'https://www.flickr.com/photos/131961022@N07', + license: 'pdm', + license_version: '1.0', + license_url: 'https://creativecommons.org/publicdomain/mark/1.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [], + attribution: '"IMG_0410" by sudesb is marked with Public Domain Mark 1.0. To view the terms, visit https://creativecommons.org/publicdomain/mark/1.0/.', + fields_matched: [], + mature: false, + height: 683, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/87e9b112-e663-42a2-9480-b1deb170ab8c/thumb/', + detail_url: 'http://localhost:49153/v1/images/87e9b112-e663-42a2-9480-b1deb170ab8c/', + related_url: 'http://localhost:49153/v1/images/87e9b112-e663-42a2-9480-b1deb170ab8c/related/', + unstable__sensitivity: [], + }, + { + id: 'c70ad0ce-8072-4583-8c98-fcadd35d8755', + title: 'ENTRAR Y SALIR ASI SEA POR LAS VENTANAS', + indexed_on: '2023-11-26T00:00:59.659756Z', + foreign_landing_url: 'https://www.flickr.com/photos/130050005@N06/53353055982', + url: 'https://live.staticflickr.com/65535/53353055982_3bce1c00ab_b.jpg', + creator: 'El77CCA', + creator_url: 'https://www.flickr.com/photos/130050005@N06', + license: 'by-nc-sa', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by-nc-sa/2.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [], + attribution: '"ENTRAR Y SALIR ASI SEA POR LAS VENTANAS" by El77CCA is licensed under CC BY-NC-SA 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/2.0/.', + fields_matched: [], + mature: false, + height: 1024, + width: 683, + thumbnail: 'http://localhost:49153/v1/images/c70ad0ce-8072-4583-8c98-fcadd35d8755/thumb/', + detail_url: 'http://localhost:49153/v1/images/c70ad0ce-8072-4583-8c98-fcadd35d8755/', + related_url: 'http://localhost:49153/v1/images/c70ad0ce-8072-4583-8c98-fcadd35d8755/related/', + unstable__sensitivity: [], + }, + { + id: 'a7cbaaf7-4482-472c-8b41-50b47e7eadec', + title: 'ENTRAR Y SALIR ASI SEA POR LAS VENTANAS', + indexed_on: '2023-11-26T00:00:59.659756Z', + foreign_landing_url: 'https://www.flickr.com/photos/130050005@N06/53353056407', + url: 'https://live.staticflickr.com/65535/53353056407_3e1b27b77d_b.jpg', + creator: 'El77CCA', + creator_url: 'https://www.flickr.com/photos/130050005@N06', + license: 'by-nc-sa', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by-nc-sa/2.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [], + attribution: '"ENTRAR Y SALIR ASI SEA POR LAS VENTANAS" by El77CCA is licensed under CC BY-NC-SA 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/2.0/.', + fields_matched: [], + mature: false, + height: 1024, + width: 683, + thumbnail: 'http://localhost:49153/v1/images/a7cbaaf7-4482-472c-8b41-50b47e7eadec/thumb/', + detail_url: 'http://localhost:49153/v1/images/a7cbaaf7-4482-472c-8b41-50b47e7eadec/', + related_url: 'http://localhost:49153/v1/images/a7cbaaf7-4482-472c-8b41-50b47e7eadec/related/', + unstable__sensitivity: [], + }, + { + id: '652a591c-e1c6-48ed-9ff5-ebe28aaefbf0', + title: 'Thanksgiving Visit to Charlotte Hall', + indexed_on: '2023-11-26T00:00:59.659756Z', + foreign_landing_url: 'https://www.flickr.com/photos/64018555@N03/53353057142', + url: 'https://live.staticflickr.com/65535/53353057142_c99bea1ffd_b.jpg', + creator: 'MDGovpics', + creator_url: 'https://www.flickr.com/photos/64018555@N03', + license: 'by', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by/2.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [ + { + name: 'arunamiller', + accuracy: null, + }, + { + name: 'governor', + accuracy: null, + }, + { + name: 'governormoore', + accuracy: null, + }, + { + name: 'governorwesmoore', + accuracy: null, + }, + { + name: 'governorwmoore', + accuracy: null, + }, + { + name: 'ltgovernorarunamiller', + accuracy: null, + }, + { + name: 'ltgovernormiller', + accuracy: null, + }, + { + name: 'thanksgivingvisittocharlottehall', + accuracy: null, + }, + { + name: 'westleymoore', + accuracy: null, + }, + { + name: 'westleywatendeomarimoore', + accuracy: null, + }, + ], + attribution: '"Thanksgiving Visit to Charlotte Hall" by MDGovpics is licensed under CC BY 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by/2.0/.', + fields_matched: [], + mature: false, + height: 1024, + width: 819, + thumbnail: 'http://localhost:49153/v1/images/652a591c-e1c6-48ed-9ff5-ebe28aaefbf0/thumb/', + detail_url: 'http://localhost:49153/v1/images/652a591c-e1c6-48ed-9ff5-ebe28aaefbf0/', + related_url: 'http://localhost:49153/v1/images/652a591c-e1c6-48ed-9ff5-ebe28aaefbf0/related/', + unstable__sensitivity: [], + }, + { + id: '77875872-b5f6-4073-9279-857ca1d5672d', + title: 'fire-2023-sat-24', + indexed_on: '2023-11-26T00:00:59.659756Z', + foreign_landing_url: 'https://www.flickr.com/photos/49503002894@N01/53353919556', + url: 'https://live.staticflickr.com/65535/53353919556_0ce8804a05_b.jpg', + creator: 'Kris Krug', + creator_url: 'https://www.flickr.com/photos/49503002894@N01', + license: 'by-nc-sa', + license_version: '2.0', + license_url: 'https://creativecommons.org/licenses/by-nc-sa/2.0/', + provider: 'flickr', + source: 'flickr', + category: 'photograph', + filesize: null, + filetype: 'jpg', + tags: [], + attribution: '"fire-2023-sat-24" by Kris Krug is licensed under CC BY-NC-SA 2.0. To view a copy of this license, visit https://creativecommons.org/licenses/by-nc-sa/2.0/.', + fields_matched: [], + mature: false, + height: 683, + width: 1024, + thumbnail: 'http://localhost:49153/v1/images/77875872-b5f6-4073-9279-857ca1d5672d/thumb/', + detail_url: 'http://localhost:49153/v1/images/77875872-b5f6-4073-9279-857ca1d5672d/', + related_url: 'http://localhost:49153/v1/images/77875872-b5f6-4073-9279-857ca1d5672d/related/', + unstable__sensitivity: [], + }, + ], + }, + }, +} \ No newline at end of file diff --git a/frontend/test/unit/specs/stores/search-store.spec.js b/frontend/test/unit/specs/stores/search-store.spec.js index eeda3f659c..ca9722320d 100644 --- a/frontend/test/unit/specs/stores/search-store.spec.js +++ b/frontend/test/unit/specs/stores/search-store.spec.js @@ -104,6 +104,21 @@ describe("Search Store", () => { } ) + it.each` + type | collectionParams | expected + ${IMAGE} | ${{ collection: "tag", tag: "cat" }} | ${"/image/tag/cat/"} + ${AUDIO} | ${{ collection: "creator", source: "jamendo", creator: "cat" }} | ${"/audio/source/jamendo/creator/cat/"} + ${IMAGE} | ${{ collection: "source", source: "flickr" }} | ${"/image/source/flickr/"} + `( + "getCollectionPath returns $expected for $type, $tag, $creator, $source", + ({ type, collectionParams, expected }) => { + const searchStore = useSearchStore() + searchStore.getCollectionPath({ type, collectionParams }) + + expect(searchStore.$nuxt.localePath).toHaveBeenCalledWith(expected) + } + ) + /** * For non-supported search types, the filters fall back to 'All content' filters. * Number of displayed filters is one less than the number of mediaFilterKeys diff --git a/frontend/test/unit/specs/utils/validate-collection-params.spec.js b/frontend/test/unit/specs/utils/validate-collection-params.spec.js new file mode 100644 index 0000000000..a3d39f7765 --- /dev/null +++ b/frontend/test/unit/specs/utils/validate-collection-params.spec.js @@ -0,0 +1,48 @@ +import { createPinia, setActivePinia } from "~~/test/unit/test-utils/pinia" + +import { parseCollectionPath } from "~/utils/parse-collection-path" +import { useProviderStore } from "~/stores/provider" +import { useFeatureFlagStore } from "~/stores/feature-flag" + +describe("validateCollectionParams", () => { + /** @type { import("pinia").Pinia } **/ + let pinia + + beforeEach(() => { + pinia = createPinia() + setActivePinia(pinia) + useProviderStore().isSourceNameValid = jest.fn(() => true) + useFeatureFlagStore().toggleFeature("additional_search_views", "on") + }) + + it("returns source collection", () => { + const collection = parseCollectionPath("/flickr") + + expect(collection).toEqual({ source: "flickr", collection: "source" }) + }) + + it("returns null if `creator` parameter is blank", () => { + const collection = parseCollectionPath("/flickr/creator/") + + expect(collection).toBeNull() + }) + it("returns creator collection without trailing slash", () => { + const collection = parseCollectionPath("/flickr/creator/me") + + expect(collection).toEqual({ + source: "flickr", + creator: "me", + collection: "creator", + }) + }) + + it("returns creator collection with trailing slash", () => { + const collection = parseCollectionPath("/flickr/creator/me/") + + expect(collection).toEqual({ + source: "flickr", + creator: "me", + collection: "creator", + }) + }) +})