def test_override_recipe_url():
    """
    check that the /recipes/recipename/tidlers url has been found
    and POST support added
    """
    reset_config()
    setup_store()
    setup_web()
    http = httplib2.Http()
    
    #verify that POST is not available
    response = http.request('http://test_domain:8001/recipes/foobar/tiddlers',
        method='POST')[0]
    assert response.status == 405
    
    #restart the server with the form plugin in place
    config['system_plugins'] = ['tiddlywebplugins.form']
    setup_web()
    
    #now verify that POST support has been added
    response = http.request('http://test_domain:8001/recipes/foobar/tiddlers',
        method='POST', 
        headers={'Content-type': 'application/x-www-form-urlencoded'},
        body='title=HelloWorld&text=Hi%20There')[0]
    assert response.status == 204
def test_override_server_prefix():
    """
    test that the overriding works when a server prefix is present
    """
    reset_config()
    config['server_prefix'] = '/prefix'
    setup_store()
    setup_web()
    http = httplib2.Http()
    
    #verify that POST is not available
    response = http.request('http://test_domain:8001/prefix/bags/foo/tiddlers',
        method='POST')[0]
    assert response.status == 405
    
    #restart the server with the form plugin in place
    config['system_plugins'] = ['tiddlywebplugins.form']
    setup_web()
    
    #now verify that POST support has been added
    response = http.request('http://test_domain:8001/prefix/bags/foo/tiddlers',
        method='POST', 
        headers={'Content-type': 'application/x-www-form-urlencoded'},
        body='title=HelloWorld&text=Hi%20There')[0]
    assert response.status == 204
def test_recipe_variables():
    """
    access a recipe with variables in it
    """
    store = setup_store()
    url(['/foo/{name:segment}', '/recipes/custom/tiddlers'])
    urls_init(config)
    setup_web()
    http = httplib2.Http()

    tiddler = Tiddler('bar', 'foo')
    tiddler.text = 'foo bar'
    store.put(tiddler)

    recipe = Recipe('custom')
    recipe.set_recipe([('{{ name:bar }}', '')])
    store.put(recipe)

    response, content = http.request('http://test_domain:8001/foo/foo')

    assert response.status == 200

    direct_url = http.request('http://test_domain:8001/recipes/custom/tiddlers')[1]
    assert content != direct_url #accessing directly, the default bag should be used instead

    #now check that the correct bag was actually loaded)
    recipe.set_recipe([('foo', '')])
    store.put(recipe)
    direct_url = http.request('http://test_domain:8001/recipes/custom/tiddlers')[1]
    assert content == direct_url
def test_unicode_in_recipes():
    """
    visit a recipe passing unicode in as one of the variables
    """
    store = setup_store()
    url(['/foo/{bar:segment}', '/recipes/custom/tiddlers'])
    urls_init(config)
    setup_web()
    http = httplib2.Http()

    bag = Bag(u'unicodeø•º∆∆˙ª')
    store.put(bag)
    tiddler = Tiddler(u'bar œ∑´®†¥', u'unicodeø•º∆∆˙ª')
    tiddler.text = 'foo bar'
    store.put(tiddler)

    recipe = Recipe('custom')
    recipe.set_recipe([('{{ bar:foo }}', '')])
    store.put(recipe)

    response, content = http.request('http://test_domain:8001/foo/unicodeø•º∆∆˙ª')

    assert response.status == 200

    direct_url = http.request(u'http://test_domain:8001/recipes/custom/tiddlers')[1]
    assert content != direct_url #direct_url should load the foo bag instead

    recipe.set_recipe([(u'unicodeø•º∆∆˙ª', '')])
    store.put(recipe)
    direct_url = http.request(u'http://test_domain:8001/recipes/custom/tiddlers')[1]
    assert content == direct_url
