mobxjs / mobx

Simple, scalable state management.
http://mobx.js.org
MIT License
27.48k stars 1.77k forks source link

[mobx] Cannot obtain atom from [object Object] #3546

Closed GayathriMaalige closed 1 year ago

GayathriMaalige commented 1 year ago

Hi, Please find my code.

// BaseRouteView.tsx file
import * as React from 'react';
import { routeNode, RouteView } from 'react-mobx-router5';
import { inject, observer } from 'mobx-react';
import {
  GlobalRouterStore,
  GlobalStore,
  DashboardStore,
  UserGroupStore
} from '@shared/stores';
import './base-route-view.scss';
import { Lambda, observe } from 'mobx';

export interface IBaseRouteViewProps {
  routerStore?: GlobalRouterStore;
  globalStore?: GlobalStore;
  dashboardStore?: DashboardStore;
  userGroupStore?: UserGroupStore;
}

@inject('routerStore', 'globalStore', 'dashboardStore', 'userGroupStore')
@observer
export class BaseRouteView extends React.Component<IBaseRouteViewProps> {

  userGroupStore: UserGroupStore;
  routerStore: GlobalRouterStore;
  userGroupStoreDisposer: Lambda;
  globalStoreDisposer: Lambda;
  permissionAuth: boolean = false;
  userSitesPermission:boolean = false;
  routerStoreDisposer: Lambda;

  constructor(props: IBaseRouteViewProps) {
    super(props);

    this.userGroupStore = this.props.userGroupStore!;
    this.routerStore = this.props.routerStore!;
    this.userGroupStoreDisposer = observe(this.userGroupStore, 'permissions', _change => {
      this.permissionAuth = true;
      }else {
        this.checkAuthorization();  
      }

    });

    this.globalStoreDisposer = observe(this.props.globalStore!, 'userSites', _change => {   
      this.userSitesPermission = true;      
      this.checkAuthorization(); 
    });

    this.routerStoreDisposer = observe(this.routerStore!, 'route',  _change => {    
      if(_change.type === 'update')  {
         this.checkAuthorization();
      }      
    }); 
  }

componentWillUnmount() {
    if(this.userGroupStoreDisposer!==undefined) {
      this.userGroupStoreDisposer();
    }

    if(this.globalStoreDisposer!==undefined) {
      this.globalStoreDisposer();
    }

    if(this.routerStoreDisposer!==undefined) {
      this.routerStoreDisposer();
    }
  }

// BaseRouteView.spec.tsx file
import * as React from 'react';
import { render,cleanup, } from '@testing-library/react';
import { RouteView } from 'react-mobx-router5';
import { GlobalRouterStore,rootStore } from '@honeywell/shared/stores';
import { BaseRouteView } from './base-route-view';
import { Provider } from 'mobx-react';

afterEach(cleanup);

const renderWithStore = () =>{
    return render(
      <Provider {...rootStore}><BaseRouteView /></Provider>
    )};
describe('<BaseRouteView />', () => {
    rootStore.routerStore = { navigate: jest.fn(), route: { name: 'login' } } as any as GlobalRouterStore;
    beforeEach(() => {
        (rootStore.routerStore.navigate as jest.Mock).mockReset();
    });
    it('renders without crashing', () => {
        renderWithStore();
    });
});

When I am running 'yarn jest' I am getting the below error

image

urugator commented 1 year ago

rootStore.routerStore = { navigate: jest.fn(), route: { name: 'login' } } as any as GlobalRouterStore;

You're replacing observable routerStore with non-oservable plain object - obviously observe won't work with non-observable.

GayathriMaalige commented 1 year ago

Hi, Thank you for your reply. We have declared GlobalRouterStore as below

image

How can we declare the routerStore as an observable and also ensure mocking the route

rootStore.routerStore = { navigate: jest.fn(), route: { name: 'login' } } as any as GlobalRouterStore;

How can the above code be written in the spec.tsx file

urugator commented 1 year ago

Either replace routerStore with a mock that is itself observable (make it observable in the same way as original) or mock/replace only methods/props of the existing already observable routerStore. Just keep in mind that re-defining prop/method will loose it's observable properties/action. For that reason mobx won't let you do it by default, you have to configure({ safeDescriptors: false }).

GayathriMaalige commented 1 year ago

Thank you so much. We could resolve our problem with your inputs.