Dropdown.test.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. import React from "react";
  2. import { shallow } from "enzyme";
  3. import {
  4. CountryDropdown,
  5. CountryItem,
  6. Dropdown,
  7. DropdownGroup,
  8. findSelectedDisplay,
  9. Item,
  10. } from "../components/util/GameCreationForm/Dropdown";
  11. jest.mock("../domain/flagLookup");
  12. import flagLookup from "../domain/flagLookup";
  13. describe("DropdownGroup", () => {
  14. it("renders with no dropdowns", () => {
  15. const rendered = shallow(<DropdownGroup />);
  16. expect(rendered).toMatchSnapshot();
  17. });
  18. it("renders with dropdowns", () => {
  19. const rendered = shallow(
  20. <DropdownGroup>
  21. <Dropdown open="dd1" />
  22. <Dropdown open="dd2" />
  23. <Dropdown open="dd3" />
  24. </DropdownGroup>
  25. );
  26. expect(rendered).toMatchSnapshot();
  27. });
  28. it("can have a dropdown opened", () => {
  29. const rendered = shallow(
  30. <DropdownGroup>
  31. <Dropdown open="dd1" />
  32. <Dropdown open="dd2" />
  33. <Dropdown open="dd3" />
  34. </DropdownGroup>
  35. );
  36. rendered.find("Dropdown").at(1).prop("onClick")();
  37. expect(rendered).toMatchSnapshot();
  38. });
  39. it("can have a dropdown closed after opening", () => {
  40. const rendered = shallow(
  41. <DropdownGroup>
  42. <Dropdown open="dd1" />
  43. <Dropdown open="dd2" />
  44. <Dropdown open="dd3" />
  45. </DropdownGroup>
  46. );
  47. rendered.find("Dropdown").at(1).prop("onClick")();
  48. rendered.find("Dropdown").at(1).prop("onClick")();
  49. expect(rendered).toMatchSnapshot();
  50. });
  51. it("selecting a dropdown re-closes it", () => {
  52. const onSelect = jest.fn();
  53. const rendered = shallow(
  54. <DropdownGroup>
  55. <Dropdown open="dd1" />
  56. <Dropdown open="dd2" onSelect={onSelect} />
  57. <Dropdown open="dd3" />
  58. </DropdownGroup>
  59. );
  60. rendered.find("Dropdown").at(1).prop("onClick")();
  61. rendered.find("Dropdown").at(1).prop("onSelect")("test");
  62. expect(rendered).toMatchSnapshot();
  63. expect(onSelect).toHaveBeenCalledWith("test");
  64. });
  65. });
  66. describe("Dropdown", () => {
  67. it("renders closed", () => {
  68. const onSelect = jest.fn();
  69. const onClick = jest.fn();
  70. const rendered = shallow(<Dropdown {...{ onSelect, onClick }} />);
  71. expect(rendered).toMatchSnapshot();
  72. });
  73. it("passes button class", () => {
  74. const onSelect = jest.fn();
  75. const onClick = jest.fn();
  76. const rendered = shallow(
  77. <Dropdown buttonClass="test-button-class" {...{ onSelect, onClick }} />
  78. );
  79. expect(rendered).toMatchSnapshot();
  80. });
  81. it("renders with no items", () => {
  82. const onSelect = jest.fn();
  83. const onClick = jest.fn();
  84. const rendered = shallow(<Dropdown open {...{ onSelect, onClick }} />);
  85. expect(rendered).toMatchSnapshot();
  86. });
  87. it("renders with items", () => {
  88. const onSelect = jest.fn();
  89. const onClick = jest.fn();
  90. const rendered = shallow(
  91. <Dropdown open {...{ onSelect, onClick }}>
  92. <Item value="test1" />
  93. <Item value="test2" />
  94. </Dropdown>
  95. );
  96. expect(rendered).toMatchSnapshot();
  97. });
  98. it("can be clicked", () => {
  99. const onSelect = jest.fn();
  100. const onClick = jest.fn();
  101. const rendered = shallow(
  102. <Dropdown {...{ onSelect, onClick }}>
  103. <Item value="test1" />
  104. <Item value="test2" />
  105. </Dropdown>
  106. );
  107. rendered.find("div.button").first().simulate("click");
  108. expect(onClick).toHaveBeenCalled();
  109. });
  110. it("can be selected with Enter", () => {
  111. const onSelect = jest.fn();
  112. const onClick = jest.fn();
  113. const rendered = shallow(
  114. <Dropdown {...{ onSelect, onClick }}>
  115. <Item value="test1" />
  116. <Item value="test2" />
  117. </Dropdown>
  118. );
  119. rendered.find("div.button").first().simulate("keydown", { key: "Enter" });
  120. expect(onClick).toHaveBeenCalled();
  121. });
  122. it("cannot be selected with other keydowns", () => {
  123. const onSelect = jest.fn();
  124. const onClick = jest.fn();
  125. const rendered = shallow(
  126. <Dropdown {...{ onSelect, onClick }}>
  127. <Item value="test1" />
  128. <Item value="test2" />
  129. </Dropdown>
  130. );
  131. rendered.find("div.button").first().simulate("keydown", { key: "Escape" });
  132. expect(onClick).not.toHaveBeenCalled();
  133. });
  134. it("responds to item selection", () => {
  135. const onSelect = jest.fn();
  136. const onClick = jest.fn();
  137. const rendered = shallow(
  138. <Dropdown open {...{ onSelect, onClick }}>
  139. <Item value="test1" />
  140. <Item value="test2" />
  141. </Dropdown>
  142. );
  143. rendered.find("Item").first().prop("onSelect")("value", "display");
  144. expect(onSelect).toHaveBeenCalledWith("value");
  145. expect(rendered).toMatchSnapshot();
  146. });
  147. describe("findSelectedDisplay", () => {
  148. it("returns null when nothing is selected", () => {
  149. expect(findSelectedDisplay()).toBeNull();
  150. });
  151. it("extracts the display of the selected element", () => {
  152. expect(
  153. findSelectedDisplay("two", [
  154. <Item display="1" value="one" />,
  155. <Item display="2" value="two" />,
  156. <Item display="3" value="three" />,
  157. ])
  158. ).toBe("2");
  159. });
  160. it("extracts the value of the selected element if there is no display", () => {
  161. expect(
  162. findSelectedDisplay("two", [
  163. <Item value="one" />,
  164. <Item value="two" />,
  165. <Item value="three" />,
  166. ])
  167. ).toBe("two");
  168. });
  169. it("returns null if there is no matching element", () => {
  170. expect(
  171. findSelectedDisplay("four", [
  172. <Item value="one" />,
  173. <Item value="two" />,
  174. <Item value="three" />,
  175. ])
  176. ).toBeNull();
  177. });
  178. it("returns the first display found if there is more than one matching element", () => {
  179. expect(
  180. findSelectedDisplay("two", [
  181. <Item display="1" value="one" />,
  182. <Item display="2" value="two" />,
  183. <Item display="3" value="three" />,
  184. <Item display="4" value="two" />,
  185. ])
  186. ).toBe("2");
  187. });
  188. });
  189. });
  190. describe("CountryItem", () => {
  191. it("renders", () => {
  192. flagLookup.mockReturnValue("flag");
  193. const rendered = shallow(
  194. <CountryItem code="test-code" country="test-country" />
  195. );
  196. expect(rendered).toMatchSnapshot();
  197. expect(flagLookup).toHaveBeenCalledWith("test-code");
  198. });
  199. it("responds to click", () => {
  200. flagLookup.mockReturnValue("flag");
  201. const onSelect = jest.fn();
  202. const rendered = shallow(
  203. <CountryItem
  204. onSelect={onSelect}
  205. code="test-code"
  206. country="test-country"
  207. />
  208. );
  209. rendered.simulate("click");
  210. expect(onSelect).toHaveBeenCalledWith("test-code");
  211. });
  212. it("responds to keydown Enter", () => {
  213. flagLookup.mockReturnValue("flag");
  214. const onSelect = jest.fn();
  215. const rendered = shallow(
  216. <CountryItem
  217. onSelect={onSelect}
  218. code="test-code"
  219. country="test-country"
  220. />
  221. );
  222. rendered.simulate("keydown", { key: "Enter" });
  223. expect(onSelect).toHaveBeenCalledWith("test-code");
  224. });
  225. it("responds to click", () => {
  226. flagLookup.mockReturnValue("flag");
  227. const onSelect = jest.fn();
  228. const rendered = shallow(
  229. <CountryItem
  230. onSelect={onSelect}
  231. code="test-code"
  232. country="test-country"
  233. />
  234. );
  235. rendered.simulate("keydown", { key: "Escape" });
  236. expect(onSelect).not.toHaveBeenCalled();
  237. });
  238. });
  239. describe("CountryDropdown", () => {
  240. it("renders closed", () => {
  241. flagLookup.mockReturnValue("flag");
  242. const countryLookup = jest.fn();
  243. const selected = "selected";
  244. const onSelect = jest.fn();
  245. const onClick = jest.fn();
  246. const rendered = shallow(
  247. <CountryDropdown {...{ countryLookup, selected, onSelect, onClick }} />
  248. );
  249. expect(rendered).toMatchSnapshot();
  250. });
  251. it("renders", () => {
  252. flagLookup.mockReturnValue("flag");
  253. const countryLookup = jest.fn();
  254. const selected = "selected";
  255. const onSelect = jest.fn();
  256. const onClick = jest.fn();
  257. const rendered = shallow(
  258. <CountryDropdown
  259. open
  260. {...{ countryLookup, selected, onSelect, onClick }}
  261. />
  262. );
  263. expect(rendered).toMatchSnapshot();
  264. });
  265. it("renders with countries", () => {
  266. flagLookup.mockReturnValue("flag");
  267. const countryLookup = jest.fn();
  268. countryLookup.mockReturnValue([
  269. { item: { country: "c1", alpha2: "a21" } },
  270. { item: { country: "c2", alpha2: "a22" } },
  271. { item: { country: "c3", alpha2: "a23" } },
  272. ]);
  273. const selected = "selected";
  274. const onSelect = jest.fn();
  275. const onClick = jest.fn();
  276. const rendered = shallow(
  277. <CountryDropdown
  278. open
  279. {...{ countryLookup, selected, onSelect, onClick }}
  280. />
  281. );
  282. expect(rendered).toMatchSnapshot();
  283. });
  284. it("can be clicked", () => {
  285. flagLookup.mockReturnValue("flag");
  286. const countryLookup = jest.fn();
  287. countryLookup.mockReturnValue([
  288. { item: { country: "c1", alpha2: "a21" } },
  289. { item: { country: "c2", alpha2: "a22" } },
  290. { item: { country: "c3", alpha2: "a23" } },
  291. ]);
  292. const selected = "selected";
  293. const onSelect = jest.fn();
  294. const onClick = jest.fn();
  295. const rendered = shallow(
  296. <CountryDropdown
  297. open
  298. {...{ countryLookup, selected, onSelect, onClick }}
  299. />
  300. );
  301. rendered.find("div.button").first().simulate("click");
  302. expect(onClick).toHaveBeenCalled();
  303. });
  304. it("can be selected with Enter", () => {
  305. flagLookup.mockReturnValue("flag");
  306. const countryLookup = jest.fn();
  307. countryLookup.mockReturnValue([
  308. { item: { country: "c1", alpha2: "a21" } },
  309. { item: { country: "c2", alpha2: "a22" } },
  310. { item: { country: "c3", alpha2: "a23" } },
  311. ]);
  312. const selected = "selected";
  313. const onSelect = jest.fn();
  314. const onClick = jest.fn();
  315. const rendered = shallow(
  316. <CountryDropdown
  317. open
  318. {...{ countryLookup, selected, onSelect, onClick }}
  319. />
  320. );
  321. rendered.find("div.button").first().simulate("keydown", { key: "Enter" });
  322. expect(onClick).toHaveBeenCalled();
  323. });
  324. it("cannot be selected with other keydowns", () => {
  325. flagLookup.mockReturnValue("flag");
  326. const countryLookup = jest.fn();
  327. countryLookup.mockReturnValue([
  328. { item: { country: "c1", alpha2: "a21" } },
  329. { item: { country: "c2", alpha2: "a22" } },
  330. { item: { country: "c3", alpha2: "a23" } },
  331. ]);
  332. const selected = "selected";
  333. const onSelect = jest.fn();
  334. const onClick = jest.fn();
  335. const rendered = shallow(
  336. <CountryDropdown
  337. open
  338. {...{ countryLookup, selected, onSelect, onClick }}
  339. />
  340. );
  341. rendered.find("div.button").first().simulate("keydown", { key: "Escape" });
  342. expect(onClick).not.toHaveBeenCalled();
  343. });
  344. it("can have a country selected", () => {
  345. flagLookup.mockReturnValue("flag");
  346. const countryLookup = jest.fn();
  347. countryLookup.mockReturnValue([
  348. { item: { country: "c1", alpha2: "a21" } },
  349. { item: { country: "c2", alpha2: "a22" } },
  350. { item: { country: "c3", alpha2: "a23" } },
  351. ]);
  352. const selected = "selected";
  353. const onSelect = jest.fn();
  354. const onClick = jest.fn();
  355. const rendered = shallow(
  356. <CountryDropdown
  357. open
  358. {...{ countryLookup, selected, onSelect, onClick }}
  359. />
  360. );
  361. rendered.find("CountryItem").first().prop("onSelect")();
  362. expect(onSelect).toHaveBeenCalled();
  363. });
  364. it("selects country based on searchbox", () => {
  365. flagLookup.mockReturnValue("flag");
  366. const countryLookup = jest.fn();
  367. countryLookup.mockReturnValue([
  368. { item: { country: "c1", alpha2: "a21" } },
  369. { item: { country: "c2", alpha2: "a22" } },
  370. { item: { country: "c3", alpha2: "a23" } },
  371. ]);
  372. const selected = "selected";
  373. const onSelect = jest.fn();
  374. const onClick = jest.fn();
  375. const rendered = shallow(
  376. <CountryDropdown
  377. open
  378. {...{ countryLookup, selected, onSelect, onClick }}
  379. />
  380. );
  381. rendered
  382. .find("input")
  383. .first()
  384. .simulate("change", { target: { value: "changed" } });
  385. expect(countryLookup).toHaveBeenCalledWith("changed");
  386. });
  387. it("can have first option selected with Enter", () => {
  388. flagLookup.mockReturnValue("flag");
  389. const countryLookup = jest.fn();
  390. countryLookup.mockReturnValue([
  391. { item: { country: "c1", alpha2: "a21" } },
  392. { item: { country: "c2", alpha2: "a22" } },
  393. { item: { country: "c3", alpha2: "a23" } },
  394. ]);
  395. const selected = "selected";
  396. const onSelect = jest.fn();
  397. const onClick = jest.fn();
  398. const rendered = shallow(
  399. <CountryDropdown
  400. open
  401. {...{ countryLookup, selected, onSelect, onClick }}
  402. />
  403. );
  404. rendered.find("input").first().simulate("keydown", { key: "Enter" });
  405. expect(onSelect).toHaveBeenCalledWith("a21");
  406. });
  407. it("can have previously selected option selected with Escape", () => {
  408. flagLookup.mockReturnValue("flag");
  409. const countryLookup = jest.fn();
  410. countryLookup.mockReturnValue([
  411. { item: { country: "c1", alpha2: "a21" } },
  412. { item: { country: "c2", alpha2: "a22" } },
  413. { item: { country: "c3", alpha2: "a23" } },
  414. ]);
  415. const selected = "selected";
  416. const onSelect = jest.fn();
  417. const onClick = jest.fn();
  418. const rendered = shallow(
  419. <CountryDropdown
  420. open
  421. {...{ countryLookup, selected, onSelect, onClick }}
  422. />
  423. );
  424. rendered.find("input").first().simulate("keydown", { key: "Escape" });
  425. expect(onSelect).toHaveBeenCalledWith("selected");
  426. });
  427. it("does not select from other keydowns", () => {
  428. flagLookup.mockReturnValue("flag");
  429. const countryLookup = jest.fn();
  430. countryLookup.mockReturnValue([
  431. { item: { country: "c1", alpha2: "a21" } },
  432. { item: { country: "c2", alpha2: "a22" } },
  433. { item: { country: "c3", alpha2: "a23" } },
  434. ]);
  435. const selected = "selected";
  436. const onSelect = jest.fn();
  437. const onClick = jest.fn();
  438. const rendered = shallow(
  439. <CountryDropdown
  440. open
  441. {...{ countryLookup, selected, onSelect, onClick }}
  442. />
  443. );
  444. rendered.find("input").first().simulate("keydown", { key: "Tab" });
  445. expect(onSelect).not.toHaveBeenCalled();
  446. });
  447. });
  448. describe("Item", () => {
  449. it("renders with no text", () => {
  450. const onSelect = jest.fn();
  451. const display = "display";
  452. const value = "value";
  453. const rendered = shallow(<Item {...{ onSelect, display, value }} />);
  454. expect(rendered).toMatchSnapshot();
  455. });
  456. it("responds to click", () => {
  457. const onSelect = jest.fn();
  458. const display = "display";
  459. const value = "value";
  460. const rendered = shallow(<Item {...{ onSelect, display, value }} />);
  461. rendered.simulate("click");
  462. expect(onSelect).toHaveBeenCalledWith(value, display);
  463. });
  464. it("responds to enter", () => {
  465. const onSelect = jest.fn();
  466. const display = "display";
  467. const value = "value";
  468. const rendered = shallow(<Item {...{ onSelect, display, value }} />);
  469. rendered.simulate("keydown", { key: "Enter" });
  470. expect(onSelect).toHaveBeenCalledWith(value, display);
  471. });
  472. it("does not respond to other keydowns", () => {
  473. const onSelect = jest.fn();
  474. const display = "display";
  475. const value = "value";
  476. const rendered = shallow(<Item {...{ onSelect, display, value }} />);
  477. rendered.simulate("keydown", { key: "Escape" });
  478. expect(onSelect).not.toHaveBeenCalled();
  479. });
  480. it("responds to click with value when no display", () => {
  481. const onSelect = jest.fn();
  482. const value = "value";
  483. const rendered = shallow(<Item {...{ onSelect, value }} />);
  484. rendered.simulate("click");
  485. expect(onSelect).toHaveBeenCalledWith(value, value);
  486. });
  487. it("responds to click with children when no display or value", () => {
  488. const onSelect = jest.fn();
  489. const child = <div>child</div>;
  490. const rendered = shallow(<Item {...{ onSelect }}>{child}</Item>);
  491. rendered.simulate("click");
  492. expect(onSelect).toHaveBeenCalledWith(child, child);
  493. });
  494. });