Fix tests

This commit is contained in:
Pieter Vander Vennet 2023-07-18 12:38:30 +02:00
parent 064f87537f
commit d036350893
2 changed files with 61 additions and 59 deletions

View file

@ -593,8 +593,9 @@ export default class SimpleMetaTaggers {
(feature: Feature, layer: LayerConfig, tagsStore: UIEventSource<OsmTags>) => { (feature: Feature, layer: LayerConfig, tagsStore: UIEventSource<OsmTags>) => {
Utils.AddLazyPropertyAsync(feature.properties, "_currency", async () => { Utils.AddLazyPropertyAsync(feature.properties, "_currency", async () => {
// Wait until _country is actually set // Wait until _country is actually set
await tagsStore.AsPromise((tags) => !!tags._country) const tags = await tagsStore.AsPromise((tags) => !!tags._country)
const country = tags._country
// Initialize a list of currencies // Initialize a list of currencies
const currencies = {} const currencies = {}
// Check if there are any currency:XXX tags, add them to the map // Check if there are any currency:XXX tags, add them to the map
@ -609,7 +610,7 @@ export default class SimpleMetaTaggers {
} }
// Determine the default currency for the country // Determine the default currency for the country
const defaultCurrency = countryToCurrency[feature.properties._country.toUpperCase()] const defaultCurrency = countryToCurrency[country.toUpperCase()]
// If the default currency is not in the list, add it // If the default currency is not in the list, add it
if (defaultCurrency && !currencies[defaultCurrency]) { if (defaultCurrency && !currencies[defaultCurrency]) {

View file

@ -255,8 +255,12 @@ export abstract class Store<T> implements Readable<T> {
resolve(data) resolve(data)
} else { } else {
self.addCallbackD((data) => { self.addCallbackD((data) => {
resolve(data) if (condition(data)) {
return true // return true to unregister as we only need to be called once resolve(data)
return true // return true to unregister as we only need to be called once
} else {
return false // We didn't resolve yet, wait for the next ping
}
}) })
} }
}) })
@ -279,13 +283,13 @@ export abstract class Store<T> implements Readable<T> {
export class ImmutableStore<T> extends Store<T> { export class ImmutableStore<T> extends Store<T> {
public readonly data: T public readonly data: T
private static readonly pass: () => void = () => {}
constructor(data: T) { constructor(data: T) {
super() super()
this.data = data this.data = data
} }
private static readonly pass: () => void = () => {}
addCallback(_: (data: T) => void): () => void { addCallback(_: (data: T) => void): () => void {
// pass: data will never change // pass: data will never change
return ImmutableStore.pass return ImmutableStore.pass
@ -322,9 +326,9 @@ export class ImmutableStore<T> extends Store<T> {
* Keeps track of the callback functions * Keeps track of the callback functions
*/ */
class ListenerTracker<T> { class ListenerTracker<T> {
public pingCount = 0
private readonly _callbacks: ((t: T) => boolean | void | any)[] = [] private readonly _callbacks: ((t: T) => boolean | void | any)[] = []
public pingCount = 0
/** /**
* Adds a callback which can be called; a function to unregister is returned * Adds a callback which can be called; a function to unregister is returned
*/ */
@ -386,18 +390,16 @@ class ListenerTracker<T> {
* The mapped store is a helper type which does the mapping of a function. * The mapped store is a helper type which does the mapping of a function.
*/ */
class MappedStore<TIn, T> extends Store<T> { class MappedStore<TIn, T> extends Store<T> {
private static readonly pass: () => {}
private readonly _upstream: Store<TIn> private readonly _upstream: Store<TIn>
private readonly _upstreamCallbackHandler: ListenerTracker<TIn> | undefined private readonly _upstreamCallbackHandler: ListenerTracker<TIn> | undefined
private _upstreamPingCount: number = -1 private _upstreamPingCount: number = -1
private _unregisterFromUpstream: () => void private _unregisterFromUpstream: () => void
private readonly _f: (t: TIn) => T private readonly _f: (t: TIn) => T
private readonly _extraStores: Store<any>[] | undefined private readonly _extraStores: Store<any>[] | undefined
private _unregisterFromExtraStores: (() => void)[] | undefined private _unregisterFromExtraStores: (() => void)[] | undefined
private _callbacks: ListenerTracker<T> = new ListenerTracker<T>() private _callbacks: ListenerTracker<T> = new ListenerTracker<T>()
private _callbacksAreRegistered = false
private static readonly pass: () => {}
constructor( constructor(
upstream: Store<TIn>, upstream: Store<TIn>,
@ -421,7 +423,6 @@ class MappedStore<TIn, T> extends Store<T> {
} }
private _data: T private _data: T
private _callbacksAreRegistered = false
/** /**
* Gets the current data from the store * Gets the current data from the store
@ -468,33 +469,6 @@ class MappedStore<TIn, T> extends Store<T> {
) )
} }
private unregisterFromUpstream() {
console.log("Unregistering callbacks for", this.tag)
this._callbacksAreRegistered = false
this._unregisterFromUpstream()
this._unregisterFromExtraStores?.forEach((unr) => unr())
}
private registerCallbacksToUpstream() {
const self = this
this._unregisterFromUpstream = this._upstream.addCallback((_) => self.update())
this._unregisterFromExtraStores = this._extraStores?.map((store) =>
store?.addCallback((_) => self.update())
)
this._callbacksAreRegistered = true
}
private update(): void {
const newData = this._f(this._upstream.data)
this._upstreamPingCount = this._upstreamCallbackHandler?.pingCount
if (this._data == newData) {
return
}
this._data = newData
this._callbacks.ping(this._data)
}
addCallback(callback: (data: T) => any | boolean | void): () => void { addCallback(callback: (data: T) => any | boolean | void): () => void {
if (!this._callbacksAreRegistered) { if (!this._callbacksAreRegistered) {
// This is the first callback that is added // This is the first callback that is added
@ -535,14 +509,40 @@ class MappedStore<TIn, T> extends Store<T> {
} }
}) })
} }
private unregisterFromUpstream() {
console.log("Unregistering callbacks for", this.tag)
this._callbacksAreRegistered = false
this._unregisterFromUpstream()
this._unregisterFromExtraStores?.forEach((unr) => unr())
}
private registerCallbacksToUpstream() {
const self = this
this._unregisterFromUpstream = this._upstream.addCallback((_) => self.update())
this._unregisterFromExtraStores = this._extraStores?.map((store) =>
store?.addCallback((_) => self.update())
)
this._callbacksAreRegistered = true
}
private update(): void {
const newData = this._f(this._upstream.data)
this._upstreamPingCount = this._upstreamCallbackHandler?.pingCount
if (this._data == newData) {
return
}
this._data = newData
this._callbacks.ping(this._data)
}
} }
export class UIEventSource<T> extends Store<T> implements Writable<T> { export class UIEventSource<T> extends Store<T> implements Writable<T> {
private static readonly pass: () => {}
public data: T public data: T
_callbacks: ListenerTracker<T> = new ListenerTracker<T>() _callbacks: ListenerTracker<T> = new ListenerTracker<T>()
private static readonly pass: () => {}
constructor(data: T, tag: string = "") { constructor(data: T, tag: string = "") {
super(tag) super(tag)
this.data = data this.data = data
@ -624,6 +624,24 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
) )
} }
static asBoolean(stringUIEventSource: UIEventSource<string>) {
return stringUIEventSource.sync(
(str) => str === "true",
[],
(b) => "" + b
)
}
/**
* Create a new UIEVentSource. Whenever 'source' changes, the returned UIEventSource will get this value as well.
* However, this value can be overriden without affecting source
*/
static feedFrom<T>(store: Store<T>): UIEventSource<T> {
const src = new UIEventSource(store.data)
store.addCallback((t) => src.setData(t))
return src
}
/** /**
* Adds a callback * Adds a callback
* *
@ -704,6 +722,7 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
): Store<J> { ): Store<J> {
return new MappedStore(this, f, extraSources, this._callbacks, f(this.data), onDestroy) return new MappedStore(this, f, extraSources, this._callbacks, f(this.data), onDestroy)
} }
/** /**
* Monoidal map which results in a read-only store. 'undefined' is passed 'as is' * Monoidal map which results in a read-only store. 'undefined' is passed 'as is'
* Given a function 'f', will construct a new UIEventSource where the contents will always be "f(this.data)' * Given a function 'f', will construct a new UIEventSource where the contents will always be "f(this.data)'
@ -779,14 +798,6 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
return this return this
} }
static asBoolean(stringUIEventSource: UIEventSource<string>) {
return stringUIEventSource.sync(
(str) => str === "true",
[],
(b) => "" + b
)
}
set(value: T): void { set(value: T): void {
this.setData(value) this.setData(value)
} }
@ -794,14 +805,4 @@ export class UIEventSource<T> extends Store<T> implements Writable<T> {
update(f: Updater<T> & ((value: T) => T)): void { update(f: Updater<T> & ((value: T) => T)): void {
this.setData(f(this.data)) this.setData(f(this.data))
} }
/**
* Create a new UIEVentSource. Whenever 'source' changes, the returned UIEventSource will get this value as well.
* However, this value can be overriden without affecting source
*/
static feedFrom<T>(store: Store<T>): UIEventSource<T> {
const src = new UIEventSource(store.data)
store.addCallback((t) => src.setData(t))
return src
}
} }