import { describe, expect, it } from 'vitest';
import { snakeCase } from './snakeCase';

describe('snakeCase', () => {
  const strings = ['foo bar', 'Foo bar', 'foo Bar', 'Foo Bar', 'FOO BAR', 'fooBar', '--foo-bar--', '__foo_bar__'];

  it(`should convert \`string\``, () => {
    const actual = strings.map(string => snakeCase(string));

    const expected = strings.map(() => 'foo_bar');

    expect(actual).toEqual(expected);
  });

  it('should convert string to snake case, identical to lodash', () => {
    expect(snakeCase('åäöÅÄÖ')).toBe('aao_aao');
    expect(snakeCase('helloÅäöWorld')).toBe('hello_aao_world');
    expect(snakeCase('café')).toBe('cafe');
    expect(snakeCase('naïve')).toBe('naive');
    expect(snakeCase('Zürich')).toBe('zurich');
    expect(snakeCase('São Paulo')).toBe('sao_paulo');
    expect(snakeCase('Москва')).toBe('москва');
  });

  it(`should handle double-converting strings`, () => {
    const actual = strings.map(string => snakeCase(snakeCase(string)));

    const expected = strings.map(() => 'foo_bar');

    expect(actual).toEqual(expected);
  });

  it(`should remove contraction apostrophes`, () => {
    const postfixes = ['d', 'll', 'm', 're', 's', 't', 've'];

    ["'", '\u2019'].forEach(apos => {
      const actual = postfixes.map(postfix => snakeCase(`a b${apos}${postfix} c`));

      const expected = postfixes.map(postfix => `a_b${postfix}_c`);

      expect(actual).toEqual(expected);
    });
  });

  it(`should remove Latin mathematical operators`, () => {
    const actual = ['\xd7', '\xf7'].map(snakeCase);
    expect(actual).toEqual(['', '']);
  });

  it(`should coerce \`string\` to a string`, () => {
    const string = 'foo bar';
    expect(snakeCase(Object(string))).toBe('foo_bar');
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-expect-error
    expect(snakeCase({ toString: () => string })).toBe('foo_bar');
  });

  it('should keep ordinal numbers as single words, identical to lodash', () => {
    expect(snakeCase('foo1stPlace')).toBe('foo_1st_place');
    expect(snakeCase('top10th')).toBe('top_10th');
    expect(snakeCase('1st place 2nd 3rd 4th')).toBe('1st_place_2nd_3rd_4th');
  });
});
