Skip to navigation

closeSurface

The closeSurface action closes one or more surfaces. A surface is anything a step can target: a background process, a browser window or tab, or a native app surface. closeSurface replaces the earlier stopProcess action.

For native apps, { "closeSurface": { "app": "notepad" } } ends the app surface, terminating the app if Doc Detective launched it. { "closeSurface": { "app": "notepad", "window": -1 } } closes just one window, a dialog say, and keeps the app open. Window selectors use the shared grammar of title, /regex/, and -1 for the newest window. See App windows. Doc Detective refuses to close an app’s last window and points at the bare form instead. A selector that matches nothing is a no-op.

Provide a surface as the value for the closeSurface key. You can identify a surface in any of these ways:

  • String name: The name of the surface.
  • Object: An object that identifies the surface by type: { "process": … } for a background process, { "browser": …, "tab": … } / { "browser": …, "window": … } for a browser tab or window, or { "app": … } for a native app surface.
  • Array: A list of names or objects to close several surfaces in one step.

Doc Detective trims leading and trailing whitespace from the surface name before matching.

Closing a surface that isn’t open, because it was already closed or never started, always passes. Doc Detective never treats a missing surface as a failure, so you can call closeSurface defensively without first checking whether the surface is still open.

You don’t have to close every surface explicitly. Doc Detective closes any surfaces that are still open when the run finishes. Use closeSurface when you want to close a surface before the run ends, such as to free a port for a later test.

The step records which surfaces it closed and which were already absent in its outputs: closed and absent are arrays of surface names, and closedCount and absentCount are their counts.

For comprehensive options, see the closeSurface reference.

Examples

Here are a few ways you might use the closeSurface action:

Close a process by name

This example starts a background server and then closes it by name.

{
"tests": [
{
"steps": [
{
"description": "Start a server in the background.",
"runShell": {
"command": "npm start",
"background": {
"name": "web",
"waitUntil": {
"port": 3000
}
}
}
},
{
"description": "Close the server.",
"closeSurface": "web"
}
]
}
]
}

Close several surfaces at once

Pass an array of surface identifiers to close more than one surface in a single step.

{
"tests": [
{
"steps": [
{
"description": "Close the web and API servers.",
"closeSurface": ["web", { "process": "api" }]
}
]
}
]
}

Close a process that might not be running

Because closing an absent surface passes, you can call closeSurface defensively without checking first whether the process is still running.

{
"tests": [
{
"steps": [
{
"description": "Close the server if it's still running.",
"closeSurface": "web"
}
]
}
]
}

Close a browser tab or window

A browser reference with a tab selector closes that tab. A window selector closes the window and its tabs. Selectors accept a name, an index in creation order (-1 is the newest), or { title, url } criteria. See Test across multiple tabs, windows, and browsers.

{
"tests": [
{
"steps": [
{
"description": "Close the cart tab.",
"closeSurface": { "browser": "chrome", "tab": "cart" }
},
{
"description": "Close the admin window and all its tabs.",
"closeSurface": { "browser": "chrome", "window": "admin" }
},
{
"description": "Close the newest tab.",
"closeSurface": { "browser": "chrome", "tab": -1 }
}
]
}
]
}

One guardrail applies. Doc Detective refuses to close the last open tab of a browser. Closing a tab isn’t how you end a session; closing the whole browser is.

Close a whole browser

A browser reference with no window/tab selector closes that entire browser session: a bare surface name, an engine keyword, or the { "browser": …, "name": … } object form. Closing a browser that isn’t open is a PASS no-op, and the active surface falls back to the most recently focused remaining browser. A browser with an active recording refuses to close until you stopRecord. See Test across multiple tabs, windows, and browsers.

{
"tests": [
{
"steps": [
{
"description": "Close the named admin browser.",
"closeSurface": "admin"
},
{
"description": "Close the chrome browser.",
"closeSurface": "chrome"
},
{
"description": "Close several surfaces — browsers and processes mix freely.",
"closeSurface": ["admin", { "browser": "firefox" }, { "process": "web" }]
}
]
}
]
}

Close an app surface

Reference an app surface with { "app": … } to close it, or with its bare name. Closing an app surface ends its session, which terminates the app Doc Detective launched.

{
"tests": [
{
"steps": [
{
"description": "Close the Notepad app surface.",
"closeSurface": { "app": "notepad" }
}
]
}
]
}

Window-scoped app closes work on Windows and macOS app surfaces. Android and iOS surfaces are single-window, so a window selector fails there. Omit it to close the app.

On Windows, index selectors other than -1 aren’t supported, because the Windows driver can’t enumerate an app’s windows in creation order. Select by title or /regex/ instead.