forked from MapComplete/MapComplete
		
	Add tests for wikimedia comons edge cases
This commit is contained in:
		
							parent
							
								
									5628be3632
								
							
						
					
					
						commit
						b5d2b99ced
					
				
					 5 changed files with 118 additions and 17 deletions
				
			
		|  | @ -16,7 +16,11 @@ export default class AllImageProviders { | ||||||
|         Mapillary.singleton, |         Mapillary.singleton, | ||||||
|         WikidataImageProvider.singleton, |         WikidataImageProvider.singleton, | ||||||
|         WikimediaImageProvider.singleton, |         WikimediaImageProvider.singleton, | ||||||
|         new GenericImageProvider([].concat(...Imgur.defaultValuePrefix, WikimediaImageProvider.commonsPrefix, ...Mapillary.valuePrefixes))] |         new GenericImageProvider( | ||||||
|  |             [].concat(...Imgur.defaultValuePrefix, ...WikimediaImageProvider.commonsPrefixes, ...Mapillary.valuePrefixes) | ||||||
|  |         ) | ||||||
|  |              | ||||||
|  |     ] | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     private static _cache: Map<string, UIEventSource<ProvidedImage[]>> = new Map<string, UIEventSource<ProvidedImage[]>>() |     private static _cache: Map<string, UIEventSource<ProvidedImage[]>> = new Map<string, UIEventSource<ProvidedImage[]>>() | ||||||
|  |  | ||||||
|  | @ -15,7 +15,7 @@ export class WikimediaImageProvider extends ImageProvider { | ||||||
|     private readonly commons_key = "wikimedia_commons" |     private readonly commons_key = "wikimedia_commons" | ||||||
|     public readonly defaultKeyPrefixes = [this.commons_key,"image"] |     public readonly defaultKeyPrefixes = [this.commons_key,"image"] | ||||||
|     public static readonly singleton = new WikimediaImageProvider(); |     public static readonly singleton = new WikimediaImageProvider(); | ||||||
|     public static readonly commonsPrefix = "https://commons.wikimedia.org/wiki/" |     public static readonly commonsPrefixes = ["https://commons.wikimedia.org/wiki/", "https://upload.wikimedia.org", "File:"] | ||||||
| 
 | 
 | ||||||
|     private constructor() { |     private constructor() { | ||||||
|         super(); |         super(); | ||||||
|  | @ -90,21 +90,39 @@ export class WikimediaImageProvider extends ImageProvider { | ||||||
|         return {url: this.PrepareUrl(image), key: undefined, provider: this} |         return {url: this.PrepareUrl(image), key: undefined, provider: this} | ||||||
|     } |     } | ||||||
|      |      | ||||||
|  |     private startsWithCommonsPrefix(value: string){ | ||||||
|  |         return  WikimediaImageProvider.commonsPrefixes.some(prefix => value.startsWith(prefix)) | ||||||
|  |     } | ||||||
|  |      | ||||||
|  |     private removeCommonsPrefix(value: string){ | ||||||
|  |         if(value.startsWith("https://upload.wikimedia.org/")){ | ||||||
|  |             value = value.substring(value.lastIndexOf("/") + 1) | ||||||
|  |             value = decodeURIComponent(value) | ||||||
|  |             if(!value.startsWith("File:")){ | ||||||
|  |                 value = "File:"+value | ||||||
|  |             } | ||||||
|  |             return value; | ||||||
|  |         } | ||||||
|  |          | ||||||
|  |         for (const prefix of WikimediaImageProvider.commonsPrefixes) { | ||||||
|  |             if(value.startsWith(prefix)){ | ||||||
|  |                 let part = value.substr(prefix.length) | ||||||
|  |                 if(prefix.startsWith("http")){ | ||||||
|  |                     part = decodeURIComponent(part) | ||||||
|  |                 } | ||||||
|  |                 return part | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         return value; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     public async ExtractUrls(key: string, value: string): Promise<Promise<ProvidedImage>[]> { |     public async ExtractUrls(key: string, value: string): Promise<Promise<ProvidedImage>[]> { | ||||||
|         if(key !== undefined && key !== this.commons_key && !value.startsWith(WikimediaImageProvider.commonsPrefix)){ |         const hasCommonsPrefix = this.startsWithCommonsPrefix(value) | ||||||
|  |         if(key !== undefined && key !== this.commons_key && !hasCommonsPrefix){ | ||||||
|             return [] |             return [] | ||||||
|         } |         } | ||||||
|          |          | ||||||
|         if (value.startsWith(WikimediaImageProvider.commonsPrefix)) { |         value = this.removeCommonsPrefix(value) | ||||||
|             value = value.substring(WikimediaImageProvider.commonsPrefix.length) |  | ||||||
|         } else if (value.startsWith("https://upload.wikimedia.org")) { |  | ||||||
|             const result: ProvidedImage = { |  | ||||||
|                 key: undefined, |  | ||||||
|                 url: value, |  | ||||||
|                 provider: this |  | ||||||
|             } |  | ||||||
|             return [Promise.resolve(result)] |  | ||||||
|         } |  | ||||||
|         if (value.startsWith("Category:")) { |         if (value.startsWith("Category:")) { | ||||||
|             const urls = await Wikimedia.GetCategoryContents(value) |             const urls = await Wikimedia.GetCategoryContents(value) | ||||||
|             return urls.filter(url => url.startsWith("File:")).map(image => this.UrlForImage(image)) |             return urls.filter(url => url.startsWith("File:")).map(image => this.UrlForImage(image)) | ||||||
|  |  | ||||||
							
								
								
									
										68
									
								
								test/ImageProvider.spec.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								test/ImageProvider.spec.ts
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,68 @@ | ||||||
|  | import T from "./TestHelper"; | ||||||
|  | import AllImageProviders from "../Logic/ImageProviders/AllImageProviders"; | ||||||
|  | import {UIEventSource} from "../Logic/UIEventSource"; | ||||||
|  | 
 | ||||||
|  | export default class ImageProviderSpec extends T { | ||||||
|  |      | ||||||
|  |     constructor() { | ||||||
|  |         super("ImageProvider", [ | ||||||
|  |             ["Search images", () => { | ||||||
|  |              | ||||||
|  |                 let i = 0 | ||||||
|  |                 function expects(url, tags, providerName = undefined) { | ||||||
|  |                     tags.id = "test/"+i | ||||||
|  |                     i++ | ||||||
|  |                     AllImageProviders.LoadImagesFor(new UIEventSource(tags)).addCallbackD(images => { | ||||||
|  |                         console.log("ImageProvider test", tags.id, "for", tags) | ||||||
|  |                         const img = images[0] | ||||||
|  |                         if(img === undefined){ | ||||||
|  |                             throw "No image found" | ||||||
|  |                         } | ||||||
|  |                         T.equals(url, img.url, tags.id) | ||||||
|  |                         if(providerName){ | ||||||
|  |                             T.equals(img.provider.constructor.name, providerName) | ||||||
|  |                         } | ||||||
|  |                         console.log("OK") | ||||||
|  |                     }) | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 const muntpoort_expected = "https://commons.wikimedia.org/wiki/Special:FilePath/File%3ABr%C3%BCgge-Muntpoort_6-29510-58192.jpg?width=500&height=400" | ||||||
|  |                 expects( | ||||||
|  |                     muntpoort_expected, | ||||||
|  |                     { "wikimedia_commons":"File:Brügge-Muntpoort_6-29510-58192.jpg" | ||||||
|  |                     } , "WikimediaImageProvider") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |                 expects(muntpoort_expected, | ||||||
|  |                     { "wikimedia_commons":"https://upload.wikimedia.org/wikipedia/commons/c/cd/Br%C3%BCgge-Muntpoort_6-29510-58192.jpg" | ||||||
|  |                     } , "WikimediaImageProvider") | ||||||
|  |                  | ||||||
|  |                 expects(muntpoort_expected , { | ||||||
|  |                     "image":"https://upload.wikimedia.org/wikipedia/commons/c/cd/Br%C3%BCgge-Muntpoort_6-29510-58192.jpg" | ||||||
|  |                 } , "WikimediaImageProvider") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |                 expects("https://commons.wikimedia.org/wiki/Special:FilePath/File%3ABelgium-5955_-_Simon_Stevin_(13746657193).jpg?width=500&height=400" , { | ||||||
|  |                     "image":"File:Belgium-5955_-_Simon_Stevin_(13746657193).jpg" | ||||||
|  |                 } , "WikimediaImageProvider") | ||||||
|  | 
 | ||||||
|  |                 expects("https://commons.wikimedia.org/wiki/Special:FilePath/File%3ABelgium-5955_-_Simon_Stevin_(13746657193).jpg?width=500&height=400" , { | ||||||
|  |                 "wikimedia_commons":"File:Belgium-5955_-_Simon_Stevin_(13746657193).jpg" | ||||||
|  |                 } , "WikimediaImageProvider") | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |                 | ||||||
|  |                  | ||||||
|  |                 expects("https://commons.wikimedia.org/wiki/Special:FilePath/File%3ABrugge_Leeuwstraat_zonder_nummer_Leeuwbrug_-_119334_-_onroerenderfgoed.jpg?width=500&height=400",{ | ||||||
|  |                     image:"File:Brugge_Leeuwstraat_zonder_nummer_Leeuwbrug_-_119334_-_onroerenderfgoed.jpg" | ||||||
|  |                 }, "WikimediaImageProvider") | ||||||
|  |                 | ||||||
|  |              | ||||||
|  |             }] | ||||||
|  |              | ||||||
|  |              | ||||||
|  |         ]); | ||||||
|  |     } | ||||||
|  |      | ||||||
|  | } | ||||||
|  | @ -11,6 +11,7 @@ import SplitActionSpec from "./SplitAction.spec"; | ||||||
| import {Utils} from "../Utils"; | import {Utils} from "../Utils"; | ||||||
| import TileFreshnessCalculatorSpec from "./TileFreshnessCalculator.spec"; | import TileFreshnessCalculatorSpec from "./TileFreshnessCalculator.spec"; | ||||||
| import WikidataSpecTest from "./Wikidata.spec.test"; | import WikidataSpecTest from "./Wikidata.spec.test"; | ||||||
|  | import ImageProviderSpec from "./ImageProvider.spec"; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| ScriptUtils.fixUtils() | ScriptUtils.fixUtils() | ||||||
|  | @ -25,7 +26,8 @@ const allTests = [ | ||||||
|     new RelationSplitHandlerSpec(), |     new RelationSplitHandlerSpec(), | ||||||
|     new SplitActionSpec(), |     new SplitActionSpec(), | ||||||
|     new TileFreshnessCalculatorSpec(), |     new TileFreshnessCalculatorSpec(), | ||||||
|     new WikidataSpecTest() |     new WikidataSpecTest(), | ||||||
|  |     new ImageProviderSpec() | ||||||
| ] | ] | ||||||
| 
 | 
 | ||||||
| Utils.externalDownloadFunction = async (url) => { | Utils.externalDownloadFunction = async (url) => { | ||||||
|  | @ -44,16 +46,17 @@ args = args.map(a => a.toLowerCase()) | ||||||
| const allFailures: { testsuite: string, name: string, msg: string } [] = [] | const allFailures: { testsuite: string, name: string, msg: string } [] = [] | ||||||
| let testsToRun = allTests | let testsToRun = allTests | ||||||
| if (args.length > 0) { | if (args.length > 0) { | ||||||
|     testsToRun = allTests.filter(t => args.indexOf(t.name) >= 0) |     args = args.map(a => a.toLowerCase()) | ||||||
|  |     testsToRun = allTests.filter(t => args.indexOf(t.name.toLowerCase()) >= 0) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| if (testsToRun.length == 0) { | if (testsToRun.length == 0) { | ||||||
|     throw "No tests found" |     throw "No tests found. Try one of "+allTests.map(t => t.name).join(", ") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| for (let i = 0; i < testsToRun.length; i++) { | for (let i = 0; i < testsToRun.length; i++) { | ||||||
|     const test = testsToRun[i]; |     const test = testsToRun[i]; | ||||||
|     console.log(" Running test", i, "/", allTests.length, test.name) |     console.log(" Running test", i, "/", testsToRun.length, test.name) | ||||||
|     allFailures.push(...(test.Run() ?? [])) |     allFailures.push(...(test.Run() ?? [])) | ||||||
|     console.log("OK!") |     console.log("OK!") | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -41,6 +41,14 @@ export default class T { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|      |      | ||||||
|  |     static equals(a, b, msg?){ | ||||||
|  |         if(a !== b){ | ||||||
|  |             throw "Not the same: "+(msg??"")+"\n" + | ||||||
|  |             "Expcected: "+a+"\n" + | ||||||
|  |             "Got      : "+b | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     static isFalse(b: boolean, msg: string) { |     static isFalse(b: boolean, msg: string) { | ||||||
|         if (b) { |         if (b) { | ||||||
|             throw "Expected false, but got true: " + msg |             throw "Expected false, but got true: " + msg | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue