簡體   English   中英

開玩笑測試某個組件是否清除了 Session 存儲

[英]Jest to Test that a Component Cleared the Session Storage

我正在嘗試測試一個組件,看看我是否可以清除 session 存儲。 我正在使用 Jest 進行測試。 我有一條線不想通過測試。 我不知道如何確保它正在測試 sessionStorage 是清楚的。 我已經嘲笑了它,並且 function 可以工作,但是測試仍然失敗了一行。 有誰知道如何讓這條線通過?

LogOutForDisagreement.js

import React from 'react';
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
import ClipboardClip from './../ClipboardClip';

const store = require('store2');

function LogOutForDisagreement(props) {
    const handleClick = (e) => {
        e.preventDefault();
        props.onChange(
            props.props.user = {
                loggedIn: false,
                email: '',
                password: '',
                firstName: ''
            },
        );
        store.clearAll();   
    };
    return (
        <div id="logOutForDisagreementClipboard" className={props.className}>
            <Form className="form">
                <ClipboardClip />
                <div className="centeredPaper">
                    <p>Sorry, you must agree to our privacy policy to access the site. You must now log out and log back in to agree to the terms.</p>
                    <Button id="logOutForDisagreement" type="" onClick={handleClick}>
                        Log Out
                    </Button>
                </div>
            </Form>
        </div>
    );
}
export default LogOutForDisagreement;

測試 LogOutForDisagreement.test.js

import React from 'react';
import { render, fireEvent, cleanup } from '@testing-library/react';
import toJson from 'enzyme-to-json';
import LogOutForDisagreement from './LogOutForDisagreement';
import store from 'store2';

const fakeLocalStorage = (function() {
    let storage = {"firstName": "Nathaniel", "email":"exampleFirstName.exampleLastName@example.com","timeOfLogin":"1657937069720","id":"bee89ba2-da07-4712-acd2-e8236660bb13"};
  
    return {
      getItem: function(key) {
        return storage[key] || null;
      },
      setItem: function(key, value) {
        storage[key] = value.toString();
      },
      removeItem: function(key) {
        delete storage[key];
      },
      clearAll: function() {
        storage = {};
      },
      getAll() {
        return storage;
      },
    };
  })();
describe('Test the log out for disagreement button', () =>{
    beforeAll(() => {
        Object.defineProperty(window, 'sessionStorage', {
          value: fakeLocalStorage,
        });
    });
    it('renders correctly enzyme and has onclick', () => {

        const { getByText } = render(<LogOutForDisagreement />);

        fireEvent.click(getByText("Log Out"));

        window.sessionStorage.clearAll();

        const allItems = window.sessionStorage.getAll();
        console.log("These are all the items in sessionStorage: " + JSON.stringify(allItems));
        console.log("These are the number of items: " + Object.keys(allItems).length);


        expect(Object.keys(allItems).length).toBe(0);
        expect(toJson(getByText)).toMatchSnapshot();
    });
});

我得到以下信息:

--------------------------|---------|----------|---------|---------|-------------------
File                      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
--------------------------|---------|----------|---------|---------|-------------------
All files                 |   83.33 |      100 |     100 |   83.33 |
 LogOutForDisagreement.js |   83.33 |      100 |     100 |   83.33 | 19
--------------------------|---------|----------|---------|---------|-------------------

所以第19行基本上是window.sessionStorage.clearAll(); ,但我不知道如何測試它。 我有幾個問題:

  • 我是否應該包含我希望它在模擬中清除的數據?
  • 我可以清除數據,但是如何測試store.clearAll(); 那實際上是這樣做的嗎?
  • 為什么 function 中的所有其他行都通過測試時,此行沒有測試?

編輯:所以,現在我正在嘗試使用 jest-localstorage-mock,但我不斷收到以下錯誤:

 ● Test the log out for disagreement button › renders correctly enzyme and has onclick

    ReferenceError: dispatch is not defined

      85 |     //expect(sessionStorage.clear).toHaveBeenCalledTimes(1);
      86 |
    > 87 |     dispatch(action.reset());
         |     ^
      88 |     expect(sessionStorage.clear).toHaveBeenCalledTimes(1);
      89 |     expect(sessionStorage.__STORE__).toEqual({}); // check store values
      90 |     expect(sessionStorage.length).toBe(0); // or check length

此調用應該檢查商店現在是否已清除,但我仍然顯示該行沒有被覆蓋:

 src/components/privacyPolicyComponents     |   24.44 |        0 |   21.05 |   24.44 |
  LogOutForDisagreement.js                  |    87.5 |      100 |     100 |    87.5 | 19

