def test_mode_fully_specified(): foo = Library('foo', '') k_debug = Resource(foo, 'k-debug.js') k = Resource(foo, 'k.js', debug=k_debug) needed = NeededResources() needed.need(k) assert needed.resources() == [k] needed = NeededResources(debug=True) needed.need(k) assert needed.resources() == [k_debug] # If no minified can be found, the 'raw' resource is taken. needed = NeededResources(minified=True) needed.need(k) assert needed.resources() == [k] with pytest.raises(ConfigurationError): NeededResources(debug=True, minified=True) # If only a minified resource is defined, debug returns the raw version. x = Resource(foo, 'x.js', minified='x-min.js') needed = NeededResources(debug=True) needed.need(x) assert needed.resources() == [x]
def test_rollup_cannot(): foo = Library('foo', '') b1 = Resource(foo, 'b1.js') b2 = Resource(foo, 'b2.js') giant = Resource(foo, 'giant.js', supersedes=[b1, b2]) needed = NeededResources(rollup=True) needed.need(b1) assert needed.resources() == [b1] assert giant not in needed.resources()
def test_fill_slot_wrong_extension(): needed = NeededResources() lib = Library("lib", "") slot = Slot(lib, ".js") a = Resource(lib, "a.js", depends=[slot]) b = Resource(lib, "b.css") needed.need(a, {slot: b}) with pytest.raises(SlotError): needed.resources()
def test_mode_shortcut(): foo = Library('foo', '') k = Resource(foo, 'k.js', debug='k-debug.js') needed = NeededResources() needed.need(k) assert needed.resources() == [k] needed = NeededResources(debug=True) needed.need(k) assert len(needed.resources()) == 1 assert needed.resources()[0].relpath == 'k-debug.js'
def test_rollup_size_competing(): foo = Library('foo', '') d1 = Resource(foo, 'd1.js') d2 = Resource(foo, 'd2.js') d3 = Resource(foo, 'd3.js') giant = Resource(foo, 'giant.js', supersedes=[d1, d2]) giant_bigger = Resource(foo, 'giant-bigger.js', supersedes=[d1, d2, d3]) needed = NeededResources(rollup=True) needed.need(d1) needed.need(d2) needed.need(d3) assert needed.resources() == [giant_bigger] assert giant not in needed.resources()
def test_dont_fill_required_slot(): needed = NeededResources() lib = Library("lib", "") slot = Slot(lib, ".js") a = Resource(lib, "a.js", depends=[slot]) b = Resource(lib, "b.js") needed.need(a) with pytest.raises(SlotError): needed.resources()
def test_slot_depends_incorrect(): needed = NeededResources() lib = Library("lib", "") c = Resource(lib, "c.js") slot = Slot(lib, ".js", depends=[c]) a = Resource(lib, "a.js", depends=[slot]) d = Resource(lib, "d.js") b = Resource(lib, "b.js", depends=[d]) needed.need(a, {slot: b}) with pytest.raises(SlotError): needed.resources()
def test_redundant_more_complicated(): foo = Library('foo', '') a1 = Resource(foo, 'a1.js') a2 = Resource(foo, 'a2.js', depends=[a1]) a3 = Resource(foo, 'a3.js', depends=[a2]) a4 = Resource(foo, 'a4.js', depends=[a1]) needed = NeededResources() needed.need(a3) assert needed.resources() == [a1, a2, a3] needed.need(a4) # a4 is sorted before a3, because it is less deep # in the dependency tree assert needed.resources() == [a1, a2, a4, a3]
def test_library_ordering_bug(): jquery_lib = Library('jquery', '') jqueryui_lib = Library('jqueryui', '') obviel_lib = Library('obviel', '') bread_lib = Library('bread', '') app_lib = Library('app', '') jquery = Resource(jquery_lib, 'jquery.js') jqueryui = Resource(jqueryui_lib, 'jqueryui.js', depends=[jquery]) obviel = Resource(obviel_lib, 'obviel.js', depends=[jquery]) obviel_forms = Resource(obviel_lib, 'obviel_forms.js', depends=[obviel]) obviel_datepicker = Resource(obviel_lib, 'obviel_datepicker.js', depends=[obviel_forms, jqueryui]) vtab = Resource(bread_lib, 'vtab.js', depends=[jqueryui]) tabview = Resource(bread_lib, 'tabview.js', depends=[obviel, vtab]) bread = Resource(bread_lib, 'bread.js', depends=[tabview, obviel_forms]) app = Resource(app_lib, 'app.js', depends=[bread, obviel_datepicker]) needed = NeededResources() needed.need(app) resources = needed.resources() for resource in resources: print resource, resource.library.library_nr assert resources == [ jquery, jqueryui, obviel, obviel_forms, obviel_datepicker, vtab, tabview, bread, app ]
def test_library_ordering_bug(): jquery_lib = Library('jquery', '') jqueryui_lib = Library('jqueryui', '') obviel_lib = Library('obviel', '') bread_lib = Library('bread', '') app_lib = Library('app', '') jquery = Resource(jquery_lib, 'jquery.js') jqueryui = Resource(jqueryui_lib, 'jqueryui.js', depends=[jquery]) obviel = Resource(obviel_lib, 'obviel.js', depends=[jquery]) obviel_forms = Resource(obviel_lib, 'obviel_forms.js', depends=[obviel]) obviel_datepicker = Resource(obviel_lib, 'obviel_datepicker.js', depends=[obviel_forms, jqueryui]) vtab = Resource(bread_lib, 'vtab.js', depends=[jqueryui]) tabview = Resource(bread_lib, 'tabview.js', depends=[obviel, vtab]) bread = Resource(bread_lib, 'bread.js', depends=[tabview, obviel_forms]) app = Resource(app_lib, 'app.js', depends=[bread, obviel_datepicker]) needed = NeededResources() needed.need(app) resources = needed.resources() for resource in resources: print resource, resource.library.library_nr assert resources == [jquery, jqueryui, obviel, obviel_forms, obviel_datepicker, vtab, tabview, bread, app]
def test_rollup_modes(): foo = Library('foo', '') f1 = Resource(foo, 'f1.js', debug='f1-debug.js') f2 = Resource(foo, 'f2.js', debug='f2-debug.js') giantf = Resource(foo, 'giantf.js', supersedes=[f1, f2], debug='giantf-debug.js') needed = NeededResources(rollup=True) needed.need(f1) needed.need(f2) assert needed.resources() == [giantf] needed = NeededResources(rollup=True, debug=True) needed.need(f1) needed.need(f2) assert needed.resources() == [giantf.modes['debug']]
def test_no_need_to_fill_in_not_required(): lib = Library("lib", "") slot = Slot(lib, ".js", required=False) a = Resource(lib, "a.js", depends=[slot]) needed = NeededResources(resources=[a]) # slot wasn't required and not filled in, so filled slot doesn't show up assert needed.resources() == set([a])
def test_redundant_resource(): foo = Library('foo', '') x1 = Resource(foo, 'a.js') x2 = Resource(foo, 'b.css') y1 = Resource(foo, 'c.js', depends=[x1, x2]) needed = NeededResources() needed.need(y1) needed.need(y1) assert needed.resources() == [x2, x1, y1] needed.need(x1) assert needed.resources() == [x2, x1, y1] needed.need(x2) assert needed.resources() == [x2, x1, y1]
def test_slot_with_default_uses_default_if_nothing_given_in_need(): lib = Library("lib", "") default_resource_for_slot = Resource(lib, "b.js") slot = Slot(lib, ".js", default=default_resource_for_slot) a = Resource(lib, "a.js", depends=[slot]) needed = NeededResources(resources=[a]) relpaths = [r.relpath for r in sort_resources(needed.resources())] assert relpaths == ["b.js", "a.js"]
def test_rollup_without_mode(): foo = Library('foo', '') h1 = Resource(foo, 'h1.js', debug='h1-debug.js') h2 = Resource(foo, 'h2.js', debug='h2-debug.js') gianth = Resource(foo, 'gianth.js', supersedes=[h1, h2]) needed = NeededResources(resources=[h1, h2], rollup=True, debug=True) # no mode available for rollup, use the rollup. assert needed.resources() == [gianth]
def test_bundle_single_dont_bundle_entry(): foo = Library('foo', '') a = Resource(foo, 'a.js', dont_bundle=True) needed = NeededResources(bundle=True) needed.need(a) resources = needed.resources() assert resources == [a]
def test_bundle_single_entry(): # we can successfully bundle a single resource (it's not bundled though) foo = Library('foo', '') a = Resource(foo, 'a.js') needed = NeededResources(bundle=True) needed.need(a) resources = needed.resources() assert resources == [a]
def test_clear(): foo = Library('foo', '') a1 = Resource(foo, 'a1.js') a2 = Resource(foo, 'a2.js', depends=[a1]) a3 = Resource(foo, 'a3.js', depends=[a2]) a4 = Resource(foo, 'a4.js', depends=[a1]) a5 = Resource(foo, 'a5.js', depends=[a4, a3]) needed = NeededResources(resources=[a1, a2, a3]) assert needed.resources() == set([a1, a2, a3]) # For some reason,for example an error page needs to be rendered, # the currently needed resources need to be cleared. needed.clear() assert len(needed.resources()) == 0 needed.need(a4) needed.need(a5) assert needed.resources() == set([a1, a2, a4, a3, a5])
def test_normalize_string(): foo = Library('foo', '') assert isinstance(normalize_string(foo, 'f.css'), Resource) r1 = Resource(foo, 'f.js') assert normalize_string(foo, r1) == r1 r2 = Resource(foo, 'r2.css') r3 = Resource(foo, 'r3.css', depends=[r2], minified='r3.min.css') needed = NeededResources(minified=True, resources=[r3]) assert needed.resources() == [r2, r3.modes['minified']]
def test_rollup_larger(): foo = Library('foo', '') c1 = Resource(foo, 'c1.css') c2 = Resource(foo, 'c2.css') c3 = Resource(foo, 'c3.css') giant = Resource(foo, 'giant.css', supersedes=[c1, c2, c3]) needed = NeededResources(rollup=True) needed.need(c1) assert needed.resources() == [c1] needed.need(c2) assert needed.resources() == [c1, c2] needed.need(c3) assert needed.resources() == [giant]
def test_slot_depends_subset(): lib = Library("lib", "") c = Resource(lib, "c.js") slot = Slot(lib, ".js", depends=[c]) a = Resource(lib, "a.js", depends=[slot]) b = Resource(lib, "b.js", depends=[]) needed = NeededResources() needed.need(a, {slot: b}) assert [r.relpath for r in sort_resources(needed.resources())] == ["c.js", "b.js", "a.js"]
def test_redundant_more_complicated_depends_on_all(): foo = Library('foo', '') a1 = Resource(foo, 'a1.js') a2 = Resource(foo, 'a2.js', depends=[a1]) a3 = Resource(foo, 'a3.js', depends=[a2]) a4 = Resource(foo, 'a4.js', depends=[a1]) a5 = Resource(foo, 'a5.js', depends=[a4, a3]) needed = NeededResources() needed.need(a5) assert needed.resources() == [a1, a2, a4, a3, a5]
def test_sort_library_by_name(): b_lib = Library('b_lib', '') a_lib = Library('a_lib', '') a_a = Resource(a_lib, 'a.js') a_b = Resource(b_lib, 'a.js') needed = NeededResources() needed.need(a_b) needed.need(a_a) assert needed.resources() == [a_a, a_b]
def test_no_need_to_fill_in_not_required(): needed = NeededResources() lib = Library('lib', '') slot = Slot(lib, '.js', required=False) a = Resource(lib, 'a.js', depends=[slot]) needed.need(a) # slot wasn't required and not filled in, so filled slot doesn't show up assert needed.resources() == [a]
def test_default_can_be_overridden(): lib = Library("lib", "") default_resource_for_slot = Resource(lib, "b.js") slot = Slot(lib, ".js", default=default_resource_for_slot) a = Resource(lib, "a.js", depends=[slot]) custom_resource_for_slot = Resource(lib, "c.js") needed = NeededResources() needed.need(a, {slot: custom_resource_for_slot}) relpaths = [r.relpath for r in sort_resources(needed.resources())] assert relpaths == ["c.js", "a.js"]
def test_sort_resources_library_sorting_by_name_deeper(): X = Library('X', '') Y = Library('Y', '') Z = Library('Z', '') # only X and Z will be at the same level now a = Resource(X, 'a.js') c = Resource(Z, 'c.js') b = Resource(Y, 'b.js', depends=[a, c]) needed = NeededResources() needed.need(b) assert needed.resources() == [a, c, b]
def test_bundle(): foo = Library('foo', '') a = Resource(foo, 'a.css') b = Resource(foo, 'b.css') needed = NeededResources(bundle=True) needed.need(a) needed.need(b) resources = bundle_resources(needed.resources()) assert len(resources) == 1 bundle = resources[0] assert bundle.resources() == [a, b]
def test_redundant_more_complicated_reversed(): foo = Library('foo', '') a1 = Resource(foo, 'a1.js') a2 = Resource(foo, 'a2.js', depends=[a1]) a3 = Resource(foo, 'a3.js', depends=[a2]) a4 = Resource(foo, 'a4.js', depends=[a1]) needed = NeededResources() needed.need(a4) needed.need(a3) # this will always be consistent, no matter # in what order we need the resources assert needed.resources() == [a1, a2, a4, a3]
def test_clear(): foo = Library('foo', '') a1 = Resource(foo, 'a1.js') a2 = Resource(foo, 'a2.js', depends=[a1]) a3 = Resource(foo, 'a3.js', depends=[a2]) a4 = Resource(foo, 'a4.js', depends=[a1]) a5 = Resource(foo, 'a5.js', depends=[a4, a3]) needed = NeededResources() needed.need(a1) needed.need(a2) needed.need(a3) assert needed.resources() == [a1, a2, a3] # For some reason,for example an error page needs to be rendered, # the currently needed resources need to be cleared. needed.clear() assert needed.resources() == [] needed.need(a4) needed.need(a5) assert needed.resources() == [a1, a2, a4, a3, a5]
def test_render_filled_slots(): needed = NeededResources() lib = Library("lib", "") slot = Slot(lib, ".js") a = Resource(lib, "a.js", depends=[slot]) b = Resource(lib, "b.js") needed.need(a, {slot: b}) assert [r.relpath for r in sort_resources(needed.resources())] == ["b.js", "a.js"]
def test_sort_group_per_renderer(): foo = Library('foo', '') a_js = Resource(foo, 'a.js') b_css = Resource(foo, 'b.css') c_js = Resource(foo, 'c.js') a1_js = Resource(foo, 'a1.js', depends=[b_css]) needed = NeededResources() needed.need(a_js) needed.need(b_css) needed.need(c_js) needed.need(a1_js) assert needed.resources() == [b_css, a_js, c_js, a1_js]
def test_fill_slot_wrong_extension(): needed = NeededResources() lib = Library('lib', '') slot = Slot(lib, '.js') a = Resource(lib, 'a.js', depends=[slot]) b = Resource(lib, 'b.css') needed.need(a, {slot: b}) with pytest.raises(SlotError): resources = needed.resources()
def test_dont_fill_required_slot(): needed = NeededResources() lib = Library('lib', '') slot = Slot(lib, '.js') a = Resource(lib, 'a.js', depends=[slot]) b = Resource(lib, 'b.js') needed.need(a) with pytest.raises(SlotError): resources = needed.resources()
def test_sort_resources_libraries_together(): K = Library('K', '') L = Library('L', '') M = Library('M', '') N = Library('N', '') k1 = Resource(K, 'k1.js') l1 = Resource(L, 'l1.js') m1 = Resource(M, 'm1.js', depends=[k1]) m2 = Resource(M, 'm2.js', depends=[l1]) n1 = Resource(N, 'n1.js', depends=[m1]) needed = NeededResources() needed.need(m1) needed.need(m2) # sort_resources makes an efficient ordering, grouping m1 and m2 together # after their dependencies (they are in the same library) assert needed.resources() == [k1, l1, m1, m2] needed = NeededResources() needed.need(n1) needed.need(m2) # the order is unaffected by the ordering of inclusions assert needed.resources() == [k1, l1, m1, m2, n1]
def test_bundle_different_directory(): # resources with different directories aren't bundled foo = Library('foo', '') a = Resource(foo, 'first/a.css') b = Resource(foo, 'second/b.css') needed = NeededResources(bundle=True) needed.need(a) needed.need(b) resources = needed.resources() assert len(resources) == 2 assert resources[0] is a assert resources[1] is b
def test_bundle_different_renderer(): # resources with different renderers aren't bundled foo = Library('foo', '') a = Resource(foo, 'a.css') b = Resource(foo, 'b.js') needed = NeededResources(bundle=True) needed.need(a) needed.need(b) resources = needed.resources() assert len(resources) == 2 assert resources[0] is a assert resources[1] is b
def test_bundle_dont_bundle_at_the_start(): foo = Library('foo', '') a = Resource(foo, 'a.css', dont_bundle=True) b = Resource(foo, 'b.css') c = Resource(foo, 'c.css') needed = NeededResources(bundle=True) needed.need(a) needed.need(b) needed.need(c) resources = bundle_resources(needed.resources()) assert len(resources) == 2 assert resources[0] is a assert resources[1].resources() == [b, c]
def test_bundle_different_library(): # resources with different libraries aren't bundled l1 = Library('l1', '') l2 = Library('l2', '') a = Resource(l1, 'a.js') b = Resource(l2, 'b.js') needed = NeededResources(bundle=True) needed.need(a) needed.need(b) resources = needed.resources() assert len(resources) == 2 assert resources[0] is a assert resources[1] is b
def test_depend_on_group(): foo = Library('foo', '') a = Resource(foo, 'a.js') b = Resource(foo, 'b.js') g = Group([a, b]) c = Resource(foo, 'c.js', depends=[g]) g2 = Group([g]) g3 = Group([g, g2]) assert c.depends == set([a, b]) assert g2.depends == set([a, b]) assert g3.depends == set([a, b]) needed = NeededResources() needed.need(c) assert needed.resources() == [a, b, c]
def test_sort_resources_library_sorting_by_name(): # these libraries are all at the same level so should be sorted by name X = Library('X', '') Y = Library('Y', '') Z = Library('Z', '') a = Resource(X, 'a.js') b = Resource(Y, 'b.js') c = Resource(Z, 'c.js') needed = NeededResources() needed.need(a) needed.need(b) needed.need(c) assert needed.resources() == [a, b, c]
def test_bundle_resources(): foo = Library('foo', '') x1 = Resource(foo, 'a.css') x2 = Resource(foo, 'b.css') bundle = bundle_resources([x1, x2]) assert len(bundle) == 1 assert isinstance(bundle[0], Bundle) x3 = Resource(foo, 'c.css', dont_bundle=True) # x3 is not bundle safe. bundle = bundle_resources([x1, x3]) assert len(bundle) == 2 # We don't create bundles of one element. assert bundle[0] == x1 assert bundle[1] == x3 # x2 and x1 are not bundled because x3 is in the way. # (sort_resources in NeededResources fixes the sorting) bundle = bundle_resources([x1, x3, x2]) assert bundle == [x1, x3, x2] # XXX sort_resources does not take care of this for us: needed = NeededResources(bundle=True) needed.need(x1) needed.need(x3) needed.need(x2) # The resources are sorted by renderer order, library dependencies # and resource dependencies. bundle = bundle_resources(needed.resources()) assert len(bundle) == 2 assert isinstance(bundle[0], Bundle) assert bundle[1] == x3 bar = Library('bar', '') y1 = Resource(bar, 'y1.css') y2 = Resource(bar, 'y2.css') bundle = bundle_resources([x1, x2, y1, y2]) assert len(bundle) == 2 y3 = Resource(bar, 'subdir/y3.css') y4 = Resource(bar, 'subdir/y4.css') bundle = bundle_resources([y1, y2, y3, y4]) assert len(bundle) == 2