def test_post_no_title():
    """
    post a tiddler with no title set
    and make sure it gets into the store
    """
    store = setup_store()
    setup_web()
    http = httplib2.Http()
    
    #post some fields to a tiddler 
    response = http.request('http://test_domain:8001/bags/foo/tiddlers',
        method='POST', 
        headers={'Content-type': 'application/x-www-form-urlencoded'},
        body='text=Hi%20There')[0]
    assert response.status == 204
    
    #now find the tiddler just entered and check it
    bag = Bag('foo')
    bag = store.get(bag)
    tiddlers = bag.list_tiddlers()
    
    assert len(tiddlers) == 1
    
    tiddler = store.get(tiddlers[0])
    assert tiddler.title != ''
    assert tiddler.text == 'Hi There'
def test_post_redirect_in_body():
    """
    add a tiddler, specifying a url to redirect to in the body of the post
    """
    store = setup_store()
    setup_web()
    http = httplib2.Http()

    #add a tiddler specifying a redirect
    http.follow_redirects = False
    response = http.request('http://test_domain:8001/recipes/foobar/tiddlers',
        method='POST',
        headers={'Content-type': 'application/x-www-form-urlencoded'},
        body='title=HelloWorld&text=Hi%20There&redirect=/bags/foo/tiddlers')[0]

    #make sure the redirect has been applied
    assert response.status == 303
    assert response['location'].split('?')[0] == '/bags/foo/tiddlers'

    #check the tiddler was saved
    tiddler = Tiddler('HelloWorld', 'bar')
    tiddler = store.get(tiddler)

    assert tiddler.title == 'HelloWorld'
    assert tiddler.text == 'Hi There'
    assert tiddler.fields.get('redirect', None) == None
def test_post_new_recipe():
    """
    add a new tiddler to a recipe
    """
    store = setup_store()
    setup_web()
    http = httplib2.Http()
    
    #make sure the tiddler we are inserting doesn't exist
    tiddler = Tiddler('HelloWorld', 'bar')
    try:
        store.get(tiddler)
        raise AssertionError('tiddler %s already exists' % tiddler.title)
    except NoTiddlerError:
        pass
    
    response = http.request('http://test_domain:8001/recipes/foobar/tiddlers',
        method='POST', 
        headers={'Content-type': 'application/x-www-form-urlencoded'},
        body='title=HelloWorld&text=Hi%20There')[0]
    assert response.status == 204
    
    #now check the tiddler is in the store
    try:
        store.get(tiddler)
    except NoTiddlerError:
        raise AssertionError('tiddler was not put into store')
    
    assert tiddler.title == 'HelloWorld'
    assert tiddler.text == 'Hi There'
    assert tiddler.bag == 'bar'
    assert tiddler.tags == []
def test_refresh_urls():
    """
    register a url after the server has been started, and then refresh them
    """
    store = setup_store()
    urls_init(config)
    setup_web()
    http = httplib2.Http()

    tiddler = Tiddler('bar', 'foo')
    tiddler.text = 'foo bar'
    store.put(tiddler)

    #check that no url exists yet
    response = http.request('http://test_domain:8001/foo')[0]
    assert response.status == 404

    url(['/foo', '/bags/foo/tiddlers/bar'])

    #resfresh the currently loaded set of urls
    response = http.request('http://test_domain:8001/urls/refresh')[0]
    assert response.status == 200

    #now check it was loaded successfully
    response = http.request('http://test_domain:8001/foo')[0]
    assert response.status == 200
def test_post_new_recipe():
    """
    add a new tiddler to a recipe
    """
    store = setup_store()
    setup_web()
    http = httplib2.Http()

    # make sure the tiddler we are inserting doesn't exist
    tiddler = Tiddler("HelloWorld", "bar")
    try:
        store.get(tiddler)
        raise AssertionError("tiddler %s already exists" % tiddler.title)
    except NoTiddlerError:
        pass

    response = http.request(
        "http://test_domain:8001/recipes/foobar/tiddlers",
        method="POST",
        headers={"Content-type": "application/x-www-form-urlencoded"},
        body="title=HelloWorld&text=Hi%20There",
    )[0]
    assert response.status == 204

    # now check the tiddler is in the store
    try:
        store.get(tiddler)
    except NoTiddlerError:
        raise AssertionError("tiddler was not put into store")

    assert tiddler.title == "HelloWorld"
    assert tiddler.text == "Hi There"
    assert tiddler.bag == "bar"
    assert tiddler.tags == []
