Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 4 additions & 7 deletions files/templates/default.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,21 +41,18 @@
{% block title %}
<title>{{SITE_TITLE}}</title>

<meta property="og:type" content="article">
<meta property="og:type" content="website">
<meta property="og:title" content="{{SITE_TITLE}}">
<meta property="og:site_name" content="{{request.host}}">
<meta property="og:image" content="{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
<meta property="og:site_name" content="{{SITE_TITLE}}">
<meta property="og:image" content="{{SITE_FULL}}{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
<meta property="og:url" content="{{SITE_FULL}}{{request.full_path}}">
<meta property="og:description" name="description" content="{{config('DESCRIPTION')}}">
<meta property="og:author" name="author" content="{{SITE_FULL}}">
<meta property="og:site_name" content="{{request.host}}">

<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="{{SITE_FULL}}">
<meta name="twitter:title" content="{{SITE_TITLE}}">
<meta name="twitter:creator" content="{{SITE_FULL}}">
<meta name="twitter:description" content="{{config('DESCRIPTION')}}">
<meta name="twitter:image" content="{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
<meta name="twitter:image" content="{{SITE_FULL}}{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
<meta name="twitter:url" content="{{SITE_FULL}}{{request.full_path}}">
{% endblock %}

Expand Down
15 changes: 14 additions & 1 deletion files/templates/errors/error.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
{% extends "default.html" %}
{% block title %}
<title>{{code}} {{error}}</title>
<title>{{code}} {{error}} - {{SITE_TITLE}}</title>

<meta property="og:type" content="website">
<meta property="og:title" content="{{code}} {{error}} - {{SITE_TITLE}}">
<meta property="og:site_name" content="{{SITE_TITLE}}">
<meta property="og:image" content="{{SITE_FULL}}{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
<meta property="og:url" content="{{SITE_FULL}}{{request.full_path}}">
<meta property="og:description" name="description" content="{{description}}">

<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="{{SITE_FULL}}">
<meta name="twitter:title" content="{{code}} {{error}} - {{SITE_TITLE}}">
<meta name="twitter:description" content="{{description}}">
<meta name="twitter:image" content="{{SITE_FULL}}{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
{% endblock %}
{% block pagetype %}error-{{code}}{% endblock %}
{% block content %}
Expand Down
14 changes: 14 additions & 0 deletions files/templates/login/authforms.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,20 @@
<meta name="description" content="{{config('DESCRIPTION')}}">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>{% block pagetitle %}{{SITE_TITLE}}{% endblock %}</title>

<meta property="og:type" content="website">
<meta property="og:title" content="{{SITE_TITLE}}">
<meta property="og:site_name" content="{{SITE_TITLE}}">
<meta property="og:image" content="{{SITE_FULL}}{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
<meta property="og:url" content="{{SITE_FULL}}{{request.full_path}}">
<meta property="og:description" name="description" content="{{config('DESCRIPTION')}}">

<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="{{SITE_FULL}}">
<meta name="twitter:title" content="{{SITE_TITLE}}">
<meta name="twitter:description" content="{{config('DESCRIPTION')}}">
<meta name="twitter:image" content="{{SITE_FULL}}{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">

