import { Store } from "../../data/Store";
import { ValidationGroup } from "./ValidationGroup";
import { Validator } from "./Validator";
import { bind } from "../../ui/bind";
import { createTestRenderer } from "../../util/test/createTestRenderer";

import assert from "assert";

describe("ValidationGroup", () => {
   it("performs validation and sets the flags", async () => {
      let widget = (
         <cx>
            <ValidationGroup invalid={bind("invalid")} valid={bind("valid")}>
               <Validator onValidate={() => "Something is wrong..."} />
               <div visible={bind("invalid")}>Invalid</div>
            </ValidationGroup>
         </cx>
      );

      let store = new Store();

      const component = await createTestRenderer(store, widget);

      let tree = component.toJSON();
      assert(tree && !Array.isArray(tree));
      assert.equal(tree.type, "div");
      assert.equal(store.get("invalid"), true);
      assert.equal(store.get("valid"), false);
   });

   it("nested validation works", async () => {
      let widget = (
         <cx>
            <div>
               <ValidationGroup invalid={bind("invalid")}>
                  <ValidationGroup invalid={bind("invalid1")}>
                     <Validator onValidate={() => "Something is wrong..."} />
                  </ValidationGroup>
                  <ValidationGroup invalid={bind("invalid2")}>
                     <Validator onValidate={() => false} />
                  </ValidationGroup>
               </ValidationGroup>
            </div>
         </cx>
      );

      let store = new Store();

      const component = await createTestRenderer(store, widget);

      let tree = component.toJSON();
      assert.equal(store.get("invalid"), true);
      assert.equal(store.get("invalid1"), true);
      assert.equal(store.get("invalid2"), false);
   });

   it("isolated validation group does not affect the parent", async () => {
      let widget = (
         <cx>
            <div>
               <ValidationGroup invalid={bind("invalid")}>
                  <ValidationGroup invalid={bind("invalid1")} isolated>
                     <Validator onValidate={() => "Something is wrong..."} />
                  </ValidationGroup>
                  <ValidationGroup invalid={bind("invalid2")}>
                     <Validator onValidate={() => false} />
                  </ValidationGroup>
               </ValidationGroup>
            </div>
         </cx>
      );

      let store = new Store();

      const component = await createTestRenderer(store, widget);

      let tree = component.toJSON();
      assert.equal(store.get("invalid"), false);
      assert.equal(store.get("invalid1"), true);
      assert.equal(store.get("invalid2"), false);
   });

   it("visited flag is propagated into nested validation groups", async () => {
      let visited = false;

      let widget = (
         <cx>
            <div>
               <ValidationGroup visited>
                  <ValidationGroup>
                     <div
                        onExplore={(context, instance) => {
                           if (context.parentVisited) visited = true;
                        }}
                     />
                  </ValidationGroup>
               </ValidationGroup>
            </div>
         </cx>
      );

      let store = new Store();

      const component = await createTestRenderer(store, widget);

      let tree = component.toJSON();
      assert(visited);
   });

   it("disabled flag can be overruled by the field props", async () => {
      let widget = (
         <cx>
            <div>
               <ValidationGroup invalid={bind("invalid")} disabled>
                  <Validator onValidate={() => "Something is wrong..."} disabled={false} />
               </ValidationGroup>
            </div>
         </cx>
      );

      let store = new Store();

      const component = await createTestRenderer(store, widget);

      let tree = component.toJSON();
      assert.equal(store.get("invalid"), true);
   });

   it("strict flag is used to enforce disabled flag", async () => {
      let widget = (
         <cx>
            <div>
               <ValidationGroup invalid={bind("invalid")} disabled strict>
                  <Validator onValidate={() => "Something is wrong..."} disabled={false} />
               </ValidationGroup>
            </div>
         </cx>
      );

      let store = new Store();

      const component = await createTestRenderer(store, widget);

      let tree = component.toJSON();
      assert.equal(store.get("invalid"), false);
   });
});
