class TestBot(unittest.TestCase): def setUp(self): self.bot = Bot("test_config.json", "test") def test_get_comic(self): self.assertIsNone(self.bot.get_comic(-1)) self.assertEqual( self.bot.get_comic(327), { "month": "10", "num": 327, "link": "", "year": "2007", "news": "", "safe_title": "Exploits of a Mom", "transcript": "[[A woman is talking on the phone, holding a cup]]\nPhone: Hi, this is your son's school. We're having some computer trouble.\nMom: Oh dear\u00e2\u0080\u0094did he break something?\nPhone: In a way\u00e2\u0080\u0094\nPhone: Did you really name your son \"Robert'); DROP TABLE Students;--\" ?\nMom: Oh, yes. Little Bobby Tables, we call him.\nPhone: Well, we've lost this year's student records. I hope you're happy.\nMom: And I hope you've learned to sanitize your database inputs.\n{{title-text: Her daughter is named Help I'm trapped in a driver's license factory.}}", "alt": "Her daughter is named Help I'm trapped in a driver's license factory.", "img": "https://imgs.xkcd.com/comics/exploits_of_a_mom.png", "title": "Exploits of a Mom", "day": "10" }) def test_match_numbers_strict(self): self.assertEqual(self.bot.match_numbers("Test", True), []) self.assertEqual(self.bot.match_numbers("!123 !123", True), ["123"]) self.assertEqual(self.bot.match_numbers("7? !080. !99", True), ["80", "99"]) self.assertEqual(self.bot.match_numbers("!900 10000", True), ["900"]) self.assertEqual( self.bot.match_numbers("!Test !001234 5678 !-1", True), ["1234"]) self.assertEqual(len(self.bot.match_numbers("!random random", True)), 1) def test_find_numbers_non_strict(self): self.assertEqual(self.bot.match_numbers("Test", False), []) self.assertEqual(self.bot.match_numbers("!123.", False), ["123"]) self.assertEqual( self.bot.match_numbers("07/ !080. !00099 99 0099", False), ["7", "80", "99"]) self.assertEqual(self.bot.match_numbers("!900 010000", False), ["900", "10000"]) self.assertEqual(self.bot.match_numbers("!Test !1234 5678 !-1", False), ["1234", "5678", "1"]) self.assertEqual(len(self.bot.match_numbers("!random random", False)), 2) def test_response_size_limited(self): comment = CommentMock() too_big_response = ''.join( ['1' for _ in range(RESPONSE_CHAR_LIMIT + 1)]) self.bot.reply(comment=comment, response=too_big_response) self.assertEqual( comment.reply_called, 0, f'Expected no reply() call, saw {comment.reply_called}') self.assertEqual(comment.save_called, 1, f'Expected 1 save() call, saw {comment.save_called}') def test_combine_responses_truncates_response(self): # There may be a less fragile way of constructing this test, but this will test the # functionality. too_many_responses = [f'1' for _ in range(RESPONSE_COUNT_LIMIT + 1)] expected_combined_response_length = \ len('\n'.join(too_many_responses[:RESPONSE_COUNT_LIMIT])) + \ len(self.bot._closer()) + len('\n') actual_combined_response = self.bot.combine_responses( responses=too_many_responses) self.assertEqual( len(actual_combined_response), expected_combined_response_length, f'Expected response of length {expected_combined_response_length}, found {len(actual_combined_response)}' )
class TestBot(unittest.TestCase): def setUp(self): self.bot = Bot("./cfg/test_config.json", "test", ":memory:") def test_get_comic(self): self.assertIsNone(self.bot.get_comic(-1)) self.assertEqual( self.bot.get_comic(327), { "month": "10", "num": 327, "link": "", "year": "2007", "news": "", "safe_title": "Exploits of a Mom", "transcript": "[[A woman is talking on the phone, holding a cup]]\nPhone: Hi, this is your son's school. We're having some computer trouble.\nMom: Oh dear\u00e2\u0080\u0094did he break something?\nPhone: In a way\u00e2\u0080\u0094\nPhone: Did you really name your son \"Robert'); DROP TABLE Students;--\" ?\nMom: Oh, yes. Little Bobby Tables, we call him.\nPhone: Well, we've lost this year's student records. I hope you're happy.\nMom: And I hope you've learned to sanitize your database inputs.\n{{title-text: Her daughter is named Help I'm trapped in a driver's license factory.}}", "alt": "Her daughter is named Help I'm trapped in a driver's license factory.", "img": "https://imgs.xkcd.com/comics/exploits_of_a_mom.png", "title": "Exploits of a Mom", "day": "10" }) def test_match_numbers_strict(self): self.assertEqual(self.bot.match_numbers("Test", True), []) self.assertEqual(self.bot.match_numbers("!123 !123", True), ["123"]) self.assertEqual(self.bot.match_numbers("7? !080. !99", True), ["80", "99"]) self.assertEqual(self.bot.match_numbers("!900 10000", True), ["900"]) self.assertEqual( self.bot.match_numbers("!Test !001234 5678 !-1", True), ["1234"]) self.assertEqual(len(self.bot.match_numbers("!random random", True)), 1) self.assertEqual( self.bot.match_numbers("!3 relevant xkcd: 6, !relevant xkcd: 5 1", True), ["3", "6", "5"]) self.assertEqual(self.bot.match_numbers("!9 !23...25 #9...7", True), ["9", "23", "24", "25", "7", "8"]) self.assertEqual( self.bot.match_numbers( "https://www.google.com/maps/dir/Okay,+Oklahoma,+USA/Whynot,+North+Carolina+27341,+USA/@35.283469,-92.0617932,6z/data=!3m1!4b1!4m14!4m13!1m5!1m1!1s0x87b60bd75e51d2d3:0x120194060a920373!2m2!1d-95.3182985!2d35.8506548!1m5!1m1!1s0x8853609903e1db5b:0x15b011f26e28c49e!2m2!1d-79.7480465!2d35.5402827!3e0", True), []) self.assertEqual(self.bot.match_numbers("number is mid!1string", True), []) self.assertEqual( self.bot.match_numbers("!12 hello https://www.google.com/!1", True), ["12"]) self.assertEqual(self.bot.match_numbers("#1mid#6number", True), ["1"]) def test_find_numbers_non_strict(self): self.assertEqual(self.bot.match_numbers("Test", False), []) self.assertEqual(self.bot.match_numbers("!123.", False), ["123"]) self.assertEqual( self.bot.match_numbers("07/ !080. !00099 99 0099", False), ["7", "80", "99"]) self.assertEqual(self.bot.match_numbers("!900 010000", False), ["900", "10000"]) self.assertEqual(self.bot.match_numbers("!Test !1234 5678 !-1", False), ["1234", "5678", "1"]) self.assertEqual(len(self.bot.match_numbers("!random random", False)), 2) self.assertEqual( self.bot.match_numbers("!3 relevant xkcd: 6, !relevant xkcd: 5 1", False), ["3", "6", "5", "1"]) self.assertEqual(self.bot.match_numbers("9 23...25 9...7", False), ["9", "23", "25", "7", "24", "8"]) def test_response_size_limited(self): comment = CommentMock() too_big_response = ''.join( ['1' for _ in range(RESPONSE_CHAR_LIMIT + 1)]) self.bot.reply(comment=comment, response=too_big_response) self.assertEqual( comment.reply_called, 0, f'Expected no reply() call, saw {comment.reply_called}') self.assertEqual(comment.save_called, 1, f'Expected 1 save() call, saw {comment.save_called}') def test_combine_responses_truncates_response(self): # There may be a less fragile way of constructing this test, but this will test the functionality. too_many_responses = [f'1' for _ in range(RESPONSE_COUNT_LIMIT + 1)] expected_combined_response_length = \ len('\n'.join(too_many_responses[:RESPONSE_COUNT_LIMIT])) + \ len(self.bot._closer()) + len('\n') actual_combined_response = self.bot.combine_responses( responses=too_many_responses) self.assertEqual( len(actual_combined_response), expected_combined_response_length, f'Expected response of length {expected_combined_response_length}, found {len(actual_combined_response)}' ) def test_urlescape(self): expected = textwrap.dedent(""" **[859:](http://xkcd.com/859)** ( **Alt-text:** >!Brains aside, I wonder how many poorly-written xkcd.com-parsing scripts will break on this title (or ;;"\'\'{<<[\' this mouseover text."!< [Image](https://imgs.xkcd.com/comics/%28.png) [Mobile](http://m.xkcd.com/859) [Explanation](http://www.explainxkcd.com/wiki/index.php/859) """) self.assertEqual(self.bot.format_response(self.bot.get_comic(859)), expected) def test_match_titles(self): self.assertEqual( self.bot.match_titles("!6 #irony #36blownApart !1000comics"), ["6", "irony", "36blownApart", "1000comics"]) self.assertEqual(self.bot.match_titles("#dummy!Title"), ["dummy!Title"]) def test_get_comic_by_title(self): self.bot.database.add_comic_title("irony", 6) self.assertEqual( self.bot.get_comic_by_title("IrOnY"), { "month": "1", "num": 6, "link": "", "year": "2006", "news": "", "safe_title": "Irony", "transcript": "Narrator: When self-reference, irony, and meta-humor go too far\nNarrator: A CAUTIONARY TALE\nMan 1: This statement wouldn't be funny if not for irony!\nMan 1: ha ha\nMan 2: ha ha, I guess.\nNarrator: 20,000 years later...\n[[desolate badlands landscape with an imposing sun in the sky]]\n{{It's commonly known that too much perspective can be a downer.}}", "alt": "It's commonly known that too much perspective can be a downer.", "img": "https://imgs.xkcd.com/comics/irony_color.jpg", "title": "Irony", "day": "1" }) self.assertIsNone(self.bot.get_comic_by_title("dummy"))
class TestBot(unittest.TestCase): def setUp(self): self.bot = Bot("./cfg/test_config.json", "test", ":memory:") def test_get_comic(self): self.assertIsNone(self.bot.get_comic(-1)) self.assertEqual( self.bot.get_comic(327), { "month": "10", "num": 327, "link": "", "year": "2007", "news": "", "safe_title": "Exploits of a Mom", "transcript": "[[A woman is talking on the phone, holding a cup]]\nPhone: Hi, this is your son's school. We're having some computer trouble.\nMom: Oh dear\u00e2\u0080\u0094did he break something?\nPhone: In a way\u00e2\u0080\u0094\nPhone: Did you really name your son \"Robert'); DROP TABLE Students;--\" ?\nMom: Oh, yes. Little Bobby Tables, we call him.\nPhone: Well, we've lost this year's student records. I hope you're happy.\nMom: And I hope you've learned to sanitize your database inputs.\n{{title-text: Her daughter is named Help I'm trapped in a driver's license factory.}}", "alt": "Her daughter is named Help I'm trapped in a driver's license factory.", "img": "https://imgs.xkcd.com/comics/exploits_of_a_mom.png", "title": "Exploits of a Mom", "day": "10" }) self.assertIsNone(self.bot.get_comic(404)) self.assertEqual( self.bot.get_comic(10000), { "title": "Does not exist yet!", "alt": " ", "img": "https://www.explainxkcd.com/wiki/images/9/92/not_found.png", "num": 404 }) self.assertEqual( self.bot.get_comic( 314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316527120190914564856692346034861045432664821339360726024914127372458700660631558817488152092096282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912983367336244065664308602139494639522473719070217986094370277053921717629317675238467481846766940513200056812714526356082778577134275778960917363717872146844090122495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837297804995105973173281609631859502445945534690830264252230825334468503526193118817101000313783875288658753320838142061717766914730359825349042875546873115956286388235378759375195778185778053217122680661300192787661119590921642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151557485724245415069595082953311686172785588907509838175463746493931925506040092770167113900984882401285836160356370766010471018194295559619894676783744944825537977472684710404753464620804668425906949129331367702898915210475216205696602405803815019351125338243003558764024749647326391419927260426992279678235478163600934172164121992458631503028618297455570674983850549458858692699569092721079750930295532116534498720275596023648066549911988183479775356636980742654252786255181841757467289097777279380008164706001614524919217321721477235014144197356854816136115735255213347574184946843852332390739414333454776241686251898356948556209921922218427255025425688767179049460165346680498862723279178608578438382796797668145410095388378636095068006422512520511739298489608412848862694560424196528502221066118630674427862203919494504712371378696095636437191728746776465757396241389086583264599581339047802759009946576407895126946839835259570982582262052248940772671947826848260147699090264013639443745530506820349625245174939965143142980919065925093722169646151570985838741059788595977297549893016175392846813826868386894277415599185592524595395943104997252468084598727364469584865383673622262609912460805124388439045124413654976278079771569143599770012961608944169486855584840635342207222582848864815845602850601684273945226746767889525213852254995466672782398645659611635488623057745649803559363456817432411251507606947945109659609402522887971089314566913686722874894056010150330861792868092087476091782493858900971490967598526136554978189312978482168299894872265880485756401427047755513237964145152374623436454285844479526586782105114135473573952311342716610213596953623144295248493718711014576540359027993440374200731057853906219838744780847848968332144571386875194350643021845319104848100537061468067491927819119793995206141966342875444064374512371819217999839101591956181467514269123974894090718649423196156794520809514655022523160388193014209376213785595663893778708303906979207734672218256259966150142150306803844773454920260541466592520149744285073251866600213243408819071048633173464965145390579626856100550810665879699816357473638405257145910289706414011097120628043903975951567715770042033786993600723055876317635942187312514712053292819182618612586732157919841484882916447060957527069572209175671167229109816909152801735067127485832228718352093539657251210835791513698820914442100675103346711031412671113699086585163983150197016515116851714376576183515565088490998985998238734552833163550764791853589322618548963213293308985706420467525907091548141654985946163718027098199430992448895757128289059232332609729971208443357326548938239119325974636673058360414281388303203824903758985243744170291327656180937734440307074692112019130203303801976211011004492932151608424448596376698389522868478312355265821314495768572624334418930396864262434107732269780280731891544110104468232527162010526522721116603966655730925471105578537634668206531098965269186205647693125705863566201855810072936065987648611791045334885034611365768675324944166803962657978771855608455296541266540853061434443185867697514566140680070023787765913440171274947042056223053899456131407112700040785473326993908145466464588079727082668306343285878569830523580893306575740679545716377525420211495576158140025012622859413021647155097925923099079654737612551765675135751782966645477917450112996148903046399471329621073404375189573596145890193897131117904297828564750320319869151402870808599048010941214722131794764777262241425485454033215718530614228813758504306332175182979866223717215916077166925474873898665494945011465406284336639379003976926567214638530673609657120918076383271664162748888007869256029022847210403172118608204190004229661711963779213375751149595015660496318629472654736425230817703675159067350235072835405670403867435136222247715891504953098444893330963408780769325993978054193414473774418426312986080998886874132604721569516239658645730216315981931951673538129741677294786724229246543668009806769282382806899640048243540370141631496589794092432378969070697794223625082216889573837986230015937764716512289357860158816175578297352334460428151262720373431465319777741603199066554187639792933441952154134189948544473456738316249934191318148092777710386387734317720754565453220777092120190516609628049092636019759882816133231666365286193266863360627356763035447762803504507772355471058595487027908143562401451718062464362679456127531813407833033625423278394497538243720583531147711992606381334677687969597030983391307710987040859133746414428227726346594704745878477872019277152807317679077071572134447306057007334924369311383504931631284042512192565179806941135280131470130478164378851852909285452011658393419656213491434159562586586557055269049652098580338507224264829397285847831630577775606888764462482468579260395352773480304802900587607582510474709164396136267604492562742042083208566119062545433721315359584506877246029016187667952406163425225771954291629919306455377991403734043287526288896399587947572917464263574552540790914513571113694109119393251910760208252026187985318877058429725916778131496990090192116971737278476847268608490033770242429165130050051683233643503895170298939223345172201381280696501178440874519601212285993716231301711444846409038906449544400619869075485160263275052983491874078668088183385102283345085048608250393021332197155184306354550076682829493041377655279397517546139539846833936383047461199665385815384205685338621867252334028308711232827892125077126294632295639898989358211674562701021835646220134967151881909730381198004973407239610368540664319395097901906996395524530054505806855019567302292191393391856803449039820595510022635353619204199474553859381023439554495977837790237421617271117236434354394782218185286240851400666044332588856986705431547069657474585503323233421073015459405165537906866273337995851156257843229882737231989875714159578111963583300594087306812160287649628674460477464915995054973742562690104903778198683593814657412680492564879855614537234786733039046883834363465537949864192705638729317487233208376011230299113679386270894387993620162951541337142489283072201269014754668476535761647737946752004907571555278196536213239264061601363581559074220202031872776052772190055614842555187925303435139844253223415762336106425063904975008656271095359194658975141310348227693062474353632569160781547818115284366795706110861533150445212747392454494542368288606134084148637767009612071512491404302725386076482363414334623518975766452164137679690314950191085759844239198629164219399490723623464684411739403265918404437805133389452574239950829659122850855582157250310712570126683024029295252201187267675622041542051618416348475651699981161410100299607838690929160302884002691041407928862150784245167090870006992821206604183718065355672525325675 ), { "title": "Does not exist yet!", "alt": " ", "img": "https://www.explainxkcd.com/wiki/images/9/92/not_found.png", "num": 404 }) def test_match_numbers_strict(self): self.assertEqual(self.bot.match_numbers("Test", True), []) self.assertEqual(self.bot.match_numbers("!123 !123", True), ["123"]) self.assertEqual(self.bot.match_numbers("7? !080. !99", True), ["80", "99"]) self.assertEqual(self.bot.match_numbers("!900 10000", True), ["900"]) self.assertEqual( self.bot.match_numbers("!Test !001234 5678 !-1", True), ["1234"]) self.assertEqual(len(self.bot.match_numbers("!random random", True)), 1) self.assertEqual( self.bot.match_numbers("!3 relevant xkcd: 6, !relevant xkcd: 5 1", True), ["3", "6", "5"]) self.assertEqual(self.bot.match_numbers("!9 !23...25 #9...7", True), ["9", "23", "24", "25", "7", "8"]) self.assertEqual( self.bot.match_numbers( "https://www.google.com/maps/dir/Okay,+Oklahoma,+USA/Whynot,+North+Carolina+27341,+USA/@35.283469,-92.0617932,6z/data=!3m1!4b1!4m14!4m13!1m5!1m1!1s0x87b60bd75e51d2d3:0x120194060a920373!2m2!1d-95.3182985!2d35.8506548!1m5!1m1!1s0x8853609903e1db5b:0x15b011f26e28c49e!2m2!1d-79.7480465!2d35.5402827!3e0", True), []) self.assertEqual(self.bot.match_numbers("number is mid!1string", True), []) self.assertEqual( self.bot.match_numbers("!12 hello https://www.google.com/!1", True), ["12"]) self.assertEqual(self.bot.match_numbers("#1mid#6number", True), ["1"]) def test_find_numbers_non_strict(self): self.assertEqual(self.bot.match_numbers("Test", False), []) self.assertEqual(self.bot.match_numbers("!123.", False), ["123"]) self.assertEqual( self.bot.match_numbers("07/ !080. !00099 99 0099", False), ["7", "80", "99"]) self.assertEqual(self.bot.match_numbers("!900 010000", False), ["900", "10000"]) self.assertEqual(self.bot.match_numbers("!Test !1234 5678 !-1", False), ["1234", "5678", "1"]) self.assertEqual(len(self.bot.match_numbers("!random random", False)), 2) self.assertEqual( self.bot.match_numbers("!3 relevant xkcd: 6, !relevant xkcd: 5 1", False), ["3", "6", "5", "1"]) self.assertEqual(self.bot.match_numbers("9 23...25 9...7", False), ["9", "23", "25", "7", "24", "8"]) def test_response_size_limited(self): comment = CommentMock() too_big_response = ''.join( ['1' for _ in range(RESPONSE_CHAR_LIMIT + 1)]) self.bot.reply(comment=comment, response=too_big_response) self.assertEqual( comment.reply_called, 0, f'Expected no reply() call, saw {comment.reply_called}') self.assertEqual(comment.save_called, 1, f'Expected 1 save() call, saw {comment.save_called}') def test_combine_responses_truncates_response(self): # There may be a less fragile way of constructing this test, but this will test the functionality. too_many_responses = [f'1' for _ in range(RESPONSE_COUNT_LIMIT + 1)] expected_combined_response_length = \ len('\n'.join(too_many_responses[:RESPONSE_COUNT_LIMIT])) + \ len(self.bot._closer()) + len('\n') actual_combined_response = self.bot.combine_responses( responses=too_many_responses) self.assertEqual( len(actual_combined_response), expected_combined_response_length, f'Expected response of length {expected_combined_response_length}, found {len(actual_combined_response)}' ) def test_urlescape(self): expected = textwrap.dedent(""" **[859:](http://xkcd.com/859)** ( **Alt-text:** >!Brains aside, I wonder how many poorly-written xkcd.com-parsing scripts will break on this title (or ;;"\'\'{<<[\' this mouseover text."!< [Image](https://imgs.xkcd.com/comics/%28.png) [Mobile](http://m.xkcd.com/859) [Explanation](http://www.explainxkcd.com/wiki/index.php/859) """) self.assertEqual(self.bot.format_response(self.bot.get_comic(859)), expected) def test_match_titles(self): self.assertEqual( self.bot.match_titles("!6 #irony #36blownApart !1000comics"), ["6", "irony", "36blownApart", "1000comics"]) self.assertEqual(self.bot.match_titles("#dummy!Title"), ["dummy!Title"]) def test_get_comic_by_title(self): self.bot.database.add_comic_title("irony", 6) self.assertEqual( self.bot.get_comic_by_title("IrOnY"), { "month": "1", "num": 6, "link": "", "year": "2006", "news": "", "safe_title": "Irony", "transcript": "Narrator: When self-reference, irony, and meta-humor go too far\nNarrator: A CAUTIONARY TALE\nMan 1: This statement wouldn't be funny if not for irony!\nMan 1: ha ha\nMan 2: ha ha, I guess.\nNarrator: 20,000 years later...\n[[desolate badlands landscape with an imposing sun in the sky]]\n{{It's commonly known that too much perspective can be a downer.}}", "alt": "It's commonly known that too much perspective can be a downer.", "img": "https://imgs.xkcd.com/comics/irony_color.jpg", "title": "Irony", "day": "1" }) self.assertIsNone(self.bot.get_comic_by_title("dummy"))