1import os 2from datetime import date 3 4from lektor.context import Context 5from lektor.db import get_alts 6 7 8def test_root(pad): 9 record = pad.root 10 11 assert record is not None 12 assert record["title"] == "Welcome" 13 assert record["_template"] == "page.html" 14 assert record["_alt"] == "_primary" 15 assert record["_slug"] == "" 16 assert record["_id"] == "" 17 assert record["_path"] == "/" 18 19 20def test_project_implied_model(pad): 21 project = pad.query("/projects").first() 22 assert project is not None 23 assert project["_model"] == "project" 24 25 26def test_child_query_visibility_setting(pad): 27 projects = pad.get("/projects") 28 assert not projects.children._include_hidden 29 30 project_query = pad.query("/projects") 31 assert project_query._include_hidden 32 assert not project_query._include_undiscoverable 33 34 35def test_alt_fallback(pad): 36 # page that is missing a german tranlation 37 wolf_page = pad.get("/projects/wolf", alt="de") 38 39 # Falls back to primary 40 assert wolf_page.alt == "de" 41 assert wolf_page["_source_alt"] == "_primary" 42 assert wolf_page["name"] == "Wolf" 43 44 # If we ask for the alts of that page, we will only get english 45 assert get_alts(wolf_page) == ["en"] 46 47 # Unless we include fallbacks in which case we will also see german 48 # show up in the list. 49 assert get_alts(wolf_page, fallback=True) == ["en", "de"] 50 51 52def test_alt_parent(pad): 53 wolf_page = pad.get("/projects/wolf", alt="de") 54 assert wolf_page.alt == "de" 55 assert wolf_page.alt == wolf_page.parent.alt 56 57 58def test_url_matching_with_customized_slug_in_alt(pad): 59 en = pad.resolve_url_path("/projects/slave/") 60 assert en.alt == "en" 61 assert en["_source_alt"] == "_primary" 62 assert en.path == "/projects/slave" 63 64 de = pad.resolve_url_path("/de/projects/sklave/") 65 assert de.alt == "de" 66 assert de["_source_alt"] == "de" 67 assert de.path == "/projects/slave" 68 69 assert get_alts(en) == ["en", "de"] 70 71 72def test_basic_alts(pad): 73 with Context(pad=pad): 74 assert get_alts() == ["en", "de"] 75 76 77def test_basic_query_syntax(pad, F): 78 projects = pad.get("/projects") 79 80 encumbered = ( 81 projects.children.filter((F._slug == "master") | (F._slug == "slave")) 82 .order_by("_slug") 83 .all() 84 ) 85 86 assert len(encumbered) == 2 87 assert [x["name"] for x in encumbered] == ["Master", "Slave"] 88 89 90def test_basic_query_syntax_template(pad, eval_expr): 91 projects = pad.get("/projects") 92 93 encumbered = eval_expr( 94 """ 95 this.children.filter( 96 (F._slug == 'master').or(F._slug == 'slave') 97 ).order_by('_slug') 98 """, 99 pad=pad, 100 this=projects, 101 ).all() 102 103 assert len(encumbered) == 2 104 assert [x["name"] for x in encumbered] == ["Master", "Slave"] 105 106 107def test_is_child_of(pad): 108 projects = pad.get("/projects") 109 assert projects.is_child_of(projects) 110 assert not projects.is_child_of(projects, strict=True) 111 child = projects.children.first() 112 assert child.is_child_of(projects) 113 assert child.is_child_of(projects, strict=True) 114 115 116def test_undiscoverable_basics(pad): 117 projects = pad.query("/projects") 118 assert projects.count() == 8 119 assert projects.include_undiscoverable(True).count() == 9 120 assert pad.get("/projects").children.count() == 8 121 assert "secret" not in [x["_id"] for x in pad.get("/projects").children] 122 assert not projects._include_undiscoverable 123 assert projects._include_hidden 124 125 secret = pad.get("/projects/secret") 126 assert secret.is_undiscoverable 127 assert secret.url_path == "/projects/secret/" 128 129 q = secret.children 130 assert q._include_undiscoverable is False 131 assert q._include_hidden is None 132 q = q.include_undiscoverable(True) 133 assert q._include_undiscoverable is True 134 assert q._include_hidden is False 135 136 secret = pad.resolve_url_path("/projects/secret") 137 assert secret is not None 138 assert secret.path == "/projects/secret" 139 140 141def test_attachment_api(pad): 142 from lektor.db import Image, Video 143 144 root = pad.root 145 root_attachments = [ 146 "hello.txt", 147 "test-progressive.jpg", 148 "test-sof-last.jpg", 149 "test.jpg", 150 "test.mp4", 151 ] 152 assert root.attachments.count() == len(root_attachments) 153 assert sorted(x["_id"] for x in root.attachments) == root_attachments 154 155 txt = root.attachments.get("hello.txt") 156 assert txt is not None 157 assert txt["_attachment_type"] == "text" 158 assert txt.url_path == "/hello.txt" 159 160 img = root.attachments.get("test.jpg") 161 assert img is not None 162 assert img["_attachment_type"] == "image" 163 assert isinstance(img, Image) 164 assert img.url_path == "/test.jpg" 165 166 video = root.attachments.get("test.mp4") 167 assert video is not None 168 assert video["_attachment_type"] == "video" 169 assert isinstance(video, Video) 170 assert video.url_path == "/test.mp4" 171 172 173def test_query_normalization(pad): 174 projects = pad.get("projects") 175 assert pad.get("projects") is projects 176 assert pad.get("/projects") is projects 177 assert pad.get("/projects/.") is projects 178 assert pad.get("//projects/.") is projects 179 180 181def test_distinct(pad): 182 posts = pad.query("blog") 183 distinct_categories = posts.distinct("category") 184 assert isinstance(distinct_categories, set) 185 assert distinct_categories == set(["My Category"]) 186 distinct_tags = posts.distinct("tags") 187 assert isinstance(distinct_tags, set) 188 assert distinct_tags == set(["tag1", "tag2", "tag3"]) 189 distinct_pub_dates = posts.distinct("pub_date") 190 assert distinct_pub_dates == set([date(2015, 12, 12), date(2015, 12, 13)]) 191 assert posts.distinct("foo") == set() 192 # Post 2 has no summary; check we don't include Undefined in distinct(). 193 assert posts.distinct("summary") == set(["hello"]) 194 195 196def test_root_pagination(scratch_project, scratch_env): 197 base = scratch_project.tree 198 with open(os.path.join(base, "models", "page.ini"), "w") as f: 199 f.write( 200 "[model]\n" 201 "label = {{ this.title }}\n\n" 202 "[children]\n" 203 "model = page\n" 204 "[pagination]\n" 205 "enabled = yes\n" 206 "per_page = 1\n" 207 "[fields.title]\n" 208 "type = string\n" 209 "[fields.body]\n" 210 "type = markdown\n" 211 ) 212 213 for name in "a", "b", "c": 214 os.mkdir(os.path.join(base, "content", name)) 215 with open(os.path.join(base, "content", name, "contents.lr"), "w") as f: 216 f.write( 217 "_model: page\n" 218 "---\n" 219 "title: Page %s\n" 220 "---\n" 221 "body: Hello World!\n" % name 222 ) 223 224 from lektor.db import Database 225 226 scratch_pad = Database(scratch_env).new_pad() 227 228 root = scratch_pad.root 229 assert root.children.count() == 3 230 231 root_1 = scratch_pad.resolve_url_path("/") 232 assert root_1.page_num == 1 233 234 root_2 = scratch_pad.resolve_url_path("/page/2/") 235 assert root_2.page_num == 2 236 237 238def test_undefined_order(pad): 239 # A missing value should sort after all others. 240 blog_post = pad.db.datamodels["blog-post"] 241 242 from lektor.db import Query 243 244 class TestQuery(Query): 245 def _iterate(self): 246 for day, pub_date in [ 247 (3, "2016-01-03"), 248 (4, None), # No pub_date. 249 (1, "2016-01-01"), 250 (2, "2016-01-02"), 251 ]: 252 yield pad.instance_from_data( 253 {"_id": str(day), "_path": "test/%s" % day, "pub_date": pub_date}, 254 datamodel=blog_post, 255 ) 256 257 ids = [c["_id"] for c in TestQuery("test", pad).order_by("pub_date")] 258 assert ["4", "1", "2", "3"] == ids 259 260 ids = [c["_id"] for c in TestQuery("test", pad).order_by("-pub_date")] 261 assert ["3", "2", "1", "4"] == ids 262 263 264def test_hidden_flag(pad): 265 # This page is just not hidden at all 266 post = pad.get("blog/post1") 267 assert not post.is_hidden 268 269 # The root is never hidden itself unless forced 270 root = pad.get("/") 271 assert not root.is_hidden 272 273 # The container is hidden 274 container = pad.get("extra/container") 275 assert container.is_hidden 276 277 # But the child of the container is not 278 a = pad.get("extra/container/a") 279 assert not a.is_hidden 280 assert container.children.all() == [a] 281 282 # Attachments are also always visible 283 attachment = pad.get("extra/container/hello.txt") 284 assert not attachment.is_hidden 285 286 287def test_default_order_by(scratch_project, scratch_env): 288 from lektor.db import Database 289 290 tree = scratch_project.tree 291 with open(os.path.join(tree, "models", "mymodel.ini"), "w") as f: 292 f.write( 293 "[children]\n" 294 "order_by = title\n" 295 "[attachments]\n" 296 "order_by = attachment_filename\n" 297 ) 298 os.mkdir(os.path.join(tree, "content", "myobj")) 299 with open(os.path.join(tree, "content", "myobj", "contents.lr"), "w") as f: 300 f.write("_model: mymodel\n" "---\n" "title: My Test Object\n") 301 302 pad = Database(scratch_env).new_pad() 303 myobj = pad.get("/myobj") 304 children = myobj.children 305 assert list(children.get_order_by()) == ["title"] 306 assert list(children.order_by("explicit").get_order_by()) == ["explicit"] 307 assert list(myobj.attachments.get_order_by()) == ["attachment_filename"] 308 309 310def test_offset_without_limit_query(pad): 311 projects = pad.get("/projects") 312 313 x = projects.children.offset(1).order_by("_slug").first() 314 315 assert x["name"] == "Coffee" 316