FIX: Redo relative-time-picker (#27651)
Fixes various issues with the picker
This commit is contained in:
parent
751750c7f8
commit
89c0123b3a
|
@ -2,104 +2,63 @@ import Component from "@glimmer/component";
|
|||
import { tracked } from "@glimmer/tracking";
|
||||
import { on } from "@ember/modifier";
|
||||
import { action } from "@ember/object";
|
||||
import didUpdate from "@ember/render-modifiers/modifiers/did-update";
|
||||
import { isBlank } from "@ember/utils";
|
||||
import { eq } from "truth-helpers";
|
||||
import I18n from "discourse-i18n";
|
||||
import ComboBox from "select-kit/components/combo-box";
|
||||
|
||||
const HOUR = 60;
|
||||
const DAY = 24 * HOUR;
|
||||
const MONTH = 30 * DAY;
|
||||
const YEAR = 365 * DAY;
|
||||
|
||||
function roundDuration(duration) {
|
||||
let rounded = parseFloat(duration.toFixed(1));
|
||||
rounded = Math.round(rounded * 2) / 2;
|
||||
|
||||
// don't show decimal point for fraction-less numbers
|
||||
return rounded % 1 === 0 ? rounded.toFixed(0) : rounded;
|
||||
}
|
||||
|
||||
function inputValueFromMinutes(minutes) {
|
||||
if (!minutes) {
|
||||
return null;
|
||||
} else if (minutes > YEAR) {
|
||||
return roundDuration(minutes / YEAR);
|
||||
} else if (minutes > MONTH) {
|
||||
return roundDuration(minutes / MONTH);
|
||||
} else if (minutes > DAY) {
|
||||
return roundDuration(minutes / DAY);
|
||||
} else if (minutes > HOUR) {
|
||||
return roundDuration(minutes / HOUR);
|
||||
} else {
|
||||
return minutes;
|
||||
}
|
||||
}
|
||||
|
||||
function intervalFromMinutes(minutes) {
|
||||
if (minutes > YEAR) {
|
||||
return "years";
|
||||
} else if (minutes > MONTH) {
|
||||
return "months";
|
||||
} else if (minutes > DAY) {
|
||||
return "days";
|
||||
} else if (minutes > HOUR) {
|
||||
return "hours";
|
||||
} else {
|
||||
return "mins";
|
||||
}
|
||||
}
|
||||
|
||||
export default class RelativeTimePicker extends Component {
|
||||
@tracked _selectedInterval;
|
||||
@tracked inputValue;
|
||||
@tracked duration;
|
||||
@tracked interval;
|
||||
|
||||
_roundedDuration(duration) {
|
||||
const rounded = parseFloat(duration.toFixed(2));
|
||||
|
||||
// showing 2.00 instead of just 2 in the input is weird
|
||||
return rounded % 1 === 0 ? parseInt(rounded, 10) : rounded;
|
||||
}
|
||||
|
||||
get duration() {
|
||||
if (this.args.durationMinutes !== undefined) {
|
||||
return this._durationFromMinutes;
|
||||
} else {
|
||||
return this._durationFromHours;
|
||||
}
|
||||
}
|
||||
|
||||
get selectedInterval() {
|
||||
if (this._selectedInterval) {
|
||||
return this._selectedInterval;
|
||||
} else if (this.args.durationMinutes !== undefined) {
|
||||
return this._intervalFromMinutes;
|
||||
} else {
|
||||
return this._intervalFromHours;
|
||||
}
|
||||
}
|
||||
|
||||
get _durationFromHours() {
|
||||
if (this.args.durationHours === null) {
|
||||
return this.args.durationHours;
|
||||
} else if (this.args.durationHours >= 8760) {
|
||||
return this._roundedDuration(this.args.durationHours / 365 / 24);
|
||||
} else if (this.args.durationHours >= 730) {
|
||||
return this._roundedDuration(this.args.durationHours / 30 / 24);
|
||||
} else if (this.args.durationHours >= 24) {
|
||||
return this._roundedDuration(this.args.durationHours / 24);
|
||||
} else if (this.args.durationHours >= 1) {
|
||||
return this.args.durationHours;
|
||||
} else {
|
||||
return this._roundedDuration(this.args.durationHours * 60);
|
||||
}
|
||||
}
|
||||
|
||||
get _intervalFromHours() {
|
||||
if (this.args.durationHours === null) {
|
||||
return "hours";
|
||||
} else if (this.args.durationHours >= 8760) {
|
||||
return "years";
|
||||
} else if (this.args.durationHours >= 730) {
|
||||
return "months";
|
||||
} else if (this.args.durationHours >= 24) {
|
||||
return "days";
|
||||
} else if (this.args.durationHours < 1) {
|
||||
return "mins";
|
||||
} else {
|
||||
return "hours";
|
||||
}
|
||||
}
|
||||
|
||||
get _durationFromMinutes() {
|
||||
if (this.args.durationMinutes >= 525600) {
|
||||
return this._roundedDuration(this.args.durationMinutes / 365 / 60 / 24);
|
||||
} else if (this.args.durationMinutes >= 43800) {
|
||||
return this._roundedDuration(this.args.durationMinutes / 30 / 60 / 24);
|
||||
} else if (this.args.durationMinutes >= 1440) {
|
||||
return this._roundedDuration(this.args.durationMinutes / 60 / 24);
|
||||
} else if (this.args.durationMinutes >= 60) {
|
||||
return this._roundedDuration(this.args.durationMinutes / 60);
|
||||
} else {
|
||||
return this.args.durationMinutes;
|
||||
}
|
||||
}
|
||||
|
||||
get _intervalFromMinutes() {
|
||||
if (this.args.durationMinutes >= 525600) {
|
||||
return "years";
|
||||
} else if (this.args.durationMinutes >= 43800) {
|
||||
return "months";
|
||||
} else if (this.args.durationMinutes >= 1440) {
|
||||
return "days";
|
||||
} else if (this.args.durationMinutes >= 60) {
|
||||
return "hours";
|
||||
} else {
|
||||
return "mins";
|
||||
}
|
||||
}
|
||||
|
||||
get durationMin() {
|
||||
return this.selectedInterval === "mins" ? 1 : 0.1;
|
||||
}
|
||||
|
||||
get durationStep() {
|
||||
return this.selectedInterval === "mins" ? 1 : 0.05;
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.initValues();
|
||||
}
|
||||
|
||||
get intervals() {
|
||||
|
@ -129,58 +88,114 @@ export default class RelativeTimePicker extends Component {
|
|||
].filter((interval) => !this.args.hiddenIntervals?.includes(interval.id));
|
||||
}
|
||||
|
||||
calculateMinutes(duration, interval) {
|
||||
if (isBlank(duration) || isNaN(duration)) {
|
||||
minutesFromInputValueAndInterval(duration, interval) {
|
||||
if (isNaN(duration)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
duration = parseFloat(duration);
|
||||
|
||||
switch (interval) {
|
||||
case "mins":
|
||||
// we round up here in case the user manually inputted a step < 1
|
||||
return Math.ceil(duration);
|
||||
case "hours":
|
||||
return duration * 60;
|
||||
return duration * HOUR;
|
||||
case "days":
|
||||
return duration * 60 * 24;
|
||||
return duration * DAY;
|
||||
case "months":
|
||||
return duration * 60 * 24 * 30; // less accurate because of varying days in months
|
||||
return duration * MONTH; // less accurate because of varying days in months
|
||||
case "years":
|
||||
return duration * 60 * 24 * 365; // least accurate because of varying days in months/years
|
||||
return duration * YEAR; // least accurate because of varying days in months/years
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
onChangeInterval(interval) {
|
||||
this._selectedInterval = interval;
|
||||
const minutes = this.calculateMinutes(this.duration, interval);
|
||||
this.args.onChange?.(minutes);
|
||||
initValues() {
|
||||
let minutes = this.args.durationMinutes;
|
||||
if (this.args.durationHours) {
|
||||
minutes ??= this.args.durationHours * HOUR;
|
||||
}
|
||||
|
||||
this.inputValue = inputValueFromMinutes(minutes);
|
||||
|
||||
if (this.args.durationMinutes !== undefined) {
|
||||
this.interval = intervalFromMinutes(this.args.durationMinutes);
|
||||
} else if (this.args.durationHours === null) {
|
||||
this.interval = "hours";
|
||||
} else if (this.args.durationHours !== undefined) {
|
||||
this.interval = intervalFromMinutes(this.args.durationHours * HOUR);
|
||||
} else {
|
||||
this.interval = "mins";
|
||||
}
|
||||
|
||||
this.duration = this.minutesFromInputValueAndInterval(
|
||||
this.inputValue,
|
||||
this.interval
|
||||
);
|
||||
}
|
||||
|
||||
@action
|
||||
onChangeDuration(event) {
|
||||
const minutes = this.calculateMinutes(
|
||||
event.target.value,
|
||||
this.selectedInterval
|
||||
if (isBlank(event.target.value)) {
|
||||
this.duration = null;
|
||||
this.inputValue = null;
|
||||
} else {
|
||||
let newDuration = this.minutesFromInputValueAndInterval(
|
||||
parseFloat(event.target.value),
|
||||
this.interval
|
||||
);
|
||||
|
||||
// if on the edge of an interval - go to the next value
|
||||
// (e.g. 24 hours -> 1.5 days, instead of 24 hours -> 1 day)
|
||||
if (
|
||||
newDuration > this.duration &&
|
||||
(this.duration === YEAR ||
|
||||
this.duration === MONTH ||
|
||||
this.duration === DAY ||
|
||||
this.duration === HOUR)
|
||||
) {
|
||||
newDuration = this.minutesFromInputValueAndInterval(
|
||||
parseFloat(event.target.value) * 1.5,
|
||||
this.interval
|
||||
);
|
||||
}
|
||||
|
||||
this.duration = newDuration;
|
||||
this.interval = intervalFromMinutes(this.duration);
|
||||
this.inputValue = inputValueFromMinutes(this.duration);
|
||||
}
|
||||
|
||||
this.args.onChange?.(this.duration);
|
||||
}
|
||||
|
||||
@action
|
||||
onChangeInterval(interval) {
|
||||
this.interval = interval;
|
||||
|
||||
const newDuration = this.minutesFromInputValueAndInterval(
|
||||
this.inputValue,
|
||||
this.interval
|
||||
);
|
||||
this.args.onChange?.(minutes);
|
||||
if (newDuration !== this.duration) {
|
||||
this.duration = newDuration;
|
||||
this.args.onChange?.(this.duration);
|
||||
}
|
||||
}
|
||||
|
||||
<template>
|
||||
<div class="relative-time-picker">
|
||||
<div class="relative-time-picker" ...attributes>
|
||||
<input
|
||||
{{didUpdate this.initValues @durationMinutes @durationHours}}
|
||||
{{on "change" this.onChangeDuration}}
|
||||
type="number"
|
||||
min={{this.durationMin}}
|
||||
step={{this.durationStep}}
|
||||
value={{this.duration}}
|
||||
min={{if (eq this.interval "mins") 1 0.5}}
|
||||
step={{if (eq this.interval "mins") 1 0.5}}
|
||||
value={{this.inputValue}}
|
||||
id={{@id}}
|
||||
class="relative-time-duration"
|
||||
/>
|
||||
<ComboBox
|
||||
@content={{this.intervals}}
|
||||
@value={{this.selectedInterval}}
|
||||
@value={{this.interval}}
|
||||
@onChange={{this.onChangeInterval}}
|
||||
class="relative-time-intervals"
|
||||
/>
|
||||
|
|
|
@ -40,9 +40,9 @@
|
|||
{{i18n "relative_time_picker.relative"}}
|
||||
</label>
|
||||
<RelativeTimePicker
|
||||
@id="bookmark-relative-time-picker"
|
||||
@durationMinutes={{this.selectedDurationMins}}
|
||||
@onChange={{action "relativeTimeChanged"}}
|
||||
@onChange={{this.relativeTimeChanged}}
|
||||
id="bookmark-relative-time-picker"
|
||||
/>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
|
|
@ -207,16 +207,14 @@ export default Component.extend({
|
|||
|
||||
@action
|
||||
relativeTimeChanged(relativeTimeMins) {
|
||||
let dateTime = now(this.userTimezone).add(relativeTimeMins, "minutes");
|
||||
const dateTime = now(this.userTimezone).add(relativeTimeMins, "minutes");
|
||||
|
||||
this.setProperties({
|
||||
selectedDurationMins: relativeTimeMins,
|
||||
selectedDatetime: dateTime,
|
||||
});
|
||||
|
||||
if (this.onTimeSelected) {
|
||||
this.onTimeSelected(TIME_SHORTCUT_TYPES.RELATIVE, dateTime);
|
||||
}
|
||||
this.onTimeSelected?.(TIME_SHORTCUT_TYPES.RELATIVE, dateTime);
|
||||
},
|
||||
|
||||
@action
|
||||
|
|
|
@ -0,0 +1,279 @@
|
|||
import { tracked } from "@glimmer/tracking";
|
||||
import { fillIn, render, settled, typeIn } from "@ember/test-helpers";
|
||||
import { module, test } from "qunit";
|
||||
import RelativeTimePicker from "discourse/components/relative-time-picker";
|
||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
||||
|
||||
module("Integration | Component | relative-time-picker", function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
test("calls the onChange arg", async function (assert) {
|
||||
let updatedValue;
|
||||
const update = (value) => (updatedValue = value);
|
||||
await render(<template>
|
||||
<RelativeTimePicker @onChange={{update}} />
|
||||
</template>);
|
||||
|
||||
// empty and "minutes" by default
|
||||
assert.dom(".relative-time-duration").hasValue("");
|
||||
assert.strictEqual(
|
||||
selectKit().header().value(),
|
||||
"mins",
|
||||
"dropdown has 'minutes' preselected"
|
||||
);
|
||||
|
||||
// type <60 minutes
|
||||
await typeIn(".relative-time-duration", "50");
|
||||
assert.dom(".relative-time-duration").hasValue("50");
|
||||
assert.strictEqual(updatedValue, 50, "onChange called with 50");
|
||||
|
||||
// select "hours"
|
||||
await selectKit().expand();
|
||||
await selectKit().selectRowByValue("hours");
|
||||
assert.dom(".relative-time-duration").hasValue("50");
|
||||
assert.strictEqual(updatedValue, 50 * 60, "onChange called with 50 * 60");
|
||||
|
||||
// clear the duration
|
||||
await fillIn(".relative-time-duration", "");
|
||||
assert.dom(".relative-time-duration").hasValue("");
|
||||
assert.strictEqual(updatedValue, null, "onChange called with null");
|
||||
assert.strictEqual(
|
||||
selectKit().header().value(),
|
||||
"hours",
|
||||
"dropdown has 'hours' selected"
|
||||
);
|
||||
|
||||
// type a new value
|
||||
await typeIn(".relative-time-duration", "22");
|
||||
assert.strictEqual(
|
||||
selectKit().header().value(),
|
||||
"hours",
|
||||
"dropdown has still 'hours' selected"
|
||||
);
|
||||
assert.dom(".relative-time-duration").hasValue("22");
|
||||
assert.strictEqual(updatedValue, 22 * 60, "onChange called with 22 * 60");
|
||||
|
||||
// select "minutes"
|
||||
await selectKit().expand();
|
||||
await selectKit().selectRowByValue("mins");
|
||||
assert.dom(".relative-time-duration").hasValue("22");
|
||||
assert.strictEqual(updatedValue, 22, "onChange called with 22");
|
||||
|
||||
// type >60 minutes
|
||||
await fillIn(".relative-time-duration", "");
|
||||
await typeIn(".relative-time-duration", "800");
|
||||
assert.dom(".relative-time-duration").hasValue("13.5");
|
||||
assert.strictEqual(updatedValue, 800, "onChange called with 800");
|
||||
assert.strictEqual(
|
||||
selectKit().header().value(),
|
||||
"hours",
|
||||
"automatically changes the dropdown to 'hours'"
|
||||
);
|
||||
});
|
||||
|
||||
test("onChange callback works w/ a start value", async function (assert) {
|
||||
const testState = new (class {
|
||||
@tracked minutes = 120;
|
||||
})();
|
||||
|
||||
const update = (value) => (testState.minutes = value);
|
||||
await render(<template>
|
||||
<RelativeTimePicker
|
||||
@onChange={{update}}
|
||||
@durationMinutes={{testState.minutes}}
|
||||
/>
|
||||
</template>);
|
||||
|
||||
// uses the value and selects the right interval
|
||||
assert.dom(".relative-time-duration").hasValue("2");
|
||||
assert.strictEqual(
|
||||
selectKit().header().value(),
|
||||
"hours",
|
||||
"dropdown has 'hours' preselected"
|
||||
);
|
||||
|
||||
// clear the duration
|
||||
await fillIn(".relative-time-duration", "");
|
||||
assert.dom(".relative-time-duration").hasValue("");
|
||||
assert.strictEqual(testState.minutes, null, "onChange called with null");
|
||||
// semi-acceptable behavior: because `initValues()` is called, it changes the interval:
|
||||
assert.strictEqual(
|
||||
selectKit().header().value(),
|
||||
"mins",
|
||||
"dropdown has 'minutes' selected"
|
||||
);
|
||||
|
||||
// type <60 minutes
|
||||
await typeIn(".relative-time-duration", "18");
|
||||
assert.dom(".relative-time-duration").hasValue("18");
|
||||
assert.strictEqual(testState.minutes, 18, "onChange called with 18");
|
||||
|
||||
// select "days"
|
||||
await selectKit().expand();
|
||||
await selectKit().selectRowByValue("days");
|
||||
assert.dom(".relative-time-duration").hasValue("18");
|
||||
assert.strictEqual(
|
||||
testState.minutes,
|
||||
18 * 60 * 24,
|
||||
"onChange called with 18 * 60 * 24"
|
||||
);
|
||||
|
||||
// type a new value
|
||||
await fillIn(".relative-time-duration", "2");
|
||||
assert.strictEqual(
|
||||
selectKit().header().value(),
|
||||
"days",
|
||||
"dropdown has still 'days' selected"
|
||||
);
|
||||
assert.dom(".relative-time-duration").hasValue("2");
|
||||
assert.strictEqual(
|
||||
testState.minutes,
|
||||
2 * 60 * 24,
|
||||
"onChange called with 2 * 60 * 24"
|
||||
);
|
||||
|
||||
// select "minutes"
|
||||
await selectKit().expand();
|
||||
await selectKit().selectRowByValue("mins");
|
||||
assert.dom(".relative-time-duration").hasValue("2");
|
||||
assert.strictEqual(testState.minutes, 2, "onChange called with 2");
|
||||
|
||||
// type >60 minutes
|
||||
await fillIn(".relative-time-duration", "90");
|
||||
assert.dom(".relative-time-duration").hasValue("1.5");
|
||||
assert.strictEqual(testState.minutes, 90, "onChange called with 90");
|
||||
assert.strictEqual(
|
||||
selectKit().header().value(),
|
||||
"hours",
|
||||
"automatically changes the dropdown to 'hours'"
|
||||
);
|
||||
});
|
||||
|
||||
test("updates the input when args change", async function (assert) {
|
||||
const testState = new (class {
|
||||
@tracked value;
|
||||
})();
|
||||
testState.value = 10;
|
||||
|
||||
await render(<template>
|
||||
<RelativeTimePicker @durationMinutes={{testState.value}} />
|
||||
</template>);
|
||||
|
||||
assert.strictEqual(selectKit().header().value(), "mins");
|
||||
assert.dom(".relative-time-duration").hasValue("10");
|
||||
|
||||
testState.value = 20;
|
||||
await settled();
|
||||
|
||||
assert.dom(".relative-time-duration").hasValue("20");
|
||||
});
|
||||
|
||||
test("prefills and preselects minutes", async function (assert) {
|
||||
await render(<template>
|
||||
<RelativeTimePicker @durationMinutes="5" />
|
||||
</template>);
|
||||
|
||||
assert.strictEqual(selectKit().header().value(), "mins");
|
||||
assert.dom(".relative-time-duration").hasValue("5");
|
||||
});
|
||||
|
||||
test("prefills and preselects null minutes", async function (assert) {
|
||||
await render(<template>
|
||||
<RelativeTimePicker @durationMinutes={{null}} />
|
||||
</template>);
|
||||
|
||||
assert.strictEqual(selectKit().header().value(), "mins");
|
||||
assert.dom(".relative-time-duration").hasValue("");
|
||||
});
|
||||
|
||||
test("prefills and preselects hours based on converted minutes", async function (assert) {
|
||||
await render(<template>
|
||||
<RelativeTimePicker @durationMinutes="90" />
|
||||
</template>);
|
||||
|
||||
assert.strictEqual(selectKit().header().value(), "hours");
|
||||
assert.dom(".relative-time-duration").hasValue("1.5");
|
||||
});
|
||||
|
||||
test("prefills and preselects days based on converted minutes", async function (assert) {
|
||||
await render(<template>
|
||||
<RelativeTimePicker @durationMinutes="2880" />
|
||||
</template>);
|
||||
|
||||
assert.strictEqual(selectKit().header().value(), "days");
|
||||
assert.dom(".relative-time-duration").hasValue("2");
|
||||
});
|
||||
|
||||
test("prefills and preselects months based on converted minutes", async function (assert) {
|
||||
await render(<template>
|
||||
<RelativeTimePicker @durationMinutes="151200" />
|
||||
</template>);
|
||||
|
||||
assert.strictEqual(selectKit().header().value(), "months");
|
||||
assert.dom(".relative-time-duration").hasValue("3.5");
|
||||
});
|
||||
|
||||
test("prefills and preselects years based on converted minutes", async function (assert) {
|
||||
await render(<template>
|
||||
<RelativeTimePicker @durationMinutes="525700" />
|
||||
</template>);
|
||||
|
||||
assert.strictEqual(selectKit().header().value(), "years");
|
||||
assert.dom(".relative-time-duration").hasValue("1");
|
||||
});
|
||||
|
||||
test("prefills and preselects hours", async function (assert) {
|
||||
await render(<template>
|
||||
<RelativeTimePicker @durationHours="5" />
|
||||
</template>);
|
||||
|
||||
assert.strictEqual(selectKit().header().value(), "hours");
|
||||
assert.dom(".relative-time-duration").hasValue("5");
|
||||
});
|
||||
|
||||
test("prefills and preselects null hours", async function (assert) {
|
||||
await render(<template>
|
||||
<RelativeTimePicker @durationHours={{null}} />
|
||||
</template>);
|
||||
|
||||
assert.strictEqual(selectKit().header().value(), "hours");
|
||||
assert.dom(".relative-time-duration").hasValue("");
|
||||
});
|
||||
|
||||
test("prefills and preselects minutes based on converted hours", async function (assert) {
|
||||
await render(<template>
|
||||
<RelativeTimePicker @durationHours="0.5" />
|
||||
</template>);
|
||||
|
||||
assert.strictEqual(selectKit().header().value(), "mins");
|
||||
assert.dom(".relative-time-duration").hasValue("30");
|
||||
});
|
||||
|
||||
test("prefills and preselects days based on converted hours", async function (assert) {
|
||||
await render(<template>
|
||||
<RelativeTimePicker @durationHours="48" />
|
||||
</template>);
|
||||
|
||||
assert.strictEqual(selectKit().header().value(), "days");
|
||||
assert.dom(".relative-time-duration").hasValue("2");
|
||||
});
|
||||
|
||||
test("prefills and preselects months based on converted hours", async function (assert) {
|
||||
await render(<template>
|
||||
<RelativeTimePicker @durationHours="2160" />
|
||||
</template>);
|
||||
|
||||
assert.strictEqual(selectKit().header().value(), "months");
|
||||
assert.dom(".relative-time-duration").hasValue("3");
|
||||
});
|
||||
|
||||
test("prefills and preselects years based on converted hours", async function (assert) {
|
||||
await render(<template>
|
||||
<RelativeTimePicker @durationHours="17520" />
|
||||
</template>);
|
||||
|
||||
assert.strictEqual(selectKit().header().value(), "years");
|
||||
assert.dom(".relative-time-duration").hasValue("2");
|
||||
});
|
||||
});
|
|
@ -1,110 +0,0 @@
|
|||
import { render } from "@ember/test-helpers";
|
||||
import { hbs } from "ember-cli-htmlbars";
|
||||
import { module, test } from "qunit";
|
||||
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
|
||||
import { query } from "discourse/tests/helpers/qunit-helpers";
|
||||
import selectKit from "discourse/tests/helpers/select-kit-helper";
|
||||
|
||||
module("Integration | Component | relative-time-picker", function (hooks) {
|
||||
setupRenderingTest(hooks);
|
||||
|
||||
hooks.beforeEach(function () {
|
||||
this.set("subject", selectKit());
|
||||
});
|
||||
|
||||
test("prefills and preselects minutes", async function (assert) {
|
||||
await render(hbs`<RelativeTimePicker @durationMinutes="5" />`);
|
||||
|
||||
const prefilledDuration = query(".relative-time-duration").value;
|
||||
assert.strictEqual(this.subject.header().value(), "mins");
|
||||
assert.strictEqual(prefilledDuration, "5");
|
||||
});
|
||||
|
||||
test("prefills and preselects null minutes", async function (assert) {
|
||||
await render(hbs`<RelativeTimePicker @durationMinutes={{null}} />`);
|
||||
|
||||
const prefilledDuration = query(".relative-time-duration").value;
|
||||
assert.strictEqual(this.subject.header().value(), "mins");
|
||||
assert.strictEqual(prefilledDuration, "");
|
||||
});
|
||||
|
||||
test("prefills and preselects hours based on translated minutes", async function (assert) {
|
||||
await render(hbs`<RelativeTimePicker @durationMinutes="90" />`);
|
||||
|
||||
const prefilledDuration = query(".relative-time-duration").value;
|
||||
assert.strictEqual(this.subject.header().value(), "hours");
|
||||
assert.strictEqual(prefilledDuration, "1.5");
|
||||
});
|
||||
|
||||
test("prefills and preselects days based on translated minutes", async function (assert) {
|
||||
await render(hbs`<RelativeTimePicker @durationMinutes="2880" />`);
|
||||
|
||||
const prefilledDuration = query(".relative-time-duration").value;
|
||||
assert.strictEqual(this.subject.header().value(), "days");
|
||||
assert.strictEqual(prefilledDuration, "2");
|
||||
});
|
||||
|
||||
test("prefills and preselects months based on translated minutes", async function (assert) {
|
||||
await render(hbs`<RelativeTimePicker @durationMinutes="129600" />`);
|
||||
|
||||
const prefilledDuration = query(".relative-time-duration").value;
|
||||
assert.strictEqual(this.subject.header().value(), "months");
|
||||
assert.strictEqual(prefilledDuration, "3");
|
||||
});
|
||||
|
||||
test("prefills and preselects years based on translated minutes", async function (assert) {
|
||||
await render(hbs`<RelativeTimePicker @durationMinutes="525600" />`);
|
||||
|
||||
const prefilledDuration = query(".relative-time-duration").value;
|
||||
assert.strictEqual(this.subject.header().value(), "years");
|
||||
assert.strictEqual(prefilledDuration, "1");
|
||||
});
|
||||
|
||||
test("prefills and preselects hours", async function (assert) {
|
||||
await render(hbs`<RelativeTimePicker @durationHours="5" />`);
|
||||
|
||||
const prefilledDuration = query(".relative-time-duration").value;
|
||||
assert.strictEqual(this.subject.header().value(), "hours");
|
||||
assert.strictEqual(prefilledDuration, "5");
|
||||
});
|
||||
|
||||
test("prefills and preselects null hours", async function (assert) {
|
||||
await render(hbs`<RelativeTimePicker @durationHours={{null}} />`);
|
||||
|
||||
const prefilledDuration = query(".relative-time-duration").value;
|
||||
assert.strictEqual(this.subject.header().value(), "hours");
|
||||
assert.strictEqual(prefilledDuration, "");
|
||||
});
|
||||
|
||||
test("prefills and preselects minutes based on translated hours", async function (assert) {
|
||||
await render(hbs`<RelativeTimePicker @durationHours="0.5" />`);
|
||||
|
||||
const prefilledDuration = query(".relative-time-duration").value;
|
||||
assert.strictEqual(this.subject.header().value(), "mins");
|
||||
assert.strictEqual(prefilledDuration, "30");
|
||||
});
|
||||
|
||||
test("prefills and preselects days based on translated hours", async function (assert) {
|
||||
await render(hbs`<RelativeTimePicker @durationHours="48" />`);
|
||||
|
||||
const prefilledDuration = query(".relative-time-duration").value;
|
||||
assert.strictEqual(this.subject.header().value(), "days");
|
||||
assert.strictEqual(prefilledDuration, "2");
|
||||
});
|
||||
|
||||
test("prefills and preselects months based on translated hours", async function (assert) {
|
||||
await render(hbs`<RelativeTimePicker @durationHours="2160" />`);
|
||||
|
||||
const prefilledDuration = query(".relative-time-duration").value;
|
||||
assert.strictEqual(this.subject.header().value(), "months");
|
||||
assert.strictEqual(prefilledDuration, "3");
|
||||
});
|
||||
|
||||
test("prefills and preselects years based on translated hours", async function (assert) {
|
||||
await render(hbs`<RelativeTimePicker @durationHours="17520" />`);
|
||||
|
||||
const prefilledDuration = query(".relative-time-duration").value;
|
||||
assert.strictEqual(this.subject.header().value(), "years");
|
||||
assert.strictEqual(prefilledDuration, "2");
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue