scriptable-testlab
Version:
A lightweight, efficient tool designed to manage and update scripts for Scriptable.
155 lines (131 loc) • 4.51 kB
text/typescript
import {AbsDatePicker} from 'scriptable-abstract';
interface DatePickerState {
minimumDate: Date | null;
maximumDate: Date | null;
countdownDuration: number;
minuteInterval: number;
initialDate: Date;
}
const DEFAULT_STATE: DatePickerState = {
minimumDate: null,
maximumDate: null,
countdownDuration: 0,
minuteInterval: 1,
initialDate: new Date(),
};
/**
* Mock implementation of Scriptable's DatePicker.
* Provides a user interface for selecting dates and times.
* @implements DatePicker
*/
export class MockDatePicker extends AbsDatePicker<DatePickerState> {
constructor() {
super(DEFAULT_STATE);
}
private validateDateRange(date: Date): void {
if (this.state.minimumDate && date.getTime() < this.state.minimumDate.getTime()) {
throw new Error('Initial date cannot be earlier than minimum date');
}
if (this.state.maximumDate && date.getTime() > this.state.maximumDate.getTime()) {
throw new Error('Initial date cannot be later than maximum date');
}
}
private validateMinMaxDates(min: Date | null, max: Date | null): void {
if (min && max && min.getTime() > max.getTime()) {
throw new Error('Minimum date cannot be later than maximum date');
}
}
get minimumDate(): Date | null {
return this.state.minimumDate ? new Date(this.state.minimumDate) : null;
}
set minimumDate(value: Date | null) {
if (value) {
const newMin = new Date(value);
this.validateMinMaxDates(newMin, this.state.maximumDate);
}
this.setState({minimumDate: value ? new Date(value) : null});
}
get maximumDate(): Date | null {
return this.state.maximumDate ? new Date(this.state.maximumDate) : null;
}
set maximumDate(value: Date | null) {
if (value) {
const newMax = new Date(value);
this.validateMinMaxDates(this.state.minimumDate, newMax);
}
this.setState({maximumDate: value ? new Date(value) : null});
}
get countdownDuration(): number {
return this.state.countdownDuration;
}
set countdownDuration(value: number) {
const numValue = Number(value);
if (isNaN(numValue) || numValue < 0) {
throw new Error('Countdown duration must be a non-negative number');
}
this.setState({countdownDuration: numValue});
}
get minuteInterval(): number {
return this.state.minuteInterval;
}
set minuteInterval(value: number) {
const numValue = Number(value);
if (isNaN(numValue) || numValue <= 0) {
throw new Error('Minute interval must be a positive number');
}
if (numValue > 30) {
throw new Error('Minute interval must not exceed 30');
}
if (60 % numValue !== 0) {
throw new Error('Minute interval must be a factor of 60');
}
this.setState({minuteInterval: numValue});
}
get initialDate(): Date {
return new Date(this.state.initialDate);
}
set initialDate(value: Date) {
this.setState({initialDate: new Date(value)});
}
/**
* Presents the date picker to the user.
* @returns A promise that resolves with the selected date.
*/
async pickDate(): Promise<Date> {
this.validateDateRange(this.state.initialDate);
return new Date(this.state.initialDate);
}
/**
* Presents the time picker to the user.
* @returns A promise that resolves with the selected date.
*/
async pickTime(): Promise<Date> {
this.validateDateRange(this.state.initialDate);
const date = new Date(this.state.initialDate);
// Ensure minutes align with interval
const minutes = date.getMinutes();
const intervalMinutes = Math.round(minutes / this.state.minuteInterval) * this.state.minuteInterval;
date.setMinutes(intervalMinutes);
return new Date(date);
}
/**
* Presents the countdown duration picker to the user.
* @returns A promise that resolves with the selected duration in seconds.
*/
async pickCountdownDuration(): Promise<number> {
return this.state.countdownDuration;
}
/**
* Presents the date picker displaying date and time.
* @returns A promise that resolves with the selected date.
*/
async pickDateAndTime(): Promise<Date> {
this.validateDateRange(this.state.initialDate);
const date = new Date(this.state.initialDate);
// Ensure minutes align with interval
const minutes = date.getMinutes();
const intervalMinutes = Math.round(minutes / this.state.minuteInterval) * this.state.minuteInterval;
date.setMinutes(intervalMinutes);
return new Date(date);
}
}