Skip to content

Commit

Permalink
Feat/add sitemap (#1828)
Browse files Browse the repository at this point in the history
* feat(sitemap): add sitemap macro

* feat(sitemap): add new route and a hard-coded sitemap

* chore: formatting

* chore: formatting

* chore: regen css

* chore: refactor sitemap; get it into its own file

* chore: formatting

* chore: re-gen css for sitemap

* chore: add stubs for missing translations

* chore: update link text + remove links that dont exist

* chore: regen css

* feat(sitemap): sort links alphabetically by link title

* chore: add translations

* chore: add more missing translations

* chore: formatting

* feat(cypress): make it easier to add tests to CI workflow

- use a common test file for CI runs (`ci.cy.js`) and include both app_pages.cy.js and sitemap.cy.js in it

* test(sitemap): add cypress tests for sitemap

* fix(workflow): update cypress workflow to use `ci.cy.js`

* fix(ci): fix typo in test path

* feat(sitemap): refactor sitemap.cy.js to remove unneeded code

* refactor(sitemap): remove unneeded code; add test to ensure links are alphabetical in each category in fr and en

* chore: rename sitemap macro param

* fix(sitemap): print out character entities properly (like ` `)

* fix(sitemap): add remaining translations

* feat(sitemap): Add sitemap link to footer navigation

* chore: regen css after merge with main

* fix(cypress): add command to get elements by `data-testid`

* test(sitemap): add `testid`s

* test(sitemap): Ensure 'You' section is displayed when logged in and not displayed when logged out.

* fix(sitemap tests): add missing import

* fix(sitemap tests): correct import

* feat(bilingual route): experiment for how we might try to do bilingual routes

* chore: formatting

* test(sitemap): add tests for sitemap link being in footer; add login command to commands.js; formatting

* chore: update translations
  • Loading branch information
andrewleith authored May 21, 2024
1 parent 9ed426c commit 60e5dd5
Show file tree
Hide file tree
Showing 10 changed files with 234 additions and 4 deletions.
2 changes: 1 addition & 1 deletion app/assets/stylesheets/index.css

Large diffs are not rendered by default.

70 changes: 70 additions & 0 deletions app/main/sitemap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
from flask import current_app, url_for
from flask_babel import _

from app import get_current_locale
from app.articles.routing import gca_url_for
from app.utils import documentation_url


def get_sitemap():
lang = get_current_locale(current_app)
return {
"groups": [
{
"title": _("About GC Notify"),
"pages": [
{"href": url_for("main.activity"), "link_text": _("Activity on GC Notify")},
{"href": url_for("main.contact"), "link_text": _("Contact us")},
{"href": gca_url_for("features"), "link_text": _("Features")},
{"href": gca_url_for("new_features"), "link_text": _("New features")},
{"href": gca_url_for("register_for_demo"), "link_text": _("Register for a demo")},
{"href": gca_url_for("whynotify"), "link_text": _("Why GC Notify")},
],
},
{
"title": _("Developers"),
"pages": [
{"href": documentation_url(), "link_text": _("Integrate the API")},
{
"href": current_app.config["SYSTEM_STATUS_URL"] + ("/#fr" if lang == "fr" else ""),
"link_text": _("System status"),
},
],
},
{
"title": _("Help and guidance"),
"pages": [
{"href": documentation_url(), "link_text": _("API documentation")},
# {"href": "/#", "link_text": _("Getting started")},
# {"href": "/#", "link_text": _("Guidance overview")},
{"href": gca_url_for("formatting_guide"), "link_text": _("Formatting emails")},
{"href": gca_url_for("spreadsheets"), "link_text": _("Using a spreadsheet")},
{"href": gca_url_for("personalisation_guide"), "link_text": _("Sending custom content")},
{"href": gca_url_for("message_delivery_status"), "link_text": _("Understanding delivery and failure")},
{"href": gca_url_for("bounce_guidance"), "link_text": _("Updating contact information")},
],
},
{
"title": _("Policy"),
"pages": [
{"href": gca_url_for("accessibility"), "link_text": _("Accessibility")},
{"href": gca_url_for("terms"), "link_text": _("GC Notify terms of use")},
{"href": gca_url_for("privacy"), "link_text": _("Privacy notice for staff using GC Notify")},
{"href": gca_url_for("security"), "link_text": _("Security")},
{"href": gca_url_for("service-level-agreement"), "link_text": _("GC Notify service level agreement")},
{
"href": gca_url_for("service-level-objectives"),
"link_text": _("Service level objectives: What to expect from GC Notify"),
},
],
},
{
"must_be_logged_in": True,
"title": _("Your GC Notify"),
"pages": [
{"href": url_for("main.user_profile"), "link_text": _("Your account")},
{"href": url_for("main.choose_account"), "link_text": _("Your services")},
],
},
]
}
22 changes: 22 additions & 0 deletions app/main/views/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
FieldWithNoneOption,
SearchByNameForm,
)
from app.main.sitemap import get_sitemap
from app.utils import (
Spreadsheet,
documentation_url,
Expand Down Expand Up @@ -257,6 +258,27 @@ def welcome():
return render_template("views/welcome.html", default_limit=current_app.config["DEFAULT_SERVICE_LIMIT"])


# TODO: refactor this out into a decorator
@main.route("/plandesite", endpoint="plandesite", methods=["GET"])
@main.route("/sitemap", methods=["GET"])
def sitemap():
requested_lang = "en" if request.endpoint == "main.sitemap" else "fr"
current_lang = get_current_locale(current_app)

# if the language is changing
if requested_lang != current_lang:
# if the user typed in the url:
if request.referrer is None:
route = "/plandesite" if requested_lang == "fr" else "/sitemap"
return redirect(url_for(**{"endpoint": "main.set_lang", "from": route}))
# if the user clicked the lang button:
else:
route = "main.sitemap" if requested_lang == "fr" else "main.plandesite"
return redirect(url_for(route))

return render_template("views/sitemap.html", sitemap=get_sitemap())


@main.route("/activity", endpoint="activity")
def activity():
return render_template("views/activity.html", **get_latest_stats(get_current_locale(current_app), filter_heartbeats=True))
Expand Down
20 changes: 20 additions & 0 deletions app/templates/components/sitemap.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{% macro site_map(sitemap=None) %}
{% if sitemap %}
{% for group in sitemap.groups %}
{% if not group.must_be_logged_in or current_user.is_authenticated %}
<ul>
<li class="flex w-full border-t-4 border-gray pt-12 pb-12">
<h2 class="w-2/5 heading-medium m-0" data-testid="sitemap-group">{{ group.title }}</h2>
<ul class="w-3/5 flex flex-wrap items-center">
{% for page in group.pages|sort(attribute='link_text') %}
<li class="w-1/2 p-4">
<a href="{{ page.href }}">{{ page.link_text | safe }}</a>
</li>
{% endfor %}
</ul>
</li>
</ul>
{% endif %}
{% endfor %}
{% endif %}
{% endmacro %}
1 change: 1 addition & 0 deletions app/templates/partials/nav/footer.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
{% else %}
{{ nav_link_dark(id_key='nav-footer-primary-doc', label=_('API documentation'), href=documentation_url(), is_external_link=True, class="-ml-2") }}
{{ nav_link_dark(id_key='nav-footer-primary-guidance', label=_('Guidance'), href=gca_url_for('guidance'), class="-ml-2") }}
{{ nav_link_dark(id_key='nav-footer-sitemap', label=_('Sitemap'), href=url_for('main.sitemap'), class="-ml-2") }}
{{ nav_link_dark(id_key='nav-footer-primary-slo', label=_('Service level objectives'), href=gca_url_for('service-level-objectives'), class="-ml-2") }}
{% endif %}
</div>
Expand Down
11 changes: 11 additions & 0 deletions app/templates/views/sitemap.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% extends "admin_template.html" %}
{% from "components/sitemap.html" import site_map with context %}

