tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Widgets.test.jsx (15444B)


      1 import React from "react";
      2 import { mount } from "enzyme";
      3 import { Provider } from "react-redux";
      4 import { INITIAL_STATE, reducers } from "common/Reducers.sys.mjs";
      5 import { combineReducers, createStore } from "redux";
      6 import {
      7  Widgets,
      8  resetTimerToDefaults,
      9 } from "content-src/components/Widgets/Widgets";
     10 import { Lists } from "content-src/components/Widgets/Lists/Lists";
     11 import { actionTypes as at } from "common/Actions.mjs";
     12 import { FocusTimer } from "content-src/components/Widgets/FocusTimer/FocusTimer";
     13 
     14 const PREF_WIDGETS_LISTS_ENABLED = "widgets.lists.enabled";
     15 const PREF_WIDGETS_SYSTEM_LISTS_ENABLED = "widgets.system.lists.enabled";
     16 const PREF_WIDGETS_TIMER_ENABLED = "widgets.focusTimer.enabled";
     17 const PREF_WIDGETS_SYSTEM_TIMER_ENABLED = "widgets.system.focusTimer.enabled";
     18 
     19 function WrapWithProvider({ children, state = INITIAL_STATE }) {
     20  const store = createStore(combineReducers(reducers), state);
     21  return <Provider store={store}>{children}</Provider>;
     22 }
     23 
     24 describe("<Widgets>", () => {
     25  it("should render and show <Lists> if list prefs are enabled", () => {
     26    const state = {
     27      ...INITIAL_STATE,
     28      Prefs: {
     29        ...INITIAL_STATE.Prefs,
     30        values: {
     31          ...INITIAL_STATE.Prefs.values,
     32          [PREF_WIDGETS_LISTS_ENABLED]: true,
     33          [PREF_WIDGETS_SYSTEM_LISTS_ENABLED]: true,
     34        },
     35      },
     36    };
     37    const wrapper = mount(
     38      <WrapWithProvider state={state}>
     39        <Widgets />
     40      </WrapWithProvider>
     41    );
     42    assert.ok(wrapper.exists());
     43    assert.ok(wrapper.find(".widgets-container").exists());
     44    assert.ok(wrapper.find(Lists).exists());
     45  });
     46 
     47  it("should render and show <FocusTimer> if timer prefs are enabled", () => {
     48    const state = {
     49      ...INITIAL_STATE,
     50      Prefs: {
     51        ...INITIAL_STATE.Prefs,
     52        values: {
     53          ...INITIAL_STATE.Prefs.values,
     54          [PREF_WIDGETS_TIMER_ENABLED]: true,
     55          [PREF_WIDGETS_SYSTEM_TIMER_ENABLED]: true,
     56        },
     57      },
     58    };
     59    const wrapper = mount(
     60      <WrapWithProvider state={state}>
     61        <Widgets />
     62      </WrapWithProvider>
     63    );
     64    assert.ok(wrapper.exists());
     65    assert.ok(wrapper.find(".widgets-container").exists());
     66    assert.ok(wrapper.find(FocusTimer).exists());
     67  });
     68 
     69  it("should not render FocusTimer when timer pref is disabled", () => {
     70    const state = {
     71      ...INITIAL_STATE,
     72      Prefs: {
     73        ...INITIAL_STATE.Prefs,
     74        values: {
     75          ...INITIAL_STATE.Prefs.values,
     76          [PREF_WIDGETS_TIMER_ENABLED]: false,
     77          [PREF_WIDGETS_SYSTEM_TIMER_ENABLED]: true,
     78        },
     79      },
     80    };
     81    const wrapper = mount(
     82      <WrapWithProvider state={state}>
     83        <Widgets />
     84      </WrapWithProvider>
     85    );
     86    assert.ok(!wrapper.find(FocusTimer).exists());
     87  });
     88 
     89  describe("resetTimerToDefaults", () => {
     90    it("should dispatch WIDGETS_TIMER_RESET with focus timer defaults", () => {
     91      const dispatch = sinon.spy();
     92      const timerType = "focus";
     93 
     94      resetTimerToDefaults(dispatch, timerType);
     95 
     96      const resetCall = dispatch
     97        .getCalls()
     98        .find(call => call.args[0]?.type === at.WIDGETS_TIMER_RESET);
     99      const setTypeCall = dispatch
    100        .getCalls()
    101        .find(call => call.args[0]?.type === at.WIDGETS_TIMER_SET_TYPE);
    102 
    103      assert.ok(resetCall, "should dispatch WIDGETS_TIMER_RESET");
    104      assert.ok(setTypeCall, "should dispatch WIDGETS_TIMER_SET_TYPE");
    105      assert.equal(
    106        resetCall.args[0].data.duration,
    107        1500,
    108        "should reset focus to 25 minutes"
    109      );
    110      assert.equal(resetCall.args[0].data.initialDuration, 1500);
    111      assert.equal(resetCall.args[0].data.timerType, "focus");
    112      assert.equal(setTypeCall.args[0].data.timerType, "focus");
    113    });
    114 
    115    it("should dispatch WIDGETS_TIMER_RESET with break timer defaults", () => {
    116      const dispatch = sinon.spy();
    117      const timerType = "break";
    118 
    119      resetTimerToDefaults(dispatch, timerType);
    120 
    121      const resetCall = dispatch
    122        .getCalls()
    123        .find(call => call.args[0]?.type === at.WIDGETS_TIMER_RESET);
    124 
    125      assert.ok(resetCall, "should dispatch WIDGETS_TIMER_RESET");
    126      assert.equal(
    127        resetCall.args[0].data.duration,
    128        300,
    129        "should reset break to 5 minutes"
    130      );
    131      assert.equal(resetCall.args[0].data.initialDuration, 300);
    132      assert.equal(resetCall.args[0].data.timerType, "break");
    133    });
    134  });
    135 
    136  describe("handleHideAllWidgets", () => {
    137    let wrapper;
    138    let state;
    139    let store;
    140 
    141    beforeEach(() => {
    142      state = {
    143        ...INITIAL_STATE,
    144        Prefs: {
    145          ...INITIAL_STATE.Prefs,
    146          values: {
    147            ...INITIAL_STATE.Prefs.values,
    148            [PREF_WIDGETS_LISTS_ENABLED]: true,
    149            [PREF_WIDGETS_SYSTEM_LISTS_ENABLED]: true,
    150            [PREF_WIDGETS_TIMER_ENABLED]: true,
    151            [PREF_WIDGETS_SYSTEM_TIMER_ENABLED]: true,
    152          },
    153        },
    154      };
    155      store = createStore(combineReducers(reducers), state);
    156      sinon.spy(store, "dispatch");
    157      wrapper = mount(
    158        <Provider store={store}>
    159          <Widgets />
    160        </Provider>
    161      );
    162    });
    163 
    164    afterEach(() => {
    165      store.dispatch.restore();
    166    });
    167 
    168    it("should dispatch SetPref actions when hide button is clicked", () => {
    169      const hideButton = wrapper.find("#hide-all-widgets-button");
    170      assert.ok(hideButton.exists(), "hide all button should exist");
    171 
    172      // Get the onClick handler and call it
    173      const onClickHandler = hideButton.prop("onClick");
    174      assert.ok(onClickHandler, "onClick handler should exist");
    175      onClickHandler({ preventDefault: () => {} });
    176 
    177      const allCalls = store.dispatch.getCalls();
    178      const setPrefCalls = allCalls.filter(
    179        call => call.args[0]?.type === at.SET_PREF
    180      );
    181 
    182      assert.equal(
    183        setPrefCalls.length,
    184        2,
    185        `should dispatch two SetPref actions, got ${setPrefCalls.length}.`
    186      );
    187 
    188      const listsPrefCall = setPrefCalls.find(
    189        call => call.args[0].data?.name === PREF_WIDGETS_LISTS_ENABLED
    190      );
    191      const timerPrefCall = setPrefCalls.find(
    192        call => call.args[0].data?.name === PREF_WIDGETS_TIMER_ENABLED
    193      );
    194 
    195      assert.ok(listsPrefCall, "should dispatch SetPref for lists");
    196      assert.equal(
    197        listsPrefCall.args[0].data.value,
    198        false,
    199        "should set lists pref to false"
    200      );
    201 
    202      assert.ok(timerPrefCall, "should dispatch SetPref for timer");
    203      assert.equal(
    204        timerPrefCall.args[0].data.value,
    205        false,
    206        "should set timer pref to false"
    207      );
    208    });
    209 
    210    it("should dispatch SetPref actions when Enter key is pressed on hide button", () => {
    211      const hideButton = wrapper.find("#hide-all-widgets-button");
    212 
    213      // Trigger onKeyDown handler directly with Enter key
    214      hideButton.prop("onKeyDown")({ key: "Enter", preventDefault: () => {} });
    215 
    216      const setPrefCalls = store.dispatch
    217        .getCalls()
    218        .filter(call => call.args[0]?.type === at.SET_PREF);
    219 
    220      assert.equal(
    221        setPrefCalls.length,
    222        2,
    223        "should dispatch two SetPref actions"
    224      );
    225 
    226      const listsPrefCall = setPrefCalls.find(
    227        call => call.args[0].data?.name === PREF_WIDGETS_LISTS_ENABLED
    228      );
    229      const timerPrefCall = setPrefCalls.find(
    230        call => call.args[0].data?.name === PREF_WIDGETS_TIMER_ENABLED
    231      );
    232 
    233      assert.ok(listsPrefCall, "should dispatch SetPref for lists");
    234      assert.equal(
    235        listsPrefCall.args[0].data.value,
    236        false,
    237        "should set lists pref to false"
    238      );
    239 
    240      assert.ok(timerPrefCall, "should dispatch SetPref for timer");
    241      assert.equal(
    242        timerPrefCall.args[0].data.value,
    243        false,
    244        "should set timer pref to false"
    245      );
    246    });
    247 
    248    it("should dispatch SetPref actions when Space key is pressed on hide button", () => {
    249      const hideButton = wrapper.find("#hide-all-widgets-button");
    250 
    251      // Trigger onKeyDown handler directly with Space key
    252      hideButton.prop("onKeyDown")({ key: " ", preventDefault: () => {} });
    253 
    254      const setPrefCalls = store.dispatch
    255        .getCalls()
    256        .filter(call => call.args[0]?.type === at.SET_PREF);
    257 
    258      assert.equal(
    259        setPrefCalls.length,
    260        2,
    261        "should dispatch two SetPref actions"
    262      );
    263 
    264      const listsPrefCall = setPrefCalls.find(
    265        call => call.args[0].data?.name === PREF_WIDGETS_LISTS_ENABLED
    266      );
    267      const timerPrefCall = setPrefCalls.find(
    268        call => call.args[0].data?.name === PREF_WIDGETS_TIMER_ENABLED
    269      );
    270 
    271      assert.ok(listsPrefCall, "should dispatch SetPref for lists");
    272      assert.equal(
    273        listsPrefCall.args[0].data.value,
    274        false,
    275        "should set lists pref to false"
    276      );
    277 
    278      assert.ok(timerPrefCall, "should dispatch SetPref for timer");
    279      assert.equal(
    280        timerPrefCall.args[0].data.value,
    281        false,
    282        "should set timer pref to false"
    283      );
    284    });
    285 
    286    it("should not dispatch SetPref actions when other keys are pressed", () => {
    287      const hideButton = wrapper.find("#hide-all-widgets-button");
    288 
    289      const testKeys = ["Escape", "Tab", "a", "ArrowDown"];
    290 
    291      for (const key of testKeys) {
    292        store.dispatch.resetHistory();
    293        // Trigger onKeyDown handler directly
    294        hideButton.prop("onKeyDown")({ key });
    295 
    296        const setPrefCalls = store.dispatch
    297          .getCalls()
    298          .filter(call => call.args[0]?.type === at.SET_PREF);
    299 
    300        assert.equal(
    301          setPrefCalls.length,
    302          0,
    303          `should not dispatch SetPref for key: ${key}`
    304        );
    305      }
    306    });
    307  });
    308 
    309  describe("handleToggleMaximize", () => {
    310    let wrapper;
    311    let state;
    312    let store;
    313 
    314    beforeEach(() => {
    315      state = {
    316        ...INITIAL_STATE,
    317        Prefs: {
    318          ...INITIAL_STATE.Prefs,
    319          values: {
    320            ...INITIAL_STATE.Prefs.values,
    321            [PREF_WIDGETS_LISTS_ENABLED]: true,
    322            [PREF_WIDGETS_SYSTEM_LISTS_ENABLED]: true,
    323            "widgets.maximized": false,
    324            "widgets.system.maximized": true,
    325          },
    326        },
    327      };
    328      store = createStore(combineReducers(reducers), state);
    329      sinon.spy(store, "dispatch");
    330      wrapper = mount(
    331        <Provider store={store}>
    332          <Widgets />
    333        </Provider>
    334      );
    335    });
    336 
    337    afterEach(() => {
    338      store.dispatch.restore();
    339    });
    340 
    341    it("should dispatch SetPref action when toggle button is clicked", () => {
    342      const toggleButton = wrapper.find("#toggle-widgets-size-button");
    343      assert.ok(toggleButton.exists(), "toggle button should exist");
    344 
    345      // Get the onClick handler and call it
    346      const onClickHandler = toggleButton.prop("onClick");
    347      assert.ok(onClickHandler, "onClick handler should exist");
    348      onClickHandler({ preventDefault: () => {} });
    349 
    350      const allCalls = store.dispatch.getCalls();
    351      const setPrefCalls = allCalls.filter(
    352        call => call.args[0]?.type === at.SET_PREF
    353      );
    354 
    355      assert.equal(
    356        setPrefCalls.length,
    357        1,
    358        `should dispatch one SetPref action, got ${setPrefCalls.length}.`
    359      );
    360 
    361      const maximizedPrefCall = setPrefCalls.find(
    362        call => call.args[0].data?.name === "widgets.maximized"
    363      );
    364 
    365      assert.ok(maximizedPrefCall, "should dispatch SetPref for maximized");
    366      assert.equal(
    367        maximizedPrefCall.args[0].data.value,
    368        true,
    369        "should toggle maximized pref to true"
    370      );
    371    });
    372 
    373    it("should dispatch SetPref action when Enter key is pressed on toggle button", () => {
    374      const toggleButton = wrapper.find("#toggle-widgets-size-button");
    375 
    376      // Trigger onKeyDown handler directly with Enter key
    377      toggleButton.prop("onKeyDown")({
    378        key: "Enter",
    379        preventDefault: () => {},
    380      });
    381 
    382      const setPrefCalls = store.dispatch
    383        .getCalls()
    384        .filter(call => call.args[0]?.type === at.SET_PREF);
    385 
    386      assert.equal(
    387        setPrefCalls.length,
    388        1,
    389        "should dispatch one SetPref action"
    390      );
    391 
    392      const maximizedPrefCall = setPrefCalls.find(
    393        call => call.args[0].data?.name === "widgets.maximized"
    394      );
    395 
    396      assert.ok(maximizedPrefCall, "should dispatch SetPref for maximized");
    397      assert.equal(
    398        maximizedPrefCall.args[0].data.value,
    399        true,
    400        "should toggle maximized pref to true"
    401      );
    402    });
    403 
    404    it("should dispatch SetPref action when Space key is pressed on toggle button", () => {
    405      const toggleButton = wrapper.find("#toggle-widgets-size-button");
    406 
    407      // Trigger onKeyDown handler directly with Space key
    408      toggleButton.prop("onKeyDown")({ key: " ", preventDefault: () => {} });
    409 
    410      const setPrefCalls = store.dispatch
    411        .getCalls()
    412        .filter(call => call.args[0]?.type === at.SET_PREF);
    413 
    414      assert.equal(
    415        setPrefCalls.length,
    416        1,
    417        "should dispatch one SetPref action"
    418      );
    419 
    420      const maximizedPrefCall = setPrefCalls.find(
    421        call => call.args[0].data?.name === "widgets.maximized"
    422      );
    423 
    424      assert.ok(maximizedPrefCall, "should dispatch SetPref for maximized");
    425      assert.equal(
    426        maximizedPrefCall.args[0].data.value,
    427        true,
    428        "should toggle maximized pref to true"
    429      );
    430    });
    431 
    432    it("should not dispatch SetPref actions when other keys are pressed", () => {
    433      const toggleButton = wrapper.find("#toggle-widgets-size-button");
    434 
    435      const testKeys = ["Escape", "Tab", "a", "ArrowDown"];
    436 
    437      for (const key of testKeys) {
    438        store.dispatch.resetHistory();
    439        // Trigger onKeyDown handler directly
    440        toggleButton.prop("onKeyDown")({ key });
    441 
    442        const setPrefCalls = store.dispatch
    443          .getCalls()
    444          .filter(call => call.args[0]?.type === at.SET_PREF);
    445 
    446        assert.equal(
    447          setPrefCalls.length,
    448          0,
    449          `should not dispatch SetPref for key: ${key}`
    450        );
    451      }
    452    });
    453 
    454    it("should toggle from maximized to minimized state", () => {
    455      // Update state to start with maximized = true
    456      const maximizedState = {
    457        ...INITIAL_STATE,
    458        Prefs: {
    459          ...INITIAL_STATE.Prefs,
    460          values: {
    461            ...INITIAL_STATE.Prefs.values,
    462            [PREF_WIDGETS_LISTS_ENABLED]: true,
    463            [PREF_WIDGETS_SYSTEM_LISTS_ENABLED]: true,
    464            "widgets.maximized": true,
    465            "widgets.system.maximized": true,
    466          },
    467        },
    468      };
    469      const maximizedStore = createStore(
    470        combineReducers(reducers),
    471        maximizedState
    472      );
    473      sinon.spy(maximizedStore, "dispatch");
    474      const maximizedWrapper = mount(
    475        <Provider store={maximizedStore}>
    476          <Widgets />
    477        </Provider>
    478      );
    479 
    480      const toggleButton = maximizedWrapper.find("#toggle-widgets-size-button");
    481      toggleButton.prop("onClick")({ preventDefault: () => {} });
    482 
    483      const setPrefCalls = maximizedStore.dispatch
    484        .getCalls()
    485        .filter(call => call.args[0]?.type === at.SET_PREF);
    486 
    487      const maximizedPrefCall = setPrefCalls.find(
    488        call => call.args[0].data?.name === "widgets.maximized"
    489      );
    490 
    491      assert.ok(maximizedPrefCall, "should dispatch SetPref for maximized");
    492      assert.equal(
    493        maximizedPrefCall.args[0].data.value,
    494        false,
    495        "should toggle maximized pref to false"
    496      );
    497 
    498      maximizedStore.dispatch.restore();
    499    });
    500  });
    501 });