Select to view content in your preferred language

reactiveUtils.watch() on a custom class?

216
4
Jump to solution
3 weeks ago
fdeters
Regular Contributor

I'm starting to lean more on `reactiveUtils.watch()` for reactivity that isn't easily handled by my JavaScript framework. Generally, things are going well, but I'm running into an issue with unit/integration tests:

A common issue is that I will want to stub or mock a JS SDK class. For example, I frequently create a fake WebMap with fake layers:

class FakeLayer {
  constructor({ id, listMode, visible, type }) {
    this.id = id;
    this.listMode = listMode;
    this.visible = visible;
    this.type = type;
  }

  when = async () => true;
}

const fakeWebMap = {
    allLayers: [
      new FakeLayer({
        id: 'layer-1',
        listMode: 'hide',
        visible: true,
      }),
      new FakeLayer({
        id: 'layer-2',
        listMode: 'hide',
        visible: false,
      }),
      new FakeLayer({
        id: 'layer-3',
        listMode: 'show',
        visible: true,
      }),
};

 

My problem is this: reactiveUtils.watch() does not seem to work on POJOs or custom classes like FakeLayer above.

In the example above, I might be testing code that watches the `visible` property on each FakeLayer and mutates `listMode` if `visible` changes. How can I implement a mock/stub testing class that works with reactiveUtils.watch()?

0 Kudos
1 Solution

Accepted Solutions
JoelBennett
MVP Regular Contributor
4 Replies
JoelBennett
MVP Regular Contributor

Have you considered extending the Accessor class?  See also https://developers.arcgis.com/javascript/latest/implementing-accessor/

fdeters
Regular Contributor

This looks like exactly the starting point I was looking for, thanks. I'll come back and accept as solution once I've seen if it works for what I need.

0 Kudos
JoelBennett
MVP Regular Contributor

Did this end up working out, or did you find something else more suitable?

0 Kudos
fdeters
Regular Contributor

Actually, yes! I just got it to work moments ago. I used this section of the article you linked: https://developers.arcgis.com/javascript/latest/implementing-accessor/#define-a-simple-property

Here's what my solution looks like for setting up a single property that I can use reactiveUtils.watch() on:

const MyCustomClass = Accessor.createSubclass({
  constructor: function () {
    this.myProperty = null;
  },

  properties: {
    myProperty: {},
  },
});

 

I wanted to use native classes, but neither of the following were working for me (I'm not using TypeScript):

// native class using the @property decorator
class MyCustomClass extends Accessor {
  @property
  state = null;
}

// native class, no decorators
class MyCustomClass extends Accessor {
  constructor() {
    super(...arguments);
    this.myProperty= null;
  }

  properties = {
    myProperty: {},
  };
}