From 92f989aa2de74e95b49cf298f9e276af3199ea4d Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Mon, 6 Feb 2023 14:29:45 -0500 Subject: [PATCH] Run and test server with test fixture root (#33816) --- .github/workflows/test.yml | 6 + lib/all-products.js | 5 +- lib/constants.js | 1 + lib/languages.js | 4 +- lib/redirects/precompile.js | 8 +- middleware/contextualizers/features.js | 8 +- middleware/find-page.js | 3 +- next.config.js | 3 +- package.json | 1 + script/copy-fixture-data.js | 104 +++++++ .../content/get-started/foo/autotitling.md | 17 ++ tests/fixtures/content/get-started/foo/bar.md | 14 + .../get-started/foo/cross-version-linking.md | 16 ++ .../fixtures/content/get-started/foo/index.md | 14 + tests/fixtures/content/get-started/index.md | 26 ++ .../get-started/quickstart/hello-world.md | 27 ++ .../content/get-started/quickstart/index.md | 11 + tests/fixtures/content/index.md | 59 ++++ tests/fixtures/content/search/index.md | 10 + tests/fixtures/data/features/volvo.yml | 3 + .../deprecation_details.md | 2 + .../version_was_deprecated.md | 1 + .../version_will_be_deprecated.md | 1 + .../data/reusables/policies/translation.md | 3 + tests/fixtures/data/ui.yml | 267 ++++++++++++++++++ tests/fixtures/data/variables/product.yml | 2 + .../data/variables/release_candidate.yml | 1 + .../footer.js | 28 +- tests/rendering-fixtures/internal-links.js | 36 +++ 29 files changed, 647 insertions(+), 34 deletions(-) create mode 100755 script/copy-fixture-data.js create mode 100644 tests/fixtures/content/get-started/foo/autotitling.md create mode 100644 tests/fixtures/content/get-started/foo/bar.md create mode 100644 tests/fixtures/content/get-started/foo/cross-version-linking.md create mode 100644 tests/fixtures/content/get-started/foo/index.md create mode 100644 tests/fixtures/content/get-started/index.md create mode 100644 tests/fixtures/content/get-started/quickstart/hello-world.md create mode 100644 tests/fixtures/content/get-started/quickstart/index.md create mode 100644 tests/fixtures/content/index.md create mode 100644 tests/fixtures/content/search/index.md create mode 100644 tests/fixtures/data/features/volvo.yml create mode 100644 tests/fixtures/data/reusables/enterprise_deprecation/deprecation_details.md create mode 100644 tests/fixtures/data/reusables/enterprise_deprecation/version_was_deprecated.md create mode 100644 tests/fixtures/data/reusables/enterprise_deprecation/version_will_be_deprecated.md create mode 100644 tests/fixtures/data/reusables/policies/translation.md create mode 100644 tests/fixtures/data/ui.yml create mode 100644 tests/fixtures/data/variables/product.yml create mode 100644 tests/fixtures/data/variables/release_candidate.yml rename tests/{rendering => rendering-fixtures}/footer.js (59%) create mode 100644 tests/rendering-fixtures/internal-links.js diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 277265806d..4869f7377e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -49,6 +49,7 @@ jobs: 'routing', 'unit', 'linting', + 'rendering-fixtures', ]; if (context.payload.repository.full_name === 'github/docs-internal') { all.push('translations'); @@ -110,6 +111,10 @@ jobs: .github/actions-scripts/merge-early-access.sh rm -fr docs-early-access + - name: Check the test fixture data (if applicable) + if: ${{ matrix.test-group == 'rendering-fixtures' }} + run: ./script/copy-fixture-data.js --check + - name: Clone all translations if: ${{ matrix.test-group == 'translations' }} uses: ./.github/actions/clone-translations @@ -172,4 +177,5 @@ jobs: # tests run only in English. The exception is the # `tests/translations/` suite which needs all languages to be set up. ENABLED_LANGUAGES: ${{ matrix.test-group == 'translations' && 'all' || '' }} + ROOT: ${{ matrix.test-group == 'rendering-fixtures' && 'tests/fixtures' || ''}} run: npm test -- tests/${{ matrix.test-group }}/ diff --git a/lib/all-products.js b/lib/all-products.js index 1593436582..0c71575607 100644 --- a/lib/all-products.js +++ b/lib/all-products.js @@ -3,9 +3,10 @@ import path from 'path' import frontmatter from './read-frontmatter.js' import getApplicableVersions from './get-applicable-versions.js' import removeFPTFromPath from './remove-fpt-from-path.js' +import { ROOT } from './constants.js' // Both internal and external products are specified in content/index.md -const homepage = path.posix.join(process.cwd(), 'content/index.md') +const homepage = path.posix.join(ROOT, 'content/index.md') const { data } = frontmatter(await fs.readFile(homepage, 'utf8')) export const productIds = data.children @@ -15,7 +16,7 @@ const internalProducts = {} for (const productId of productIds) { const relPath = productId - const dir = path.posix.join('content', relPath) + const dir = path.join(ROOT, 'content', relPath) // Early Access may not exist in the current checkout try { diff --git a/lib/constants.js b/lib/constants.js index 370bbc99a1..8a98f93edf 100644 --- a/lib/constants.js +++ b/lib/constants.js @@ -1,2 +1,3 @@ +export const ROOT = process.env.ROOT || '.' export const USER_LANGUAGE_COOKIE_NAME = 'user_language' export const TRANSLATIONS_ROOT = process.env.TRANSLATIONS_ROOT || 'translations' diff --git a/lib/languages.js b/lib/languages.js index 6d9168ac28..c52fa7ecc5 100644 --- a/lib/languages.js +++ b/lib/languages.js @@ -4,7 +4,7 @@ import dotenv from 'dotenv' -import { TRANSLATIONS_ROOT } from './constants.js' +import { ROOT, TRANSLATIONS_ROOT } from './constants.js' import path from 'path' dotenv.config() @@ -21,7 +21,7 @@ const possibleEnvVars = { } function getRoot(languageCode) { - if (languageCode === 'en') return '' + if (languageCode === 'en') return ROOT if (languageCode in possibleEnvVars) { const possibleEnvVar = possibleEnvVars[languageCode] if (possibleEnvVar) { diff --git a/lib/redirects/precompile.js b/lib/redirects/precompile.js index f7b7f6ca00..53b1ffaad2 100755 --- a/lib/redirects/precompile.js +++ b/lib/redirects/precompile.js @@ -1,14 +1,8 @@ -import path from 'path' -import { fileURLToPath } from 'url' - import { readCompressedJsonFileFallback } from '../read-json-file.js' import getExceptionRedirects from './exception-redirects.js' - import { latest } from '../enterprise-server-releases.js' -const __dirname = path.dirname(fileURLToPath(import.meta.url)) - -const EXCEPTIONS_FILE = path.join(__dirname, './static/redirect-exceptions.txt') +const EXCEPTIONS_FILE = './lib/redirects/static/redirect-exceptions.txt' // This function runs at server warmup and precompiles possible redirect routes. // It outputs them in key-value pairs within a neat Javascript object: { oldPath: newPath } diff --git a/middleware/contextualizers/features.js b/middleware/contextualizers/features.js index 0de51a8781..c05c71329e 100644 --- a/middleware/contextualizers/features.js +++ b/middleware/contextualizers/features.js @@ -1,3 +1,6 @@ +import path from 'path' + +import { ROOT } from '../../lib/constants.js' import getApplicableVersions from '../../lib/get-applicable-versions.js' import { getDeepDataByLanguage } from '../../lib/get-data.js' @@ -29,7 +32,10 @@ function getFeaturesByVersion(currentVersion) { // Determine whether the currentVersion belongs to the list of versions the feature is available in. for (const [featureName, feature] of Object.entries(allFeatures)) { const { versions } = feature - const applicableVersions = getApplicableVersions(versions, `data/features/${featureName}.yml`) + const applicableVersions = getApplicableVersions( + versions, + path.join(ROOT, `data/features/${featureName}.yml`) + ) // Adding the resulting boolean to the context object gives us the ability to use // `{% if featureName ... %}` conditionals in content files. diff --git a/middleware/find-page.js b/middleware/find-page.js index eae0bab518..7e1097cddd 100644 --- a/middleware/find-page.js +++ b/middleware/find-page.js @@ -1,12 +1,13 @@ import path from 'path' import { existsSync } from 'fs' +import { ROOT } from '../lib/constants.js' import Page from '../lib/page.js' import { languageKeys } from '../lib/languages.js' const languagePrefixRegex = new RegExp(`^/(${languageKeys.join('|')})(/|$)`) const englishPrefixRegex = /^\/en(\/|$)/ -const CONTENT_ROOT = 'content' +const CONTENT_ROOT = path.join(ROOT, 'content') export default async function findPage( req, diff --git a/next.config.js b/next.config.js index 50aa6fcec0..e096412938 100644 --- a/next.config.js +++ b/next.config.js @@ -3,8 +3,9 @@ import path from 'path' import frontmatter from 'gray-matter' import { languageKeys } from './lib/languages.js' +import { ROOT } from './lib/constants.js' -const homepage = path.posix.join(process.cwd(), 'content/index.md') +const homepage = path.posix.join(ROOT, 'content/index.md') const { data } = frontmatter(fs.readFileSync(homepage, 'utf8')) const productIds = data.children diff --git a/package.json b/package.json index b96e0cce72..b05c78c0fd 100644 --- a/package.json +++ b/package.json @@ -185,6 +185,7 @@ "build": "next build", "debug": "cross-env NODE_ENV=development ENABLED_LANGUAGES=en nodemon --inspect server.js", "dev": "cross-env npm start", + "fixture-dev": "cross-env ROOT=tests/fixtures npm start", "index-test-fixtures": "node script/search/index-elasticsearch.js -l en -l ja -V ghae -V dotcom --index-prefix tests -- tests/content/fixtures/search-indexes", "lint": "eslint '**/*.{js,mjs,ts,tsx}'", "lint-translation": "cross-env NODE_OPTIONS=--experimental-vm-modules jest tests/linting/lint-files.js", diff --git a/script/copy-fixture-data.js b/script/copy-fixture-data.js new file mode 100755 index 0000000000..ee41029a1d --- /dev/null +++ b/script/copy-fixture-data.js @@ -0,0 +1,104 @@ +#!/usr/bin/env node + +// [start-readme] +// +// There are certain files that have to be manually copied from the +// real data into the test fixture data. +// +// This script copies the files from `data/` into `tests/fitures/data/...` +// that are files that are both needed for fixture testing yet can't +// live with the code. For example, `data/ui.yml` is part of the rendering +// code, but it lives in `data/` so it can be translated. +// +// [end-readme] + +import fs from 'fs' +import path from 'path' + +import { program } from 'commander' +import chalk from 'chalk' +import mkdirp from 'mkdirp' + +// Here, write down all the files that are actually part of the rendering +// functionality yet live in data. +const MANDATORY_FILES = [ + 'data/ui.yml', + 'data/reusables/policies/translation.md', + 'data/reusables/enterprise_deprecation/deprecation_details.md', + 'data/reusables/enterprise_deprecation/version_was_deprecated.md', + 'data/reusables/enterprise_deprecation/version_will_be_deprecated.md', + 'data/variables/release_candidate.yml', +] + +const DESTINATION = path.resolve('tests/fixtures') + +program + .description('Make sure the test fixtures have up-to-date data from the real content') + .option('--check', 'Exit non-zero if it had to actually do something') + .option('--dry-run', "Don't actually write changes to disk") + .option('-v, --verbose', 'Verbose outputs') + .parse(process.argv) + +main(program.opts()) + +async function main(opts) { + let errors = 0 + for (const file of MANDATORY_FILES) { + const source = fs.readFileSync(file, 'utf-8') + const destination = path.join(DESTINATION, file) + + if (opts.check) { + // The destination has to exist and be identical + try { + const copied = fs.readFileSync(destination, 'utf-8') + if (copied !== source) { + // console.warn(chalk.red(`The file ${destination} is different from ${file}`)) + console.warn(`The file ${chalk.red(destination)} is different from ${chalk.red(file)}`) + errors++ + } else if (opts.verbose) { + console.log(`The file ${chalk.green(destination)} is up-to-date 🥰`) + } + } catch (error) { + if (error.code === 'ENOENT') { + console.warn(`The file ${chalk.red(destination)} does not exist`) + errors++ + } else { + throw error + } + } + } else { + try { + const copied = fs.readFileSync(destination, 'utf-8') + if (copied === source) { + if (opts.verbose) { + console.log(`The file ${chalk.green(destination)} was perfect already 👌`) + } + continue + } + } catch (error) { + if (error.code !== 'ENOENT') throw error + } + if (!opts.dryRun) { + await mkdirp(path.dirname(destination)) + fs.writeFileSync(destination, source, 'utf-8') + if (opts.verbose) { + console.log(`Copied latest ${chalk.green(file)} to ${chalk.bold(destination)} 👍🏼`) + } + } else if (opts.verbose) { + console.log(`Would copy latest ${chalk.bold(file)} to ${chalk.bold(destination)}`) + } + } + } + + if (errors > 0) { + console.warn( + '\n', + chalk.yellow( + 'Run this script again without --check to make all fixture data files up-to-date. ' + + 'Then commit and check in.' + ) + ) + } + + process.exitCode = errors +} diff --git a/tests/fixtures/content/get-started/foo/autotitling.md b/tests/fixtures/content/get-started/foo/autotitling.md new file mode 100644 index 0000000000..fe4715cd48 --- /dev/null +++ b/tests/fixtures/content/get-started/foo/autotitling.md @@ -0,0 +1,17 @@ +--- +title: Autotitling +intro: Internal links that use AUTOTITLE should just work +versions: + fpt: '*' + ghes: '*' + ghae: '*' + ghec: '*' +type: how_to +--- + +## Introduction + +Links that use the word `AUTOTITLE` in the Markdown become the +title of the document it links to. + +For example "[AUTOTITLE](/get-started/quickstart/hello-world)." diff --git a/tests/fixtures/content/get-started/foo/bar.md b/tests/fixtures/content/get-started/foo/bar.md new file mode 100644 index 0000000000..69083b20ca --- /dev/null +++ b/tests/fixtures/content/get-started/foo/bar.md @@ -0,0 +1,14 @@ +--- +title: Bar Usually Comes After Foo +shortTitle: Bar +intro: This page doesn't really have an intro +versions: + fpt: '*' + ghes: '*' + ghae: '*' + ghec: '*' +--- + +## Heading + +Nothing here to see. diff --git a/tests/fixtures/content/get-started/foo/cross-version-linking.md b/tests/fixtures/content/get-started/foo/cross-version-linking.md new file mode 100644 index 0000000000..c3cb1a1a26 --- /dev/null +++ b/tests/fixtures/content/get-started/foo/cross-version-linking.md @@ -0,0 +1,16 @@ +--- +title: Cross Version Linking +intro: Testing to cross the version boundary with hardcoded cross-version links +versions: + fpt: '*' + ghes: '*' + ghae: '*' + ghec: '*' +type: how_to +--- + +## Get right into it + +[Hello world always in free-pro-team](/free-pro-team@latest/get-started/quickstart/hello-world) + +[Autotitling page always in enterprise-server latest](/enterprise-server@latest/get-started/quickstart/hello-world) diff --git a/tests/fixtures/content/get-started/foo/index.md b/tests/fixtures/content/get-started/foo/index.md new file mode 100644 index 0000000000..df893b02b6 --- /dev/null +++ b/tests/fixtures/content/get-started/foo/index.md @@ -0,0 +1,14 @@ +--- +title: Fooing Around +shortTitle: Foo +intro: 'The most basic of fixture data for {% data variables.product.product_name %}' +versions: + fpt: '*' + ghes: '*' + ghae: '*' + ghec: '*' +children: + - /bar + - /autotitling + - /cross-version-linking +--- diff --git a/tests/fixtures/content/get-started/index.md b/tests/fixtures/content/get-started/index.md new file mode 100644 index 0000000000..d253b4a408 --- /dev/null +++ b/tests/fixtures/content/get-started/index.md @@ -0,0 +1,26 @@ +--- +title: Getting started with HubGit +shortTitle: Get started +intro: 'This is the intro' +versions: + fpt: '*' + ghes: '*' + ghae: '*' + ghec: '*' +layout: product-landing +introLinks: + quickstart: /get-started/quickstart +featuredLinks: + guides: + - /get-started/quickstart/hello-world + popular: + - /get-started/foo/bar + guideCards: + - /get-started/foo/autotitling +children: + - /quickstart + - /foo +communityRedirect: + name: Provide HubGit Feedback + href: 'https://hubgit.com/orgs/community/discussions/categories/get-started' +--- diff --git a/tests/fixtures/content/get-started/quickstart/hello-world.md b/tests/fixtures/content/get-started/quickstart/hello-world.md new file mode 100644 index 0000000000..ccf082858f --- /dev/null +++ b/tests/fixtures/content/get-started/quickstart/hello-world.md @@ -0,0 +1,27 @@ +--- +title: Hello World +intro: 'Follow this Hello World exercise to get started with {% data variables.product.product_name %}.' +versions: + fpt: '*' + ghes: '*' + ghae: '*' + ghec: '*' +type: quick_start +topics: + - Pull requests + - Fundamentals +miniTocMaxHeadingLevel: 3 +--- + +## Introduction + +This is just a test. + +{% ifversion volvo %} +Ove loves Volvos. +{% else %} +Apparently, a Saab it is. +{% endif %} + +Try changing the current version from "Free, Pro, & Team" to something +like "Enterprise Server X.Y". It should change the above sentence. diff --git a/tests/fixtures/content/get-started/quickstart/index.md b/tests/fixtures/content/get-started/quickstart/index.md new file mode 100644 index 0000000000..40e9cb45b8 --- /dev/null +++ b/tests/fixtures/content/get-started/quickstart/index.md @@ -0,0 +1,11 @@ +--- +title: Quickstart +intro: 'Get started using {% data variables.product.product_name %} to manage Git repositories and collaborate with others.' +versions: + fpt: '*' + ghes: '*' + ghae: '*' + ghec: '*' +children: + - /hello-world +--- diff --git a/tests/fixtures/content/index.md b/tests/fixtures/content/index.md new file mode 100644 index 0000000000..6580cd6703 --- /dev/null +++ b/tests/fixtures/content/index.md @@ -0,0 +1,59 @@ +--- +title: '{% data variables.product.product_name %}{% ifversion fpt or ghec%}.com{% endif %} Fixture Documentation' +featuredLinks: + gettingStarted: + - /get-started/foo/hello-world + popular: + - get-started +redirect_from: + - /olden-days +versions: '*' +children: + # The list of childen in the fixtures has to be the same names + # as we use in the real content. It can have fewer but can't include + # anything that the real `/content/index.md` doesn't contain for this. + # The reason is that the `npm run build` compiles a list of rewrites + # so that URLs like `/en/get-started/anything` can be treated, + # as if the URL had been `/en/free-pro-team@latest/get-started/anything`. + - search + - get-started + # - account-and-profile + # - authentication + # - repositories + # - admin + # - billing + # - site-policy + # - organizations + # - code-security + # - pull-requests + # - issues + # - actions + # - copilot + # - codespaces + # - packages + # - search-github + # - developers + # - rest + # - graphql + # - github-cli + # - discussions + # - sponsors + # - communities + # - pages + # - education + # - desktop + # - early-access + # - support +childGroups: + - name: Get started + octicon: RocketIcon + children: + - get-started + +externalProducts: + electron: + id: mothership + name: GitHub itself + href: 'https://github.com' + external: true +--- diff --git a/tests/fixtures/content/search/index.md b/tests/fixtures/content/search/index.md new file mode 100644 index 0000000000..e3b3da45f7 --- /dev/null +++ b/tests/fixtures/content/search/index.md @@ -0,0 +1,10 @@ +--- +title: Search +hidden: true +versions: + fpt: '*' + ghec: '*' + ghes: '*' + ghae: '*' +--- + diff --git a/tests/fixtures/data/features/volvo.yml b/tests/fixtures/data/features/volvo.yml new file mode 100644 index 0000000000..14ba8f5e2d --- /dev/null +++ b/tests/fixtures/data/features/volvo.yml @@ -0,0 +1,3 @@ +versions: + fpt: '*' + ghec: '*' diff --git a/tests/fixtures/data/reusables/enterprise_deprecation/deprecation_details.md b/tests/fixtures/data/reusables/enterprise_deprecation/deprecation_details.md new file mode 100644 index 0000000000..ed570ed576 --- /dev/null +++ b/tests/fixtures/data/reusables/enterprise_deprecation/deprecation_details.md @@ -0,0 +1,2 @@ +No patch releases will be made, even for critical security issues. For better performance, improved security, and new features, upgrade to the latest version of GitHub Enterprise. +For help with the upgrade, contact GitHub Enterprise support. diff --git a/tests/fixtures/data/reusables/enterprise_deprecation/version_was_deprecated.md b/tests/fixtures/data/reusables/enterprise_deprecation/version_was_deprecated.md new file mode 100644 index 0000000000..917aa3a6c4 --- /dev/null +++ b/tests/fixtures/data/reusables/enterprise_deprecation/version_was_deprecated.md @@ -0,0 +1 @@ +This version of GitHub Enterprise was discontinued on diff --git a/tests/fixtures/data/reusables/enterprise_deprecation/version_will_be_deprecated.md b/tests/fixtures/data/reusables/enterprise_deprecation/version_will_be_deprecated.md new file mode 100644 index 0000000000..d1812b0977 --- /dev/null +++ b/tests/fixtures/data/reusables/enterprise_deprecation/version_will_be_deprecated.md @@ -0,0 +1 @@ +This version of GitHub Enterprise will be discontinued on diff --git a/tests/fixtures/data/reusables/policies/translation.md b/tests/fixtures/data/reusables/policies/translation.md new file mode 100644 index 0000000000..fd1157c558 --- /dev/null +++ b/tests/fixtures/data/reusables/policies/translation.md @@ -0,0 +1,3 @@ +This document is translated from English. In the event of any conflict, uncertainty, or apparent inconsistency between this version and the English version(s) of this document, the English version is the controlling version. + +If you have suggestions to improve our translation, please open an issue in our site-policy repository. diff --git a/tests/fixtures/data/ui.yml b/tests/fixtures/data/ui.yml new file mode 100644 index 0000000000..ea68ef2cc6 --- /dev/null +++ b/tests/fixtures/data/ui.yml @@ -0,0 +1,267 @@ +meta: + default_description: Get started, troubleshoot, and make the most of GitHub. Documentation for new users, developers, administrators, and all of GitHub's products. +header: + github_docs: GitHub Docs + contact: Contact + notices: + ghae_silent_launch: GitHub AE is currently under limited release. + release_candidate: + # The version name is rendered before the below text via includes/header-notification.html + ' is currently available as a release candidate. For more information, see "About upgrades to new releases."' + localization_complete: + We publish frequent updates to our documentation, and translation of this page may still be in progress. + For the most current information, please visit the + English documentation. + early_access: 📣 Please do not share this URL publicly. This page contains content about an early access feature. + release_notes_use_latest: Please use the latest release for the latest security, performance, and bug fixes. + # GHES release notes + ghes_release_notes_upgrade_patch_only: 📣 This is not the latest patch release of Enterprise Server. + ghes_release_notes_upgrade_release_only: 📣 This is not the latest release of Enterprise Server. + ghes_release_notes_upgrade_patch_and_release: 📣 This is not the latest patch release of this release series, and this is not the latest release of Enterprise Server. + sign_up_cta: Sign up + menu: Menu +picker: + language_picker_default_text: Choose a language + product_picker_default_text: All products + version_picker_default_text: Choose a version +release_notes: + banner_text: GitHub began rolling these changes out to enterprises on +search: + need_help: Need help? + placeholder: Search GitHub Docs + no_results: No results found + search_results_for: Search results for + no_content: No content + matches_found: Results found + matches_displayed: Matches displayed + search_error: An error occurred trying to perform the search. + description: Enter a search term to find it in the GitHub Documentation. + label: Search GitHub Docs + found_results: Found {n} results + one_result_found: Found 1 result +homepage: + explore_by_product: Explore by product + version_picker: Version + description: Help for wherever you are on your GitHub journey. +toc: + getting_started: Getting started + popular: Popular + startHere: Start here + whats_new: What's new + videos: Videos + all_changelogs: All changelog posts +pages: + article_version: 'Article version' + miniToc: In this article + all_enterprise_releases: All Enterprise Server releases + about_versions: About versions + permissions_statement: Who can use this feature +errors: + oops: Ooops! + something_went_wrong: It looks like something went wrong. + we_track_errors: We track these errors automatically, but if the problem persists please feel free to contact us. + page_doesnt_exist: It looks like this page doesn't exist. +support: + still_need_help: Still need help? + contact_support: Contact support + ask_community: Ask the GitHub community +survey: + able_to_find: Did this doc help you? + yes: Yes + no: No + comment_yes_label: Let us know what we do well + comment_no_label: Let us know what we can do better + optional: Optional + required: Required + email_placeholder: email@example.com + email_label: If we can contact you with more questions, please enter your email address + email_validation: Please enter a valid email address + send: Send + feedback: Thank you! We received your feedback. + not_support: If you need a reply, please contact support instead. + privacy_policy: Privacy policy +contribution_cta: + title: Help us make these docs great! + body: All GitHub docs are open source. See something that's wrong or unclear? Submit a pull request. + button: Make a contribution + or: Or, + to_guidelines: learn how to contribute. +parameter_table: + body: Body parameters + default: Default + description: Description + enum_description_title: Can be one of + headers: Headers + name: Name + path: Path parameters + query: Query parameters + required: Required + see_preview_notice: See preview notice + see_preview_notices: See preview notices + type: Type + single_enum_description: Value +products: + graphql: + reference: + implements: Implements + fields: Fields + arguments: Arguments + name: Name + type: Type + description: Description + input_fields: Input fields + return_fields: Return fields + implemented_by: Implemented by + values: Values + possible_types: Possible types + preview_notice: Preview notice + deprecation_notice: Deprecation notice + preview_period: During the preview period, the API may change without notice. + overview: + preview_header: 'To toggle this preview and access the following schema members, you must provide a custom media type in the `Accept` header:' + preview_schema_members: 'Previewed schema members' + announced: Announced + updates: Updates + rest: + banner: + api_versioned: The REST API is now versioned. + api_version_info: For more information, see "About API versioning." + ghes_api_versioned: After a site administrator upgrades your Enterprise Server instance to {{ firstGhesReleaseWithApiVersions.versionTitle }} or later, the REST API will be versioned. To learn how to find your instance's version, see "About versions of GitHub Docs". + versioning: + about_versions: About REST API versions + reference: + in: In + description: Description + notes: Notes + parameters: Parameters + response: Response + example_response: Example response + status_code: Status code + http_status_code: HTTP response status codes + code_sample: Code sample + code_samples: Code samples + preview_notice: Preview notice + preview_notices: Preview notices + preview_header_is_required: This header is required + preview_notice_to_change: This API is under preview and subject to change + works_with: Works with + api_reference: REST API reference + enum_description_title: Can be one of + required: Required + headers: Headers + query: Query parameters + path: Path parameters + body: Body parameters + webhooks: + action_type_switch_error: There was an error switching webhook action types. + action_type: Action type + availability: Availability + webhook_payload_object: Webhook payload object + webhook_payload_example: Webhook payload example + rephrase_availability: + repository: Repositories + organization: Organizations + app: GitHub Apps + business: Enterprises + marketplace: GitHub Marketplace + sponsors_listing: Sponsored accounts +footer: + all_rights_reserved: All rights reserved + terms: Terms + privacy: Privacy + security: Security + product: + heading: Product + links: + features: Features + security: Security + enterprise: Enterprise + case_studies: Case Studies + pricing: Pricing + resources: Resources + platform: + heading: Platform + links: + developer_api: Developer API + partners: Partners + atom: Atom + electron: Electron + github_desktop: GitHub Desktop + support: + heading: Support + links: + help: Help + community_forum: Community Forum + training: Training + status: Status + contact_github: Contact GitHub + company: + heading: Company + links: + about: About + blog: Blog + careers: Careers + press: Press + shop: Shop +product_landing: + quickstart: Quickstart + reference: Reference + overview: Overview + guides: Guides + code_examples: Code examples + search_code_examples: Search code examples + search_results_for: Search results for + matches_displayed: Matches displayed + show_more: Show more + explore_people_and_projects: Explore people and projects + sorry: Sorry, there is no result for + no_example: It looks like we don't have an example that fits your filter. + try_another: Try another filter or add your code example. + no_result: Sorry, there are no guides that match your filter. + learn: Learn how to add a code example + communities_using_discussions: Communities on GitHub.com using discussions + add_your_community: Add your community + sponsor_community: GitHub Sponsors community + supported_releases: Supported releases + release_notes_for: Release notes for + upgrade_from: Upgrade from + browse_all_docs: Browse all docs + browse_all: Browse all + docs: docs + explore_release_notes: Explore release notes + view: View all +product_guides: + start_path: Start learning path + learning_paths: '{{ productMap[currentProduct].name }} learning paths' + learning_paths_desc: Learning paths are a collection of guides that help you master a particular subject. + guides: '{{ productMap[currentProduct].name }} guides' + more_guides: more guides + load_more: Load more guides + all_guides: 'All {{ productMap[currentProduct].name }} guides' + filter_instructions: Filter the guide list using these controls + filters: + type: Type + topic: Topic + all: All + guides_found: + multiple: '{n} guides found' + one: 1 guide found + none: No guides found + guide_types: + overview: Overview + quick_start: Quickstart + tutorial: Tutorial + how_to: How-to guide + reference: Reference +learning_track_nav: + prev_guide: Previous + next_guide: Next + more_guides: More guides → + current_progress: '{i} of {n} in learning path' +toggle_images: + off: Images are off, click to show + on: Images are on, click to hide + hide_single: Hide image + show_single: Show image +scroll_button: + scroll_to_top: Scroll to top diff --git a/tests/fixtures/data/variables/product.yml b/tests/fixtures/data/variables/product.yml new file mode 100644 index 0000000000..b54a6cf5d8 --- /dev/null +++ b/tests/fixtures/data/variables/product.yml @@ -0,0 +1,2 @@ +product_name: >- + {% ifversion ghec %}HubGit Enterprise Cloud{% elsif ghes %}HubGit Enterprise Server{% elsif ghae %}HubGit AE{% else %}HubGit{% endif %} diff --git a/tests/fixtures/data/variables/release_candidate.yml b/tests/fixtures/data/variables/release_candidate.yml new file mode 100644 index 0000000000..026d2f7e61 --- /dev/null +++ b/tests/fixtures/data/variables/release_candidate.yml @@ -0,0 +1 @@ +version: '' diff --git a/tests/rendering/footer.js b/tests/rendering-fixtures/footer.js similarity index 59% rename from tests/rendering/footer.js rename to tests/rendering-fixtures/footer.js index 2fc0c22cd0..8525980ffb 100644 --- a/tests/rendering/footer.js +++ b/tests/rendering-fixtures/footer.js @@ -8,7 +8,9 @@ describe('footer', () => { describe('"contact us" link', () => { test('leads to support from articles', async () => { - const $ = await getDOM(`/en/${nonEnterpriseDefaultVersion}/issues`) + const $ = await getDOM( + `/en/${nonEnterpriseDefaultVersion}/get-started/quickstart/hello-world` + ) expect($('a#contact-us').attr('href')).toBe('https://support.github.com/contact') }) @@ -20,37 +22,23 @@ describe('footer', () => { describe('"contact us" link with nextjs', () => { test('leads to support from articles', async () => { - const $ = await getDOM(`/en/${nonEnterpriseDefaultVersion}/issues?nextjs=`) + const $ = await getDOM(`/en/${nonEnterpriseDefaultVersion}/get-started?nextjs=`) expect($('a#contact-us').attr('href')).toBe('https://support.github.com/contact') }) }) describe('test redirects for product landing community links pages', () => { - test('codespaces product landing page leads to codespaces discussions page', async () => { - const $ = await getDOM(`/en/codespaces`) + test('codespaces product landing page leads to discussions page', async () => { + const $ = await getDOM('/en/get-started') expect($('a#ask-community').attr('href')).toBe( - 'https://github.com/community/community/discussions/categories/codespaces' - ) - }) - - test('sponsors product landing page leads to sponsors discussions page', async () => { - const $ = await getDOM(`/en/sponsors`) - expect($('a#ask-community').attr('href')).toBe( - 'https://github.com/community/community/discussions/categories/sponsors' - ) - }) - - test('codespaces product landing page leads to discussions discussions page', async () => { - const $ = await getDOM(`/en/discussions`) - expect($('a#ask-community').attr('href')).toBe( - 'https://github.com/community/community/discussions/categories/discussions' + 'https://hubgit.com/orgs/community/discussions/categories/get-started' ) }) }) describe('test redirects for non-product landing community links pages', () => { test('leads to https://github.community/ when clicking on the community link', async () => { - const $ = await getDOM(`/en/github/authenticating-to-github`) + const $ = await getDOM(`/en/get-started/quickstart/hello-world`) expect($('a#ask-community').attr('href')).toBe( 'https://github.com/orgs/community/discussions' ) diff --git a/tests/rendering-fixtures/internal-links.js b/tests/rendering-fixtures/internal-links.js new file mode 100644 index 0000000000..e585d3df4c --- /dev/null +++ b/tests/rendering-fixtures/internal-links.js @@ -0,0 +1,36 @@ +import { getDOM } from '../helpers/e2etest.js' +import enterpriseServerReleases from '../../lib/enterprise-server-releases.js' +import { allVersions } from '../../lib/all-versions.js' + +describe('autotitle', () => { + test('internal links with AUTOTITLE resolves', async () => { + const $ = await getDOM('/get-started/foo/autotitling') + const firstLink = $('#article-contents a[href]') + expect(firstLink.text()).toBe('Hello World') + }) +}) + +describe('cross-version-links', () => { + test.each(Object.keys(allVersions))( + 'links to free-pro-team should be implicit even on %p', + async (version) => { + const URL = `/${version}/get-started/foo/cross-version-linking` + const $ = await getDOM(URL) + const links = $('#article-contents a[href]') + + // Tests that the hardcoded prefix is always removed + const firstLink = links.filter(function () { + return $(this).text() === 'Hello world always in free-pro-team' + }) + expect(firstLink.attr('href')).toBe('/en/get-started/quickstart/hello-world') + + // Tests that the second link always goes to enterprise-server@X.Y + const secondLink = links.filter(function () { + return $(this).text() === 'Autotitling page always in enterprise-server latest' + }) + expect(secondLink.attr('href')).toBe( + `/en/enterprise-server@${enterpriseServerReleases.latest}/get-started/quickstart/hello-world` + ) + } + ) +})