{% block per_page_title %}
{{ _('Sitemap') }}
{% endblock %}

{% block maincolumn_content %}
<h1 class="heading-large pb-8">{{ _('Sitemap') }}</h1>
{{ site_map(sitemap) }}
{% endblock %}
17 changes: 17 additions & 0 deletions app/translations/csv/fr.csv
Original file line number Diff line number Diff line change
Expand Up @@ -1861,7 +1861,24 @@
"Select a priority queue","Sélectionnez une file de sécurité"
"Select a folder","Sélectionnez un dossier"
"Select template","Sélectionner un gabarit"
"Updating contact information","Maintenir à jour les coordonnées"
"Developers","Développeurs"
"Formatting emails","Guide de mise en forme de courriels"
"GC Notify terms of use","Conditions d’utilisation de Notification GC"
"Privacy notice for staff using GC Notify","Avis de confidentialité à l’intention du personnel utilisant Notification GC"
"Help and guidance","Aide et conseils"
"Why Notify","Pourquoi Notification GC"
"About GC Notify","À propos de Notification GC"
"Understanding delivery and failure","Comprendre le statut de livraison"
"Sending custom content","Envoyer des messages avec du contenu personnalisé"
"Using a spreadsheet","Utiliser une feuille de calcul"
"Your GC Notify","Votre Notification GC"
"Policy","Politique"
"Make sure we have formatted your email address correctly.","Assurez-vous que nous avons correctement formaté votre courriel."
"GC Notify service level agreement","Accord sur les niveaux de service de Notification GC"
"Service level objectives: What to expect from GC Notify","Objectifs de niveau de service&nbsp;: qu’attendre de Notification GC"
"Integrate the API","Intégrer l’API"
"Sitemap","Plan de site"
"This is an english description of the logo for screenreaders.","Voici une description anglaise du logo pour les lecteurs d'écran."
"This is a french description of the logo for screenreaders","Voici une description française du logo pour les lecteurs d'écran."
"Alternative text in English","Texte alternatif en anglais"
Expand Down
1 change: 1 addition & 0 deletions tests_cypress/cypress/e2e/admin/ci.cy.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
import "./a11y/app_pages.cy";
import "./sign_out/sign_out.cy";
import './sitemap/sitemap.cy';
88 changes: 88 additions & 0 deletions tests_cypress/cypress/e2e/admin/sitemap/sitemap.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/// <reference types="cypress" />

