From c2bd8e5e07e0bf2fad47a9a6fd1d243edc6a1afe Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Fri, 28 Apr 2023 11:09:32 -0400 Subject: [PATCH] Test local dev better (#36700) --- .github/actions-scripts/test-local-dev.js | 113 ++++++++++++++++++++++ .github/workflows/local-dev.yml | 9 +- tests/content/featured-links.js | 20 +--- tests/rendering/products.js | 25 ----- tests/rendering/server.js | 21 ---- tests/rendering/versions.js | 26 ----- 6 files changed, 116 insertions(+), 98 deletions(-) create mode 100755 .github/actions-scripts/test-local-dev.js delete mode 100644 tests/rendering/products.js delete mode 100644 tests/rendering/versions.js diff --git a/.github/actions-scripts/test-local-dev.js b/.github/actions-scripts/test-local-dev.js new file mode 100755 index 0000000000..f32865f98c --- /dev/null +++ b/.github/actions-scripts/test-local-dev.js @@ -0,0 +1,113 @@ +#!/usr/bin/env node + +import assert from 'node:assert/strict' +import fs from 'fs' + +import got from 'got' + +/** + * A very basic script that tests the local dev server. + * + * We use this in CI to make sure the local development server works. + * There are certain things that only work and happen when in + * local dev, that don't make sense to test in regular end-to-end tests + * such as `jest` rendering. + */ + +main() + +async function get(path) { + // By default, got() will use retries and follow redirects. + const response = await got(makeURL(path)) + console.log(`GET ${path} => ${response.statusCode}`) + return response +} + +function makeURL(path) { + return `http://localhost:4000${path}` +} + +async function main() { + // Edit a page's content and expect to see that change when viewed + await testEditingPage() + + // Only in local dev is the `?json=...` query string working + await testJSONParameters() +} + +async function testEditingPage() { + const string = `Today's date is ${new Date().toString()}` + const filePath = 'content/get-started/quickstart/hello-world.md' + const content = fs.readFileSync(filePath, 'utf-8') + try { + fs.appendFileSync(filePath, string, 'utf-8') + + const res = await get('/get-started/quickstart/hello-world') + if (!res.body.includes(string)) { + throw new Error(`Couldn't find the string '${string}' in the response body`) + } + } finally { + fs.writeFileSync(filePath, content, 'utf-8') + } +} + +async function testJSONParameters() { + // currentVersion should be free-pro-team@latest + { + const res = await get('/get-started/quickstart/hello-world?json=currentVersion') + const info = JSON.parse(res.body) + assert(info === 'free-pro-team@latest') + } + + // currentVersion should be free-pro-team@latest + { + const res = await get('/enterprise-server@latest/admin?json=currentVersion') + const info = JSON.parse(res.body) + assert(/enterprise-server@\d/.test(info)) + } + + // activeProducts + { + const res = await get('/en?json=activeProducts') + const activeProducts = JSON.parse(res.body) + assert(Array.isArray(activeProducts)) + } + + // currentProduct (home page) + { + const res = await get('/en?json=currentProduct') + const currentProduct = JSON.parse(res.body) + assert(currentProduct === 'homepage') + } + + // currentProduct (actions) + { + const res = await get('/en/actions?json=currentProduct') + const currentProduct = JSON.parse(res.body) + assert(currentProduct === 'actions') + } + + // page + { + const res = await get('/en?json=page') + const info = JSON.parse(res.body) + assert(info.title === 'GitHub.com Help Documentation') + } + + // Just ?json + { + const res = await get('/en?json') + const info = JSON.parse(res.body) + assert(info.message) + assert(info.keys && Array.isArray(info.keys)) + } + + // Featured links + { + const res = await get('/en?json=featuredLinks.gettingStarted') + const links = JSON.parse(res.body) + assert(links && Array.isArray(links)) + assert(links[0].href) + assert(links[0].page) + } +} diff --git a/.github/workflows/local-dev.yml b/.github/workflows/local-dev.yml index a596be0cf4..2f2f980d3d 100644 --- a/.github/workflows/local-dev.yml +++ b/.github/workflows/local-dev.yml @@ -35,13 +35,8 @@ jobs: sleep 10 curl --fail --retry-connrefused --retry 5 http://localhost:4000/ - - name: Edit a page's .md file and expect it to appear - run: | - # First append anything to the Markdown page - echo "Today's date $(date)" >> content/get-started/quickstart/hello-world.md - - # This pipe to grep will fail if it can't find it in the curl output - curl -L http://localhost:4000/get-started/quickstart/hello-world | grep "Today's date" + - name: Run basic tests + run: node .github/actions-scripts/test-local-dev.js - if: ${{ failure() }} name: Debug server outputs on errors diff --git a/tests/content/featured-links.js b/tests/content/featured-links.js index cbe2135a87..92a5ab20bc 100644 --- a/tests/content/featured-links.js +++ b/tests/content/featured-links.js @@ -1,6 +1,6 @@ import { jest } from '@jest/globals' -import { getDOM, getJSON } from '../helpers/e2etest.js' +import { getDOM } from '../helpers/e2etest.js' import enterpriseServerReleases from '../../lib/enterprise-server-releases.js' describe('featuredLinks', () => { @@ -69,22 +69,4 @@ describe('featuredLinks', () => { expect($productArticlesLinks.text().includes('Setting your billing email'), msg).toBe(false) }) }) - - describe('context.page object', () => { - test('returns modified array of links', async () => { - const gettingStartedLinks = await getJSON('/en?json=featuredLinks.gettingStarted') - const expectedFirstLink = { - href: '/en/get-started/quickstart/set-up-git', - title: 'Set up Git', - } - expect(gettingStartedLinks[0].href).toEqual(expectedFirstLink.href) - expect(gettingStartedLinks[0].title).toEqual(expectedFirstLink.title) - expect(gettingStartedLinks[0].intro.startsWith('At the heart of GitHub')).toBe(true) - }) - - test('returns raw array of links on the page object', async () => { - const rawGettingStartedLinks = await getJSON('/en?json=page.featuredLinks.gettingStarted') - expect(rawGettingStartedLinks[0]).toEqual('/get-started/quickstart/set-up-git') - }) - }) }) diff --git a/tests/rendering/products.js b/tests/rendering/products.js deleted file mode 100644 index 7a30a42c22..0000000000 --- a/tests/rendering/products.js +++ /dev/null @@ -1,25 +0,0 @@ -import { describe, jest } from '@jest/globals' - -import { getJSON } from '../helpers/e2etest.js' -import nonEnterpriseDefaultVersion from '../../lib/non-enterprise-default-version.js' - -describe('products middleware', () => { - jest.setTimeout(5 * 60 * 1000) - - test('adds res.context.activeProducts array', async () => { - const products = await getJSON('/en?json=activeProducts') - expect(Array.isArray(products)).toBe(true) - }) - - test('adds res.context.currentProduct string on homepage', async () => { - const currentProduct = await getJSON('/en?json=currentProduct') - expect(currentProduct).toBe('homepage') - }) - - test('adds res.context.currentProduct object', async () => { - const currentProduct = await getJSON( - `/en/${nonEnterpriseDefaultVersion}/actions?json=currentProduct` - ) - expect(currentProduct).toBe('actions') - }) -}) diff --git a/tests/rendering/server.js b/tests/rendering/server.js index a695082e40..a9f92e6d5c 100644 --- a/tests/rendering/server.js +++ b/tests/rendering/server.js @@ -499,27 +499,6 @@ describe('GitHub Enterprise URLs', () => { }) }) -describe('?json query param for context debugging', () => { - it('uses query param value as a key', async () => { - const res = await get('/en?json=page') - expect(res.statusCode).toBe(200) - const page = JSON.parse(res.body) - expect(typeof page.title).toBe('string') - }) - - it('returns a helpful message with top-level keys if query param has no value', async () => { - const res = await get('/en?json') - expect(res.statusCode).toBe(200) - const context = JSON.parse(res.body) - - expect(context.message.includes('context object is too big to display')).toBe(true) - expect(Array.isArray(context.keys)).toBe(true) - expect(context.keys.includes('page')).toBe(true) - expect(context.keys.includes('pages')).toBe(true) - expect(context.keys.includes('redirects')).toBe(true) - }) -}) - describe('static routes', () => { it('serves content from the /assets directory', async () => { const res = await get('/assets/images/site/be-social.gif') diff --git a/tests/rendering/versions.js b/tests/rendering/versions.js deleted file mode 100644 index 3f83f0a489..0000000000 --- a/tests/rendering/versions.js +++ /dev/null @@ -1,26 +0,0 @@ -import { describe, jest } from '@jest/globals' - -import { allVersions } from '../../lib/all-versions.js' -import { latest } from '../../lib/enterprise-server-releases.js' -import nonEnterpriseDefaultVersion from '../../lib/non-enterprise-default-version.js' -import { getJSON } from '../helpers/e2etest.js' - -describe('versions middleware', () => { - jest.setTimeout(60 * 1000) - - test('adds res.context.allVersions object', async () => { - const allVersionsFromMiddleware = await getJSON('/en?json=allVersions') - expect(allVersionsFromMiddleware).toEqual(allVersions) - }) - - test('adds res.context.currentVersion string', async () => { - let currentVersion = await getJSON('/en?json=currentVersion') - expect(currentVersion).toBe(nonEnterpriseDefaultVersion) - - currentVersion = await getJSON(`/en/${nonEnterpriseDefaultVersion}?json=currentVersion`) - expect(currentVersion).toBe(nonEnterpriseDefaultVersion) - - currentVersion = await getJSON(`/en/enterprise-server@${latest}?json=currentVersion`) - expect(currentVersion).toBe(`enterprise-server@${latest}`) - }) -})