<commit_before>import { jest, beforeEach, describe, expect, test } from '@jest/globals';
import { prop } from 'common';
import keyboardMove from './keyboardMove';

// Tips for working with this file:
// - use https://lichess.org/editor to create positions and get their FENs
// - use https://lichess.org/editor/<FEN> to check what FENs look like

// Set up the globals that are normally attached to window
declare let global: any;
global.lichess = { sound: { say: () => null, play: () => null } };
global.Mousetrap = { bind: () => null };

// Set up the common defaults
document.body.innerHTML = `<input id="keyboardInput" />`;
let input = document.getElementById('keyboardInput') as HTMLInputElement;
const unexpectedErrorThrower = (name: string) => () => {
  throw new Error(`unexpected call to ${name}()`);
};
const defaultCtrl = {
  clock: unexpectedErrorThrower('clock'),
  confirmMove: () => null,
  draw: unexpectedErrorThrower('draw'),
  drop: unexpectedErrorThrower('drop'),
  hasFocus: () => true,
  hasSelected: () => undefined,
  jump: () => null,
  justSelected: () => true,
  promote: unexpectedErrorThrower('promote'),
  registerHandler: () => null,
  resign: unexpectedErrorThrower('resign'),
  san: unexpectedErrorThrower('san'),
  select: unexpectedErrorThrower('select'),
  setFocus: () => null,
  update: () => null,
  usedSan: true,
  helpModalOpen: prop(false),
};
const startingFen = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1';

const toMap = (obj: object) => new Map(Object.entries(obj));

