vue.jspiniavitest

Vue, pinia plugin testing with vitest store.$subscribe not working as expected


I am creating a pinia plugin to do basic momentum patern undo/redo on the store.

My code is working well in the application, but I cannot make the test working.

I create the app and use the plugin in pinia:

describe('UndoRedoPlugin', () => {
  beforeEach(() => {
    const app = createApp({});
    const pinia = createPinia();
    pinia.use(UndoRedoPlugin);
    app.use(pinia);
    setActivePinia(pinia);
  });

Then in my test I define a store (which is a simple counter) and when I call an action (increment) it should also call the plugin update, but I have the impression it is not calling, and it seems to me like the reactivity of the store is not working.

here is the test:

it('Allows undo when store is modified', () => {
    const useCounterStore = defineStore('counter', {
      state: () => ({ count: 0 }),
      actions: {
        increment() {
          this.count++;
        },
      },
      undoRedoPluginSettings: { max: 3 },
    });

    const counter = useCounterStore();

    expect(counter.canUndo).toBe(false);

    console.log('increment 1');
    counter.increment();
    expect(counter.count).toBe(1);

    console.log('increment 2');
    counter.increment();
    expect(counter.count).toBe(2);

    // Should be true. <<< ----------------- H E R E
    expect(counter.canUndo).toBe(true);
  });

Here you can play with the application, and with the tests as well: https://stackblitz.com/edit/vitejs-vite-txqjhe?file=src/pinia-plugins/UndoRedoPlugin.test.js

Note: for the tests to run, just go to terminal and run npm run test


Solution

  • I've finally found the solution:

    I had to add the extra option flush: 'sync' to store.$subscribe.

    The flush option does not affect calls to store.$patch() and this fixed my problem.

    store.$subscribe(
       (mutation, state) => {
            ...
       },
       { flush: 'sync' } <<< ----------- HERE
    );