UNPKG

scriptable-testlab

Version:

A lightweight, efficient tool designed to manage and update scripts for Scriptable.

178 lines (154 loc) 5.07 kB
import {AbsLocation} from 'scriptable-abstract'; export interface LocationMockState { currentLocation: Location.CurrentLocation; accuracy: 'best' | 'tenMeters' | 'hundredMeters' | 'kilometer' | 'threeKilometers'; simulatedDelay?: number; } const ACCURACY_METERS = { best: 5, tenMeters: 10, hundredMeters: 100, kilometer: 1000, threeKilometers: 3000, }; const DEFAULT_STATE: LocationMockState = { currentLocation: { latitude: 0, longitude: 0, altitude: 0, horizontalAccuracy: ACCURACY_METERS.best, verticalAccuracy: ACCURACY_METERS.best, }, accuracy: 'best', simulatedDelay: 100, }; // 添加多语言支持的模拟数据 const MOCK_LOCATIONS = { 'zh-CN': { name: '模拟位置', locality: '模拟城市', subLocality: '模拟区', thoroughfare: '模拟路', subThoroughfare: '123号', administrativeArea: '模拟省', subAdministrativeArea: '模拟县', country: '中国', isoCountryCode: 'CN', }, 'en-US': { name: 'Mock Location', locality: 'Mock City', subLocality: 'Mock District', thoroughfare: 'Mock Street', subThoroughfare: '123', administrativeArea: 'Mock State', subAdministrativeArea: 'Mock County', country: 'United States', isoCountryCode: 'US', }, 'ja-JP': { name: 'モック位置', locality: 'モック市', subLocality: 'モック区', thoroughfare: 'モック通り', subThoroughfare: '123', administrativeArea: 'モック県', subAdministrativeArea: 'モック郡', country: '日本', isoCountryCode: 'JP', }, }; const createMockGeocodeSummary = (latitude: number, longitude: number, locale = 'en-US'): Location.GeocodeSummary => { // 获取指定语言的模拟数据,如果不存在则使用英文 const localeData = MOCK_LOCATIONS[locale] || MOCK_LOCATIONS['en-US']; return { name: `${localeData.name} (${latitude.toFixed(6)}, ${longitude.toFixed(6)})`, locality: localeData.locality, subLocality: localeData.subLocality, thoroughfare: localeData.thoroughfare, subThoroughfare: localeData.subThoroughfare, administrativeArea: localeData.administrativeArea, subAdministrativeArea: localeData.subAdministrativeArea, postalCode: '123456', country: localeData.country, isoCountryCode: localeData.isoCountryCode, timeZone: 'UTC', ocean: null, inlandWater: null, areasOfInterest: [`${localeData.name} POI`], location: { latitude, longitude, altitude: 0, }, postalAddress: { street: `${localeData.thoroughfare} ${localeData.subThoroughfare}`, city: localeData.locality, state: localeData.administrativeArea, country: localeData.country, postalCode: '123456', isoCountryCode: localeData.isoCountryCode, subAdministrativeArea: localeData.subAdministrativeArea, subLocality: localeData.subLocality, }, }; }; export class MockLocation extends AbsLocation<LocationMockState> { protected static _instance: MockLocation | undefined; static get instance(): MockLocation { return super.instance as MockLocation; } protected constructor() { super(DEFAULT_STATE); } private addLocationNoise(value: number, accuracyInMeters: number): number { const maxOffset = accuracyInMeters / 111000; return value + (Math.random() - 0.5) * maxOffset; } private async simulateDelay(): Promise<void> { if (this.state.simulatedDelay) { await new Promise(resolve => setTimeout(resolve, this.state.simulatedDelay)); } } async current(): Promise<Location.CurrentLocation> { await this.simulateDelay(); const accuracyInMeters = ACCURACY_METERS[this.state.accuracy]; const base = this.state.currentLocation; return { latitude: this.addLocationNoise(base.latitude, accuracyInMeters), longitude: this.addLocationNoise(base.longitude, accuracyInMeters), altitude: this.addLocationNoise(base.altitude, accuracyInMeters), horizontalAccuracy: accuracyInMeters, verticalAccuracy: accuracyInMeters, }; } setAccuracyToBest(): void { this.setState({accuracy: 'best'}); } setAccuracyToTenMeters(): void { this.setState({accuracy: 'tenMeters'}); } setAccuracyToHundredMeters(): void { this.setState({accuracy: 'hundredMeters'}); } setAccuracyToKilometer(): void { this.setState({accuracy: 'kilometer'}); } setAccuracyToThreeKilometers(): void { this.setState({accuracy: 'threeKilometers'}); } async reverseGeocode(latitude: number, longitude: number, locale?: string): Promise<Location.GeocodeSummary[]> { await this.simulateDelay(); return [createMockGeocodeSummary(latitude, longitude, locale)]; } // Testing helpers setCurrentLocation(location: Location.CurrentLocation): void { this.setState({currentLocation: location}); } setSimulatedDelay(delay: number): void { this.setState({simulatedDelay: delay}); } disableSimulatedDelay(): void { this.setState({simulatedDelay: 0}); } }