def test_post_existing():
    """
    overwrite an existing tiddler
    """
    store = setup_store()
    setup_web()
    http = httplib2.Http()

    # pre-add a tiddler
    tiddler = Tiddler("HelloWorld", "foo")
    tiddler.text = "Hi There"
    store.put(tiddler)

    response = http.request(
        "http://test_domain:8001/bags/foo/tiddlers",
        method="POST",
        headers={"Content-type": "application/x-www-form-urlencoded"},
        body="title=HelloWorld&text=Changed%20Text",
    )[0]
    assert response.status == 204

    # now check the tiddler is in the store and has been overwritten
    tiddler = Tiddler("HelloWorld", "foo")
    try:
        store.get(tiddler)
    except NoTiddlerError:
        raise AssertionError("tiddler was not put into store")

    assert tiddler.title == "HelloWorld"
    assert tiddler.text == "Changed Text"
    assert tiddler.tags == []
def test_post_fields():
    """
    post some fields to a tiddler
    """
    store = setup_store()
    setup_web()
    http = httplib2.Http()

    # make sure there is nothing in bag 'foo'
    bag = Bag("foo")
    bag = store.get(bag)
    tiddlers = [tiddler for tiddler in store.list_bag_tiddlers(bag)]
    assert len(tiddlers) == 0

    response = http.request(
        "http://test_domain:8001/bags/foo/tiddlers",
        method="POST",
        headers={"Content-type": "application/x-www-form-urlencoded"},
        body="title=HelloWorld&field1=foo&field2=bar",
    )[0]
    assert response.status == 204

    # now find the tiddler just entered
    tiddler = Tiddler("HelloWorld", "foo")
    try:
        store.get(tiddler)
    except NoTiddlerError:
        raise AssertionError("tiddler was not put into store")

    # and check the fields
    assert tiddler.title == "HelloWorld"
    assert len(tiddler.fields) == 2
    assert tiddler.fields["field1"] == "foo"
    assert tiddler.fields["field2"] == "bar"
def test_post_redirect_in_body():
    """
    add a tiddler, specifying a url to redirect to in the body of the post
    """
    store = setup_store()
    setup_web()
    http = httplib2.Http()

    # add a tiddler specifying a redirect
    http.follow_redirects = False
    response = http.request(
        "http://test_domain:8001/recipes/foobar/tiddlers",
        method="POST",
        headers={"Content-type": "application/x-www-form-urlencoded"},
        body="title=HelloWorld&text=Hi%20There&redirect=/bags/foo/tiddlers",
    )[0]

    # make sure the redirect has been applied
    assert response.status == 303
    assert response["location"].split("?")[0] == "/bags/foo/tiddlers"

    # check the tiddler was saved
    tiddler = Tiddler("HelloWorld", "bar")
    tiddler = store.get(tiddler)

    assert tiddler.title == "HelloWorld"
    assert tiddler.text == "Hi There"
    assert tiddler.fields.get("redirect", None) == None
def test_post_no_title():
    """
    post a tiddler with no title set
    and make sure it gets into the store
    """
    store = setup_store()
    setup_web()
    http = httplib2.Http()

    # post some fields to a tiddler
    response = http.request(
        "http://test_domain:8001/bags/foo/tiddlers",
        method="POST",
        headers={"Content-type": "application/x-www-form-urlencoded"},
        body="text=Hi%20There",
    )[0]
    assert response.status == 204

    # now find the tiddler just entered and check it
    bag = Bag("foo")
    bag = store.get(bag)
    tiddlers = [tiddler for tiddler in store.list_bag_tiddlers(bag)]

    assert len(tiddlers) == 1

    tiddler = store.get(tiddlers[0])
    assert tiddler.title != ""
    assert tiddler.text == "Hi There"
