fix(webServer): do not set baseURL equal to webServer.url (#11951)

This commit is contained in:
Dmitry Gozman 2022-02-08 15:57:36 -08:00 committed by GitHub
parent 8dff2e35c8
commit e92caf01b3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 70 additions and 56 deletions

View file

@ -139,9 +139,16 @@ export const test = base.extend<{ saveLogs: void }>({
To launch a server during the tests, use the `webServer` option in the [configuration file](#configuration-object). To launch a server during the tests, use the `webServer` option in the [configuration file](#configuration-object).
You can specify a port via `port` or additional environment variables, see [here](#configuration-object). The server will wait for it to be available (on `127.0.0.1` or `::1`) before running the tests. For continuous integration, you may want to use the `reuseExistingServer: !process.env.CI` option which does not use an existing server on the CI. To see the stdout, you can set the `DEBUG=pw:webserver` environment variable. If `port` is specified in the config, test runner will wait for `127.0.0.1:port` or `::1:port` to be available before running the tests.
If `url` is specified in the config, test runner will wait for that `url` to return 2xx response before running the tests.
The port gets then passed over to Playwright as a [`param: baseURL`] when creating the context [`method: Browser.newContext`]. For continuous integration, you may want to use the `reuseExistingServer: !process.env.CI` option which does not use an existing server on the CI. To see the stdout, you can set the `DEBUG=pw:webserver` environment variable.
The `port` (but not the `url`) gets passed over to Playwright as a [`property: TestOptions.baseURL`]. For example port `8080` produces `baseURL` equal `http://localhost:8080`.
:::note
It is also recommended to specify [`property: TestOptions.baseURL`] in the config, so that tests could use relative urls.
:::
```js js-flavor=ts ```js js-flavor=ts
// playwright.config.ts // playwright.config.ts

View file

@ -568,10 +568,15 @@ export default config;
Launch a development web server during the tests. Launch a development web server during the tests.
If the port is specified, the server will wait for it to be available on `127.0.0.1` or `::1`, before running the tests. If the url is specified, the server will wait for the URL to return a 2xx status code before running the tests. For continuous integration, you may want to use the `reuseExistingServer: !process.env.CI` option which does not use an existing server on the CI. To see the stdout, you can set the `DEBUG=pw:webserver` environment variable. If the port is specified, the server will wait for it to be available on `127.0.0.1` or `::1`, before running the tests. If the url is specified, the server will wait for the URL to return a 2xx status code before running the tests.
The port or url gets then passed over to Playwright as a `baseURL` when creating the context [`method: Browser.newContext`]. For continuous integration, you may want to use the `reuseExistingServer: !process.env.CI` option which does not use an existing server on the CI. To see the stdout, you can set the `DEBUG=pw:webserver` environment variable.
For example port `8080` ends up in `baseURL` to be `http://localhost:8080`. If you want to instead use `https://` you need to manually specify the `baseURL` inside `use` or use a url instead of a port in the `webServer` configuration. The url ends up in `baseURL` without any change.
The `port` (but not the `url`) gets passed over to Playwright as a [`property: TestOptions.baseURL`]. For example port `8080` produces `baseURL` equal `http://localhost:8080`.
:::note
It is also recommended to specify [`property: TestOptions.baseURL`] in the config, so that tests could use relative urls.
:::
```js js-flavor=ts ```js js-flavor=ts
// playwright.config.ts // playwright.config.ts
@ -583,6 +588,9 @@ const config: PlaywrightTestConfig = {
timeout: 120 * 1000, timeout: 120 * 1000,
reuseExistingServer: !process.env.CI, reuseExistingServer: !process.env.CI,
}, },
use: {
baseURL: 'http://localhost:3000/',
},
}; };
export default config; export default config;
``` ```
@ -598,22 +606,21 @@ const config = {
timeout: 120 * 1000, timeout: 120 * 1000,
reuseExistingServer: !process.env.CI, reuseExistingServer: !process.env.CI,
}, },
use: {
baseURL: 'http://localhost:3000/',
},
}; };
module.exports = config; module.exports = config;
``` ```
Now you can use a relative path when navigating the page, or use `baseURL` fixture: Now you can use a relative path when navigating the page:
```js js-flavor=ts ```js js-flavor=ts
// test.spec.ts // test.spec.ts
import { test } from '@playwright/test'; import { test } from '@playwright/test';
test('test', async ({ page, baseURL }) => {
// baseURL is taken directly from your web server, test('test', async ({ page }) => {
// e.g. http://localhost:3000 // This will result in http://localhost:3000/foo
await page.goto(baseURL + '/bar');
// Alternatively, just use relative path, because baseURL is already
// set for the default context and page.
// For example, this will result in http://localhost:3000/foo
await page.goto('/foo'); await page.goto('/foo');
}); });
``` ```
@ -621,13 +628,9 @@ test('test', async ({ page, baseURL }) => {
```js js-flavor=js ```js js-flavor=js
// test.spec.js // test.spec.js
const { test } = require('@playwright/test'); const { test } = require('@playwright/test');
test('test', async ({ page, baseURL }) => {
// baseURL is taken directly from your web server, test('test', async ({ page }) => {
// e.g. http://localhost:3000 // This will result in http://localhost:3000/foo
await page.goto(baseURL + '/bar');
// Alternatively, just use relative path, because baseURL is already
// set for the default context and page.
// For example, this will result in http://localhost:3000/foo
await page.goto('/foo'); await page.goto('/foo');
}); });
``` ```

View file

@ -91,8 +91,8 @@ export class WebServer {
private async _waitForProcess() { private async _waitForProcess() {
await this._waitForAvailability(); await this._waitForAvailability();
const baseURL = this.config.url ?? `http://localhost:${this.config.port}`; if (this.config.port !== undefined)
process.env.PLAYWRIGHT_TEST_BASE_URL = baseURL; process.env.PLAYWRIGHT_TEST_BASE_URL = `http://localhost:${this.config.port}`;
} }
private async _waitForAvailability() { private async _waitForAvailability() {
@ -148,10 +148,10 @@ async function waitFor(waitFn: () => Promise<boolean>, delay: number, cancellati
} }
function getIsAvailableFunction({ url, port }: Pick<WebServerConfig, 'port' | 'url'>) { function getIsAvailableFunction({ url, port }: Pick<WebServerConfig, 'port' | 'url'>) {
if (url && typeof port === 'undefined') { if (url !== undefined && port === undefined) {
const urlObject = new URL(url); const urlObject = new URL(url);
return () => isURLAvailable(urlObject); return () => isURLAvailable(urlObject);
} else if (port && typeof url === 'undefined') { } else if (port !== undefined && url === undefined) {
return () => isPortUsed(port); return () => isPortUsed(port);
} else { } else {
throw new Error(`Exactly one of 'port' or 'url' is required in config.webServer.`); throw new Error(`Exactly one of 'port' or 'url' is required in config.webServer.`);

View file

@ -577,15 +577,18 @@ interface TestConfig {
* Launch a development web server during the tests. * Launch a development web server during the tests.
* *
* If the port is specified, the server will wait for it to be available on `127.0.0.1` or `::1`, before running the tests. * If the port is specified, the server will wait for it to be available on `127.0.0.1` or `::1`, before running the tests.
* If the url is specified, the server will wait for the URL to return a 2xx status code before running the tests. For * If the url is specified, the server will wait for the URL to return a 2xx status code before running the tests.
* continuous integration, you may want to use the `reuseExistingServer: !process.env.CI` option which does not use an *
* For continuous integration, you may want to use the `reuseExistingServer: !process.env.CI` option which does not use an
* existing server on the CI. To see the stdout, you can set the `DEBUG=pw:webserver` environment variable. * existing server on the CI. To see the stdout, you can set the `DEBUG=pw:webserver` environment variable.
* *
* The port or url gets then passed over to Playwright as a `baseURL` when creating the context * The `port` (but not the `url`) gets passed over to Playwright as a
* [browser.newContext([options])](https://playwright.dev/docs/api/class-browser#browser-new-context). For example port * [testOptions.baseURL](https://playwright.dev/docs/api/class-testoptions#test-options-base-url). For example port `8080`
* `8080` ends up in `baseURL` to be `http://localhost:8080`. If you want to instead use `https://` you need to manually * produces `baseURL` equal `http://localhost:8080`.
* specify the `baseURL` inside `use` or use a url instead of a port in the `webServer` configuration. The url ends up in *
* `baseURL` without any change. * > NOTE: It is also recommended to specify
* [testOptions.baseURL](https://playwright.dev/docs/api/class-testoptions#test-options-base-url) in the config, so that
* tests could use relative urls.
* *
* ```ts * ```ts
* // playwright.config.ts * // playwright.config.ts
@ -597,22 +600,21 @@ interface TestConfig {
* timeout: 120 * 1000, * timeout: 120 * 1000,
* reuseExistingServer: !process.env.CI, * reuseExistingServer: !process.env.CI,
* }, * },
* use: {
* baseURL: 'http://localhost:3000/',
* },
* }; * };
* export default config; * export default config;
* ``` * ```
* *
* Now you can use a relative path when navigating the page, or use `baseURL` fixture: * Now you can use a relative path when navigating the page:
* *
* ```ts * ```ts
* // test.spec.ts * // test.spec.ts
* import { test } from '@playwright/test'; * import { test } from '@playwright/test';
* test('test', async ({ page, baseURL }) => { *
* // baseURL is taken directly from your web server, * test('test', async ({ page }) => {
* // e.g. http://localhost:3000 * // This will result in http://localhost:3000/foo
* await page.goto(baseURL + '/bar');
* // Alternatively, just use relative path, because baseURL is already
* // set for the default context and page.
* // For example, this will result in http://localhost:3000/foo
* await page.goto('/foo'); * await page.goto('/foo');
* }); * });
* ``` * ```
@ -1068,15 +1070,18 @@ export interface FullConfig<TestArgs = {}, WorkerArgs = {}> {
* Launch a development web server during the tests. * Launch a development web server during the tests.
* *
* If the port is specified, the server will wait for it to be available on `127.0.0.1` or `::1`, before running the tests. * If the port is specified, the server will wait for it to be available on `127.0.0.1` or `::1`, before running the tests.
* If the url is specified, the server will wait for the URL to return a 2xx status code before running the tests. For * If the url is specified, the server will wait for the URL to return a 2xx status code before running the tests.
* continuous integration, you may want to use the `reuseExistingServer: !process.env.CI` option which does not use an *
* For continuous integration, you may want to use the `reuseExistingServer: !process.env.CI` option which does not use an
* existing server on the CI. To see the stdout, you can set the `DEBUG=pw:webserver` environment variable. * existing server on the CI. To see the stdout, you can set the `DEBUG=pw:webserver` environment variable.
* *
* The port or url gets then passed over to Playwright as a `baseURL` when creating the context * The `port` (but not the `url`) gets passed over to Playwright as a
* [browser.newContext([options])](https://playwright.dev/docs/api/class-browser#browser-new-context). For example port * [testOptions.baseURL](https://playwright.dev/docs/api/class-testoptions#test-options-base-url). For example port `8080`
* `8080` ends up in `baseURL` to be `http://localhost:8080`. If you want to instead use `https://` you need to manually * produces `baseURL` equal `http://localhost:8080`.
* specify the `baseURL` inside `use` or use a url instead of a port in the `webServer` configuration. The url ends up in *
* `baseURL` without any change. * > NOTE: It is also recommended to specify
* [testOptions.baseURL](https://playwright.dev/docs/api/class-testoptions#test-options-base-url) in the config, so that
* tests could use relative urls.
* *
* ```ts * ```ts
* // playwright.config.ts * // playwright.config.ts
@ -1088,22 +1093,21 @@ export interface FullConfig<TestArgs = {}, WorkerArgs = {}> {
* timeout: 120 * 1000, * timeout: 120 * 1000,
* reuseExistingServer: !process.env.CI, * reuseExistingServer: !process.env.CI,
* }, * },
* use: {
* baseURL: 'http://localhost:3000/',
* },
* }; * };
* export default config; * export default config;
* ``` * ```
* *
* Now you can use a relative path when navigating the page, or use `baseURL` fixture: * Now you can use a relative path when navigating the page:
* *
* ```ts * ```ts
* // test.spec.ts * // test.spec.ts
* import { test } from '@playwright/test'; * import { test } from '@playwright/test';
* test('test', async ({ page, baseURL }) => { *
* // baseURL is taken directly from your web server, * test('test', async ({ page }) => {
* // e.g. http://localhost:3000 * // This will result in http://localhost:3000/foo
* await page.goto(baseURL + '/bar');
* // Alternatively, just use relative path, because baseURL is already
* // set for the default context and page.
* // For example, this will result in http://localhost:3000/foo
* await page.goto('/foo'); * await page.goto('/foo');
* }); * });
* ``` * ```

View file

@ -114,8 +114,8 @@ test('should create a server with url', async ({ runInlineTest }, { workerIndex
'test.spec.ts': ` 'test.spec.ts': `
const { test } = pwt; const { test } = pwt;
test('connect to the server', async ({baseURL, page}) => { test('connect to the server', async ({baseURL, page}) => {
expect(baseURL).toBe('http://localhost:${port}/ready'); expect(baseURL).toBe(undefined);
await page.goto(baseURL); await page.goto('http://localhost:${port}/ready');
expect(await page.textContent('body')).toBe('hello'); expect(await page.textContent('body')).toBe('hello');
}); });
`, `,