How to determine type when an Ember Array is passed in?

I would really like for my component to work with strings, arrays and Ember Arrays. But I run into a problem when the type is Ember Array.

The problem is with this line: let local = typeof input === ‘string’ ? [input] : input; So, how do I test for types?

Promise rejected during “it handles a trail as an Ember Array”: Assertion Failed: Cannot call meta on string@ 23 ms Source: Error: Assertion Failed: Cannot call meta on string

component

  // split up crumb by -, _, and space; discard empties.
  // Capitalize the first letter and each letter preceded by a space.
  // Glue the bits with spaces.
  transformPath(input) {
    if (!input) return '';

    let local = typeof input === 'string' ? [input] : input;

    const transformedSegments = local.map((crumb) => {
      crumb = this.stripOutAllHexSections(crumb);
      crumb = this.addSpaceBetweenAdjacentWords(crumb);
      return crumb
        .split(/[-_ ]/)
        .filter(Boolean)
        .map((word) => this.capitalizeFirstLetter(word))
        .join(' ');
    });
    return transformedSegments.join(' > ');
  }

  get breadCrumb() {
    return this.transformPath(this.args.model);
  }

  <template>
    <div
      class='w-full bg-slate-200 pb-[.3rem] pl-3 text-blue-900 font-semibold text-lg'
      ...attributes
    >{{this.breadCrumb}}</div>
  </template>
}

Intended tests

  test('it handles a specific path with hex section (3)', async function (assert) {
    // Render the component with the specific path
    const crumbs = [
      'some path',
      'someOtherPath-0123456789abcdefFEDCBA9876543210',
    ];
    await render(<template><BreadCrumb @model={{crumbs}} /></template>);

    // Check that the breadcrumb is correctly formatted
    assert.dom(this.element).hasText('Some Path > Some Other Path');
  });

  test('it handles a trail as a string', async function (assert) {
    // Render the component with a URL without a leading /
    const crumb = 'invoicing';
    await render(<template><BreadCrumb @model={{crumb}} /></template>);

    // Check that the breadcrumb is correctly formatted
    assert.dom(this.element).hasText('Invoicing');
  });

  test('it handles a trail as an Ember Array', async function (assert) {
    // Render the component with a URL without a leading /
    const crumb = A('invoicing');
    await render(<template><BreadCrumb @model={{crumb}} /></template>);

    // Check that the breadcrumb is correctly formatted
    assert.dom(this.element).hasText('Invoicing');
  });

Assuming this line is the problem then can you flip the check here?

let local = Array.isArray(input) ? input : [input];

I think that would work fine based on a quick twiddle test:

    const ea = A([1,2,3,4,5]);
    const na = [1,2,3,4,5];
    const st = 'abcdef';
    return [Array.isArray(ea), Array.isArray(na), Array.isArray(st)] 
    // [true, true, false]

That said I also couldn’t reproduce any issues with your original code in the Twiddle. Are you sure that line is the problem?

NVM i see… in the test you’re passing in a string to the A() constructor which for some reason doesn’t actually return an array as far as i can tell, it returns a string.

    const a = A('invoicing');
    Array.isArray(a); // => false
    typeof a; // => 'string'

This is a little unexpected to me but I think what it means is that as long as your Ember array is actually an Ember array your code should work. The problem is the result of A('some string') is a string and not an array?

Thank you for your insight.

Making it a JS array inside the ember array constructor allows the component to work with an Ember Array.

const crumb = A([‘HaveANiceDay’]);

This works:

  test('it handles a trail as an Ember Array (5)', async function (assert) {
    // spent ALL day trying to bread crumb work with an Ember Array.
    // Render the component with a URL without a leading /
    const crumb = A(['HaveANiceDay']);
    await render(<template><BreadCrumb @model={{crumb}} /></template>);

    // Check that the breadcrumb is correctly formatted
    assert.dom(this.element).hasText('Have A Nice Day');
  });
1 Like