def test_post_with_tags():
    """
    check that tags are properly entered
    """
    store = setup_store()
    setup_web()
    http = httplib2.Http()

    response = http.request(
        "http://test_domain:8001/bags/foo/tiddlers",
        method="POST",
        headers={"Content-type": "application/x-www-form-urlencoded"},
        body="title=HelloWorld&text=Hi%20There&" "tags=tag1%20tag2%20[[tag%20with%20spaces]]",
    )[0]
    assert response.status == 204

    # now check the tiddler tags
    tiddler = Tiddler("HelloWorld", "foo")
    try:
        store.get(tiddler)
    except NoTiddlerError:
        raise AssertionError("tiddler was not put into store")

    assert len(tiddler.tags) == 3
    for tag in ["tag1", "tag2", "tag with spaces"]:
        assert tag in tiddler.tags
def test_post_fields():
    """
    post some fields to a tiddler
    """
    store = setup_store()
    setup_web()
    http = httplib2.Http()
    
    #make sure there is nothing in bag 'foo'
    bag = Bag('foo')
    bag = store.get(bag)
    assert len(bag.list_tiddlers()) == 0
    
    response = http.request('http://test_domain:8001/bags/foo/tiddlers',
        method='POST', 
        headers={'Content-type': 'application/x-www-form-urlencoded'},
        body='title=HelloWorld&field1=foo&field2=bar')[0]
    assert response.status == 204
    
    #now find the tiddler just entered
    tiddler = Tiddler('HelloWorld', 'foo')
    try:
        store.get(tiddler)
    except NoTiddlerError:
        raise AssertionError('tiddler was not put into store')
    
    #and check the fields
    assert tiddler.title == 'HelloWorld'
    assert len(tiddler.fields) == 2
    assert tiddler.fields['field1'] == 'foo'
    assert tiddler.fields['field2'] == 'bar'
def test_post_with_tags():
    """
    check that tags are properly entered
    """
    store = setup_store()
    setup_web()
    http = httplib2.Http()
    
    response = http.request('http://test_domain:8001/bags/foo/tiddlers',
        method='POST', 
        headers={'Content-type': 'application/x-www-form-urlencoded'},
        body='title=HelloWorld&text=Hi%20There&' \
            'tags=tag1%20tag2%20[[tag%20with%20spaces]]')[0]
    assert response.status == 204
    
    #now check the tiddler tags
    tiddler = Tiddler('HelloWorld', 'foo')
    try:
        store.get(tiddler)
    except NoTiddlerError:
        raise AssertionError('tiddler was not put into store')
    
    assert len(tiddler.tags) == 3
    for tag in ['tag1', 'tag2', 'tag with spaces']:
        assert tag in tiddler.tags
def test_post_existing():
    """
    overwrite an existing tiddler
    """
    store = setup_store()
    setup_web()
    http = httplib2.Http()
    
    #pre-add a tiddler
    tiddler = Tiddler('HelloWorld', 'foo')
    tiddler.text = 'Hi There'
    store.put(tiddler)
    
    response = http.request('http://test_domain:8001/bags/foo/tiddlers',
        method='POST', 
        headers={'Content-type': 'application/x-www-form-urlencoded'},
        body='title=HelloWorld&text=Changed%20Text')[0]
    assert response.status == 204
    
    #now check the tiddler is in the store and has been overwritten
    tiddler = Tiddler('HelloWorld', 'foo')
    try:
        store.get(tiddler)
    except NoTiddlerError:
        raise AssertionError('tiddler was not put into store')
    
    assert tiddler.title == 'HelloWorld'
    assert tiddler.text == 'Changed Text'
    assert tiddler.tags == []
def test_add_invalid_selector():
    """
    add an invalid selector path
    """
    store = setup_store()
    urls_init(config)

    try:
        url(['/invalid/{variable:unrecognisedtype}', 'www.google.com'])
        raise AssertionError('Invalid URL put into store successfully')
    except InvalidSelectorURL:
        pass #success
def test_bad_input_error():
    """
    if the form cannot be read, then a 400 should be returned
    """
    store = setup_store()
    setup_web()
    http = httplib2.Http()

    response = http.request('http://test_domain:8001/bags/foo/tiddlers',
        method='POST',
        headers={'Content-type': 'multipart/form-data'},
        body='title=HelloWorld&text=Hi%20There')[0]

    assert response['status'] == '400'
