discourse/plugins/discourse-policy/test/javascripts/integration/components/policy-builder-form-test.gjs
Sam a20a6a465c
FEATURE: Inline policy editing in rich editor (#39820)
Policy nodes in the rich editor now display a summary of their
attributes (groups, version, renew, accept, etc.) and expose an edit
button that opens the policy builder modal pre-populated with the
current values. Changes are applied directly to the node, so policies
can be tweaked without dropping back to markdown source.

Also migrates the policy builder form to FormKit, replacing the
bespoke `policy-form-field` component. This brings tooltips, proper
field-level validation and a layout consistent with the rest of the
UI. The "add users to group" picker now excludes automatic groups,
which cannot be assigned to.

Before:

<img width="1238" height="337" alt="image"
src="https://github.com/user-attachments/assets/44b21b44-a669-4474-8d14-5855326debfa"
/>


<img width="1030" height="1539" alt="image"
src="https://github.com/user-attachments/assets/a816a491-ba25-4b0a-aa50-cbee32c60962"
/>


After:

<img width="1280" height="574" alt="image"
src="https://github.com/user-attachments/assets/6c4b4e18-674d-4e5a-be20-6008c730d348"
/>

<img width="1160" height="1499" alt="image"
src="https://github.com/user-attachments/assets/7d47782c-9b53-43ee-b135-3bb3a2b9ae43"
/>
2026-05-08 06:58:39 +10:00

110 lines
3.4 KiB
Text

import { click, fillIn, render } from "@ember/test-helpers";
import { module, test } from "qunit";
import { AUTO_GROUPS } from "discourse/lib/constants";
import { setupRenderingTest } from "discourse/tests/helpers/component-test";
import selectKit from "discourse/tests/helpers/select-kit-helper";
import { i18n } from "discourse-i18n";
import PolicyBuilderForm from "discourse/plugins/discourse-policy/discourse/components/policy-builder-form";
module(
"Discourse Policy | Integration | Component | policy-builder-form",
function (hooks) {
setupRenderingTest(hooks);
hooks.beforeEach(function () {
this.site = this.owner.lookup("service:site");
this.site.groups = [
AUTO_GROUPS.everyone,
AUTO_GROUPS.admins,
AUTO_GROUPS.moderators,
AUTO_GROUPS.staff,
AUTO_GROUPS.trust_level_0,
{ id: 100, name: "team" },
];
this.set("data", { reminder: null, version: 1 });
this.set("onRegisterApi", (api) => (this.formApi = api));
this.set("onSubmit", (data) => (this.submittedData = data));
});
test("submits form data", async function (assert) {
await render(
<template>
<PolicyBuilderForm
@data={{this.data}}
@onRegisterApi={{this.onRegisterApi}}
@onSubmit={{this.onSubmit}}
/>
</template>
);
const groupsChooser = selectKit(
".policy-builder-form__groups .group-chooser"
);
await groupsChooser.expand();
await groupsChooser.selectRowByValue("admins");
await fillIn("input[name='version']", "1");
await fillIn("input[name='renew']", "1");
await fillIn("input[name='renewStart']", "2022-06-07");
const reminderChooser = selectKit(".combo-box");
assert
.dom(reminderChooser.header().el())
.hasText(
i18n("discourse_policy.builder.reminder.no_reminder"),
"should be set by default"
);
await reminderChooser.expand();
await reminderChooser.selectRowByValue("weekly");
await fillIn("input[name='accept']", "foo");
await fillIn("input[name='revoke']", "bar");
const addGroupsChooser = selectKit(
".policy-builder-form__add-users-to-group .group-chooser"
);
await addGroupsChooser.expand();
assert
.dom(addGroupsChooser.rowByValue("moderators").el())
.doesNotExist("automatic groups are not listed");
await addGroupsChooser.selectRowByValue("team");
await click("input[name='private']");
await this.formApi.submit();
assert.deepEqual(this.submittedData, {
groups: "admins",
version: 1,
renew: 1,
renewStart: "2022-06-07",
reminder: "weekly",
accept: "foo",
revoke: "bar",
addUsersToGroup: "team",
private: true,
});
});
test("does not submit invalid form data", async function (assert) {
this.set("data", { version: 1 });
this.set("onSubmit", () => (this.submitted = true));
this.submitted = false;
await render(
<template>
<PolicyBuilderForm
@data={{this.data}}
@onRegisterApi={{this.onRegisterApi}}
@onSubmit={{this.onSubmit}}
/>
</template>
);
await this.formApi.submit();
assert.false(this.submitted, "onSubmit is not called");
});
}
);