parent
39b760aafb
commit
8f8d03d695
@ -0,0 +1,12 @@ |
||||
export let gUserSettings = Cookies.getJSON( "user-settings" ) || {} ; //eslint-disable-line no-undef
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
export function saveUserSettings() |
||||
{ |
||||
// save the user settings
|
||||
Cookies.set( //eslint-disable-line no-undef
|
||||
"user-settings", gUserSettings, |
||||
{ SameSite: "strict", expires: 999 } |
||||
) ; |
||||
} |
@ -1,9 +1,17 @@ |
||||
#nav .tabbed-page[data-tabid='search'] .wrapper { |
||||
display: flex ; flex-direction: column ; |
||||
overflow-y: none ; |
||||
} |
||||
|
||||
/* search box */ |
||||
#search-box { display: flex ; padding: 1px ; margin-bottom: 8px ; } |
||||
#search-box { display: flex ; flex-direction: column ; padding: 1px ; margin-bottom: 8px ; } |
||||
#search-box .row { display: flex ; } |
||||
#search-box input#query-string { margin-right: 5px ; flex-grow: 1 ; } |
||||
#search-box .sr-filters { margin-top: 4px ; font-size: 80% ; } |
||||
#search-box .sr-filters input[type="checkbox"] { margin: 0 2px 0 6px ; } |
||||
#search-box .sr-count { flex-grow: 1 ; text-align: right ; font-style: italic ; color: #888 ; } |
||||
|
||||
/* search results */ |
||||
#nav .tabbed-page[data-tabid='search'] .wrapper { overflow-y: none ; } |
||||
#search-results { height: calc(100% - 35px) ; overflow-y: auto ; } |
||||
#search-results { height: 100% ; overflow-y: auto ; } |
||||
#search-results .no-results { font-style: italic ; color: #666 ; } |
||||
#search-results .error .pre { font-family: monospace ; margin: 0.25em 0 0 0.5em ; } |
||||
|
@ -0,0 +1,163 @@ |
||||
/*! |
||||
* JavaScript Cookie v2.2.0 |
||||
* https://github.com/js-cookie/js-cookie
|
||||
* |
||||
* Copyright 2006, 2015 Klaus Hartl & Fagner Brack |
||||
* Released under the MIT license |
||||
*/ |
||||
;(function (factory) { |
||||
var registeredInModuleLoader; |
||||
if (typeof define === 'function' && define.amd) { |
||||
define(factory); |
||||
registeredInModuleLoader = true; |
||||
} |
||||
if (typeof exports === 'object') { |
||||
module.exports = factory(); |
||||
registeredInModuleLoader = true; |
||||
} |
||||
if (!registeredInModuleLoader) { |
||||
var OldCookies = window.Cookies; |
||||
var api = window.Cookies = factory(); |
||||
api.noConflict = function () { |
||||
window.Cookies = OldCookies; |
||||
return api; |
||||
}; |
||||
} |
||||
}(function () { |
||||
function extend () { |
||||
var i = 0; |
||||
var result = {}; |
||||
for (; i < arguments.length; i++) { |
||||
var attributes = arguments[ i ]; |
||||
for (var key in attributes) { |
||||
result[key] = attributes[key]; |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
function decode (s) { |
||||
return s.replace(/(%[0-9A-Z]{2})+/g, decodeURIComponent); |
||||
} |
||||
|
||||
function init (converter) { |
||||
function api() {} |
||||
|
||||
function set (key, value, attributes) { |
||||
if (typeof document === 'undefined') { |
||||
return; |
||||
} |
||||
|
||||
attributes = extend({ |
||||
path: '/' |
||||
}, api.defaults, attributes); |
||||
|
||||
if (typeof attributes.expires === 'number') { |
||||
attributes.expires = new Date(new Date() * 1 + attributes.expires * 864e+5); |
||||
} |
||||
|
||||
// We're using "expires" because "max-age" is not supported by IE
|
||||
attributes.expires = attributes.expires ? attributes.expires.toUTCString() : ''; |
||||
|
||||
try { |
||||
var result = JSON.stringify(value); |
||||
if (/^[\{\[]/.test(result)) { |
||||
value = result; |
||||
} |
||||
} catch (e) {} |
||||
|
||||
value = converter.write ? |
||||
converter.write(value, key) : |
||||
encodeURIComponent(String(value)) |
||||
.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent); |
||||
|
||||
key = encodeURIComponent(String(key)) |
||||
.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent) |
||||
.replace(/[\(\)]/g, escape); |
||||
|
||||
var stringifiedAttributes = ''; |
||||
for (var attributeName in attributes) { |
||||
if (!attributes[attributeName]) { |
||||
continue; |
||||
} |
||||
stringifiedAttributes += '; ' + attributeName; |
||||
if (attributes[attributeName] === true) { |
||||
continue; |
||||
} |
||||
|
||||
// Considers RFC 6265 section 5.2:
|
||||
// ...
|
||||
// 3. If the remaining unparsed-attributes contains a %x3B (";")
|
||||
// character:
|
||||
// Consume the characters of the unparsed-attributes up to,
|
||||
// not including, the first %x3B (";") character.
|
||||
// ...
|
||||
stringifiedAttributes += '=' + attributes[attributeName].split(';')[0]; |
||||
} |
||||
|
||||
return (document.cookie = key + '=' + value + stringifiedAttributes); |
||||
} |
||||
|
||||
function get (key, json) { |
||||
if (typeof document === 'undefined') { |
||||
return; |
||||
} |
||||
|
||||
var jar = {}; |
||||
// To prevent the for loop in the first place assign an empty array
|
||||
// in case there are no cookies at all.
|
||||
var cookies = document.cookie ? document.cookie.split('; ') : []; |
||||
var i = 0; |
||||
|
||||
for (; i < cookies.length; i++) { |
||||
var parts = cookies[i].split('='); |
||||
var cookie = parts.slice(1).join('='); |
||||
|
||||
if (!json && cookie.charAt(0) === '"') { |
||||
cookie = cookie.slice(1, -1); |
||||
} |
||||
|
||||
try { |
||||
var name = decode(parts[0]); |
||||
cookie = (converter.read || converter)(cookie, name) || |
||||
decode(cookie); |
||||
|
||||
if (json) { |
||||
try { |
||||
cookie = JSON.parse(cookie); |
||||
} catch (e) {} |
||||
} |
||||
|
||||
jar[name] = cookie; |
||||
|
||||
if (key === name) { |
||||
break; |
||||
} |
||||
} catch (e) {} |
||||
} |
||||
|
||||
return key ? jar[key] : jar; |
||||
} |
||||
|
||||
api.set = set; |
||||
api.get = function (key) { |
||||
return get(key, false /* read as raw */); |
||||
}; |
||||
api.getJSON = function (key) { |
||||
return get(key, true /* read as json */); |
||||
}; |
||||
api.remove = function (key, attributes) { |
||||
set(key, '', extend(attributes, { |
||||
expires: -1 |
||||
})); |
||||
}; |
||||
|
||||
api.defaults = {}; |
||||
|
||||
api.withConverter = init; |
||||
|
||||
return api; |
||||
} |
||||
|
||||
return init(function () {}); |
||||
})); |
@ -0,0 +1,5 @@ |
||||
[ |
||||
|
||||
{ "_comment_": "This file is here to fool the front-end in thinking there is index content, thus showing the ASOP filter checkbox." } |
||||
|
||||
] |
@ -0,0 +1,13 @@ |
||||
[ |
||||
|
||||
{ "title": "Red Barricades", |
||||
"chapter_id": "O", |
||||
"page_no": 1, |
||||
"sections": [ |
||||
{ "caption": "1. Debris", "ruleid": "O1" }, |
||||
{ "caption": "2. Railway Embankment", "ruleid": "O2" }, |
||||
{ "caption": "3. Printed Rubble", "ruleid": "O3" } |
||||
] |
||||
} |
||||
|
||||
] |
@ -0,0 +1,6 @@ |
||||
{ |
||||
|
||||
"O6.7": { "caption": "ENCIRCLEMENT", "page_no": 5 } |
||||
|
||||
|
||||
} |
@ -0,0 +1,83 @@ |
||||
[ |
||||
|
||||
{ "title": "Infantry And Basic Game Rules", |
||||
"chapter_id": "A", |
||||
"page_no": 42, |
||||
"sections": [ |
||||
{ "caption": "1. Personnel Counters", "ruleid": "A1" }, |
||||
{ "caption": "2. The Mapboard", "ruleid": "A2" }, |
||||
{ "caption": "3. Basic Sequence Of Play", "ruleid": "A3" } |
||||
] }, |
||||
|
||||
{ "title": "Terrain", |
||||
"chapter_id": "B", |
||||
"page_no": 109, |
||||
"sections": [ |
||||
{ "caption": "1. Open Ground", "ruleid": "B1" }, |
||||
{ "caption": "2. Shellholes", "ruleid": "B2" }, |
||||
{ "caption": "3. Roads", "ruleid": "B3" } |
||||
] }, |
||||
|
||||
{ "title": "Ordnance & Offboard Artillery (OBA)", |
||||
"chapter_id": "C", |
||||
"page_no": 158, |
||||
"sections": [ |
||||
{ "caption": "1. Offboard Artillery (OBA)", "ruleid": "C1" }, |
||||
{ "caption": "2. Gun Classifications", "ruleid": "C2" }, |
||||
{ "caption": "3. The To Hit Process", "ruleid": "C3" } |
||||
] }, |
||||
|
||||
{ "title": "Vehicles", |
||||
"chapter_id": "D", |
||||
"page_no": 187, |
||||
"sections": [ |
||||
{ "caption": "1. Vehicle Counters", "ruleid": "D1" }, |
||||
{ "caption": "2. Vehicular Movement", "ruleid": "D2" }, |
||||
{ "caption": "3. AFV Combat", "ruleid": "D3" } |
||||
] }, |
||||
|
||||
{ "title": "Miscellaneous", |
||||
"chapter_id": "E", |
||||
"page_no": 216, |
||||
"sections": [ |
||||
{ "caption": "1. Night", "ruleid": "E1" }, |
||||
{ "caption": "2. Interrogation", "ruleid": "E2" }, |
||||
{ "caption": "3. Weather", "ruleid": "E3" } |
||||
] }, |
||||
|
||||
{ "title": "North Africa", |
||||
"chapter_id": "F", |
||||
"page_no": 247, |
||||
"sections": [ |
||||
{ "caption": "1. Open Ground", "ruleid": "F1" }, |
||||
{ "caption": "2. Scrub", "ruleid": "F2" }, |
||||
{ "caption": "3. Hammada", "ruleid": "F3" } |
||||
] }, |
||||
|
||||
{ "title": "Pacific Theater", |
||||
"chapter_id": "G", |
||||
"page_no": 270, |
||||
"sections": [ |
||||
{ "caption": "1. The Japanese", "ruleid": "G1" }, |
||||
{ "caption": "2. Jungle", "ruleid": "G2" }, |
||||
{ "caption": "3. Bamboo", "ruleid": "G3" } |
||||
] }, |
||||
|
||||
{ "title": "Deluxe ASL", |
||||
"chapter_id": "J", |
||||
"page_no": 593, |
||||
"sections": [ |
||||
{ "caption": "1. Miniatures", "ruleid": "J1" }, |
||||
{ "caption": "2. Converting ASL Rules To Deluxe ASL", "ruleid": "J2" } |
||||
] }, |
||||
|
||||
{ "title": "Korean War", |
||||
"chapter_id": "W", |
||||
"page_no": 647, |
||||
"sections": [ |
||||
{ "caption": "1. KW Terrain", "ruleid": "W1" }, |
||||
{ "caption": "2. The Americans", "ruleid": "W2" }, |
||||
{ "caption": "3. The South Koreans", "ruleid": "W3" } |
||||
] } |
||||
|
||||
] |
@ -0,0 +1,12 @@ |
||||
{ |
||||
|
||||
"A": { |
||||
|
||||
"1": { |
||||
"captions": [ { "caption": "ERRORS", "ruleid": "A.2" } ], |
||||
"content": "To the unscrupulous, these mechanics for handling errors might be viewed as a license to steal. We do not mean to insinuate that cheating is acceptable behavior; rather, that backing up a game to accommodate a forgotten rule/unit is a drag on play. In essence, the player's knowledge of the system and methodical application of its benefits as opportunities present themselves becomes an added skill factor better reflecting the abilities of an experienced battlefield commander. Ultimately, the only protection against a cheater is not to play him." |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
@ -0,0 +1,80 @@ |
||||
[ |
||||
|
||||
{ "title": "Errors", |
||||
"ruleids": [ "A.2" ] |
||||
}, |
||||
|
||||
{ "title": "CCPh", |
||||
"subtitle": "Close Combat Phase", |
||||
"content": "This rule has had an errata attached to it. Click through to see it.", |
||||
"ruleids": [ "A3.8" ], |
||||
"rulerefs": [ |
||||
{ "caption": "ENEMY Attacks", "ruleids": [ "S11.5" ] }, |
||||
{ "caption": "dropping SW before CC", "ruleids": [ "A4.43" ] } |
||||
] |
||||
}, |
||||
|
||||
{ "title": "CC", |
||||
"subtitle": "Close Combat", |
||||
"ruleids": [ "A11" ], |
||||
"rulerefs": [ |
||||
{ "caption": "Armor Leader", "ruleids": [ "D3.44" ] }, |
||||
{ "caption": "ATMM", "ruleids": [ "C13.7" ] }, |
||||
{ "caption": "Berserk", "ruleids": [ "A15.43" ] }, |
||||
{ "caption": "units in Boats", "ruleids": [ "E5.6" ] }, |
||||
{ "caption": "Broken Units", "ruleids": [ "A11.16" ] }, |
||||
{ "caption": "BU", "ruleids": [ "D5.2" ] } |
||||
] |
||||
}, |
||||
|
||||
{ "title": "BU", |
||||
"subtitle": "Buttoned Up", |
||||
"ruleids": [ "D5.2" ], |
||||
"rulerefs": [ |
||||
{ "caption": "Amphibian", "ruleids": [ "G14.31" ] }, |
||||
{ "caption": "can change BU/CE status during MPh or APh", "ruleids": [ "D5.33" ] }, |
||||
{ "caption": "ENEMY Vehicles", "ruleids": [ "S9.31" ] }, |
||||
{ "caption": "MA Interdiction NA", "ruleids": [ "A10.532" ] }, |
||||
{ "caption": "OT AFV", "ruleids": [ "D6.61" ] }, |
||||
{ "caption": "Passengers on LC", "ruleids": [ "G12.123" ] }, |
||||
{ "caption": "Pinning", "ruleids": [ "A7.82" ] }, |
||||
{ "caption": "Secret Record", "ruleids": [ "A12.2" ] }, |
||||
{ "caption": "sN", "ruleids": [ "D13.34" ] }, |
||||
{ "caption": "Sighting TC", "ruleids": [ "E7.43" ] }, |
||||
{ "caption": "sM", "ruleids": [ "D13.3" ] }, |
||||
{ "caption": "TH Penalty", "ruleids": [ "C5.9" ] } |
||||
] |
||||
}, |
||||
|
||||
{ "title": "Encirclement", |
||||
"ruleids": [ "A7.7" ], |
||||
"rulerefs": [ |
||||
{ "caption": "Cellars NA", "ruleids": [ "O6.7", "R4.7" ] }, |
||||
{ "caption": "Japanese do not lower their morale by 1", "ruleids": [ "G1.62" ] }, |
||||
{ "caption": "Mission End", "ruleids": [ "S17.43" ] }, |
||||
{ "caption": "EXC Pillbox", "ruleids": [ "B30.32" ] }, |
||||
{ "caption": "RePh", "ruleids": [ "O11.6041", "P8.6041", "Q9.6041", "R9.6041", "T15.6041", "T15.606" ] }, |
||||
{ "caption": "Rout Effects", "ruleids": [ "A20.21" ] }, |
||||
{ "caption": "Upper Level", "ruleids": [ "A7.72" ] } |
||||
] |
||||
}, |
||||
|
||||
{ "title": "White Phosphorus", |
||||
"ruleids": [ "A24.3" ], |
||||
"see_also": [ "WP" ] |
||||
}, |
||||
|
||||
{ "title": "WP", |
||||
"subtitle": "White Phosphorus", |
||||
"ruleids": [ "A24.3" ], |
||||
"rulerefs": [ |
||||
{ "caption": "vs Cave", "ruleids": [ "G11.85" ] }, |
||||
{ "caption": "DM", "ruleids": [ "A10.62" ] }, |
||||
{ "caption": "FFE", "ruleids": [ "C3.76" ] }, |
||||
{ "caption": "Germans in ABtF", "ruleids": [ "SSR18" ] }, |
||||
{ "caption": "Straying", "ruleids": [ "E1.53" ] }, |
||||
{ "caption": "G.M.D.", "ruleids": [ "G18.21" ] } |
||||
] |
||||
} |
||||
|
||||
] |
@ -0,0 +1,37 @@ |
||||
{ |
||||
|
||||
"A.2": { "caption": "ERRORS" }, |
||||
"A3.8": { "caption": "CLOSE COMBAT PHASE (CCPh)" }, |
||||
"A7.7": { "caption": "ENCIRCLEMENT" }, |
||||
"A11": { "caption": "CLOSE COMBAT (CC)" }, |
||||
"A24.3": { "caption": "WHITE PHOSPHORUS (WP)" }, |
||||
"D5.2": { "caption": "BUTTONED UP (BU)" }, |
||||
|
||||
"A1": { "caption": "PERSONNEL COUNTERS" }, |
||||
"A2": { "caption": "THE MAPBOARD" }, |
||||
"A3": { "caption": "BASIC SEQUENCE OF PLAY" }, |
||||
"B1": { "caption": "OPEN GROUND" }, |
||||
"B2": { "caption": "SHELLHOLES" }, |
||||
"B3": { "caption": "ROADS" }, |
||||
"C1": { "caption": "OFFBOARD ARTILLERY (OBA)" }, |
||||
"C2": { "caption": "GUN CLASSIFICATIONS" }, |
||||
"C3": { "caption": "THE TO HIT PROCESS" }, |
||||
"D1": { "caption": "VEHICLE COUNTERS" }, |
||||
"D2": { "caption": "VEHICULAR MOVEMENT" }, |
||||
"D3": { "caption": "AFV COMBAT" }, |
||||
"E1": { "caption": "NIGHT" }, |
||||
"E2": { "caption": "INTERROGATION" }, |
||||
"E3": { "caption": "WEATHER" }, |
||||
"F1": { "caption": "OPEN GROUND" }, |
||||
"F2": { "caption": "SCRUB" }, |
||||
"F3": { "caption": "HAMMADA" }, |
||||
"G1": { "caption": "THE JAPANESE" }, |
||||
"G2": { "caption": "JUNGLE" }, |
||||
"G3": { "caption": "BAMBOO" }, |
||||
"J1": { "caption": "MINIATURES" }, |
||||
"J2": { "caption": "CONVERTING ASL RULES TO DELUXE ASL" }, |
||||
"W1": { "caption": "KW TERRAIN" }, |
||||
"W2": { "caption": "THE AMERICANS" }, |
||||
"W3": { "caption": "THE SOUTH KOREANS" } |
||||
|
||||
} |
After Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1,7 @@ |
||||
[ |
||||
|
||||
{ "ruleid": "A24.3", |
||||
"content": "Mmmm, White Phosphorous. Is there anything it can't do...?" |
||||
} |
||||
|
||||
] |
@ -0,0 +1 @@ |
||||
../asop/asop/ |
@ -0,0 +1,7 @@ |
||||
[ |
||||
|
||||
{ "ruleid": "A3.8", |
||||
"content": "The new eASLRB will, of course, be kept up-to-date, and there will be no need for errata :-), but other rulebooks might, so this is an example of how you would set them up." |
||||
} |
||||
|
||||
] |
@ -0,0 +1,53 @@ |
||||
{ |
||||
|
||||
"Chapter A": [ |
||||
|
||||
{ "caption": "A4.63 & A11.8", |
||||
"ruleids": [ "A4.63", "A11.8" ], |
||||
"content": [ |
||||
{ "question": "In the image (RB map), wherein Rubble is eligible for Street-Fighting Ambush like a building. would a unit in G7 be eligible for Street-Fighting Ambush against an AFV in G8? <p> Could a unit in G7 Dash (through G8) to F8 or H8?", |
||||
"image": "a4.63, a11.8.png", |
||||
"answers": [ |
||||
[ "No to both.", "ps" ] |
||||
] |
||||
} |
||||
] |
||||
}, |
||||
|
||||
{ "caption": "A7.7", |
||||
"ruleids": [ "A7.7" ], |
||||
"content": [ |
||||
{ "question": "All German units combine as a Fire Group to take a 30/+3 shot at the Russian 447. Given that the 247 is one of two units in the Fire Group that potentially enable the shot to cause Encirclement, and that the 247's shot alone is not sufficient to be an Encirclement-causing shot, does the shot from this Fire Group cause Encirclement?", |
||||
"image": "a7.7.png", |
||||
"answers": [ |
||||
[ "Yes.", "ps" ] |
||||
] |
||||
} |
||||
] |
||||
}, |
||||
|
||||
{ "caption": "A7.7 & A23.3", |
||||
"ruleids": [ "A7.7", "A23.3" ], |
||||
"content": [ |
||||
{ "question": "Does a placed DC attack count for encirclement (using the hexside it was placed through as its direction)?", |
||||
"answers": [ |
||||
[ "No.", "ps" ] |
||||
] |
||||
} |
||||
] |
||||
}, |
||||
|
||||
{ "caption": "A24.31", |
||||
"ruleids": [ "A24.31" ], |
||||
"content": [ |
||||
{ "question": "May a MMC attempt to throw WP grenades into its own location? <p> Into an adjacent location solely occupied by friendly units?", |
||||
"answers": [ |
||||
[ "Yes to both; A24.31", "ps" ] |
||||
] |
||||
} |
||||
] |
||||
} |
||||
|
||||
] |
||||
|
||||
} |
After Width: | Height: | Size: 120 KiB |
@ -0,0 +1,6 @@ |
||||
{ |
||||
|
||||
"ps": "Perry Sez", |
||||
"gs": "GameSquad" |
||||
|
||||
} |
@ -0,0 +1,127 @@ |
||||
""" Test search result filtering. """ |
||||
|
||||
from asl_rulebook2.webapp.tests.test_search import do_search, unload_search_results |
||||
from asl_rulebook2.webapp.tests.utils import init_webapp, \ |
||||
check_sr_filters, find_child |
||||
|
||||
# --------------------------------------------------------------------- |
||||
|
||||
def test_sr_filtering( webdriver, webapp ): |
||||
"""Test filtering search results.""" |
||||
|
||||
# initialize |
||||
webapp.control_tests.set_data_dir( "full" ) |
||||
webapp.control_tests.set_app_config_val( "DISABLE_AUTO_SHOW_RULE_INFO", True ) |
||||
init_webapp( webapp, webdriver ) |
||||
check_sr_filters( [ "index", "qa", "errata", "asop-entry" ] ) |
||||
|
||||
def check_sr_count( nvisible, ntotal ): |
||||
"""Check the search result count reported in the UI.""" |
||||
elem = find_child( "#search-box .sr-count" ) |
||||
assert elem.text == "{}/{}".format( nvisible, ntotal ) |
||||
|
||||
def do_test( query_string, sr_type, expected ): |
||||
|
||||
# make sure the checkbox for the specified search result type is enabled |
||||
sel = "#search-box input[type='checkbox'][name='show-{}-sr']".format( sr_type ) |
||||
elem = find_child( sel ) |
||||
assert elem.is_selected() |
||||
|
||||
# do the search |
||||
results = _do_search( query_string ) |
||||
assert results == expected |
||||
check_sr_count( len(expected), len(expected) ) |
||||
|
||||
# filter out the specified type of search result |
||||
find_child( sel ).click() |
||||
results = _unload_search_results() |
||||
sr_type2 = "anno" if sr_type == "errata" else sr_type |
||||
expected2 = [ e for e in expected if e["sr_type"] != sr_type2 ] |
||||
if not expected2: |
||||
expected2 = "All search results have been filtered." |
||||
assert results == expected2 |
||||
check_sr_count( len(expected2) if isinstance(expected2,list) else 0, len(expected) ) |
||||
|
||||
# refresh the page |
||||
webdriver.refresh() |
||||
elem = find_child( sel ) |
||||
assert not elem.is_selected() |
||||
|
||||
# repeat the search |
||||
results = _do_search( query_string ) |
||||
assert results == expected2 |
||||
check_sr_count( len(expected2) if isinstance(expected2,list) else 0, len(expected) ) |
||||
|
||||
# re-enable the specified type of search result |
||||
elem.click() |
||||
results = _unload_search_results() |
||||
assert results == expected |
||||
check_sr_count( len(expected), len(expected) ) |
||||
|
||||
# test filtering index search results |
||||
do_test( "bu", "index", [ |
||||
{ "sr_type": "index", "title": "((BU))" }, |
||||
{ "sr_type": "index", "title": "CC" }, |
||||
] ) |
||||
|
||||
# test filtering Q+A search results |
||||
do_test( "encirclement", "qa", [ |
||||
{ "sr_type": "index", "title": "((Encirclement))" }, |
||||
{ "sr_type": "qa", "caption": "A7.7" }, |
||||
{ "sr_type": "qa", "caption": "A7.7 & A23.3" }, |
||||
] ) |
||||
|
||||
# test filtering errata search results |
||||
do_test( "errata", "errata", [ |
||||
{ "sr_type": "index", "title": "CCPh" }, |
||||
{ "sr_type": "anno", "caption": "A3.8" }, |
||||
] ) |
||||
|
||||
# test filtering ASOP search results |
||||
do_test( "cc", "asop-entry", [ |
||||
{ "sr_type": "index", "title": "((CC))" }, |
||||
{ "sr_type": "index", "title": "CCPh" }, |
||||
{ "sr_type": "asop-entry", "caption": "8.2: DURING LOCATION's CCPh (ASOP)" }, |
||||
] ) |
||||
|
||||
# --------------------------------------------------------------------- |
||||
|
||||
def test_sr_count( webdriver, webapp ): |
||||
"""Test the search result count reported in the UI.""" |
||||
|
||||
# initialize |
||||
webapp.control_tests.set_data_dir( "full" ) |
||||
init_webapp( webapp, webdriver ) |
||||
|
||||
# NOTE: Most of the testing is done in test_sr_filtering(), we just test error cases here. |
||||
|
||||
# check the search result when there are no search results |
||||
results = do_search( "xyz" ) |
||||
assert results is None |
||||
assert find_child( "#search-box .sr-count" ).text == "" |
||||
|
||||
# check the search result when there was an error |
||||
results = do_search( "!:simulated-error:!" ) |
||||
assert results.startswith( "Search error:" ) |
||||
assert find_child( "#search-box .sr-count" ).text == "" |
||||
|
||||
# --------------------------------------------------------------------- |
||||
|
||||
def _do_search( query_string ): |
||||
"""Do a search.""" |
||||
return _strip_results( do_search( query_string ) ) |
||||
|
||||
def _unload_search_results(): |
||||
"""Unload the current search results.""" |
||||
return _strip_results( unload_search_results() ) |
||||
|
||||
def _strip_results( results ): |
||||
"""Strip search results down to only include what we're interested in.""" |
||||
if results is None or isinstance( results, str ): |
||||
return results |
||||
for result_no, result in enumerate( results ): |
||||
results[ result_no ] = { |
||||
key: val for key, val in result.items() |
||||
if key in ( "sr_type", "title", "caption" ) |
||||
} |
||||
return results |
Loading…
Reference in new issue