mirror of https://github.com/sveltejs/svelte
parent
23484d6875
commit
7df85f4d0e
@ -1,102 +1,160 @@
|
||||
import { source, set } from '../internal/client/reactivity/sources.js';
|
||||
import { get } from '../internal/client/runtime.js';
|
||||
|
||||
/** @type {Array<keyof Date>} */
|
||||
const read = [
|
||||
'getDate',
|
||||
'getDay',
|
||||
'getFullYear',
|
||||
'getHours',
|
||||
'getMilliseconds',
|
||||
'getMinutes',
|
||||
'getMonth',
|
||||
'getSeconds',
|
||||
'getTime',
|
||||
'getTimezoneOffset',
|
||||
'getUTCDate',
|
||||
'getUTCDay',
|
||||
'getUTCFullYear',
|
||||
'getUTCHours',
|
||||
'getUTCMilliseconds',
|
||||
'getUTCMinutes',
|
||||
'getUTCMonth',
|
||||
'getUTCSeconds',
|
||||
// @ts-expect-error this is deprecated
|
||||
'getYear',
|
||||
'toDateString',
|
||||
'toISOString',
|
||||
'toJSON',
|
||||
'toLocaleDateString',
|
||||
'toLocaleString',
|
||||
'toLocaleTimeString',
|
||||
'toString',
|
||||
'toTimeString',
|
||||
'toUTCString'
|
||||
];
|
||||
|
||||
/** @type {Array<keyof Date>} */
|
||||
const write = [
|
||||
'setDate',
|
||||
'setFullYear',
|
||||
'setHours',
|
||||
'setMilliseconds',
|
||||
'setMinutes',
|
||||
'setMonth',
|
||||
'setSeconds',
|
||||
'setTime',
|
||||
'setUTCDate',
|
||||
'setUTCFullYear',
|
||||
'setUTCHours',
|
||||
'setUTCMilliseconds',
|
||||
'setUTCMinutes',
|
||||
'setUTCMonth',
|
||||
'setUTCSeconds',
|
||||
// @ts-expect-error this is deprecated
|
||||
'setYear'
|
||||
];
|
||||
|
||||
var inited = false;
|
||||
|
||||
export class ReactiveDate extends Date {
|
||||
#raw_time = source(super.getTime());
|
||||
/**
|
||||
* @type {Date}
|
||||
*/
|
||||
#modified_date_to_compare;
|
||||
|
||||
/**
|
||||
* @type {Map<keyof Date, import("#client").Source<boolean>>}
|
||||
*/
|
||||
#signals = new Map();
|
||||
|
||||
/**
|
||||
* @param {ConstructorParameters<typeof Date>} params
|
||||
*/
|
||||
constructor(...params) {
|
||||
super(...params);
|
||||
this.#modified_date_to_compare = new Date(...params);
|
||||
this.#init();
|
||||
}
|
||||
|
||||
// We init as part of the first instance so that we can treeshake this class
|
||||
#init() {
|
||||
if (!inited) {
|
||||
inited = true;
|
||||
const proto = ReactiveDate.prototype;
|
||||
const date_proto = Date.prototype;
|
||||
if (inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const method of read) {
|
||||
inited = true;
|
||||
var proto = ReactiveDate.prototype;
|
||||
var date_proto = Date.prototype;
|
||||
|
||||
var read = /** @type {Array<keyof Date>} */ (
|
||||
Object.getOwnPropertyNames(Date.prototype).filter(
|
||||
(prop) => prop.startsWith('get') || prop.startsWith('to')
|
||||
)
|
||||
);
|
||||
|
||||
var write = /** @type {Array<keyof Date>} */ (
|
||||
Object.getOwnPropertyNames(Date.prototype).filter((prop) => prop.startsWith('set'))
|
||||
);
|
||||
|
||||
for (const method of read) {
|
||||
// @ts-ignore
|
||||
proto[method] = function (...args) {
|
||||
var sig = this.#signals.get(method);
|
||||
if (!sig) {
|
||||
sig = source(false);
|
||||
this.#signals.set(method, sig);
|
||||
}
|
||||
get(sig);
|
||||
// @ts-ignore
|
||||
proto[method] = function (...args) {
|
||||
get(this.#raw_time);
|
||||
// @ts-ignore
|
||||
return date_proto[method].apply(this, args);
|
||||
};
|
||||
}
|
||||
return date_proto[method].apply(this, args);
|
||||
};
|
||||
}
|
||||
|
||||
for (const method of write) {
|
||||
for (const method of write) {
|
||||
// @ts-ignore
|
||||
proto[method] = function (...args) {
|
||||
// @ts-ignore
|
||||
proto[method] = function (...args) {
|
||||
// @ts-ignore
|
||||
const v = date_proto[method].apply(this, args);
|
||||
const time = date_proto.getTime.call(this);
|
||||
if (time !== this.#raw_time.v) {
|
||||
set(this.#raw_time, time);
|
||||
}
|
||||
return v;
|
||||
};
|
||||
}
|
||||
var v = date_proto[method].apply(this, args);
|
||||
this.#notify_datetime_changes();
|
||||
// @ts-ignore
|
||||
this.#modified_date_to_compare[method](...args);
|
||||
return v;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {any[]} values
|
||||
* we have to have another date instance to compare it with, because setting `X` might or might not affect `Y`
|
||||
* for instance calling `date.setMonth(55)` will also change the `date.getYear()`
|
||||
* but calling `date.setMonth(1)` (assuming its not 12) will not increase the year.
|
||||
* we could check all of these edge-cases but I think that might become complicated very soon and introduce more bugs
|
||||
* also there is the possibility of these behaviors to change as well,
|
||||
* so using another date instance and applying the change is a better idea I guess
|
||||
*/
|
||||
constructor(...values) {
|
||||
// @ts-ignore
|
||||
super(...values);
|
||||
this.#init();
|
||||
#notify_datetime_changes() {
|
||||
if (this.#modified_date_to_compare.getTime() == super.getTime()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var is_date_changed = false;
|
||||
var is_time_changed = false;
|
||||
|
||||
if (super.getFullYear() !== this.#modified_date_to_compare.getFullYear()) {
|
||||
this.#increment_signal('getFullYear', 'getUTCFullYear');
|
||||
is_date_changed = true;
|
||||
}
|
||||
|
||||
// @ts-expect-error
|
||||
if (super.getYear && super.getYear() !== this.#modified_date_to_compare.getYear()) {
|
||||
// @ts-expect-error
|
||||
this.#increment_signal('getYear');
|
||||
is_date_changed = true;
|
||||
}
|
||||
|
||||
if (super.getMonth() !== this.#modified_date_to_compare.getMonth()) {
|
||||
this.#increment_signal('getMonth', 'getUTCMonth');
|
||||
is_date_changed = true;
|
||||
}
|
||||
|
||||
if (super.getDate() !== this.#modified_date_to_compare.getDate()) {
|
||||
this.#increment_signal('getDate', 'getUTCDate');
|
||||
is_date_changed = true;
|
||||
}
|
||||
|
||||
if (super.getDay() !== this.#modified_date_to_compare.getDay()) {
|
||||
this.#increment_signal('getDay', 'getUTCDay');
|
||||
is_date_changed = true;
|
||||
}
|
||||
|
||||
if (super.getHours() !== this.#modified_date_to_compare.getHours()) {
|
||||
this.#increment_signal('getHours', 'getUTCHours');
|
||||
is_time_changed = true;
|
||||
}
|
||||
|
||||
if (super.getMinutes() !== this.#modified_date_to_compare.getMinutes()) {
|
||||
this.#increment_signal('getMinutes', 'getUTCMinutes');
|
||||
is_time_changed = true;
|
||||
}
|
||||
|
||||
if (super.getSeconds() !== this.#modified_date_to_compare.getSeconds()) {
|
||||
this.#increment_signal('getSeconds', 'getUTCSeconds');
|
||||
is_time_changed = true;
|
||||
}
|
||||
|
||||
if (super.getMilliseconds() !== this.#modified_date_to_compare.getMilliseconds()) {
|
||||
this.#increment_signal('getMilliseconds', 'getUTCMilliseconds');
|
||||
is_time_changed = true;
|
||||
}
|
||||
|
||||
if (is_time_changed) {
|
||||
this.#increment_signal('toTimeString', 'toLocaleTimeString');
|
||||
}
|
||||
|
||||
if (is_date_changed) {
|
||||
this.#increment_signal('toDateString', 'toLocaleDateString');
|
||||
}
|
||||
|
||||
if (is_time_changed || is_date_changed) {
|
||||
this.#increment_signal('getTimezoneOffset', 'getTime');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {...keyof Date} methods
|
||||
*/
|
||||
#increment_signal(...methods) {
|
||||
methods.forEach((method) => {
|
||||
var signal = this.#signals.get(method);
|
||||
if (!signal) {
|
||||
return;
|
||||
}
|
||||
// not using a number intentionally because its enough (it will increment the internal signal's version)
|
||||
set(signal, !signal.v);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,681 @@
|
||||
import { render_effect, effect_root } from '../internal/client/reactivity/effects.js';
|
||||
import { flushSync } from '../index-client.js';
|
||||
import { ReactiveDate } from './date.js';
|
||||
import { assert, test } from 'vitest';
|
||||
|
||||
const initial_date = new ReactiveDate('2023-01-01T00:00:00.000Z');
|
||||
const new_dates = [
|
||||
new Date('2024-02-02T01:01:01.001Z'),
|
||||
new Date('2025-03-03T02:02:02.002Z'),
|
||||
new Date('2026-04-04T03:03:03.003Z')
|
||||
];
|
||||
|
||||
test('date.setDate', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
const log: any = [];
|
||||
|
||||
const cleanup = effect_root(() => {
|
||||
render_effect(() => {
|
||||
log.push(date.getDate());
|
||||
});
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setDate(new_dates[0].getDate());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setDate(new_dates[1].getDate());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
// nothing should happen here
|
||||
date.setDate(new_dates[1].getDate());
|
||||
});
|
||||
|
||||
assert.deepEqual(log, [initial_date.getDate(), new_dates[0].getDate(), new_dates[1].getDate()]);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('date.setFullYear', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
const log: any = [];
|
||||
|
||||
const cleanup = effect_root(() => {
|
||||
render_effect(() => {
|
||||
log.push(date.getFullYear());
|
||||
});
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setFullYear(new_dates[0].getFullYear());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setFullYear(new_dates[1].getFullYear());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
// nothing should happen here
|
||||
date.setFullYear(new_dates[1].getFullYear());
|
||||
});
|
||||
|
||||
assert.deepEqual(log, [
|
||||
initial_date.getFullYear(),
|
||||
new_dates[0].getFullYear(),
|
||||
new_dates[1].getFullYear()
|
||||
]);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('date.setHours', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
const log: any = [];
|
||||
|
||||
const cleanup = effect_root(() => {
|
||||
render_effect(() => {
|
||||
log.push(date.getHours());
|
||||
});
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setHours(new_dates[0].getHours());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setHours(new_dates[1].getHours());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
// nothing should happen here
|
||||
date.setHours(new_dates[1].getHours());
|
||||
});
|
||||
|
||||
assert.deepEqual(log, [
|
||||
initial_date.getHours(),
|
||||
new_dates[0].getHours(),
|
||||
new_dates[1].getHours()
|
||||
]);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('date.setMilliseconds', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
const log: any = [];
|
||||
|
||||
const cleanup = effect_root(() => {
|
||||
render_effect(() => {
|
||||
log.push(date.getMilliseconds());
|
||||
});
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setMilliseconds(new_dates[0].getMilliseconds());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setMilliseconds(new_dates[1].getMilliseconds());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
// nothing should happen here
|
||||
date.setMilliseconds(new_dates[1].getMilliseconds());
|
||||
});
|
||||
|
||||
assert.deepEqual(log, [
|
||||
initial_date.getMilliseconds(),
|
||||
new_dates[0].getMilliseconds(),
|
||||
new_dates[1].getMilliseconds()
|
||||
]);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('date.setMinutes', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
const log: any = [];
|
||||
|
||||
const cleanup = effect_root(() => {
|
||||
render_effect(() => {
|
||||
log.push(date.getMinutes());
|
||||
});
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setMinutes(new_dates[0].getMinutes());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setMinutes(new_dates[1].getMinutes());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
// nothing should happen here
|
||||
date.setMinutes(new_dates[1].getMinutes());
|
||||
});
|
||||
|
||||
assert.deepEqual(log, [
|
||||
initial_date.getMinutes(),
|
||||
new_dates[0].getMinutes(),
|
||||
new_dates[1].getMinutes()
|
||||
]);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('date.setMonth', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
const log: any = [];
|
||||
|
||||
const cleanup = effect_root(() => {
|
||||
render_effect(() => {
|
||||
log.push(date.getMonth());
|
||||
});
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setMonth(new_dates[0].getMonth());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setMonth(new_dates[1].getMonth());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
// nothing should happen here
|
||||
date.setMonth(new_dates[1].getMonth());
|
||||
});
|
||||
|
||||
assert.deepEqual(log, [
|
||||
initial_date.getMonth(),
|
||||
new_dates[0].getMonth(),
|
||||
new_dates[1].getMonth()
|
||||
]);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('date.setSeconds', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
const log: any = [];
|
||||
|
||||
const cleanup = effect_root(() => {
|
||||
render_effect(() => {
|
||||
log.push(date.getSeconds());
|
||||
});
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setSeconds(new_dates[0].getSeconds());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setSeconds(new_dates[1].getSeconds());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
// nothing should happen here
|
||||
date.setSeconds(new_dates[1].getSeconds());
|
||||
});
|
||||
|
||||
assert.deepEqual(log, [
|
||||
initial_date.getSeconds(),
|
||||
new_dates[0].getSeconds(),
|
||||
new_dates[1].getSeconds()
|
||||
]);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('date.setTime', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
const log: any = [];
|
||||
|
||||
const cleanup = effect_root(() => {
|
||||
render_effect(() => {
|
||||
log.push(date.getTime());
|
||||
});
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setTime(new_dates[0].getTime());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setTime(new_dates[1].getTime());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
// nothing should happen here
|
||||
date.setTime(new_dates[1].getTime());
|
||||
});
|
||||
|
||||
assert.deepEqual(log, [initial_date.getTime(), new_dates[0].getTime(), new_dates[1].getTime()]);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('date.setUTCDate', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
const log: any = [];
|
||||
|
||||
const cleanup = effect_root(() => {
|
||||
render_effect(() => {
|
||||
log.push(date.getUTCDate());
|
||||
});
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setUTCDate(new_dates[0].getUTCDate());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setUTCDate(new_dates[1].getUTCDate());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
// nothing should happen here
|
||||
date.setUTCDate(new_dates[1].getUTCDate());
|
||||
});
|
||||
|
||||
assert.deepEqual(log, [
|
||||
initial_date.getUTCDate(),
|
||||
new_dates[0].getUTCDate(),
|
||||
new_dates[1].getUTCDate()
|
||||
]);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('date.setUTCFullYear', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
const log: any = [];
|
||||
|
||||
const cleanup = effect_root(() => {
|
||||
render_effect(() => {
|
||||
log.push(date.getUTCFullYear());
|
||||
});
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setUTCFullYear(new_dates[0].getUTCFullYear());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setUTCFullYear(new_dates[1].getUTCFullYear());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
// nothing should happen here
|
||||
date.setUTCFullYear(new_dates[1].getUTCFullYear());
|
||||
});
|
||||
|
||||
assert.deepEqual(log, [
|
||||
initial_date.getUTCFullYear(),
|
||||
new_dates[0].getUTCFullYear(),
|
||||
new_dates[1].getUTCFullYear()
|
||||
]);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('date.setUTCHours', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
const log: any = [];
|
||||
|
||||
const cleanup = effect_root(() => {
|
||||
render_effect(() => {
|
||||
log.push(date.getUTCHours());
|
||||
});
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setUTCHours(new_dates[0].getUTCHours());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setUTCHours(new_dates[1].getUTCHours());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
// nothing should happen here
|
||||
date.setUTCHours(new_dates[1].getUTCHours());
|
||||
});
|
||||
|
||||
assert.deepEqual(log, [
|
||||
initial_date.getUTCHours(),
|
||||
new_dates[0].getUTCHours(),
|
||||
new_dates[1].getUTCHours()
|
||||
]);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('date.setUTCMilliseconds', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
const log: any = [];
|
||||
|
||||
const cleanup = effect_root(() => {
|
||||
render_effect(() => {
|
||||
log.push(date.getUTCMilliseconds());
|
||||
});
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setUTCMilliseconds(new_dates[0].getUTCMilliseconds());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setUTCMilliseconds(new_dates[1].getUTCMilliseconds());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
// nothing should happen here
|
||||
date.setUTCMilliseconds(new_dates[1].getUTCMilliseconds());
|
||||
});
|
||||
|
||||
assert.deepEqual(log, [
|
||||
initial_date.getUTCMilliseconds(),
|
||||
new_dates[0].getUTCMilliseconds(),
|
||||
new_dates[1].getUTCMilliseconds()
|
||||
]);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('date.setUTCMinutes', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
const log: any = [];
|
||||
|
||||
const cleanup = effect_root(() => {
|
||||
render_effect(() => {
|
||||
log.push(date.getUTCMinutes());
|
||||
});
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setUTCMinutes(new_dates[0].getUTCMinutes());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setUTCMinutes(new_dates[1].getUTCMinutes());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
// nothing should happen here
|
||||
date.setUTCMinutes(new_dates[1].getUTCMinutes());
|
||||
});
|
||||
|
||||
assert.deepEqual(log, [
|
||||
initial_date.getUTCMinutes(),
|
||||
new_dates[0].getUTCMinutes(),
|
||||
new_dates[1].getUTCMinutes()
|
||||
]);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('date.setUTCMonth', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
const log: any = [];
|
||||
|
||||
const cleanup = effect_root(() => {
|
||||
render_effect(() => {
|
||||
log.push(date.getUTCMonth());
|
||||
});
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setUTCMonth(new_dates[0].getUTCMonth());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setUTCMonth(new_dates[1].getUTCMonth());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
// nothing should happen here
|
||||
date.setUTCMonth(new_dates[1].getUTCMonth());
|
||||
});
|
||||
|
||||
assert.deepEqual(log, [
|
||||
initial_date.getUTCMonth(),
|
||||
new_dates[0].getUTCMonth(),
|
||||
new_dates[1].getUTCMonth()
|
||||
]);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('date.setUTCSeconds', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
const log: any = [];
|
||||
|
||||
const cleanup = effect_root(() => {
|
||||
render_effect(() => {
|
||||
log.push(date.getUTCSeconds());
|
||||
});
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setUTCSeconds(new_dates[0].getUTCSeconds());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setUTCSeconds(new_dates[1].getUTCSeconds());
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
// nothing should happen here
|
||||
date.setUTCSeconds(new_dates[1].getUTCSeconds());
|
||||
});
|
||||
|
||||
assert.deepEqual(log, [
|
||||
initial_date.getUTCSeconds(),
|
||||
new_dates[0].getUTCSeconds(),
|
||||
new_dates[1].getUTCSeconds()
|
||||
]);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('date.setYear', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
const log: any = [];
|
||||
|
||||
// @ts-expect-error
|
||||
if (!date.setYear) {
|
||||
return;
|
||||
}
|
||||
const cleanup = effect_root(() => {
|
||||
render_effect(() => {
|
||||
// @ts-expect-error
|
||||
log.push(date.getYear());
|
||||
});
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
// @ts-expect-error
|
||||
date.setYear(22);
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
// @ts-expect-error
|
||||
date.setYear(23);
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
// nothing should happen here
|
||||
// @ts-expect-error
|
||||
date.setYear(23);
|
||||
});
|
||||
|
||||
// @ts-expect-error
|
||||
assert.deepEqual(log, [initial_date.getYear(), 22, 23]);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('date.setSeconds - edge cases', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
const log: any = [];
|
||||
|
||||
const cleanup = effect_root(() => {
|
||||
render_effect(() => {
|
||||
log.push(date.getSeconds());
|
||||
});
|
||||
render_effect(() => {
|
||||
log.push(date.getMinutes());
|
||||
});
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setSeconds(60);
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setSeconds(61);
|
||||
});
|
||||
|
||||
assert.deepEqual(log, [
|
||||
initial_date.getSeconds(),
|
||||
initial_date.getMinutes(),
|
||||
initial_date.getMinutes() + 1,
|
||||
initial_date.getSeconds() + 1,
|
||||
initial_date.getMinutes() + 2
|
||||
]);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('Date propagated changes', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
const log: any = [];
|
||||
|
||||
const cleanup = effect_root(() => {
|
||||
render_effect(() => {
|
||||
log.push(date.getSeconds());
|
||||
});
|
||||
render_effect(() => {
|
||||
log.push(date.getMonth());
|
||||
});
|
||||
render_effect(() => {
|
||||
log.push(date.getFullYear());
|
||||
});
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
date.setMonth(13);
|
||||
});
|
||||
|
||||
assert.deepEqual(log, [
|
||||
initial_date.getSeconds(),
|
||||
initial_date.getMonth(),
|
||||
initial_date.getFullYear(),
|
||||
1,
|
||||
2024
|
||||
]);
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('date fine grained tests', () => {
|
||||
const date = new ReactiveDate(initial_date);
|
||||
|
||||
let changes: Record<string, boolean> = {
|
||||
getFullYear: true,
|
||||
getUTCFullYear: true,
|
||||
getMonth: true,
|
||||
getUTCMonth: true,
|
||||
getDate: true,
|
||||
getUTCDate: true,
|
||||
getDay: true,
|
||||
getUTCDay: true,
|
||||
getHours: true,
|
||||
getUTCHours: true,
|
||||
getMinutes: true,
|
||||
getUTCMinutes: true,
|
||||
getSeconds: true,
|
||||
getUTCSeconds: true,
|
||||
getMilliseconds: true,
|
||||
getUTCMilliseconds: true
|
||||
};
|
||||
let test_description: string = '';
|
||||
|
||||
const expect_all_changes_to_be_false = () => {
|
||||
for (const key of Object.keys(changes) as Array<keyof typeof Date>) {
|
||||
assert.equal(changes[key], false, `${test_description}: effect for ${key} was not fired`);
|
||||
}
|
||||
};
|
||||
|
||||
const cleanup = effect_root(() => {
|
||||
for (const key of Object.keys(changes)) {
|
||||
render_effect(() => {
|
||||
// @ts-ignore
|
||||
date[key]();
|
||||
assert.equal(changes[key], true, `${test_description}: for ${key}`);
|
||||
changes[key] = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
expect_all_changes_to_be_false();
|
||||
changes = {
|
||||
...changes,
|
||||
getFullYear: true,
|
||||
getUTCFullYear: true,
|
||||
getMonth: true,
|
||||
getUTCMonth: true,
|
||||
getDay: true,
|
||||
getUTCDay: true
|
||||
};
|
||||
test_description = 'changing setFullYear that will cause month/day change as well';
|
||||
date.setFullYear(initial_date.getFullYear() + 1, initial_date.getMonth() + 1);
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
expect_all_changes_to_be_false();
|
||||
changes = {
|
||||
...changes,
|
||||
getDate: true,
|
||||
getUTCDate: true,
|
||||
getDay: true,
|
||||
getUTCDay: true,
|
||||
getHours: true,
|
||||
getUTCHours: true,
|
||||
getMinutes: true,
|
||||
getUTCMinutes: true,
|
||||
getSeconds: true,
|
||||
getUTCSeconds: true,
|
||||
getMilliseconds: true,
|
||||
getUTCMilliseconds: true
|
||||
};
|
||||
test_description = 'changing seconds that will change day/hour/minutes/seconds/milliseconds';
|
||||
date.setSeconds(61 * 60 * 25 + 1, 10);
|
||||
});
|
||||
|
||||
flushSync(() => {
|
||||
expect_all_changes_to_be_false();
|
||||
changes = {
|
||||
...changes,
|
||||
getMonth: true,
|
||||
getUTCMonth: true,
|
||||
getDay: true,
|
||||
getUTCDay: true,
|
||||
getMilliseconds: true,
|
||||
getUTCMilliseconds: true
|
||||
};
|
||||
test_description = 'changing month';
|
||||
date.setMonth(date.getMonth() + 1);
|
||||
});
|
||||
|
||||
cleanup();
|
||||
});
|
||||
|
||||
test('Date.instanceOf', () => {
|
||||
assert.equal(new ReactiveDate() instanceof Date, true);
|
||||
});
|
||||
Loading…
Reference in new issue