Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add function to generate and compare marble diagrams #96

Open
daerogami opened this issue Nov 21, 2023 · 0 comments
Open

Add function to generate and compare marble diagrams #96

daerogami opened this issue Nov 21, 2023 · 0 comments

Comments

@daerogami
Copy link

daerogami commented Nov 21, 2023

This might be out-of-scope for this package, but I find myself wanting some debugging tooling to inspect what character(s) I am missing in my marble diagrams. The provided snippet is basically the reverse of the notification mappings and it seems to generate the marble diagrams I am expecting. There are still scenarios I am not accounting for such as emissions within the same frame and using parenthesis, but this is massively helpful when trying to reason about more complex observables that may have multiple pipe operators. I can't find any existing utility packages that already do this.

import { getTestScheduler } from 'jasmine-marbles';
import { Observable } from 'rxjs';

export function createMarbleDiagram<T>(
  source: Observable<T>,
  values: Record<string, T>
): Array<string> {
  const scheduler = getTestScheduler();
  let diagram: Array<string> = [];
  let lastFrame = scheduler.frame;

  source.subscribe({
    next: (value: T) => {
      appendFrames(scheduler.frame-lastFrame, diagram);
      lastFrame = scheduler.frame;
      diagram.push(
        Object.keys(values).find((key) => values[key] === value) || '?'
      );
    },
    error: (error) => {
      appendFrames(scheduler.frame-lastFrame, diagram);
      lastFrame = scheduler.frame;
      diagram.push('#');
    },
    complete: () => {
      appendFrames(scheduler.frame-lastFrame, diagram);
      lastFrame = scheduler.frame;
      diagram.push('|');
    },
  });

  return diagram;
}

function appendFrames(frameDuration: number, diagram: Array<string>) {
  const lastEmissionDeduction = diagram.length ? 10 : 0;
  const frames = Math.floor((frameDuration - lastEmissionDeduction)/10);
  for(let i = 0; i < frames; i++) {
    diagram.push('-');
  }
}

Here is a really simple test from my angular project using this method to debug

  it('should combine data from DataService and an additional source in the correct order', () => {
    const values = { a: { name: 'Test Data 1' }, b: { name: 'Test Data 2' } };
    let source1 = cold('-a---|', values);
    let source2 = cold('---b-|', values);
    someHttpService.getData.and.returnValue(source1);
    someHttpService.getMoreData.and.returnValue(source2);

    const expectedObservable = cold('-a-b-|', values);

    const result = component.getSequentialDataFromHttp();

    const diagram = createMarbleDiagram(result, values); // Debug
    expect(result).toBeObservable(expectedObservable);

    getTestScheduler().flush();
    console.debug(`Expect marble: -a-b-|`); // Debug
    console.debug(`Actual marble: ${diagram.join('')}`); // Debug
  });

which results in the output

DEBUG: 'Expect marble: -a-b-|'
DEBUG: 'Actual marble: -a-b-|'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant