Testing the html elements in flask routing templates unittest - python

I have a login page for a flask app with cloud database, I want to test the results after logging in, specifically, I want to test the HTML elements after logging in. I have seen people test return status code or using assertIn to check if data exist.
Is there a way for me to target a specific HTML tag, like <h1 id="userTitle"> </h1> from rendered templates after POST username, password to the route function login()
def test_users_login(self):
result = self.app.post('/login', data=dict(username='Nicole', password='abc123'), follow_redirects=True)
# I want to check the HTML tag's text value data after logging in
self.assertEqual(result.data.getTag("h1", b"Nicole") #What I imagined using <h1>
self.assertEqual(result.data.getId("user", b"Nicole") #What I imagined using id
#This returns true which is okay, because 'Nicole' exists in the whole page
self.assertIn(b'Nicole', result.data)
In my rendered jinja2 template I have this which is after logging in.
<h1 id="userTitle">{{ session['username'] }},Welcome!</h1>
I guess assertIn works well, but I just want to know how to test an HTML tag without running a browser test.

Although I didn't get a correct answer from here, but I just managed to do the unit-test with just assertIn, by checking the contents of the page.
Thanks everyone

Related

Calling a function on HTML page, not found

I am writing a tool to record and monitor downtime on a range of equipment.
I have my file structure as below:
File Structure
Sites is just a subfolder containing individual HTMLS for where the equipment is located.
Currently, flask runs webapp.py which contains:
>from . import app
>#app = (__init__.app)
>from . import views
>from . import ReportingTool
views.py has all of my #app.route's in it, up until the [site].html files. From there, on the [site].html file I ask for input from the user. I haven't started writing code to record the user input in any meaningful way, just want to get the data to a python script and commit them to variables. To this end, in the html file I have
<body>
<div class="menu">
<form method="post" enctype="multipart\form-data" action="{{ url_for('downTime') }}">
<fieldset class="datafieldset">
This then requests different data from the user in the form of multiple field sets as seen here: fieldsets
as you see in the code snippet above I set the action to be url_for('downTime'), downTime is a function in my python file ReportingTool.py. this throws out an error, "werkzeug.routing.exceptions.BuildError: Could not build url for endpoint 'downTime'. Did you mean 'supportguide' instead?" traceback
Is there something I need to add or specify on the html document to enable this page (and the other [site].html pages to call functions from the ReportingTool.py file? the #app.route that calls the [site].html file is this and that is called with a redirected from here I've only got it setup like that becuase I wanted the name for the site to appear in the address bar.
Thanks in advance.
I am not sure on steps to fix as I am kind of throwing myself in the deep end to learn basic coding by creating an application for my workplace to replace an excel spreadsheet I created.
You are not reaching the downTime function in the ReportingTool.py file. I suggest trying add_url_rule in your views.py by adding the /reported endpoint referencing the downTime function in ReportingTool.py. Something like this;
app.add_url_rule('/reported', 'ReportingTool.downTime', view_func=ReportingTool.downTime, methods=METHODS)
This answer is based on the responds for this question. You are trying to reach a function in a different file from your main view file. Assuming you are calling the page with the form from a function in the views.py file.
Solved with info from Kakedis' input, and the links they provided.
I added:
app.add_url_rule('/reported', 'ReportingTool.downTime', view_func=ReportingTool.downTime, methods=METHODS)
to webbapp.py, then:
#app.route('/reported')
def downTime():
try:
DTref = request.form['refDT']
except:
DTref = "No Reference"
print(DTref)
print("reported")
return(render_template("/UserRip.html"))
to ReportingTool.py
This now prints the above to console to confirm it's pulling the correct func and brings the user back to the starting page.

How to update session object

With two <a>:
<a id="100" onclick="createTriggered(this.id)"<i></i> Click Link </a>
<a id="200" onclick="createTriggered(this.id)"<i></i> Click Link </a>
both linked to the same onClick javascript function:
<script type=text/javascript>
$SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
function onClick(id){
var data = $.getJSON($SCRIPT_ROOT + '/triggered', {a:id} );
window.alert({{ "session.keys()" }});
}
</script>
This javascript function takes the clicked <a> id and sends it to flask function:
#app.route('/onClick')
def onClick():
session['a_id'] = request.args.get('a')
return ('ok')
After Flask function gets id it updates session object creating a new key session['a_id'].
Finally javascript window.alert is used to check if the session object has the new 'a_id' key which should be already set by Flask function. When window.alert pops up it shows that the new key is missing. Refreshing the page and re-clicking the <a> link will pop up the window.alert() again but this time showing the new session['a_id'] key is there. It looks like the update of the session object is lagging behind. I have to refresh the page in order for the browser to pick up the change made by Flask function. Is there a way to assure that the update made by the Flask function to the session object is reflected immediately?
Finally, since I am updating the session object which is global to the entire session I really don't want to return any template or to redirect to another link. All I want is Flask function to set the session variables so it could be used somewhere down the logic. Would it be ok to return a dummy string from Flask function in this case?
It looks like the update of the session object is lagging behind.
It is not lagging. The issue is that originally you don't have anything in your session, thus your HTML page and your javascript is equivalent to
window.alert().
After you update your session, re-render the page update the javascript code to window.alert('a_id').
Is there a way to assure that the update made by the Flask function to the session object is reflected immediately?
You can examine your javascript callback to check the cookie return. The cookie is encrypted, so you won't see the value unless you know how to decrypt it. It is not recommended to do that. However, at the very least you can see the value of the cookie is changed.

How to store/deal with django exception webpages in acceptance testing

I am running a series of selenium functional tests of a django site for acceptance testing purposes. I notice that when I run these and exceptions occur, I get back an entire page ( eg a HTTP status 500 ).
I am running acceptance testing using a simple loop and storing the outputted html to a db using the django orm:
def my_functional_tests(request):
import requests
from mytests.models import Entry
for i in range(3):
p1 = { ....... }
r1 = requests.post('http://127.0.0.1:8000/testfunction1/',data=p1)
..............
entry = Entry(output1 = r1.text, output2 = r2.text, output3 = r3.text)
entry.save()
return HttpResponse("completed")
My Model is defined as (where the outputs are the HTML results of 3 functional tests ):
class Entry(models.Model):
output1 = models.CharField(max_length=240)
output2 = models.CharField(max_length=240)
output3 = models.CharField(max_length=240)
When I get an error, the resulting approximately 65K webpage causes an exception on saving, and breaks the testing. I want to get as much info as possible, so I could increase the max_length to lets say 70,000 to store the entire page, but is there a more concise way to capture and store relevant data including the specific errors to the db ?
If you did this with Django's testing client, you could get more concise information--but by using requests, you're really hitting your page as a web browser would, so the full page is what you get (but 65K for a 500 Error page? Wow).
Could you embed in the error page an HTML comment with a marker and concise explanation?
<html>
<h1>Error</h1>
... 64k of stuff follows ...
<!-- ERR:"info about error" -->
</html>
That way, you could parse the results for that error code and store just that.
Of course, you'll want to make sure you don't put anything confidential in that error message or, if you do, that you emit it only when in DEBUG mode or when the request comes from localhost, or logged in as staff, or whatever other security constraint would work.
Slightly prettier would be to write a piece of middleware that emits the error-info as an HTTP Header; then your page could stay the same and you could look at the response headers for your error info.

Reading and writing files from html in Google App Engine

I am working with GAE and Python, I know python, but I don't know HTML, which seems to be what I need right now. I want to take in a text file write something in it then return it for download. I am using other people's examples, but far all I have is:
class MainPage(webapp.RequestHandler):
#http://bukhantsov.org/2011/12/python-google-app-engine-calculator/
def get(self):
self.response.out.write("""<html>
<body>
<form action='/' method='get' autocomplete='off'>
<input type='file' name='file'/><br/>
</form>
</body>
</html>""")
I imagine there is something I need to put in the file line so I can access what the user feeds it, but I don't know what or how to access it from the python code. So what should I do here?
If I understand your question correctly, you are trying to grab the text data being sent by the user via the GET call that is defined by the form action HTML line.
Concisely, you are looking for this call:
file = self.request.get('file')
This may also be useful:
filename = self.request.GET['file'].filename
These can be used in the same location and in conjunction with your "self.response.out".
More information can be found here:
https://developers.google.com/appengine/docs/python/tools/webapp/requestclass#Request_get
Alternatively, the BlobStore APIs may be easier.
https://developers.google.com/appengine/docs/python/blobstore/overview
Possibly related:
Upload files in Google App Engine,
Get original filename google app engine
Hope that helps!
Jess

how to access values from the url using python

I am working with python web.py framework,i had an anchor tag with html code as below for example
<p><a href = "/edit.py?tr=%d"%1>Edit</a></p>
So when i click this link it goes to edit.py file in my project directory, but as you observe i am passing some values after edit.py like /edit.py?tr=%d"%1. Actually i will pass these values dynamically in further process.
Here after redirecting to edit.py, how to access the values after ? from the py file?
because my intention is to edit the record after saving in to database.
You can get them using web.input, e.g.
def GET(self):
data = web.input()
tr = data.tr
Documentation is avaliable here: http://webpy.org/cookbook/input

Categories

Resources