我按照 package 中的說明進行操作,但我仍然不知道出了什么問題。

需要在測試文件中導入package嗎? 我找不到辦法做到這一點。 我把更新的文件放在下面:

LogOutForDisagreement.js

import React from 'react';
import Form from 'react-bootstrap/Form';
import Button from 'react-bootstrap/Button';
import ClipboardClip from './../ClipboardClip';

const store = require('store2');

function LogOutForDisagreement(props) {
    const handleClick = (e) => {
        e.preventDefault();
        props.onChange(
            props.props.user = {
                loggedIn: false,
                email: '',
                password: '',
                firstName: ''
            },
        );
        store.clearAll();

    };
    return (
        <div id="logOutForDisagreementClipboard" className={props.className}>
            <Form className="form">
                <ClipboardClip />
                <div className="centeredPaper">
                    <p>Sorry, you must agree to our privacy policy to access the site. You must now log out and log back in to agree to the terms.</p>
                    <Button id="logOutForDisagreement" type="" onClick={handleClick}>
                        Log Out
                    </Button>
                </div>
            </Form>
        </div>
    );
}

export default LogOutForDisagreement;

LogOutForDisagreement.test.js

import React from 'react';
import { render, fireEvent, cleanup } from '@testing-library/react';
import toJson from 'enzyme-to-json';
import LogOutForDisagreement from './LogOutForDisagreement';
import store from 'store2';
//import { dispatch, action, reset } from 'jest-localstorage-mock';

let props = {
  props:
  {
    user: {
      loggedIn: false,
      email: 'email@example.com',
      password: '0cc3dd4ad221f83270f876908064fa67d43407aa4bd580731b30c58c4fe2d8de00464107e5a143594068461af21ece9fb542e2f254b6f895eea6a6627f4f7c438a42fb18af7f539c4be2456661a5beec4a561f9443988182445b3952a5d9321a2d725b24b151f79a2806432c848b0b0c02576676e3a5c6f0661b4e318ca4f3e134d066808fab8fdd5322ed5cf5ad68aae43254a8fefdb69809c1bfdc07fe0365f38baa424d0c059c3a9fbff1f3525dae410740b9719929ef3f34235da519591f0410a08438132600fa802079b8d6f372f6dc439eb1b100aed28bb55cc3c6dc8982644940bd506278943fa8e430836cb874283e9f4438aac04a817f86bd1606036f03d196a211bdd91ac683d4ec63fcd503aa97b53d5c2571d39855b2be5f77be80a7f767271c8789aec26c66530c22387007c704f96b1a76a47e8e13fb263a0a6b24b2959495d34b47e03bcb95e8af13b555c5c403ec01427182afa1bae35ff81224b051fde7a61bd9044ed74042444a05e06186eedacc38c0128ff7d70c',
      firstName: 'FirstName'
    },
    className: "logOutForDisagreement"
  }
};

describe('Test the log out for disagreement button', () => {
  beforeAll(() => {
    store.setAll({ "firstName": "FirstName", "email": "email@example.com", "timeOfLogin": "1657937069720", "id": "0cc3dd4ad221f83270f876908064fa67d43407aa4bd580731b30c58c4fe2d8de00464107e5a143594068461af21ece9fb542e2f254b6f895eea6a6627f4f7c438a42fb18af7f539c4be2456661a5beec4a561f9443988182445b3952a5d9321a2d725b24b151f79a2806432c848b0b0c02576676e3a5c6f0661b4e318ca4f3e134d066808fab8fdd5322ed5cf5ad68aae43254a8fefdb69809c1bfdc07fe0365f38baa424d0c059c3a9fbff1f3525dae410740b9719929ef3f34235da519591f0410a08438132600fa802079b8d6f372f6dc439eb1b100aed28bb55cc3c6dc8982644940bd506278943fa8e430836cb874283e9f4438aac04a817f86bd1606036f03d196a211bdd91ac683d4ec63fcd503aa97b53d5c2571d39855b2be5f77be80a7f767271c8789aec26c66530c22387007c704f96b1a76a47e8e13fb263a0a6b24b2959495d34b47e03bcb95e8af13b555c5c403ec01427182afa1bae35ff81224b051fde7a61bd9044ed74042444a05e06186eedacc38c0128ff7d70c" });
  });


  it('renders correctly enzyme and has onclick', () => {

    const { getByText } = render(<LogOutForDisagreement id="logOutForDisagreementClipboard" className={props.className} />);

    fireEvent.click(getByText("Log Out"));

    dispatch(action.reset());
    expect(sessionStorage.clear).toHaveBeenCalledTimes(1);
    expect(sessionStorage.__STORE__).toEqual({}); // check store values
    expect(sessionStorage.length).toBe(0); // or check length

    expect(Object.keys(allItems).length).toBe(0);

    expect(toJson(getByText)).toMatchSnapshot();
  });
});