{% if v %}
<style>:root{--primary:#{{v.themecolor}}}</style>
<link rel="stylesheet" href="{{ 'css/main.css' | asset }}">
Expand Down
19 changes: 8 additions & 11 deletions files/templates/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,19 @@
<link rel="icon" type="image/png" href="{{ ('images/'~SITE_ID~'/icon.webp') | asset }}">

<title>{% block pagetitle %}Settings - {{SITE_TITLE}}{% endblock %}</title>
<meta property="og:type" content="article">
<meta property="og:title" content="{{SITE_TITLE}}">
<meta property="og:site_name" content="{{request.host}}">
<meta property="og:image" content="{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
<meta property="og:url" content="{{request.host}}">
<meta property="og:type" content="website">
<meta property="og:title" content="Settings - {{SITE_TITLE}}">
<meta property="og:site_name" content="{{SITE_TITLE}}">
<meta property="og:image" content="{{SITE_FULL}}{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
<meta property="og:url" content="{{SITE_FULL}}{{request.full_path}}">
<meta property="og:description" name="description" content="{{config('DESCRIPTION')}}">
<meta property="og:author" name="author" content="{{SITE_FULL}}">
<meta property="og:site_name" content="{{request.host}}">

<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="{{SITE_FULL}}">
<meta name="twitter:title" content="{{SITE_TITLE}}">
<meta name="twitter:creator" content="{{SITE_FULL}}">
<meta name="twitter:title" content="Settings - {{SITE_TITLE}}">
<meta name="twitter:description" content="{{config('DESCRIPTION')}}">
<meta name="twitter:image" content="{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
<meta name="twitter:url" content="{{request.host}}">
<meta name="twitter:image" content="{{SITE_FULL}}{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
<meta name="twitter:url" content="{{SITE_FULL}}{{request.full_path}}">


<style>:root{--primary:#{{v.themecolor}}}</style>
Expand Down
11 changes: 4 additions & 7 deletions files/templates/settings2.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,18 @@
<meta name="thumbnail" content="{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
<link rel="icon" type="image/png" href="{{ ('images/'~SITE_ID~'/icon.webp') | asset }}">

<meta property="og:type" content="article">
<meta property="og:type" content="website">
<meta property="og:title" content="{{SITE_TITLE}}">
<meta property="og:site_name" content="{{request.host}}">
<meta property="og:image" content="{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
<meta property="og:site_name" content="{{SITE_TITLE}}">
<meta property="og:image" content="{{SITE_FULL}}{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
<meta property="og:url" content="{{SITE_FULL}}{{request.full_path}}">
<meta property="og:description" name="description" content="{{config('DESCRIPTION')}}">
<meta property="og:author" name="author" content="{{SITE_FULL}}">
<meta property="og:site_name" content="{{request.host}}">

<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="{{SITE_FULL}}">
<meta name="twitter:title" content="{{SITE_TITLE}}">
<meta name="twitter:creator" content="{{SITE_FULL}}">
<meta name="twitter:description" content="{{config('DESCRIPTION')}}">
<meta name="twitter:image" content="{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
<meta name="twitter:image" content="{{SITE_FULL}}{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
<meta name="twitter:url" content="{{SITE_FULL}}{{request.full_path}}">


Expand Down
8 changes: 3 additions & 5 deletions files/templates/submission.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,22 +46,21 @@
<meta property="article:published_time" content="{{comment_info.created_datetime}}">
{% if comment_info.edited_utc %}<meta property="article:modified_time" content="{{comment_info.edited_string}}">{% endif %}
<meta property="og:description" name="description" content="{{comment_info.plainbody(v)}}">
<meta property="og:author" name="author" content="{{'@'+comment_info.author_name}}">
<meta property="og:title" content="{{'@'+comment_info.author_name}} comments on {{p.plaintitle(v)}} - {{SITE_TITLE}}">
<meta property="og:image" content="{% if p.is_image %}{{p.realurl(v)}}{% elif p.has_thumb%}{{p.thumb_url}}{% else %}{{SITE_FULL}}{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}{% endif %}">
{% if p.is_video %}
<meta property="og:video" content="{{p.realurl(v)}}">
{% endif %}
<meta property="og:url" content="{{comment_info.permalink}}">
<meta property="og:site_name" content="{{request.host}}">
<meta property="og:site_name" content="{{SITE_TITLE}}">

<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="{{SITE_FULL}}">
<meta name="twitter:title" content="{{'@'+comment_info.author_name}} comments on {{p.plaintitle(v)}} - {{SITE_TITLE}}">
<meta name="twitter:creator" content="{{'@'+comment_info.author_name}}">
<meta name="twitter:description" content="{{comment_info.plainbody(v)}}">
<meta name="twitter:image" content="{% if p.is_image %}{{p.realurl(v)}}{% elif p.has_thumb%}{{p.thumb_url}}{% else %}{{SITE_FULL}}{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}{% endif %}">
<meta name="twitter:url" content="{{p.permalink}}">
<meta name="twitter:url" content="{{comment_info.permalink}}">

{% else %}
<title>{{p.plaintitle(v)}} - {{SITE_TITLE}}</title>
Expand All @@ -71,14 +70,13 @@
<meta property="article:published_time" content="{{p.created_datetime}}">
{% if p.edited_utc %}<meta property="article:modified_time" content="{{p.edited_string}}">{% endif %}
<meta property="og:description" name="description" content="{{p.plainbody(v)}}">
{% if p.author %}<meta property="og:author" name="author" content="{{'@'+p.author_name}}">{% endif %}
<meta property="og:title" content="{{p.plaintitle(v)}} - {{SITE_TITLE}}">
<meta property="og:image" content="{% if p.is_image %}{{p.realurl(v)}}{% elif p.has_thumb%}{{p.thumb_url}}{% else %}{{SITE_FULL}}{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}{% endif %}">
{% if p.url and p.is_video %}
<meta property="og:video" content="{{p.realurl(v)}}">
{% endif %}
<meta property="og:url" content="{{p.permalink}}">
<meta property="og:site_name" content="{{request.host}}">
<meta property="og:site_name" content="{{SITE_TITLE}}">

<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="{{SITE_FULL}}">
Expand Down
12 changes: 12 additions & 0 deletions files/templates/submit.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,18 @@
<link rel="icon" type="image/png" href="{{ ('images/'~SITE_ID~'/icon.webp') | asset }}">
{% block title %}
<title>Create a post - {{SITE_TITLE}}</title>
<meta property="og:type" content="website">
<meta property="og:title" content="Create a post - {{SITE_TITLE}}">
<meta property="og:site_name" content="{{SITE_TITLE}}">
<meta property="og:image" content="{{SITE_FULL}}{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
<meta property="og:url" content="{{SITE_FULL}}{{request.full_path}}">
<meta property="og:description" name="description" content="{{config('DESCRIPTION')}}">

<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="{{SITE_FULL}}">
<meta name="twitter:title" content="Create a post - {{SITE_TITLE}}">
<meta name="twitter:description" content="{{config('DESCRIPTION')}}">
<meta name="twitter:image" content="{{SITE_FULL}}{{ ('images/'~SITE_ID~'/site_preview.webp') | asset }}">
{% endblock %}


Expand Down
9 changes: 4 additions & 5 deletions files/templates/userpage.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,20 @@
{% endif %}

<title>{{u.username}}'s profile - {{SITE_TITLE}}</title>
<meta property="og:type" content="profile">
<meta property="og:article:author" content="@{{u.username}}">
<meta property="article:section" content="{{u.username}}'s profile - {{SITE_TITLE}}">
<meta property="article:published_time" content="{{u.created_date}}">
<meta property="og:description" name="description" content="Joined {{u.created_date}} - {% if u.stored_subscriber_count >=1 and not u.is_private and not u.is_nofollow %}{{u.stored_subscriber_count}} Followers - {% endif %}{% if not u.is_private %} {{0 if u.shadowbanned else u.post_count}} Posts - {{0 if u.shadowbanned else u.comment_count}} Comments - {% endif %}{{u.bio}}">
<meta property="og:author" name="author" content="@{{u.username}}">
<meta property="og:title" content="{{u.username}}">
<meta property="og:title" content="{{u.username}}'s profile - {{SITE_TITLE}}">
<meta property="og:image" content="{{u.banner_url}}">
<meta property="og:url" content="{{u.url}}">
<meta property="og:site_name" content="{{request.host}}">
<meta property="og:site_name" content="{{SITE_TITLE}}">

<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="{{SITE_FULL}}">
<meta name="twitter:title" content="{{u.username}}'s profile - {{SITE_TITLE}}">
<meta name="twitter:creator" content="@{{u.username}}">
<meta name="twitter:description" content="Joined {{u.created_date}} - {% if u.stored_subscriber_count >=1 and not u.is_private and not u.is_nofollow %}{{u.stored_subscriber_count}} Followers -{% endif %} {% if not u.is_private %} {{0 if u.shadowbanned else u.post_count}} Posts - {{0 if u.shadowbanned else u.comment_count}} Comments - {% endif %}{{u.bio}}">
<meta name="twitter:description" content="Joined {{u.created_date}} - {% if u.stored_subscriber_count >=1 and not u.is_private and not u.is_nofollow %}{{u.stored_subscriber_count}} Followers - {% endif %}{% if not u.is_private %} {{0 if u.shadowbanned else u.post_count}} Posts - {{0 if u.shadowbanned else u.comment_count}} Comments - {% endif %}{{u.bio}}">
<meta name="twitter:image" content="{{u.banner_url}}">
<meta name="twitter:url" content="{{u.url}}">
{% endblock %}
Expand Down
127 changes: 127 additions & 0 deletions files/tests/test_opengraph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
"""Tests for OpenGraph meta tags (#130).

Verifies that key pages include proper og:title, og:image, and og:site_name
meta tags, and that image URLs are absolute (prefixed with SITE_FULL).
"""
from . import util_accounts
from . import util_submissions


def test_front_page_has_og_title():
"""Test that the front page includes og:title meta tag"""
client = util_accounts.create_logged_off_client()

response = client.get("/")
assert response.status_code == 200
assert 'og:title' in response.text


def test_front_page_has_og_image():
"""Test that the front page includes og:image meta tag"""
client = util_accounts.create_logged_off_client()

response = client.get("/")
assert response.status_code == 200
assert 'og:image' in response.text


def test_front_page_og_type_is_website():
"""Test that the front page uses og:type website (not article)"""
client = util_accounts.create_logged_off_client()

response = client.get("/")
assert response.status_code == 200
assert 'og:type' in response.text
# Should be "website" not "article" for the homepage
assert 'content="website"' in response.text


def test_front_page_og_site_name_not_request_host():
"""Test that og:site_name uses SITE_TITLE, not request.host"""
client = util_accounts.create_logged_off_client()

response = client.get("/")
assert response.status_code == 200
# Should not use request.host (which would be 'localhost' in tests)
assert 'og:site_name' in response.text
# og:site_name should appear exactly once (no duplicates)
assert response.text.count('og:site_name') == 1


def test_front_page_has_twitter_tags():
"""Test that the front page includes Twitter card meta tags"""
client = util_accounts.create_logged_off_client()

response = client.get("/")
assert response.status_code == 200
assert 'twitter:card' in response.text
assert 'twitter:title' in response.text
assert 'twitter:image' in response.text


def test_post_page_has_og_title():
"""Test that a post page includes og:title meta tag"""
client, user = util_accounts.create_test_client_and_user()
post = util_submissions.create_submission_for_client(client)

response = client.get(f"/post/{post.id}")
assert response.status_code == 200
assert 'og:title' in response.text


def test_post_page_has_og_image():
"""Test that a post page includes og:image meta tag"""
client, user = util_accounts.create_test_client_and_user()
post = util_submissions.create_submission_for_client(client)

response = client.get(f"/post/{post.id}")
assert response.status_code == 200
assert 'og:image' in response.text


def test_post_page_og_type_is_article():
"""Test that a post page uses og:type article"""
client, user = util_accounts.create_test_client_and_user()
post = util_submissions.create_submission_for_client(client)

response = client.get(f"/post/{post.id}")
assert response.status_code == 200
assert 'content="article"' in response.text


def test_login_page_has_og_tags():
"""Test that the login page includes OG meta tags"""
client = util_accounts.create_logged_off_client()

response = client.get("/login")
assert response.status_code == 200
assert 'og:title' in response.text
assert 'og:image' in response.text


def test_user_profile_has_og_tags():
"""Test that a user profile page includes OG meta tags"""
client, user = util_accounts.create_test_client_and_user()

response = client.get(f"/@{user.username}")
assert response.status_code == 200
assert 'og:title' in response.text
assert 'og:image' in response.text


def test_user_profile_og_type_is_profile():
"""Test that a user profile page uses og:type profile"""
client, user = util_accounts.create_test_client_and_user()

response = client.get(f"/@{user.username}")
assert response.status_code == 200
assert 'content="profile"' in response.text


def test_no_og_author_on_non_article_pages():
"""Test that og:author is not present on pages that are not articles"""
client = util_accounts.create_logged_off_client()

response = client.get("/")
assert response.status_code == 200
assert 'og:author' not in response.text