Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Lines marked **Upgrade step** need you to act after updating.
### Fixed

- A new long text question now shows in your form and in the editor preview, also before you set any options for it. Before, it failed to show. (#286)
- A long text question with an empty "Max characters" now has no limit, also when you open it again. Before, the editor showed 500 and saved it back. New long text questions still start at 500. (#291)
- Ticking "Remember me" on the login page now keeps you logged in after your browser session ends. Before, it was ignored. (#227)
- The counter under the text editor shows the length of your text as soon as a text opens. Before, it showed a larger number until your first edit. (#228)
- A question or completion page text that holds only an image keeps the image when you save it. Before, it was saved as empty and the image was lost. (#229)
Expand Down
2 changes: 1 addition & 1 deletion resources/js/components/CharCount.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { computed, ref } from "vue";

const props = defineProps<{
text?: string;
maxChars?: number;
maxChars?: number | null;
}>();

const charCount = ref<number>(props.text?.length ?? 0);
Expand Down
67 changes: 67 additions & 0 deletions resources/js/components/Factory/Main/ConfigureTextarea.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { flushPromises, mount } from "@vue/test-utils";
import { createPinia, setActivePinia } from "pinia";
import { describe, expect, it, vi } from "vitest";
import ConfigureTextarea from "./ConfigureTextarea.vue";
import { useWorkbench } from "@/stores";

const saved = vi.hoisted(() => ({
options: {} as Record<string, unknown>,
}));

vi.mock("../utils/useInteractionsUtils", () => ({
useInteractionsUtils: () => ({
findOrCreate: async () => ({ id: 7, label: "", options: saved.options }),
}),
}));

// a long text answer that was saved before, with the given options
const reopen = async (options: Record<string, unknown>) => {
saved.options = options;
const pinia = createPinia();
setActivePinia(pinia);
const workbench = useWorkbench();
workbench.block = {
interactions: [{ type: "textarea" }],
} as unknown as FormBlockModel;
const save = vi
.spyOn(workbench, "updateInteraction")
.mockImplementation(() => {});

const wrapper = mount(ConfigureTextarea, {
global: { plugins: [pinia], provide: { block: { type: "input" } } },
});
await flushPromises();

return { wrapper, save };
};

describe("long text max characters", () => {
it("stays empty and saves nothing when a question with no limit reopens", async () => {
const { wrapper, save } = await reopen({ rows: 5, max_chars: null });

expect(
(wrapper.find("input#textarea-max-chars").element as HTMLInputElement)
.value,
).toBe("");
expect(save).not.toHaveBeenCalled();
});

it("shows the saved limit when a question with a limit reopens", async () => {
const { wrapper } = await reopen({ rows: 5, max_chars: 120 });

expect(
(wrapper.find("input#textarea-max-chars").element as HTMLInputElement)
.value,
).toBe("120");
});

it("saves no limit when the owner empties the field", async () => {
const { wrapper, save } = await reopen({ rows: 5, max_chars: 500 });

await wrapper.find("input#textarea-max-chars").setValue("");
await flushPromises();

expect(save).toHaveBeenCalledTimes(1);
expect(save.mock.lastCall?.[0].options.max_chars).toBeNull();
});
});
9 changes: 5 additions & 4 deletions resources/js/components/Factory/Main/ConfigureTextarea.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<D9Label id="textarea-max-chars" label="Max characters" />
<D9Input
id="textarea-max-chars"
placeholder="e.g. 500"
placeholder="No limit"
type="number"
block
v-model="maxChars"
Expand All @@ -52,7 +52,8 @@ const { findOrCreate } = useInteractionsUtils();

const label = ref<FormBlockInteractionModel["label"]>("");
const rows = ref<number>(5);
const maxChars = ref<number>(500);
// empty means no limit; a new question starts at 500
const maxChars = ref<number | "">(500);
const interaction = ref(null) as unknown as Ref<FormBlockInteractionModel>;

onMounted(async () => {
Expand All @@ -65,7 +66,7 @@ onMounted(async () => {

label.value = interaction.value.label;
rows.value = interaction.value.options?.rows ?? 5;
maxChars.value = interaction.value.options?.max_chars ?? 500;
maxChars.value = isNew ? 500 : (interaction.value.options?.max_chars ?? "");
await settled(isNew);
}
});
Expand All @@ -76,7 +77,7 @@ const settled = useSettingsWatch([label, rows, maxChars], (newValues) => {
label: newValues[0],
options: {
rows: Math.max(1, Math.min(10, parseInt(newValues[1]))),
max_chars: parseInt(newValues[2]),
max_chars: parseInt(newValues[2]) || null,
},
};

Expand Down
2 changes: 1 addition & 1 deletion resources/js/types/models.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ type FormBlockInteractionType =

type FormBlockInteractionSettings = {
rows?: number;
max_chars?: number;
max_chars?: number | null;
minDate?: string;
maxDate?: string;
noPastDates?: boolean;
Expand Down
Loading