編輯:我包括index.d.ts的 index.d.ts 的內容。 如果您想查看完整的 package,它位於 npm 注冊表: https://www.npmjs.com/package/store2/ 我還更新了上面的最后一個文件,並包含了jest-localstorage-mock的配置,但是我仍然收到關於 dispatch not defined 的錯誤,但是當我在dispatch之前添加store時,我可以得到 go 的錯誤,所以它是store.dispatch ,但隨后我收到另一個關於未定義操作的錯誤。 我想出了如何定義action ,但后來我收到一個關於reset的錯誤,我無法到達 go 。

index.d.ts

export interface StoredData {
  [key: string]: any;
}
export type Replacer = (key: any, value: any) => string | String[] | number[];
export type Reviver = (key: string, value: any) => any;
export type EachFn = (key: any, data: any) => false | any;
export type TransactFn = (data: any) => any | undefined;

type BaseSet = (key: any, data: any) => any;
type BaseGet = (key: any) => any;
type BaseSetAll = (obj: Object) => StoredData;
type BaseGetAll = () => StoredData;
type BaseTransact = (fn: EachFn, value?: any) => StoredData;
type BaseClear = (clear: false) => StoreBase;
export type Base = BaseSet & BaseGet & BaseSetAll & BaseGetAll & BaseTransact & BaseClear;

export interface StoreAPI {
  clear(): StoreBase;
  clearAll(): StoreBase;
  each(callback: EachFn): StoreBase;
  get(key: any, alt?: any|Reviver): any;
  getAll(fillObj?: StoredData): StoredData;
  has(key: any): boolean;
  isFake(force?: boolean): boolean;
  keys(fillList?: string[]): string[];
  namespace(namespace: string, noSession?: true): StoreType;
  remove(key: any, alt?: any|Reviver): any;
  set(key: any, data: any, overwrite?: boolean|Replacer): any;
  setAll(data: Object, overwrite?: boolean|Replacer): StoredData;
  add(key: any, data: any): any;
  size(): number;
  transact(key: any, fn: TransactFn, alt?: any|Reviver): StoreBase;
  area(id: string, area: Storage): StoreBase
}

export type StoreBase = StoreAPI & Base;

export type StoreType = StoreBase & {
  local: StoreBase;
  session: StoreBase;
  page: StoreBase;
};

declare const store: StoreType
export default store

package.json

{
  "name": "client",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
...
  },
  "devDependencies": {
    "jest-localstorage-mock": "^2.4.22"
  },
  "jest": {
    "resetMocks": false
  }
}

setupTests.js

require('jest-localstorage-mock');

FWIW @Sandog,我嘗試了您使用的方法,但無法使其正常工作,盡管我的用例與您的用例有些不同。 當用戶選擇不同的投資組合時,我們會清除(graphQL)緩存,以便新的投資組合可以使用(所有數據更改)。 因此,對於我的測試,我需要做的就是設置並確保實際調用了client.resetStore() function。 我是這樣做的:

 it('responds to ribbonName clicks', async () => {
    // setup the mocked resetStore() and test it.
    // Things didn't work as expected sometimes 
    // so I wanted to make sure it was setup properly :=))
    const mockResetStore = jest.fn();
    client.resetStore = mockResetStore;
    expect(mockResetStore).not.toHaveBeenCalled();

    // setup and issue the call the EntityRibbon component
    const myInitialState = {...initialState};
    myInitialState.entitiesList.push(...testEntities);
    const providerValue = {state: myInitialState, dispatch: () => {}};
    await render(
      <AppContext.Provider value={providerValue}>
        <EntityRibbon />
      </AppContext.Provider>
    );

    // Another check to make sure the mock is working correctly
    expect(mockResetStore).not.toHaveBeenCalled();

    // find and click the portfolio names on the EntityRibbon
    R.pluck('ribbonName', testEntities).forEach(async ribbonName => {
      const ribbonElement = await screen.getByText(ribbonName);
      expect(ribbonElement).toBeInTheDocument();
      await fireEvent.click(ribbonElement);
      // Ensure that client.resetStore() was actually called as expected
      expect(client.resetStore).toHaveBeenCalled();
    });
 })

也許這會有所幫助...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM