예제 #1
0
def test_inter_library_dependencies_ordering():
    lib1 = Library('lib1', '')
    lib2 = Library('lib2', '')
    lib3 = Library('lib3', '')
    lib4 = Library('lib4', '')

    js1 = Resource(lib1, 'js1.js')
    js2 = Resource(lib2, 'js2.js', depends=[js1])
    js3 = Resource(lib3, 'js3.js', depends=[js2])

    style1 = Resource(lib3, 'style1.css')
    style2 = Resource(lib4, 'style2.css', depends=[style1])

    needed = init_needed(resources=[js3, style2])
    assert sort_resources(needed.resources()) == \
        [style1, style2, js1, js2, js3]
예제 #2
0
def test_cannot_add_dependency_loop():
    foo = Library('foo', '')
    a1 = Resource(foo, 'a1.js')
    b1 = Resource(foo, 'b1.js', depends=[a1])

    with pytest.raises(ValueError):
        a1.add_dependency(b1)
예제 #3
0
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 = init_needed()
    needed.need(a)
    needed.need(b)
    needed.need(c)

    assert sort_resources(needed.resources()) == [a, b, c]
예제 #4
0
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')

    resources = bundle_resources([a])
    assert resources == [a]
예제 #5
0
def test_rendering_base_url():
    foo = Library('foo', '')
    x1 = Resource(foo, 'a.js')
    x2 = Resource(foo, 'b.css')
    y1 = Resource(foo, 'c.js', depends=[x1, x2])

    needed = init_needed(resources=[y1])
    incl = Inclusion(needed)
    assert incl.render() == '''\
<link rel="stylesheet" type="text/css" href="/fanstatic/foo/b.css" />
<script type="text/javascript" src="/fanstatic/foo/a.js"></script>
<script type="text/javascript" src="/fanstatic/foo/c.js"></script>'''

    needed = init_needed(base_url='http://localhost/static', resources=[y1])
    incl = Inclusion(needed)
    assert incl.render() == '''\
<link rel="stylesheet" type="text/css" href="http://localhost/static/fanstatic/foo/b.css" />
<script type="text/javascript" src="http://localhost/static/fanstatic/foo/a.js"></script>
<script type="text/javascript" src="http://localhost/static/fanstatic/foo/c.js"></script>'''
    # The base_url has been set.
    assert needed.has_base_url()

    needed.set_base_url('foo')
    # The base_url can only be set once.
    assert needed._base_url == 'http://localhost/static'
예제 #6
0
def test_delegator(tmpdir):
    foo_library_dir = tmpdir.mkdir('foo')
    resource = tmpdir.join('foo').join('test.js')
    resource.write('/* a test */')

    libraries = LibraryRegistry([Library('foo', foo_library_dir.strpath)])

    publisher = Publisher(libraries)

    def real_app(environ, start_response):
        start_response('200 OK', [])
        return ['Hello world!']

    delegator = Delegator(real_app, publisher)

    request = webob.Request.blank('/fanstatic/foo/test.js')
    response = request.get_response(delegator)
    assert response.body == '/* a test */'

    # A deeper fanstatic.
    request = webob.Request.blank('/foo/bar/fanstatic/foo/test.js')
    response = request.get_response(delegator)
    assert response.body == '/* a test */'

    request = webob.Request.blank('/somethingelse')
    response = request.get_response(delegator)
    assert response.body == 'Hello world!'