def test_redirect_with_www():
    """
    add a redirect without a protocol
    """
    store = setup_store()
    url(['/foo', 'www.google.com'])
    urls_init(config)
    setup_web()
    http =  httplib2.Http()

    http.follow_redirects = False
    response = http.request('http://test_domain:8001/foo')[0]
    assert response.status == 301
    assert response['location'] == 'http://www.google.com'
def test_redirect_with_tag():
    """
    add a redirect defined by tagging 'redirect'
    """
    store = setup_store()
    url(['--redirect', '/foo', '/bags'])
    urls_init(config)
    setup_web()
    http =  httplib2.Http()

    http.follow_redirects = False
    response = http.request('http://test_domain:8001/foo')[0]
    assert response.status == 301
    assert response['location'] == '/bags'
def test_upload_binary_with_meta():
    """
    upload a binary file with some tags and an explicit title
    """
    store = setup_store()
    setup_web()
    http = httplib2.Http()
    
    #set the binary file to upload (NB - this POST data taken from HTTPFox)
    binary_data = open('test/test.bmp').read()
    post_data = [
        '-----------------------------984943658114410893',
        'Content-Disposition: form-data; name="title"',
        '',
        'RGBSquare.bmp',
        '-----------------------------984943658114410893',
        'Content-Disposition: form-data; name="tags"',
        '',
        'image bitmap [[test data]]',
        '-----------------------------984943658114410893',
        'Content-Disposition: form-data; name="file"; filename="test.bmp"',
        'Content-Type: image/bmp',
        ''
    ]
    post_data.append(binary_data)
    post_data.append('-----------------------------984943658114410893--')
    
    post_body = '\n'.join(post_data)

    response = http.request('http://test_domain:8001/bags/foo/tiddlers',
        method='POST', 
        headers={'Content-type': 'multipart/form-data; '
            'boundary=---------------------------984943658114410893',
            'Content-Length': '301'
        },
        body=post_body)[0]
    assert response.status == 204
    
    tiddler = Tiddler('RGBSquare.bmp', 'foo')
    try:
        tiddler = store.get(tiddler)
    except NoTiddlerError:
        raise AssertionError('tiddler not put into store')
    
    assert tiddler.title == 'RGBSquare.bmp'
    assert tiddler.text == binary_data
    assert len(tiddler.tags) == 3
    for tag in ['image', 'bitmap', 'test data']:
        assert tag in tiddler.tags
def test_bad_input_error():
    """
    if the form cannot be read, then a 400 should be returned
    """
    store = setup_store()
    setup_web()
    http = httplib2.Http()

    response = http.request(
        "http://test_domain:8001/bags/foo/tiddlers",
        method="POST",
        headers={"Content-type": "multipart/form-data"},
        body="title=HelloWorld&text=Hi%20There",
    )[0]

    assert response["status"] == "400"
def test_add_patterned_url():
    """
    add a URL with variables inside it
    """
    store = setup_store()
    urls_init(config)

    url(['/foobar/{baz:segment}[/]', '/recipes/foobar/tiddlers'])

    tiddler = Tiddler('/foobar/{baz:segment}[/]', 'urls')
    try:
        tiddler = store.get(tiddler)
    except NoTiddlerError:
        raise AssertionError('URL not put into store')

    assert tiddler.title == '/foobar/{baz:segment}[/]'
    assert tiddler.text == '/recipes/foobar/tiddlers'
def test_unicode_redirect():
    """
    redirect to a unicode url
    """
    store = setup_store()
    setup_web()
    http = httplib2.Http()

    #add a tiddler specifying a redirect that is unicode
    http.follow_redirects = False
    response = http.request('http://test_domain:8001/recipes/foobar/tiddlers?redirect=/bags/foo/tiddlers/%E2%82%AC%E2%88%91%C2%AA%C2%A8~%C3%9F',
        method='POST',
        headers={'Content-type': 'application/x-www-form-urlencoded'},
        body='title=HelloWorld&text=Hi%20There')[0]

    #check that we get a 303 response
    assert response.status == 303
