diff --git a/.changeset/seven-bottles-warn.md b/.changeset/seven-bottles-warn.md new file mode 100644 index 0000000000..653618200d --- /dev/null +++ b/.changeset/seven-bottles-warn.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Fixes dev server not stopping cleanly diff --git a/packages/astro/src/core/dev/index.ts b/packages/astro/src/core/dev/index.ts index 56808fd784..a7856bf332 100644 --- a/packages/astro/src/core/dev/index.ts +++ b/packages/astro/src/core/dev/index.ts @@ -26,7 +26,7 @@ export interface DevOptions { logging: LogOptions; } -interface DevServer { +export interface DevServer { hostname: string; port: number; server: connect.Server; @@ -96,7 +96,7 @@ export class AstroDevServer { await this.viteServer.close(); } if (this.httpServer) { - await promisify(this.httpServer.close)(); + await promisify(this.httpServer.close.bind(this.httpServer))(); } } diff --git a/packages/astro/test/astro-styles-ssr.test.js b/packages/astro/test/astro-styles-ssr.test.js index 168cded3e0..ad9e0b7ee9 100644 --- a/packages/astro/test/astro-styles-ssr.test.js +++ b/packages/astro/test/astro-styles-ssr.test.js @@ -3,7 +3,7 @@ import cheerio from 'cheerio'; import { loadFixture } from './test-utils.js'; describe('Styles SSR', function () { - this.timeout(5000); + this.timeout(10000); let fixture; let index$; diff --git a/packages/astro/test/dev-routing.test.js b/packages/astro/test/dev-routing.test.js new file mode 100644 index 0000000000..0a96aefdb4 --- /dev/null +++ b/packages/astro/test/dev-routing.test.js @@ -0,0 +1,129 @@ +import { expect } from 'chai'; +import cheerio from 'cheerio'; +import { loadFixture } from './test-utils.js'; + +describe('Development Routing', () => { + describe('No site config', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture + /** @type {import('./test-utils').DevServer} */ + let devServer; + + before(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/without-site-config/' }); + devServer = await fixture.startDevServer(); + }); + + after(async () => { + devServer && await devServer.stop(); + }); + + it('200 when loading /', async () => { + const response = await fixture.fetch('/'); + expect(response.status).to.equal(200); + }); + + it('200 when loading non-root page', async () => { + const response = await fixture.fetch('/another'); + expect(response.status).to.equal(200); + }) + }); + + describe('No subpath used', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture + /** @type {import('./test-utils').DevServer} */ + let devServer; + + before(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/without-subpath/' }); + devServer = await fixture.startDevServer(); + }); + + after(async () => { + devServer && await devServer.stop(); + }); + + it('200 when loading /', async () => { + const response = await fixture.fetch('/'); + expect(response.status).to.equal(200); + }); + + it('200 when loading non-root page', async () => { + const response = await fixture.fetch('/another'); + expect(response.status).to.equal(200); + }) + }); + + describe('Subpath with trailing slash', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture + /** @type {import('./test-utils').DevServer} */ + let devServer; + + before(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/with-subpath-trailing-slash/' }); + devServer = await fixture.startDevServer(); + }); + + after(async () => { + devServer && await devServer.stop(); + }); + + it('404 when loading /', async () => { + const response = await fixture.fetch('/'); + expect(response.status).to.equal(404); + }); + + it('200 when loading subpath root', async () => { + const response = await fixture.fetch('/blog/'); + expect(response.status).to.equal(200); + }); + + it('404 when loading subpath root without trailing slash', async () => { + const response = await fixture.fetch('/blog'); + expect(response.status).to.equal(404); + }); + + it('200 when loading another page with subpath used', async () => { + const response = await fixture.fetch('/blog/another/'); + expect(response.status).to.equal(200); + }); + }); + + describe('Subpath without trailing slash', () => { + /** @type {import('./test-utils').Fixture} */ + let fixture + /** @type {import('./test-utils').DevServer} */ + let devServer; + + before(async () => { + fixture = await loadFixture({ projectRoot: './fixtures/with-subpath-no-trailing-slash/' }); + devServer = await fixture.startDevServer(); + }); + + after(async () => { + devServer && await devServer.stop(); + }); + + it('404 when loading /', async () => { + const response = await fixture.fetch('/'); + expect(response.status).to.equal(404); + }); + + it('200 when loading subpath root with trailing slash', async () => { + const response = await fixture.fetch('/blog/'); + expect(response.status).to.equal(200); + }); + + it('200 when loading subpath root without trailing slash', async () => { + const response = await fixture.fetch('/blog'); + expect(response.status).to.equal(200); + }); + + it('200 when loading another page with subpath used', async () => { + const response = await fixture.fetch('/blog/another/'); + expect(response.status).to.equal(200); + }); + }); +}); \ No newline at end of file diff --git a/packages/astro/test/fixtures/with-subpath-no-trailing-slash/astro.config.mjs b/packages/astro/test/fixtures/with-subpath-no-trailing-slash/astro.config.mjs new file mode 100644 index 0000000000..616285e2b4 --- /dev/null +++ b/packages/astro/test/fixtures/with-subpath-no-trailing-slash/astro.config.mjs @@ -0,0 +1,6 @@ + +export default { + buildOptions: { + site: 'http://example.com/blog' + } +} \ No newline at end of file diff --git a/packages/astro/test/fixtures/with-subpath-no-trailing-slash/src/pages/another.astro b/packages/astro/test/fixtures/with-subpath-no-trailing-slash/src/pages/another.astro new file mode 100644 index 0000000000..d0563f4145 --- /dev/null +++ b/packages/astro/test/fixtures/with-subpath-no-trailing-slash/src/pages/another.astro @@ -0,0 +1 @@ +
another page
\ No newline at end of file diff --git a/packages/astro/test/fixtures/with-subpath-no-trailing-slash/src/pages/index.astro b/packages/astro/test/fixtures/with-subpath-no-trailing-slash/src/pages/index.astro new file mode 100644 index 0000000000..42e6a51771 --- /dev/null +++ b/packages/astro/test/fixtures/with-subpath-no-trailing-slash/src/pages/index.astro @@ -0,0 +1 @@ +
testing
\ No newline at end of file diff --git a/packages/astro/test/fixtures/with-subpath-trailing-slash/astro.config.mjs b/packages/astro/test/fixtures/with-subpath-trailing-slash/astro.config.mjs new file mode 100644 index 0000000000..5f2ab2688d --- /dev/null +++ b/packages/astro/test/fixtures/with-subpath-trailing-slash/astro.config.mjs @@ -0,0 +1,6 @@ + +export default { + buildOptions: { + site: 'http://example.com/blog/' + } +} \ No newline at end of file diff --git a/packages/astro/test/fixtures/with-subpath-trailing-slash/src/pages/another.astro b/packages/astro/test/fixtures/with-subpath-trailing-slash/src/pages/another.astro new file mode 100644 index 0000000000..d0563f4145 --- /dev/null +++ b/packages/astro/test/fixtures/with-subpath-trailing-slash/src/pages/another.astro @@ -0,0 +1 @@ +
another page
\ No newline at end of file diff --git a/packages/astro/test/fixtures/with-subpath-trailing-slash/src/pages/index.astro b/packages/astro/test/fixtures/with-subpath-trailing-slash/src/pages/index.astro new file mode 100644 index 0000000000..8dca56dd88 --- /dev/null +++ b/packages/astro/test/fixtures/with-subpath-trailing-slash/src/pages/index.astro @@ -0,0 +1 @@ +
Hello world
\ No newline at end of file diff --git a/packages/astro/test/fixtures/without-site-config/src/pages/another.astro b/packages/astro/test/fixtures/without-site-config/src/pages/another.astro new file mode 100644 index 0000000000..d0563f4145 --- /dev/null +++ b/packages/astro/test/fixtures/without-site-config/src/pages/another.astro @@ -0,0 +1 @@ +
another page
\ No newline at end of file diff --git a/packages/astro/test/fixtures/without-site-config/src/pages/index.astro b/packages/astro/test/fixtures/without-site-config/src/pages/index.astro new file mode 100644 index 0000000000..42e6a51771 --- /dev/null +++ b/packages/astro/test/fixtures/without-site-config/src/pages/index.astro @@ -0,0 +1 @@ +
testing
\ No newline at end of file diff --git a/packages/astro/test/fixtures/without-subpath/astro.config.mjs b/packages/astro/test/fixtures/without-subpath/astro.config.mjs new file mode 100644 index 0000000000..7ac59b3413 --- /dev/null +++ b/packages/astro/test/fixtures/without-subpath/astro.config.mjs @@ -0,0 +1,6 @@ + +export default { + buildOptions: { + site: 'http://example.com/' + } +} \ No newline at end of file diff --git a/packages/astro/test/fixtures/without-subpath/src/pages/another.astro b/packages/astro/test/fixtures/without-subpath/src/pages/another.astro new file mode 100644 index 0000000000..d0563f4145 --- /dev/null +++ b/packages/astro/test/fixtures/without-subpath/src/pages/another.astro @@ -0,0 +1 @@ +
another page
\ No newline at end of file diff --git a/packages/astro/test/fixtures/without-subpath/src/pages/index.astro b/packages/astro/test/fixtures/without-subpath/src/pages/index.astro new file mode 100644 index 0000000000..42e6a51771 --- /dev/null +++ b/packages/astro/test/fixtures/without-subpath/src/pages/index.astro @@ -0,0 +1 @@ +
testing
\ No newline at end of file diff --git a/packages/astro/test/test-utils.js b/packages/astro/test/test-utils.js index d4876563da..eb282b4c79 100644 --- a/packages/astro/test/test-utils.js +++ b/packages/astro/test/test-utils.js @@ -3,13 +3,25 @@ import fetch from 'node-fetch'; import fs from 'fs'; import { fileURLToPath } from 'url'; import { loadConfig } from '../dist/core/config.js'; +import dev from '../dist/core/dev/index.js'; import build from '../dist/core/build/index.js'; import preview from '../dist/core/preview/index.js'; +/** + * @typedef {import('node-fetch').Response} Response + * @typedef {import('../src/core/dev/index').DevServer} DevServer + * + * + * @typedef {Object} Fixture + * @property {typeof build} build + * @property {(url: string, opts: any) => Promise} fetch + * @property {(path: string) => Promise} readFile + * @property {() => Promise} startDevServer + */ /** * Load Astro fixture * @param {Object} inlineConfig Astro config partial (note: must specify projectRoot) - * @returns {Object} Fixture. Has the following properties: + * @returns {Fixture} The fixture. Has the following properties: * .config - Returns the final config. Will be automatically passed to the methods below: * * Build @@ -40,6 +52,7 @@ export async function loadFixture(inlineConfig) { return { build: (opts = {}) => build(config, { mode: 'development', logging: 'error', ...opts }), + startDevServer: () => dev(config, { logging: 'error' }), config, fetch: (url, init) => fetch(`http://${config.devOptions.hostname}:${config.devOptions.port}${url.replace(/^\/?/, '/')}`, init), preview: async (opts = {}) => {