describe('keyboardMove', () => {
  beforeEach(() => {
    document.body.innerHTML = `<input id="keyboardInput" />`;
    input = document.getElementById('keyboardInput') as HTMLInputElement;
  });

  test('resigns game', () => {
    input.value = 'resign';
    const mockResign = jest.fn();
    const keyboardMovePlugin = keyboardMove({
      input,
      ctrl: {
        ...defaultCtrl,
        resign: mockResign,
      },
    }) as any;

    keyboardMovePlugin(startingFen, toMap({}), true);

    expect(mockResign.mock.calls.length).toBe(1);
    expect(input.value).toBe('');
  });

  test('draws game', () => {
    input.value = 'draw';
    const mockDraw = jest.fn();
    const keyboardMovePlugin = keyboardMove({
      input,
      ctrl: {
        ...defaultCtrl,
        draw: mockDraw,
      },
    }) as any;

    keyboardMovePlugin(startingFen, toMap({}), true);

    expect(mockDraw.mock.calls.length).toBe(1);
    expect(input.value).toBe('');
  });

  test('reads out clock', () => {
    input.value = 'clock';
    const mockMillisOf = jest.fn(_ => 1000);
    const keyboardMovePlugin = keyboardMove({
      input,
      ctrl: {
        ...defaultCtrl,
        clock: () => ({ millisOf: mockMillisOf } as any),
      },
    }) as any;

    keyboardMovePlugin(startingFen, toMap({}), true);

    expect(mockMillisOf.mock.calls.length).toBe(2);
    expect(input.value).toBe('');
  });

  test('opens help modal with ?', () => {
    input.value = '?';
    const mockSetHelpModalOpen = jest.fn();
    const keyboardMovePlugin = keyboardMove({
      input,
      ctrl: {
        ...defaultCtrl,
        helpModalOpen: prop(false),
      },
    }) as any;

    keyboardMovePlugin(startingFen, toMap({}), true);

    expect(mockSetHelpModalOpen.mock.calls.length).toBe(1);
    expect(input.value).toBe('');
  });

  describe('from starting position', () => {
    test('plays e4 via SAN', () => {
      input.value = 'e4';
      const mockSan = jest.fn();
      const keyboardMovePlugin = keyboardMove({
        input,
        ctrl: {
          ...defaultCtrl,
          san: mockSan,<commit_msg>fix ui test<commit_after>import { jest, beforeEach, describe, expect, test } from '@jest/globals';
import { Prop, prop } from 'common';
import keyboardMove from './keyboardMove';

// Tips for working with this file:
// - use https://lichess.org/editor to create positions and get their FENs
// - use https://lichess.org/editor/<FEN> to check what FENs look like

// Set up the globals that are normally attached to window
declare let global: any;
global.lichess = { sound: { say: () => null, play: () => null } };
global.Mousetrap = { bind: () => null };

// Set up the common defaults
document.body.innerHTML = `<input id="keyboardInput" />`;
let input = document.getElementById('keyboardInput') as HTMLInputElement;
const unexpectedErrorThrower = (name: string) => () => {
  throw new Error(`unexpected call to ${name}()`);
};
const defaultCtrl = {
  clock: unexpectedErrorThrower('clock'),
  confirmMove: () => null,
  draw: unexpectedErrorThrower('draw'),
  drop: unexpectedErrorThrower('drop'),
  hasFocus: () => true,
  hasSelected: () => undefined,
  jump: () => null,
  justSelected: () => true,
  promote: unexpectedErrorThrower('promote'),
  registerHandler: () => null,
  resign: unexpectedErrorThrower('resign'),
  san: unexpectedErrorThrower('san'),
  select: unexpectedErrorThrower('select'),
  setFocus: () => null,
  update: () => null,
  usedSan: true,
  helpModalOpen: prop(false),
};
const startingFen = 'rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1';

const toMap = (obj: object) => new Map(Object.entries(obj));

describe('keyboardMove', () => {
  beforeEach(() => {
    document.body.innerHTML = `<input id="keyboardInput" />`;
    input = document.getElementById('keyboardInput') as HTMLInputElement;
  });

  test('resigns game', () => {
    input.value = 'resign';
    const mockResign = jest.fn();
    const keyboardMovePlugin = keyboardMove({
      input,
      ctrl: {
        ...defaultCtrl,
        resign: mockResign,
      },
    }) as any;

    keyboardMovePlugin(startingFen, toMap({}), true);

    expect(mockResign.mock.calls.length).toBe(1);
    expect(input.value).toBe('');
  });

  test('draws game', () => {
    input.value = 'draw';
    const mockDraw = jest.fn();
    const keyboardMovePlugin = keyboardMove({
      input,
      ctrl: {
        ...defaultCtrl,
        draw: mockDraw,
      },
    }) as any;

    keyboardMovePlugin(startingFen, toMap({}), true);

    expect(mockDraw.mock.calls.length).toBe(1);
    expect(input.value).toBe('');
  });

  test('reads out clock', () => {
    input.value = 'clock';
    const mockMillisOf = jest.fn(_ => 1000);
    const keyboardMovePlugin = keyboardMove({
      input,
      ctrl: {
        ...defaultCtrl,
        clock: () => ({ millisOf: mockMillisOf } as any),
      },
    }) as any;

    keyboardMovePlugin(startingFen, toMap({}), true);

    expect(mockMillisOf.mock.calls.length).toBe(2);
    expect(input.value).toBe('');
  });

  test('opens help modal with ?', () => {
    input.value = '?';
    const mockSetHelpModalOpen = jest.fn();
    const keyboardMovePlugin = keyboardMove({
      input,
      ctrl: {
        ...defaultCtrl,
        helpModalOpen: mockSetHelpModalOpen as Prop<boolean>,
      },
    }) as any;

    keyboardMovePlugin(startingFen, toMap({}), true);

    expect(mockSetHelpModalOpen.mock.calls.length).toBe(1);
    expect(input.value).toBe('');
  });

  describe('from starting position', () => {
    test('plays e4 via SAN', () => {
      input.value = 'e4';
      const mockSan = jest.fn();
      const keyboardMovePlugin = keyboardMove({
        input,
        ctrl: {
          ...defaultCtrl,
          san: mockSan,
{'fraction_non_alphanumeric': 0.16552386176631925, 'fraction_numerical': 0.004388370817334065, 'mean_word_length': 3.220486111111111, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 58, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 4, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3826605', 'n_tokens_mistral': 2307, 'n_tokens_neox': 2274, 'n_words': 518}