Dropdown.test.js 15 KB

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