def test_add_variable_destination_url():
    """
    add a url with a variable destination
    """
    store = setup_store()
    urls_init(config)

    url(['/foobar/{baz:segment}[/]', '/recipes/foobar/tiddlers/{{ baz }}'])

    tiddler = Tiddler('/foobar/{baz:segment}[/]', 'urls')
    try:
        tiddler = store.get(tiddler)
    except NoTiddlerError:
        raise AssertionError('URL not put into store')

    assert tiddler.title == '/foobar/{baz:segment}[/]'
    assert tiddler.text == '/recipes/foobar/tiddlers/{{ baz }}'
def test_post_multipart_mime_type():
    """
    test adding a tiddler with a multipart mime type
    """
    store = setup_store()
    setup_web()
    http = httplib2.Http()

    response = http.request(
        "http://test_domain:8001/bags/foo/tiddlers",
        method="POST",
        headers={
            "Content-type": "multipart/form-data; " "boundary=---------------------------168072824752491622650073",
            "Content-Length": "283",
        },
        body="""-----------------------------168072824752491622650073
Content-Disposition: form-data; name="title"

HelloWorld
-----------------------------168072824752491622650073
Content-Disposition: form-data; name="tags"

ben
-----------------------------168072824752491622650073
Content-Disposition: form-data; name="tags"

jon
-----------------------------168072824752491622650073
Content-Disposition: form-data; name="text"

Hi There
-----------------------------168072824752491622650073--""",
    )[0]
    assert response.status == 204

    # check the tiddler is in the store
    tiddler = Tiddler("HelloWorld", "foo")
    try:
        store.get(tiddler)
    except NoTiddlerError:
        raise AssertionError("tiddler was not put into store")

    assert tiddler.title == "HelloWorld"
    assert tiddler.text == "Hi There"
    assert len(tiddler.tags) == 2
def test_post_multipart_mime_type():
    """
    test adding a tiddler with a multipart mime type
    """
    store = setup_store()
    setup_web()
    http = httplib2.Http()

    response = http.request('http://test_domain:8001/bags/foo/tiddlers',
        method='POST', 
        headers={'Content-type': 'multipart/form-data; ' \
                'boundary=---------------------------168072824752491622650073',
            'Content-Length': '283'},
        body='''-----------------------------168072824752491622650073
Content-Disposition: form-data; name="title"

HelloWorld
-----------------------------168072824752491622650073
Content-Disposition: form-data; name="tags"

ben
-----------------------------168072824752491622650073
Content-Disposition: form-data; name="tags"

jon
-----------------------------168072824752491622650073
Content-Disposition: form-data; name="text"

Hi There
-----------------------------168072824752491622650073--''')[0]
    assert response.status == 204

    #check the tiddler is in the store
    tiddler = Tiddler('HelloWorld', 'foo')
    try:
        store.get(tiddler)
    except NoTiddlerError:
        raise AssertionError('tiddler was not put into store')

    assert tiddler.title == 'HelloWorld'
    assert tiddler.text == 'Hi There'
    assert len(tiddler.tags) == 2
def test_load_url_collection():
    """
    visit a collection of tiddlers at a custom url
    """
    store = setup_store()
    url(['/foo', '/bags/foo/tiddlers.json'])
    urls_init(config)
    setup_web()
    http = httplib2.Http()

    tiddler = Tiddler('bar', 'foo')
    tiddler.text = 'foo bar'
    store.put(tiddler)

    response, content = http.request('http://test_domain:8001/foo')

    assert response.status == 200

    direct_url = http.request('http://test_domain:8001/bags/foo/tiddlers.json')[1]
    assert content == direct_url
def test_add_interal_redirect():
    """
    add an internal url, but make it a redirect
    """
    store = setup_store()
    urls_init(config)
    
    url(['--redirect', '/foobar', '/recipes/foobar/tiddlers'])
    
    tiddler = Tiddler('/foobar', 'urls')
    try:
        tiddler = store.get(tiddler)
    except NoTiddlerError:
        raise AssertionError('URL not put into store')
    except NoBagError:
        raise AssertionError('urls bag not created')
    
    assert tiddler.title == '/foobar'
    assert tiddler.text == '/recipes/foobar/tiddlers'
    assert tiddler.tags == ['redirect']