예제 #7
0
def test_delegator(tmpdir):
    foo_library_dir = tmpdir.mkdir('foo')
    resource = tmpdir.join('foo').join('test.js')
    resource.write('/* a test */')

    libraries = LibraryRegistry([Library('foo', foo_library_dir.strpath)])

    publisher = Publisher(libraries)

    def real_app(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html')])
        return ['Hello world!']

    delegator = Delegator(real_app, publisher)

    request = webob.Request.blank('/fanstatic/foo/test.js')
    response = request.get_response(delegator)
    assert response.body == b'/* a test */'
    assert response.content_type == 'text/javascript'

    # A deeper fanstatic.
    request = webob.Request.blank('/foo/bar/fanstatic/foo/test.js')
    response = request.get_response(delegator)
    assert response.body == b'/* a test */'
    assert response.content_type == 'text/javascript'

    request = webob.Request.blank('/somethingelse')
    response = request.get_response(delegator)
    assert response.body == 'Hello world!'
    # Default content type from WebOb
    assert response.content_type == 'text/html'
예제 #8
0
def test_rollup():
    foo = Library('foo', '')
    b1 = Resource(foo, 'b1.js')
    b2 = Resource(foo, 'b2.js')
    giant = Resource(foo, 'giant.js', supersedes=[b1, b2])

    assert rollup_resources([b1, b2]) == set([giant])
def test_logging_when_compiling(tmpdir, compilers, caplog):
    caplog.set_level(logging.INFO, logger='fanstatic')

    class WhiteSpaceRemover(fanstatic.compiler.Compiler):
        """A silly minifier, to showcase logging."""
        name = 'whitespace'
        source_extension = '.frop'

        def process(self, source, target):
            with open(target, 'wb') as output:
                output.write(
                    compat.as_bytestring(
                        open(source, 'r').read().replace(' ', '')))

    compilers.add_compiler(WhiteSpaceRemover())

    lib = Library('lib', str(tmpdir))
    tmpdir.join('a.frop').write(' foo bar baz ')
    a = Resource(lib, 'a.js', compiler='whitespace')
    assert len(caplog.records) == 0
    a.compile()
    assert len(caplog.records) == 1
    assert "Compiling <Resource 'a.js' in library 'lib'> in" in caplog.text
    # The 'compiler' really worked!
    assert tmpdir.join('a.js').read() == 'foobarbaz'
def test_resource_name_conflict_raises_error(compilers):
    compilers.add_minifier(MockMinifier())
    lib = Library('lib', '', minifiers={'.js': 'mock'})
    a = Resource(lib, 'a.js')
    with pytest.raises(fanstatic.ConfigurationError) as exc:
        Resource(lib, 'a.min.js')
    assert str(exc.value) == 'Resource path a.min.js is already defined.'
예제 #11
0
def test_add_dependency_resource_to_group():
    foo = Library('foo', '')
    a1 = Resource(foo, 'a1.js')
    b1 = Group([a1])
    c1 = Resource(foo, 'c1.js', depends=[b1])

    assert a1.depends == set([])
    assert a1.resources == set([a1])

    assert b1.depends == set([a1])
    assert b1.resources == set([a1])

    assert c1.depends == set([b1])
    assert c1.resources == set([a1, c1])

    a2 = Resource(foo, 'a2.js')
    b1.add_dependency(a2)

    assert b1.depends == set([a1, a2])
    assert b1.resources == set([a1, a2])

    assert c1.depends == set([b1])
    assert c1.resources == set([a1, a2, c1])

    # Adding it twice does not change anything.
    b1.add_dependency(a2)

    assert b1.depends == set([a1, a2])
    assert b1.resources == set([a1, a2])

    assert c1.depends == set([b1])
    assert c1.resources == set([a1, a2, c1])
예제 #12
0
def test_mode_fully_specified():
    foo = Library('foo', '')
    k_debug = Resource(foo, 'k-debug.js')
    k = Resource(foo, 'k.js', debug=k_debug)
    x = Resource(foo, 'x.js', minified='x-min.js')

    needed = init_needed()
    needed.need(k)
    incl = Inclusion(needed)
    assert incl.resources == [k]

    incl = Inclusion(needed, mode='debug')
    assert incl.resources == [k_debug]

    # If no minified can be found, the 'raw' resource is taken.
    incl = Inclusion(needed, mode='minified')
    assert incl.resources == [k]

    # If only a minified resource is defined, debug returns the raw version.
    needed = init_needed()
    needed.need(x)

    incl = Inclusion(needed, mode='debug')
    assert incl.resources == [x]
    incl = Inclusion(needed, mode='minified')
    assert incl.resources == [x.modes['minified']]
예제 #13
0
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 = init_needed(resources=[a])
    relpaths = [r.relpath for r in sort_resources(needed.resources())]
    assert relpaths == ['b.js', 'a.js']
예제 #14
0
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 = init_needed(resources=[a])
    # slot wasn't required and not filled in, so filled slot doesn't show up
    assert needed.resources() == set([a])
def test_compile_only_for_libraries_under_development(compilers):
    compilers.add_compiler(MockCompiler())

    lib = Library('lib', '')
    a = Resource(lib, 'a.js', compiler='mock')

    needed = init_needed(resources=[a])
    incl = Inclusion(needed, compile=True)
    assert len(compilers.compiler('mock').calls) == 1
    # Gathering all resources again will add a call.
    incl = Inclusion(needed, compile=True)
    assert len(compilers.compiler('mock').calls) == 2

    lib.version = 1

    incl = Inclusion(needed, compile=True)
    assert len(compilers.compiler('mock').calls) == 2
def test_minifier_available_and_minified_file_not_present_should_not_raise(
        tmpdir, compilers):
    open(str(tmpdir / 'a.js'), 'w').close()
    compilers.add_minifier(MockMinifier())
    set_resource_file_existence_checking(True)
    lib = Library('lib', str(tmpdir))
    # assert_nothing_raised
    a = Resource(lib, 'a.js', minifier='mock')
def test_do_add_library_after_register():
    set_auto_register_library(False)

    library_registry = get_library_registry()
    bar = Library('bar', '')

    assert 'bar' not in library_registry

    library_registry.add(bar)

    assert 'bar' in library_registry

    library_registry.prepare()
    foo = Library('foo', '')

    with pytest.raises(ValueError):
        library_registry.add(foo)
def test_compiler_available_and_source_not_present_should_raise(
        tmpdir, compilers):
    compilers.add_compiler(MockCompiler())
    set_resource_file_existence_checking(True)
    lib = Library('lib', str(tmpdir))
    with pytest.raises(fanstatic.UnknownResourceError) as exc:
        a = Resource(lib, 'a.js', compiler='mock')
    assert 'a.source' in str(exc.value)
예제 #19
0
def test_html_insert_head_with_attributes():
    # ticket 72: .need() broken when <head> tag has attributes
    foo = Library('foo', '')
    x1 = Resource(foo, 'a.js')
    needed = NeededResources(resources=[x1])

    html = '<html><head profile="http://example.org">something</head></html>'
    assert needed.render_into_html(html) == '''\
예제 #20
0
def test_generate_source():
    foo = Library('foo', '')
    i1 = Resource(foo, 'i1.js')
    i2 = Resource(foo, 'i2.js', depends=[i1])
    i3 = Resource(foo, 'i3.js', depends=[i2])
    i5 = Resource(foo, 'i5.js', depends=[i3])

    assert generate_code(i1=i1, i2=i2, i3=i3, i5=i5) == '''\
예제 #21
0
def test_empty_base_url_and_publisher_signature():
    ''' When the base_url is not set and the publisher_signature is an empty string,
    render a URL without them. '''
    foo = Library('foo', '')
    x1 = Resource(foo, 'a.js')
    needed = init_needed(publisher_signature='', resources=[x1])
    incl = Inclusion(needed)
    assert incl.render() == '''\
예제 #22
0
def test_library_url_script_name_base_url():
    foo = Library('foo', '')
    needed = NeededResources(script_name='/root',
                             base_url="http://example.com/something")

    # base_url is set so script_name should be ignored
    assert (needed.library_url(foo) ==
            'http://example.com/something/fanstatic/foo')
예제 #23
0
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
예제 #24
0
def test_compile_only_for_libraries_under_development(
    compilers):
    compilers.add_compiler(MockCompiler())

    lib = Library('lib', '')
    a = Resource(lib, 'a.js', compiler='mock')

    needed = NeededResources(resources=[a])
    incl = Inclusion(needed, compile=True)
    assert len(compilers.compiler('mock').calls) == 1
    # Gathering all resources again will add a call.
    incl = Inclusion(needed, compile=True)
    assert len(compilers.compiler('mock').calls) == 2

    lib.version = 1

    incl = Inclusion(needed, compile=True)
    assert len(compilers.compiler('mock').calls) == 2
예제 #25
0
def test_html_insert_head_with_attributes():
    # ticket 72: .need() broken when <head> tag has attributes
    foo = Library('foo', '')
    x1 = Resource(foo, 'a.js')
    needed = init_needed(resources=[x1])

    injector = TopBottomInjector({})
    html = b'<html><head profile="http://example.org">something</head></html>'
    assert injector(html, needed) == b'''\
예제 #26
0
def test_sort_group_per_library():
    foo = Library('foo', '')
    bar = Library('bar', '')

    e = Resource(foo, 'e.js')
    d = Resource(foo, 'd.js', depends=[e])
    c = Resource(bar, 'c.js', depends=[e])
    b = Resource(bar, 'b.js')
    a = Resource(bar, 'a.js', depends=[c])

    needed = NeededResources()
    needed.need(a)
    needed.need(b)
    needed.need(c)
    needed.need(d)
    needed.need(e)

    assert needed.resources() == [e, d, b, c, a]
예제 #27
0
def test_empty_base_url_and_publisher_signature():
    ''' When the base_url is not set and the publisher_signature is an empty string,
    render a URL without them. '''
    foo = Library('foo', '')
    x1 = Resource(foo, 'a.js')
    needed = NeededResources(publisher_signature='')
    needed.need(x1)

    assert needed.render() == '''\
예제 #28
0
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]
예제 #29
0
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]
예제 #30
0
def test_sort_resources_topological():
    foo = Library('foo', '')

    a1 = Resource(foo, 'a1.js')
    a2 = Resource(foo, 'a2.js', depends=[a1])
    a3 = Resource(foo, 'a3.js', depends=[a2])
    a5 = Resource(foo, 'a5.js', depends=[a3])

    assert sort_resources_topological([a5, a3, a1, a2]) == [a1, a2, a3, a5]
예제 #31
0
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])

    assert rollup_resources([d1, d2, d3]) == set([giant_bigger])
예제 #32
0
def test_library_nr():
    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])

    X.init_library_nr()
    Y.init_library_nr()
    Z.init_library_nr()

    assert a.library.library_nr == 0
    assert c.library.library_nr == 0
    assert b.library.library_nr == 1
from fanstatic import Resource, Group, Library

library = Library('dummy', '.')
library.need = lambda: 'No, sorry, that is a Library.'

resource = Resource(library, 'fanstatic_dummy_resource.css')
resource.need = lambda: 'needed resource'

group = Group([resource])
group.need = lambda: 'needed group'