scriptable-testlab
Version:
A lightweight, efficient tool designed to manage and update scripts for Scriptable.
162 lines (134 loc) • 4.34 kB
text/typescript
import {AbsCalendar} from 'scriptable-abstract';
import {MockColor} from '../ui/color';
interface CalendarState {
identifier: string;
title: string;
allowsContentModifications: boolean;
isSubscribed: boolean;
color: Color;
}
const DEFAULT_STATE: CalendarState = {
identifier: '',
title: '',
allowsContentModifications: true,
isSubscribed: false,
color: new MockColor('#000000') as unknown as Color,
};
/**
* Mock implementation of Scriptable's Calendar.
* Provides functionality for managing calendars.
* @implements Calendar
*/
export class MockCalendar extends AbsCalendar<CalendarState> {
private static _instance: MockCalendar | null = null;
private static _calendars: MockCalendar[] = [];
static get instance(): MockCalendar {
if (!this._instance) {
this._instance = new MockCalendar();
}
return this._instance;
}
constructor() {
super(DEFAULT_STATE);
}
// Static methods
static async forReminders(): Promise<Calendar[]> {
return this._calendars.filter(cal => !cal.isSubscribed) as unknown as Calendar[];
}
static async forEvents(): Promise<Calendar[]> {
return this._calendars.filter(cal => !cal.isSubscribed) as unknown as Calendar[];
}
static async forRemindersByTitle(title: string): Promise<Calendar> {
const calendar = this._calendars.find(cal => cal.title === title && !cal.isSubscribed);
if (!calendar) {
throw new Error(`No calendar found with title: ${title}`);
}
return calendar as unknown as Calendar;
}
static async forEventsByTitle(title: string): Promise<Calendar> {
const calendar = this._calendars.find(cal => cal.title === title && !cal.isSubscribed);
if (!calendar) {
throw new Error(`No calendar found with title: ${title}`);
}
return calendar as unknown as Calendar;
}
static async createForReminders(title: string): Promise<Calendar> {
const calendar = new MockCalendar();
calendar.title = title;
calendar.save();
return calendar as unknown as Calendar;
}
static async findOrCreateForReminders(title: string): Promise<Calendar> {
try {
return await this.forRemindersByTitle(title);
} catch {
return this.createForReminders(title);
}
}
static async defaultForReminders(): Promise<Calendar> {
const calendars = await this.forReminders();
if (calendars.length === 0) {
return this.createForReminders('Default Reminders');
}
return calendars[0];
}
static async defaultForEvents(): Promise<Calendar> {
const calendars = await this.forEvents();
if (calendars.length === 0) {
const calendar = new MockCalendar();
calendar.title = 'Default Events';
calendar.save();
return calendar as unknown as Calendar;
}
return calendars[0];
}
static async presentPicker(allowMultiple = false): Promise<Calendar[]> {
// In a mock environment, we'll just return all calendars
// In a real implementation, this would show a UI picker
return allowMultiple ? (this._calendars as unknown as Calendar[]) : ([this._calendars[0]] as unknown as Calendar[]);
}
// Instance methods
get identifier(): string {
return this.state.identifier;
}
get title(): string {
return this.state.title;
}
set title(value: string) {
this.setState({title: value});
}
get allowsContentModifications(): boolean {
return this.state.allowsContentModifications;
}
set allowsContentModifications(value: boolean) {
this.setState({allowsContentModifications: value});
}
get isSubscribed(): boolean {
return this.state.isSubscribed;
}
get color(): Color {
return this.state.color;
}
set color(value: Color) {
this.setState({color: value});
}
supportsAvailability(_availability: 'busy' | 'free' | 'tentative' | 'unavailable'): boolean {
// In this mock implementation, we'll support all availabilities
return true;
}
save(): void {
if (!MockCalendar._calendars.includes(this)) {
MockCalendar._calendars.push(this);
}
}
remove(): void {
const index = MockCalendar._calendars.indexOf(this);
if (index > -1) {
MockCalendar._calendars.splice(index, 1);
}
}
// Helper method to clear all calendars (for testing)
static clearAll(): void {
this._calendars = [];
}
}