import config from "../../../../config";
let sitemaplinks = [];
const path = '/sitemap';
const sitemap_footer_id = 'nav-footer-sitemap';

describe(`Sitemap`, () => {
it('Has link text that corresponds to page titles', () => {
cy.then(Cypress.session.clearCurrentSessionData)
cy.visit(path);
cy.get('main').within(() => {
cy.get('a').each((link) => {
sitemaplinks.push({
url: link.prop('href'),
text: link.text().trim()
});
const link_url = link.prop('href');
const link_text = link.text().trim();

cy.log(`Checking sitemap link: ${link_text}/${link_url}`);
if (link_url.includes(config.Hostnames.Admin) && !link_url.includes('/#')) {
cy.visit(link_url);
cy.get('h1').should('contain', `${link_text}`);
}

});
});
});

context('Has links ordered alphabetically in each category', () => {
['en', 'fr'].forEach((lang) => {
it(lang === 'en' ? 'English' : 'French', () => {
cy.visit(`/sitemap?lang=${lang}`);
cy.get('main').within(() => {
cy.get('h2').each((category) => {
const category_links = category.next('ul').find('a');
const category_links_text = category_links.map((i, el) => Cypress.$(el).text().trim()).get();
const category_links_text_sorted = [...category_links_text].sort();
expect(category_links_text).to.deep.equal(category_links_text_sorted);
});
});
});
});

it("Does NOT display the 'You' group when logged out", () => {
cy.visit(path);
cy.getByTestId('sitemap-group').should('not.have.text', 'You');

cy.login(Cypress.env('NOTIFY_USER'), Cypress.env('NOTIFY_PASSWORD'));
});

it("Does display the 'You' group when logged in", () => {
cy.login(Cypress.env('NOTIFY_USER'), Cypress.env('NOTIFY_PASSWORD'));
cy.visit(path);

cy.getByTestId('sitemap-group').contains('You');
});
});

context('Footer', () => {
it('Has the sitemap link on app pages when logged out', () => {
cy.then(Cypress.session.clearCurrentSessionData)
cy.visit('/activity');

cy.get(`#${sitemap_footer_id}`).should('be.visible');
});
it('Has the sitemap link on GCA pages when logged out', () => {
cy.then(Cypress.session.clearCurrentSessionData)
cy.visit('/features');

cy.get(`#${sitemap_footer_id}`).should('be.visible');
});
it('Has the sitemap link on app pages when logged in', () => {
cy.login(Cypress.env('NOTIFY_USER'), Cypress.env('NOTIFY_PASSWORD'));
cy.visit('/activity');

cy.get(`#${sitemap_footer_id}`).should('be.visible');
});
it('Has the sitemap link on GCA pages when logged in', () => {
cy.login(Cypress.env('NOTIFY_USER'), Cypress.env('NOTIFY_PASSWORD'));
cy.visit('/features');

cy.get(`#${sitemap_footer_id}`).should('be.visible');
});

});
});
6 changes: 3 additions & 3 deletions tests_cypress/cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import LoginPage from "../Notify/Admin/Pages/LoginPage";
let links_checked = [];
let svgs_checked = [];

Cypress.Commands.add('a11yScan', (url, options={ a11y: true, htmlValidate: true, deadLinks: true, mimeTypes: true }) => {
Cypress.Commands.add('a11yScan', (url, options = { a11y: true, htmlValidate: true, deadLinks: true, mimeTypes: true }) => {
const current_hostname = config.Hostnames.Admin;
// bypass rate limiting
cy.intercept(`${current_hostname}/*`, (req) => {
Expand Down Expand Up @@ -115,7 +115,7 @@ Cypress.Commands.add('a11yScan', (url, options={ a11y: true, htmlValidate: true,
});
});
}
})
});

Cypress.Commands.add('getByTestId', (selector, ...args) => {
return cy.get(`[data-testid=${selector}]`, ...args)
Expand All @@ -125,4 +125,4 @@ Cypress.Commands.add('login', (username, password) => {
cy.session([username, password], () => {
LoginPage.Login(username, password);
});
});
});

0 comments on commit 60e5dd5

Please sign in to comment.