From 154c168eadd2f2c3cbe52bf105dca660d7198b18 Mon Sep 17 00:00:00 2001 From: William Lachance Date: Thu, 28 Feb 2019 17:58:38 -0500 Subject: [PATCH] Add proper page titles to all server-returned pages (#1557) This makes pages appear much cleaner in the URL bar (we already had client-side code to set the title for the notebook view, but it would only be activated after the page had fully loaded and its javascript code was interpreted/run) --- CHANGELOG.md | 1 + server/notebooks/views.py | 4 +++- server/templates/base.html | 1 + server/tests/helpers/helpers.py | 8 +++++++ server/tests/test_notebook_view.py | 36 +++++++++++++++++++++++++++++- server/tests/test_server_pages.py | 5 ++++- server/views.py | 2 ++ 7 files changed, 54 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3934a81f1a..2b77f1cd43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - redesign / refactor of console entries - fix bug where user would be prompted to save a notebook they already own after logging in - add link to github from user pages +- add document-level titles to all pages returned by the iodide server # 0.1.0 (2019-02-21) diff --git a/server/notebooks/views.py b/server/notebooks/views.py index 6a3762029e..ee8ddbe4b8 100644 --- a/server/notebooks/views.py +++ b/server/notebooks/views.py @@ -50,6 +50,7 @@ def notebook_view(request, pk): else: notebook_info['forked_from'] = False return render(request, 'notebook.html', { + 'title': revision.title, 'user_info': _get_user_info_json(request.user), 'notebook_info': notebook_info, 'jsmd': revision.content, @@ -64,7 +65,7 @@ def notebook_revisions(request, pk): owner = get_object_or_404(User, pk=nb.owner_id) owner_info = { 'username': owner.username, - 'full_name': '{} {}'.format(owner.first_name, owner.last_name), + 'full_name': owner.get_full_name(), 'avatar': owner.avatar, 'title': nb.title, 'notebookId': nb.id, @@ -89,6 +90,7 @@ def notebook_revisions(request, pk): 'date': revision.created.isoformat()} for revision in NotebookRevision.objects.filter(notebook_id=pk)]) return render(request, '../templates/index.html', { + 'title': f'Revisions - {nb.title}', 'page_data': { 'userInfo': get_user_info_dict(request.user), 'ownerInfo': owner_info, diff --git a/server/templates/base.html b/server/templates/base.html index 2cd28e61e4..ee80e5247d 100644 --- a/server/templates/base.html +++ b/server/templates/base.html @@ -3,6 +3,7 @@ {% block head %}{% endblock %} + {{ title }} {% block content %}{% endblock %} diff --git a/server/tests/helpers/helpers.py b/server/tests/helpers/helpers.py index da6164b4bb..0356951e87 100644 --- a/server/tests/helpers/helpers.py +++ b/server/tests/helpers/helpers.py @@ -19,3 +19,11 @@ def get_script_block(page_content, id, mimetype='application/json'): return json.loads(m.group(1)) raise Exception('Script block with id `%s` and mimetype %s not found', id, mimetype) + + +# get the specified title of the page +def get_title_block(page_content): + m = re.search(r'(.*)', str(page_content)) + if m: + return m.group(1) + raise Exception("Expected to find title element but didn't!") diff --git a/server/tests/test_notebook_view.py b/server/tests/test_notebook_view.py index 21e4ae9366..7263be08ff 100644 --- a/server/tests/test_notebook_view.py +++ b/server/tests/test_notebook_view.py @@ -1,6 +1,8 @@ import pytest from django.urls import reverse +from helpers import (get_script_block, + get_title_block) from server.notebooks.models import (Notebook, NotebookRevision) @@ -9,18 +11,20 @@ def test_notebook_view(client, test_notebook): initial_revision = NotebookRevision.objects.filter(notebook=test_notebook).last() resp = client.get(reverse('notebook-view', args=[str(test_notebook.id)])) assert resp.status_code == 200 + assert get_title_block(resp.content) == initial_revision.title expected_content = ''.format( initial_revision.content) assert expected_content in str(resp.content) # add a new revision, verify that a fresh load gets it new_revision_content = 'My new fun content' - NotebookRevision.objects.create( + new_revision = NotebookRevision.objects.create( content=new_revision_content, notebook=test_notebook, title='Second revision') resp = client.get(reverse('notebook-view', args=[str(test_notebook.id)])) assert resp.status_code == 200 + assert get_title_block(resp.content) == new_revision.title new_expected_content = ''.format( new_revision_content) assert new_expected_content in str(resp.content) @@ -62,3 +66,33 @@ def test_tryit_view(client, fake_user, logged_in): assert NotebookRevision.objects.count() == 0 assert Notebook.objects.count() == 0 assert len(response.redirect_chain) == 0 + + +def test_notebook_revisions_page(fake_user, test_notebook, client): + # create another notebook revision + NotebookRevision.objects.create( + notebook=test_notebook, + title="second revision", + content="*fake notebook content 2*") + resp = client.get(reverse('notebook-revisions', args=[str(test_notebook.id)])) + assert get_title_block(resp.content) == f'Revisions - {test_notebook.title}' + assert get_script_block(resp.content, 'pageData') == { + 'files': [], + 'ownerInfo': { + 'avatar': None, + 'full_name': fake_user.get_full_name(), + 'notebookId': test_notebook.id, + 'title': test_notebook.title, + 'username': fake_user.username + }, + 'revisions': [ + { + 'date': r.created.isoformat(), + 'id': r.id, + 'notebookId': test_notebook.id, + 'title': r.title + } for r in NotebookRevision.objects.filter( + notebook_id=test_notebook.id) + ], + 'userInfo': {} + } diff --git a/server/tests/test_server_pages.py b/server/tests/test_server_pages.py index e91c3144cd..0ad93d83ed 100644 --- a/server/tests/test_server_pages.py +++ b/server/tests/test_server_pages.py @@ -1,7 +1,8 @@ import pytest from django.urls import reverse -from helpers import get_script_block +from helpers import (get_script_block, + get_title_block) from server.base.models import User from server.notebooks.models import (Notebook, NotebookRevision) @@ -22,6 +23,7 @@ def test_index_view(client, two_test_notebooks, fake_user, logged_in): assert fake_user.avatar is None # assert that the pageData element has the expected structure + assert get_title_block(resp.content) == 'Iodide' assert get_script_block(resp.content, 'pageData') == { 'notebookList': [ { @@ -62,6 +64,7 @@ def test_user_view_with_different_names(transactional_db, client, username): content="*fake notebook content*") resp = client.get(reverse('user', kwargs={'name': test_user.username})) assert resp.status_code == 200 + assert get_title_block(resp.content) == f'{test_user.username} ({test_user.get_full_name()})' assert get_script_block(resp.content, 'pageData') == { 'notebookList': [ { diff --git a/server/views.py b/server/views.py index 5cbba66608..87e0fba5f4 100644 --- a/server/views.py +++ b/server/views.py @@ -33,6 +33,7 @@ def index(request): for (nb_id, title, latest_revision) in get_formatted_notebooks(request.user)] return render( request, 'index.html', { + 'title': 'Iodide', 'page_data': { 'userInfo': user_info, # this is horrible and will not scale @@ -76,6 +77,7 @@ def user(request, name=None): notebooks = get_formatted_notebooks(user) return render(request, 'index.html', { + 'title': f"{this_user['name']} ({this_user['full_name']})", 'page_data': { 'userInfo': user_info, 'thisUser': this_user,