2

I get an InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe' error on the unit test when I use the | async pipe in the template.

Tried to solve this with tick, fakeAsync and whenStable but that did not work.

When I remove the | async part in the template, the error disappears and the unit test works but this time the code doesn't work. I need to use the | async in the template to let the code work.

How can I solve this InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe' error?

Template:

<ngb-accordion  
    [closeOthers]="true"  
    [activeIds]="setActiveAcc()">
    <div *ngFor="let child of el?.children | async; let i = index">
        <ngb-panel id="{{(child?.value?.properties | async)?.style.includes('OpenAcc')}}-{{i}}">
            <ng-template ngbPanelHeader>
                <div class="d-flex align-items-center justify-content-between">
                    <button ngbPanelToggle class="btn btn-link container-fluid text-left">
                        {{ (child?.value?.properties | async)?.content}}
                    </button>
                </div>
            </ng-template>
            <ng-template ngbPanelContent>
                <tst-element [item]="child"></tst-element>
            </ng-template>
        </ngb-panel>
    </div>
</ngb-accordion>

Component:

export class AccComponent implements OnInit {
    constructor(
      public el: ItemModelTree
    ) {}

    @Input() childrens: Array<any> = [];

    ngOnInit() {
        this.el.children.pipe(
          mapObservableArray((children: ObservableTree<ItemModel>) => children.value.properties))
            .subscribe((props: Properties[]) => {
            this.childrens = props as any;
        });
    }

    setActiveAcc() {
        if (this.childrens.find((child: any) => child.style.includes('OpenAcc'))) {
          const activeAcc = this.childrens.findIndex((child: any) => child.style.includes('OpenAcc'));
          return 'true-' + activeAcc;
        } else {
            return 'false'
        }
    }
}

Unit test:

import { NO_ERRORS_SCHEMA } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { ItemModelTree } from './core';
import { AccComponent } from './accordion.component';
import { of } from 'rxjs';

describe('accardion component', () => {
  const itemModel = {
    value: {
      name: 'accordion'
    },
    children: [
      {
        id: 'acc-1',
        value: {
          properties: [
            {
              content: 'test',
              style: ['OpenAcc']
            }
          ]
        }
      }
    ],
  };
  const mockTree = jasmine.createSpyObj('el', itemModel);
  mockTree.children = of(itemModel.children);
  
  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [],
      declarations: [AccComponent],
      providers: [
        { provide: ItemModelTree, useValue: mockTree }
      ],
      schemas: [NO_ERRORS_SCHEMA],
    }).compileComponents();
  });

  it('should set the activeAccordion to true', async () => {
    const fixture = TestBed.createComponent(AccComponent);
    const componentInst = fixture.componentInstance;

    (componentInst as any).tree = {
      children: of([
        {
          id: 'acc-1',
          value: {
            properties: [
              {
                label: 'test',
                styles: ['OpenAcc']
              }
            ]
          }
        }
      ])
    };

    fixture.detectChanges();
    
    
    expect(componentInst).toBeDefined();
    expect(componentInst.setActiveAcc()).toEqual('true-0');
  });
});

How to solve the InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe' error by using the | async pipe?

Can
  • 553
  • 1
  • 9
  • 29

1 Answers1

0

Inside itemModel mock you need to make properties: of(/* your data */) because of these lines in the template: child?.value?.properties | async.

vadimk7
  • 6,559
  • 1
  • 12
  • 15
  • The properties are there inside the `children.value.properties`. I can solve the issue by removing the async and translate the observables to an array. But I want to use the Observable. – Can Aug 03 '20 at 12:44
  • yep and they should be an observable because in the template you are using async pipe to access theirs values – vadimk7 Aug 03 '20 at 12:48
  • the problem is in your mock for `itemModel`, just make the `properties` observable and the error gone – vadimk7 Aug 03 '20 at 12:49
  • how to make the properties an observable? by adding `of` ? – Can Aug 03 '20 at 12:59
  • yeah, [doc](https://rxjs-dev.firebaseapp.com/api/index/function/of) – vadimk7 Aug 03 '20 at 13:00