@interopio/iocd-cli 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/changelog.md CHANGED
@@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.0.3](https://github.com/InteropIO/iocd-cli/compare/iocd-cli-v1.0.2...iocd-cli-v1.0.3) (2026-08-19)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **test:** prepare seed before running generated tests ([#97](https://github.com/InteropIO/iocd-cli/issues/97)) ([4baded9](https://github.com/InteropIO/iocd-cli/commit/4baded957c1e4afeb73d15cf98db9e2afd1f3464))
14
+
15
+ ## [1.0.2](https://github.com/InteropIO/iocd-cli/compare/iocd-cli-v1.0.1...iocd-cli-v1.0.2) (2026-08-18)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * **templates:** pin wdio service 1.0.0-next.3 and document sso startup login in the skill ([fa49dc1](https://github.com/InteropIO/iocd-cli/commit/fa49dc15f541cfa79437f78c1fd5647d6dfd4aea))
21
+
8
22
  ## [1.0.1](https://github.com/InteropIO/iocd-cli/compare/iocd-cli-v1.0.0...iocd-cli-v1.0.1) (2026-08-16)
9
23
 
10
24
 
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.startDevMode = startDevMode;
7
+ exports.prepareIocdForDev = prepareIocdForDev;
7
8
  const modifications_service_1 = require("./modifications/modifications.service");
8
9
  const child_process_1 = require("child_process");
9
10
  const logger_1 = require("../utils/logger");
@@ -15,6 +16,10 @@ const license_file_service_1 = require("./license-file.service");
15
16
  const logger = logger_1.Logger.getInstance("dev.service");
16
17
  async function startDevMode(extraArgs) {
17
18
  logger.info("Will start io.cd in dev mode....");
19
+ await prepareIocdForDev();
20
+ await launchIocdComponent(extraArgs);
21
+ }
22
+ async function prepareIocdForDev() {
18
23
  (0, ensure_iocd_exists_1.ensureIOCDComponentExists)();
19
24
  // some applications have base modifications
20
25
  await app_service_1.default.copyBaseModifications();
@@ -24,7 +29,6 @@ async function startDevMode(extraArgs) {
24
29
  await license_file_service_1.LicenseFileService.copyLicenseFile();
25
30
  // sign ioconnect desktop if MacOS
26
31
  await signIocdAppIfMacOs();
27
- await launchIocdComponent(extraArgs);
28
32
  }
29
33
  async function signIocdAppIfMacOs() {
30
34
  // Code signing is only needed on macOS
@@ -1 +1 @@
1
- {"version":3,"file":"dev.service.js","sourceRoot":"","sources":["../../src/services/dev.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dev.service.js","sourceRoot":"","sources":["../../src/services/dev.service.ts"],"names":[],"mappings":"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"}
@@ -39,18 +39,32 @@ const fs = __importStar(require("fs"));
39
39
  const path = __importStar(require("path"));
40
40
  const path_1 = require("../utils/path");
41
41
  const child_process_1 = require("child_process");
42
- const license_file_service_1 = require("./license-file.service");
42
+ const license_service_1 = require("./license.service");
43
43
  /**
44
44
  * TestService handles running automated tests for the io.Connect Desktop application.
45
45
  *
46
46
  * This service:
47
47
  * - Locates the tests directory in the project
48
48
  * - Ensures node_modules are installed in the tests directory
49
+ * - Prepares the in-place component with the seed's dev modifications
49
50
  * - Sets the BINARY_PATH environment variable to point to the built executable
51
+ * - Passes the seed license to the test process through IOCD_LICENSE_KEY
50
52
  * - Runs the test script defined in the tests package.json
51
53
  */
52
54
  class TestService {
53
55
  logger = logger_1.Logger.getInstance("test.service");
56
+ prepareIocd;
57
+ getLicenseKey;
58
+ constructor(options = {}) {
59
+ this.prepareIocd =
60
+ options.prepareIocd ??
61
+ (async () => {
62
+ const { prepareIocdForDev } = await import("./dev.service.js");
63
+ await prepareIocdForDev();
64
+ });
65
+ this.getLicenseKey =
66
+ options.getLicenseKey ?? (() => new license_service_1.LicenseService().getLicenseKey());
67
+ }
54
68
  /**
55
69
  * Run tests for the io.Connect Desktop application
56
70
  */
@@ -64,19 +78,17 @@ class TestService {
64
78
  this.logger.debug(`Tests directory: ${testsDir}`);
65
79
  // Check if node_modules exists, if not run npm install
66
80
  await this.ensureNodeModulesInstalled(testsDir);
81
+ // Prepare the in-place component exactly as dev mode does before launching it.
82
+ await this.prepareIocd();
67
83
  // Get the binary path based on platform
68
84
  const binaryPath = path_1.PathUtils.getIOCDExePath();
69
85
  this.logger.info(`Binary path: ${binaryPath}`);
70
86
  // Verify binary exists
71
87
  if (!fs.existsSync(binaryPath)) {
72
- throw new Error(`Binary not found at ${binaryPath}. Please run 'iocd dev' first to create the executable.`);
88
+ throw new Error(`Binary not found at ${binaryPath} after dev preparation. Run 'iocd setup' to reinstall the configured component.`);
73
89
  }
74
- // copy license file to binary directory if it exists
75
- await license_file_service_1.LicenseFileService.copyLicenseFile(true);
76
90
  // Run the test script
77
- await this.runTestScript(testsDir, binaryPath, args);
78
- // remove license file after tests (as tests ignore the copy setting)
79
- await license_file_service_1.LicenseFileService.removeLicenseFile();
91
+ await this.runTestScript(testsDir, binaryPath, args, this.getLicenseKey());
80
92
  }
81
93
  /**
82
94
  * Ensure node_modules are installed in the tests directory
@@ -122,7 +134,7 @@ class TestService {
122
134
  /**
123
135
  * Run the test script in the tests directory
124
136
  */
125
- async runTestScript(testsDir, binaryPath, args = []) {
137
+ async runTestScript(testsDir, binaryPath, args = [], licenseKey) {
126
138
  this.logger.info("Running tests...");
127
139
  return new Promise((resolve, reject) => {
128
140
  const npmCommand = process.platform === "win32" ? "npm.cmd" : "npm";
@@ -134,6 +146,7 @@ class TestService {
134
146
  env: {
135
147
  ...process.env,
136
148
  BINARY_PATH: binaryPath,
149
+ ...(licenseKey ? { IOCD_LICENSE_KEY: licenseKey } : {}),
137
150
  },
138
151
  });
139
152
  child.on("close", code => {
@@ -1 +1 @@
1
- {"version":3,"file":"test.service.js","sourceRoot":"","sources":["../../src/services/test.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"test.service.js","sourceRoot":"","sources":["../../src/services/test.service.ts"],"names":[],"mappings":"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"}
@@ -57,6 +57,17 @@ cd tests && npm run typecheck # type-check without launching the
57
57
  window and switch by `workspaceWindow.getGdWindow().id` for its DOM. Refresh the Workspace
58
58
  reference after structural changes before reading its updated tree.
59
59
  - **Keep the seed's config**: the `platform-wdio` runner and `binary: process.env.BINARY_PATH`.
60
+ - **Keep the test config layer minimal.** `config/system.json` is merged over the config the seed
61
+ already ships. Use it for test plumbing (fixture app store, `folders.userData`, log locations),
62
+ not to change platform behavior — that belongs in the seed's `modifications/`.
63
+ - **A test that needs different platform settings needs its own launch.** Platform-wide settings
64
+ (Channel mode, group type, dialogs) can't change mid-process: add a delta
65
+ `config/system.<variant>.json` and a second capability in `wdio.config.ts` with its own
66
+ `configOverrides` + `wdio:specs`, and `wdio:exclude` those specs from the default capability so
67
+ they don't also run under it. See [configuration](./references/configuration.md).
68
+ - **A seed with an SSO login page needs the service's `login` option** — the platform blocks startup
69
+ on the login window, so without it `npm test` hangs until the startup timeout. Credentials come
70
+ from env vars, never from specs or config. See [configuration](./references/configuration.md).
60
71
  - **Prefer service models for built-in UI.** Check the installed `models/index.d.ts`; model exports
61
72
  vary by `@interopio/wdio-iocd-service` version. Use ordinary WebdriverIO selectors for app UI.
62
73
  - **Preserve user files.** Never put the license (or `user-data`) in specs, logs, or CI artifacts.
@@ -67,5 +78,5 @@ cd tests && npm run typecheck # type-check without launching the
67
78
  - [authoring](./references/authoring.md) — spec shape, fixtures, synchronization, isolation.
68
79
  - [commands](./references/commands.md) — the IOCD-specific WebdriverIO commands (for the rest, read the service `.d.ts`).
69
80
  - [models](./references/models.md) — built-in IOCD UI page objects, current exports, and version rules.
70
- - [configuration](./references/configuration.md) — env vars, overrides, optional libraries, runners, CI.
81
+ - [configuration](./references/configuration.md) — env vars, overrides, per-capability extra config for tests that need other platform settings, SSO startup login automation, optional libraries, runners, CI.
71
82
  - [troubleshooting](./references/troubleshooting.md) — executable, license, startup, IO API, dead window handles, flaky tests.
@@ -34,7 +34,9 @@ describe("behavior under test", () => {
34
34
 
35
35
  Arrange platform state with the io.Connect API (`io`); exercise and assert user-visible behavior with
36
36
  WebdriverIO (`$`, `browser`). For config-dependent suites, read `globalThis.ioCDPlatformConfig` at
37
- describe time (the API isn't available then).
37
+ describe time (the API isn't available then) — and when the behavior needs *different* platform
38
+ settings, give it its own capability and config override, see
39
+ [configuration](./configuration.md).
38
40
 
39
41
  ## The generated specs are your templates
40
42
 
@@ -51,7 +53,8 @@ Each demonstrates a pattern worth copying — read the one closest to your goal:
51
53
  second app received an Interop invocation.
52
54
  - `notifications.spec.ts` — raise a notification and assert it in the Notification Panel.
53
55
  - `workspace-add-app.spec.ts` — add an app through the Workspaces add-application popup (UI clicks).
54
- The popup flow assumes universal mode (`config/system.json` sets `"advancedMode": false`).
56
+ In universal mode the popup renders inside the frame window; check the mode the seed ships and
57
+ adapt the spec instead of forcing `advancedMode` in the test override.
55
58
 
56
59
  ## Fixtures
57
60
 
@@ -66,8 +69,8 @@ For a Channel-enabled fixture, initialize the client API with `IODesktop({ chann
66
69
  enable `details.channelSelector` in its app definition. The built-in selector belongs to the Web
67
70
  Group, not the client app DOM: use `Group` and its frame caption model from
68
71
  `@interopio/wdio-iocd-service/models`, then switch to the selector popup before querying its DOM.
69
- See [models](./models.md), `channel-selector.spec.ts`, and the deterministic Channel definitions in
70
- `config/system.json`.
72
+ See [models](./models.md) and `channel-selector.spec.ts`. Read the configured Channels at runtime
73
+ with `io.channels.all()` — don't hard-code names or redefine Channels in the test override.
71
74
  Register membership changes with `io.channels.onChannelsChanged()` — it isn't a window API. Expose
72
75
  an app readiness signal and wait for it before changing the Channel through the UI, so the test
73
76
  can't act before the app has initialized Channels and registered its listener.
@@ -10,8 +10,144 @@ Read `tests/wdio.config.ts` — it composes `IOCDBaseConfiguration` + `IOCDServi
10
10
  | `iocd:options.configOverrides` | Extra platform config (absolute paths) applied only to tests. |
11
11
  | `iocd:options.ioInitOptions` | APIs + optional `libraries` used to build the test API. |
12
12
 
13
- `config/system.json` registers `tests/tests/config/apps.json` as a path app store and isolates
14
- `folders.userData` to `tests/user-data` (disposable — never commit it or reuse its state).
13
+ ## Configuration layers
14
+
15
+ The config the platform runs with is three layers, each deep-merged over the previous:
16
+
17
+ | Layer | Owner | Where |
18
+ |-------|-------|-------|
19
+ | Default `system.json` | io.Connect Desktop | inside the installed `iocd` component |
20
+ | Seed modifications | the seed | `modifications/base/` plus `modifications/dev/` for tests; packed builds use `modifications/build/` |
21
+ | Test overrides | the test package | `config/system.json`, merged on top for the test process only |
22
+
23
+ **Keep the test layer minimal.** Whatever the seed configures is already in effect during a test
24
+ run because `iocd test` prepares the component in dev mode — don't restate it. Override only what
25
+ makes the run isolated and reproducible: the fixture app
26
+ store, `folders.userData`, log/crash output locations, and similar plumbing. Changing platform
27
+ behavior here (window mode, Channels, gateway, auth, themes) means the tests no longer exercise the
28
+ platform the seed ships — you'd be testing something else. Behavior changes belong in
29
+ `modifications/`; another *supported* configuration belongs in its own capability (below).
30
+
31
+ The generated `config/system.json` registers `tests/tests/config/apps.json` as a path app store and
32
+ isolates `folders.userData` to `tests/user-data` (disposable — never commit it or reuse its state).
33
+
34
+ ## Tests that need extra config
35
+
36
+ Platform-wide settings (Channel mode, group type, default dialogs, gateway) are fixed for the life
37
+ of a process — a spec can't switch them at run time. Tests that need a configuration other than the
38
+ one the seed ships therefore need **their own platform launch**: one capability per configuration in
39
+ the single `tests/wdio.config.ts`.
40
+
41
+ 1. Add a **delta** file next to the base one — `tests/config/system.<variant>.json`, containing only
42
+ the keys that differ.
43
+ 2. Put the specs that need it in their own folder — `tests/tests/<variant>/`.
44
+ 3. Add a capability for it: same `binary`, `iocd:runner` and `ioInitOptions` as the default one,
45
+ different `configOverrides` and `wdio:specs`.
46
+
47
+ ```ts
48
+ // tests/wdio.config.ts
49
+ const ioInitOptions = { appManager: "full", layouts: "full", channels: true, libraries: ["@interopio/workspaces-api"] };
50
+
51
+ const capability = (specs: string[], extraConfig: string[] = [], exclude: string[] = []) => ({
52
+ browserName: "iocd",
53
+ "iocd:runner": "platform-wdio" as const,
54
+ "iocd:options": {
55
+ binary,
56
+ ioInitOptions,
57
+ // Merged in order over the platform + seed config; the last file wins.
58
+ configOverrides: [path.resolve(rootDir, "config/system.json"), ...extraConfig],
59
+ },
60
+ // Nested array = all matching specs in ONE worker, so the platform starts once per capability.
61
+ "wdio:specs": [specs],
62
+ "wdio:exclude": exclude,
63
+ });
64
+
65
+ capabilities: [
66
+ capability(["./tests/**/*.spec.ts"], [], ["./tests/multi-channel/**/*.spec.ts"]),
67
+ capability(
68
+ ["./tests/multi-channel/**/*.spec.ts"],
69
+ [path.resolve(rootDir, "config/system.multi-channel.json")]
70
+ ),
71
+ ],
72
+ ```
73
+
74
+ Rules:
75
+
76
+ - **Exclude the variant specs from the default capability** (`wdio:exclude`). Without it they run
77
+ twice — once under a configuration they weren't written for.
78
+ - **The default capability keeps the seed's shipped configuration.** A variant covers another
79
+ configuration your seed genuinely supports; it's not a way to make a failing test pass. Behavior
80
+ your users always get belongs in the seed's `modifications/`.
81
+ - **One launch per capability, run sequentially** (`IOCDBaseConfiguration` sets `maxInstances: 1`).
82
+ Budget a full platform startup + shutdown for each — group specs by configuration; never add a
83
+ capability per spec.
84
+ - **`npm test -- --spec <file>` overrides capability spec patterns**, so a single-spec run executes
85
+ that spec under *every* capability. Config-dependent specs must read the live config and skip when
86
+ it doesn't apply (below).
87
+
88
+ ### Read the live config in a spec
89
+
90
+ `globalThis.ioCDPlatformConfig` is the resolved system config, available **synchronously at describe
91
+ time** (the IO API is not) — so it can drive `describe.skip`/`this.skip()` or per-mode test
92
+ generation:
93
+
94
+ ```ts
95
+ type PlatformConfigView = { windows?: { channelSelector?: { type?: "single" | "multi" } } };
96
+ const selectorType = (globalThis as { ioCDPlatformConfig?: PlatformConfigView }).ioCDPlatformConfig
97
+ ?.windows?.channelSelector?.type;
98
+
99
+ describe("multi-Channel selection", function () {
100
+ before(function () {
101
+ if (selectorType !== "multi") {
102
+ this.skip();
103
+ }
104
+ });
105
+ });
106
+ ```
107
+
108
+ Never treat a missing value as `false`/absent: a spec asserting "nothing happens" would then pass
109
+ under every configuration — green for the wrong reason. Skip explicitly, or throw a message naming
110
+ the configuration that was actually found.
111
+
112
+ ## Platform with an SSO login at startup
113
+
114
+ A seed configured with an interactive login (`ssoAuth` in the system config) reports readiness only
115
+ **after** someone signs in — without automation, `npm test` sits on the login window until the
116
+ startup timeout and no spec runs. The service's `login` option drives that window while the
117
+ platform boots. Requires `@interopio/wdio-iocd-service` 1.0.0-next.3+ (the version currently
118
+ generated); older test packages must update `tests/package.json` first.
119
+
120
+ ```ts
121
+ // tests/wdio.config.ts
122
+ services: IOCDService({
123
+ login: {
124
+ window: { url: /login\.mycompany\.com/ }, // substring or RegExp; `title` also works
125
+ handler: async (browser) => {
126
+ await browser.$("#username").setValue(process.env.IOCD_TEST_USER!);
127
+ await browser.$("#password").setValue(process.env.IOCD_TEST_PASSWORD!);
128
+ await browser.$("button[type=submit]").click();
129
+ },
130
+ },
131
+ }),
132
+ ```
133
+
134
+ Rules:
135
+
136
+ - **The handler runs before the platform is ready.** No `browser.io()`, no models — plain
137
+ WebdriverIO against the login page only. The WDIO globals (`browser`, `$`, `$$`) are set while it
138
+ runs, so page objects work.
139
+ - **The signed-in session belongs to the platform process**, so the apps under test are
140
+ authenticated exactly as in production.
141
+ - **Credentials come from env vars / CI secrets** — never from specs or config files.
142
+ - **A still-valid session skips the phase** (no login window appears; `onNoLoginWindow` defaults to
143
+ `"skip"`, set `"fail"` to require one). Budgets: `timeoutMs` (find window + handler) and
144
+ `readyTimeoutMs` (readiness after the handler), both defaulting to 120000.
145
+ - **Any login failure stops the run** — no window, a handler error/timeout, or no readiness after
146
+ the handler. The platform is destroyed and the capability's specs are reported failed. The login
147
+ is never retried.
148
+ - **MFA prompts and native OS dialogs can't be driven by WebDriver** — use an exempt test account or
149
+ a non-interactive auth configuration for the test platform.
150
+ - `login` also accepts `(capability) => LoginOptions | undefined` for per-capability variants.
15
151
 
16
152
  ## Add an optional IO library
17
153
 
@@ -11,7 +11,7 @@ over copying internal IOCD selectors into a spec.
11
11
 
12
12
  ## Current Generated Version
13
13
 
14
- The generated test package currently pins `@interopio/wdio-iocd-service@1.0.0-next.2`. Its
14
+ The generated test package currently pins `@interopio/wdio-iocd-service@1.0.0-next.4`. Its
15
15
  `@interopio/wdio-iocd-service/models` subpath exports:
16
16
 
17
17
  | Area | Models and types |
@@ -2,25 +2,28 @@
2
2
 
3
3
  ## Missing platform executable
4
4
 
5
- Ensure the configured `iocd` component is installed: run `npm run setup`, or start the seed once with
6
- `npm run dev` and close it before `npm test` (the service starts its own instance).
7
-
8
- If `iocd test` searches for an executable named after the seed's `productName`, but the installed
9
- component still has its default `io.Connect Desktop` name, run `npm run dev` once. Development
10
- preparation applies the seed branding and creates the executable path that the test command expects;
11
- close that development instance before rerunning the tests.
5
+ Ensure the configured `iocd` component is installed by running `npm run setup`. `iocd test`
6
+ automatically performs the same bundle preparation as `iocd dev`: it generates application-owned
7
+ base modifications, applies the seed's base and dev modifications, copies the configured output
8
+ license when enabled, and signs the macOS bundle before resolving the executable. It does not launch
9
+ a separate development instance.
12
10
 
13
11
  ## License prompt or failure
14
12
 
15
- Run from the seed root through `npm test` so the CLI can use `config/iocd.license.key`. In CI, supply
16
- the license via secrets. Never hard-code a license in a spec or fixture.
13
+ Run from the seed root through `npm test` so the CLI can read `config/iocd.license.key` and forward it
14
+ to the test platform as `IOCD_LICENSE_KEY`. In CI, supply the license via secrets. Never hard-code a
15
+ license in a spec or fixture.
17
16
 
18
17
  ## Startup timeout
19
18
 
20
19
  Temporarily set `iocd:options.enableLogging: true` in `tests/wdio.config.ts` and read the platform
21
- output. Check for invalid config/app paths, license failures, gateway port conflicts (the generated
22
- `config/system.json` pins the test gateway to port 8385), and stale test user-data before raising
23
- `startupTimeoutMs`.
20
+ output. Check for invalid config/app paths, license failures, gateway port conflicts (the port comes
21
+ from the seed's own config — another running instance holds it), and stale test user-data before
22
+ raising `startupTimeoutMs`.
23
+
24
+ If a login window appears and stays open, the seed configures an interactive SSO login and startup
25
+ is blocked until someone signs in. Automate it with the service's `login` option — see
26
+ [configuration](./configuration.md).
24
27
 
25
28
  ## Missing IO API
26
29
 
@@ -29,12 +29,54 @@ npm run typecheck
29
29
  ## Layout
30
30
 
31
31
  - `wdio.config.ts` — WebdriverIO + `IOCDService` configuration (the `platform-wdio` runner).
32
- - `config/system.json` — platform overrides applied only to the test process.
32
+ - `config/system.json` — test-only overrides applied to the test process.
33
33
  - `tests/common/iocd.ts` — polling, event-waiting, and cleanup-registry helpers.
34
34
  - `tests/config/apps.json` — fixture app definitions.
35
35
  - `tests/assets/applications/` — static fixture app HTML.
36
36
  - `tests/*.spec.ts` — the specifications below.
37
37
 
38
+ `config/system.json` is merged over the platform configuration the seed already ships (the io.Connect
39
+ Desktop defaults plus the seed's `modifications/`). Keep it minimal — the fixture app store and the
40
+ isolated `folders.userData` — so the tests exercise the same platform behavior as the built app.
41
+ Change platform behavior in the seed's `modifications/` instead.
42
+
43
+ ## Tests that need extra configuration
44
+
45
+ Platform-wide settings (Channel mode, group type, default dialogs) can't change while the platform
46
+ runs, so specifications that need a different configuration need their own platform launch. Add one
47
+ capability per configuration in `wdio.config.ts`:
48
+
49
+ ```typescript
50
+ capabilities: [
51
+ // Default configuration: everything except the multi-Channel specifications.
52
+ {
53
+ ...baseCapability,
54
+ "iocd:options": { ...baseOptions, configOverrides: [path.resolve(rootDir, "config/system.json")] },
55
+ "wdio:specs": [["./tests/**/*.spec.ts"]],
56
+ "wdio:exclude": ["./tests/multi-channel/**/*.spec.ts"],
57
+ },
58
+ // Extra configuration: only the specifications written for it.
59
+ {
60
+ ...baseCapability,
61
+ "iocd:options": {
62
+ ...baseOptions,
63
+ configOverrides: [
64
+ path.resolve(rootDir, "config/system.json"),
65
+ path.resolve(rootDir, "config/system.multi-channel.json"),
66
+ ],
67
+ },
68
+ "wdio:specs": [["./tests/multi-channel/**/*.spec.ts"]],
69
+ },
70
+ ],
71
+ ```
72
+
73
+ Capabilities run one after another (`maxInstances` is `1`), each starting and stopping its own
74
+ platform, so group specifications by configuration rather than adding a capability per file. Exclude
75
+ the variant specifications from the default capability so they don't run twice, keep the default
76
+ capability on the configuration the seed ships, and let a configuration-dependent specification read
77
+ `globalThis.ioCDPlatformConfig` at `describe` time to skip when it isn't running under its own
78
+ capability (`npm test -- --spec` overrides the capability spec patterns).
79
+
38
80
  ## Sample specifications
39
81
 
40
82
  | Specification | What it demonstrates |
@@ -1,12 +1,4 @@
1
1
  {
2
- "advancedMode": false,
3
- "channels": {
4
- "enabled": true,
5
- "definitions": [
6
- { "name": "Red", "meta": { "color": "red" } },
7
- { "name": "Green", "meta": { "color": "green" } }
8
- ]
9
- },
10
2
  "appStores": [
11
3
  {
12
4
  "type": "path",
@@ -15,21 +7,6 @@
15
7
  }
16
8
  }
17
9
  ],
18
- "gw": {
19
- "configuration": {
20
- "port": 8385,
21
- "ip": "127.0.0.1",
22
- "authentication": {
23
- "available": ["basic"],
24
- "default": "basic"
25
- }
26
- }
27
- },
28
- "windowManagement": {
29
- "group": {
30
- "type": "Web"
31
- }
32
- },
33
10
  "folders": {
34
11
  "userData": "%WDIO_ROOT_DIR%/user-data"
35
12
  }
@@ -10,7 +10,7 @@
10
10
  "license": "MIT",
11
11
  "devDependencies": {
12
12
  "@interopio/desktop": "^6.21.0",
13
- "@interopio/wdio-iocd-service": "1.0.0-next.2",
13
+ "@interopio/wdio-iocd-service": "1.0.0-next.4",
14
14
  "@interopio/workspaces-api": "^4.5.0",
15
15
  "@types/chai": "^5.2.3",
16
16
  "@types/mocha": "^10.0.10",
@@ -1141,9 +1141,9 @@
1141
1141
  }
1142
1142
  },
1143
1143
  "node_modules/@interopio/wdio-iocd-service": {
1144
- "version": "1.0.0-next.2",
1145
- "resolved": "https://registry.npmjs.org/@interopio/wdio-iocd-service/-/wdio-iocd-service-1.0.0-next.2.tgz",
1146
- "integrity": "sha512-ZjWJ4CQSQIcLLmlPhXT0BSKp5Gn+4NAMp4ybHGmghW3v3h8Wi0ip0VNQvmrqpTj5/gily9USmRXByJu2Ls2FnQ==",
1144
+ "version": "1.0.0-next.4",
1145
+ "resolved": "https://registry.npmjs.org/@interopio/wdio-iocd-service/-/wdio-iocd-service-1.0.0-next.4.tgz",
1146
+ "integrity": "sha512-l91dDhUdqYt9l49jAu6CTKjge8T12LnMODG2VrTqDk9ffSyGIvxK3gCsqtV3US7wRcCCbFHrStepaZhSrL9BSw==",
1147
1147
  "dev": true,
1148
1148
  "license": "MIT",
1149
1149
  "dependencies": {
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "devDependencies": {
12
12
  "@interopio/desktop": "^6.21.0",
13
- "@interopio/wdio-iocd-service": "1.0.0-next.2",
13
+ "@interopio/wdio-iocd-service": "1.0.0-next.4",
14
14
  "@interopio/workspaces-api": "^4.5.0",
15
15
  "@types/chai": "^5.2.3",
16
16
  "@types/mocha": "^10.0.10",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@interopio/iocd-cli",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "CLI tool for setting up, building and packaging io.Connect Desktop platforms",
5
5
  "engines": {
6
6
  "node": ">=22.0.0",