screenci 0.0.71 → 0.0.72
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/README.md +12 -12
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +133 -10
- package/dist/cli.js.map +1 -1
- package/dist/docs/manifest.d.ts +3 -3
- package/dist/docs/manifest.js +1 -1
- package/dist/docs/manifest.js.map +1 -1
- package/dist/docs/video-sources/installation.screenci.js +13 -12
- package/dist/docs/video-sources/installation.screenci.js.map +1 -1
- package/dist/docs/video-sources/landing.screenci.js +16 -9
- package/dist/docs/video-sources/landing.screenci.js.map +1 -1
- package/dist/docs/video-sources/product-pitch.screenci.js +97 -32
- package/dist/docs/video-sources/product-pitch.screenci.js.map +1 -1
- package/dist/docs/video-sources/public-urls.screenci.js +16 -9
- package/dist/docs/video-sources/public-urls.screenci.js.map +1 -1
- package/dist/docs/video-sources/studio.screenci.js +42 -27
- package/dist/docs/video-sources/studio.screenci.js.map +1 -1
- package/dist/index.d.ts +7 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/index.js.map +1 -1
- package/dist/src/asset.d.ts +8 -23
- package/dist/src/asset.d.ts.map +1 -1
- package/dist/src/asset.js +10 -32
- package/dist/src/asset.js.map +1 -1
- package/dist/src/audio.d.ts +6 -24
- package/dist/src/audio.d.ts.map +1 -1
- package/dist/src/audio.js +10 -35
- package/dist/src/audio.js.map +1 -1
- package/dist/src/builder.d.ts +214 -0
- package/dist/src/builder.d.ts.map +1 -0
- package/dist/src/builder.js +212 -0
- package/dist/src/builder.js.map +1 -0
- package/dist/src/cue.d.ts +40 -123
- package/dist/src/cue.d.ts.map +1 -1
- package/dist/src/cue.js +190 -30
- package/dist/src/cue.js.map +1 -1
- package/dist/src/events.d.ts +80 -15
- package/dist/src/events.d.ts.map +1 -1
- package/dist/src/events.js +72 -6
- package/dist/src/events.js.map +1 -1
- package/dist/src/init.d.ts.map +1 -1
- package/dist/src/init.js +14 -13
- package/dist/src/init.js.map +1 -1
- package/dist/src/locales.d.ts +19 -0
- package/dist/src/locales.d.ts.map +1 -0
- package/dist/src/locales.js +60 -0
- package/dist/src/locales.js.map +1 -0
- package/dist/src/localize.d.ts +135 -0
- package/dist/src/localize.d.ts.map +1 -0
- package/dist/src/localize.js +195 -0
- package/dist/src/localize.js.map +1 -0
- package/dist/src/localizeRuntime.d.ts +53 -0
- package/dist/src/localizeRuntime.d.ts.map +1 -0
- package/dist/src/localizeRuntime.js +79 -0
- package/dist/src/localizeRuntime.js.map +1 -0
- package/dist/src/recordingData.d.ts +5 -4
- package/dist/src/recordingData.d.ts.map +1 -1
- package/dist/src/runtimeContext.d.ts +3 -4
- package/dist/src/runtimeContext.d.ts.map +1 -1
- package/dist/src/runtimeContext.js.map +1 -1
- package/dist/src/runtimeMode.d.ts +47 -0
- package/dist/src/runtimeMode.d.ts.map +1 -1
- package/dist/src/runtimeMode.js +124 -0
- package/dist/src/runtimeMode.js.map +1 -1
- package/dist/src/screenshot.d.ts +56 -2
- package/dist/src/screenshot.d.ts.map +1 -1
- package/dist/src/screenshot.js +47 -10
- package/dist/src/screenshot.js.map +1 -1
- package/dist/src/stillCapture.d.ts +2 -3
- package/dist/src/stillCapture.d.ts.map +1 -1
- package/dist/src/stillCapture.js.map +1 -1
- package/dist/src/studio.d.ts +55 -22
- package/dist/src/studio.d.ts.map +1 -1
- package/dist/src/studio.js +38 -12
- package/dist/src/studio.js.map +1 -1
- package/dist/src/types.d.ts +18 -5
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/types.js.map +1 -1
- package/dist/src/video.d.ts +149 -13
- package/dist/src/video.d.ts.map +1 -1
- package/dist/src/video.js +91 -24
- package/dist/src/video.js.map +1 -1
- package/dist/src/voiceConfig.d.ts +110 -0
- package/dist/src/voiceConfig.d.ts.map +1 -0
- package/dist/src/voiceConfig.js +2 -0
- package/dist/src/voiceConfig.js.map +1 -0
- package/dist/src/voices.d.ts +27 -23
- package/dist/src/voices.d.ts.map +1 -1
- package/dist/src/voices.js +7 -4
- package/dist/src/voices.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/skills/screenci/SKILL.md +39 -30
package/README.md
CHANGED
|
@@ -71,18 +71,18 @@ but remap its rendered duration.
|
|
|
71
71
|
|
|
72
72
|
## Authoring helpers
|
|
73
73
|
|
|
74
|
-
| Export
|
|
75
|
-
|
|
|
76
|
-
| `defineConfig`
|
|
77
|
-
| `video`
|
|
78
|
-
| `
|
|
79
|
-
| `hide`
|
|
80
|
-
| `autoZoom`
|
|
81
|
-
| `zoomTo`
|
|
82
|
-
| `resetZoom`
|
|
83
|
-
| `createOverlays`
|
|
84
|
-
| `voices`
|
|
85
|
-
| `modelTypes`
|
|
74
|
+
| Export | What it does |
|
|
75
|
+
| ---------------- | ------------------------------------------------------------ |
|
|
76
|
+
| `defineConfig` | Wraps Playwright config with ScreenCI defaults |
|
|
77
|
+
| `video` | Declares a video recording test |
|
|
78
|
+
| `video.localize` | Declares localized narration / text and records per language |
|
|
79
|
+
| `hide` | Cuts setup or cleanup out of the visible recording |
|
|
80
|
+
| `autoZoom` | Smooth camera follow for an interaction block |
|
|
81
|
+
| `zoomTo` | Manual camera framing for a locator or point |
|
|
82
|
+
| `resetZoom` | Returns from manual framing to the full viewport |
|
|
83
|
+
| `createOverlays` | Inserts timed media overlays into the recording timeline |
|
|
84
|
+
| `voices` | Available voice constants such as `voices.Ava` |
|
|
85
|
+
| `modelTypes` | Narration model constants |
|
|
86
86
|
|
|
87
87
|
See the [docs](https://screenci.com/docs) for configuration, narration,
|
|
88
88
|
camera, and CI setup.
|
package/dist/cli.d.ts
CHANGED
|
@@ -75,5 +75,13 @@ export declare function ensureScreenciSecret(resolvedConfigPath?: string, opts?:
|
|
|
75
75
|
pollAuth?: boolean;
|
|
76
76
|
}): Promise<string | undefined>;
|
|
77
77
|
export declare function main(): Promise<void>;
|
|
78
|
+
export declare function parseRecordCliArgs(args: string[]): {
|
|
79
|
+
configPath: string | undefined;
|
|
80
|
+
verbose: boolean;
|
|
81
|
+
pollAuth: boolean;
|
|
82
|
+
remote: boolean;
|
|
83
|
+
languages: string | undefined;
|
|
84
|
+
otherArgs: string[];
|
|
85
|
+
};
|
|
78
86
|
export declare function logCliError(error: unknown): void;
|
|
79
87
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EACV,uBAAuB,EACvB,aAAa,EAEd,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../cli.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -10,7 +10,7 @@ import { Command, CommanderError } from 'commander';
|
|
|
10
10
|
import pc from 'picocolors';
|
|
11
11
|
import { logger } from './src/logger.js';
|
|
12
12
|
import { determinePackageManager, parsePackageManager, runInit, } from './src/init.js';
|
|
13
|
-
import { SCREENCI_DISABLE_RECORDING_TIMINGS_ENV, SCREENCI_MOCK_RECORD_ENV, } from './src/runtimeMode.js';
|
|
13
|
+
import { SCREENCI_DISABLE_RECORDING_TIMINGS_ENV, SCREENCI_MOCK_RECORD_ENV, SCREENCI_LANGUAGES_ENV, SCREENCI_TEXT_OVERRIDES_ENV, SCREENCI_RECORD_OPTIONS_ENV, } from './src/runtimeMode.js';
|
|
14
14
|
import { DEFAULT_RECORD_UPLOAD_POLICY } from './src/defaults.js';
|
|
15
15
|
import { findDuplicateTitles, formatDuplicateTitlesMessage, } from './src/titleValidation.js';
|
|
16
16
|
import { createLinkSessionSpec, deletePersistedLinkSessionSpec, getCliLinkSessionApiUrl, getDevBackendUrl, getDevFrontendUrl, getLinkSessionFilePath, getScreenCIEnvironment, isStoredLinkSessionReusable, readPersistedLinkSessionSpec, SCREENCI_LINK_SESSION_FILE, writePersistedLinkSessionSpec, } from './src/linkSession.js';
|
|
@@ -1004,7 +1004,7 @@ export function formatFailedVideoMessage(videoName, message) {
|
|
|
1004
1004
|
if (message.startsWith(EXPRESSIVE_TIER_ERROR_PREFIX)) {
|
|
1005
1005
|
return [
|
|
1006
1006
|
`${videoName}: ${message}`,
|
|
1007
|
-
"If you want to keep using the current tier, remove `voice.style` or `modelType: 'expressive'` from `
|
|
1007
|
+
"If you want to keep using the current tier, remove `voice.style` or `modelType: 'expressive'` from the localize `voice`.",
|
|
1008
1008
|
].join('\n');
|
|
1009
1009
|
}
|
|
1010
1010
|
return `${videoName}: ${message}`;
|
|
@@ -1447,7 +1447,7 @@ export function extractGrep(args) {
|
|
|
1447
1447
|
// authenticated commands; the backend dispatches the workflow using the GitHub
|
|
1448
1448
|
// token stored for the project. An optional `--grep` records only matching
|
|
1449
1449
|
// videos/screenshots.
|
|
1450
|
-
async function triggerRemoteRun(configPath, grep) {
|
|
1450
|
+
async function triggerRemoteRun(configPath, grep, languages) {
|
|
1451
1451
|
const { screenciConfig, secret, apiUrl } = await requireScreenCISecret(configPath, { interactive: detectInteractiveSession() });
|
|
1452
1452
|
const res = await fetch(`${apiUrl}/cli/trigger-run`, {
|
|
1453
1453
|
method: 'POST',
|
|
@@ -1458,14 +1458,19 @@ async function triggerRemoteRun(configPath, grep) {
|
|
|
1458
1458
|
body: JSON.stringify({
|
|
1459
1459
|
projectName: screenciConfig.projectName,
|
|
1460
1460
|
...(grep ? { grep } : {}),
|
|
1461
|
+
...(languages ? { languages } : {}),
|
|
1461
1462
|
}),
|
|
1462
1463
|
});
|
|
1463
1464
|
if (!res.ok) {
|
|
1464
1465
|
const text = await res.text();
|
|
1465
1466
|
throw new Error(`Failed to trigger remote run: ${res.status} ${text}${hint401(res.status, secret)}`);
|
|
1466
1467
|
}
|
|
1467
|
-
|
|
1468
|
-
? `
|
|
1468
|
+
const filters = [
|
|
1469
|
+
...(grep ? [`filter: ${grep}`] : []),
|
|
1470
|
+
...(languages ? [`languages: ${languages}`] : []),
|
|
1471
|
+
];
|
|
1472
|
+
logger.info(filters.length > 0
|
|
1473
|
+
? `Triggered the remote recording workflow for "${screenciConfig.projectName}" (${filters.join(', ')}).`
|
|
1469
1474
|
: `Triggered the remote recording workflow for "${screenciConfig.projectName}".`);
|
|
1470
1475
|
}
|
|
1471
1476
|
function getLastRecordFilePath(screenciDir) {
|
|
@@ -1721,19 +1726,21 @@ export async function main() {
|
|
|
1721
1726
|
.option('-v, --verbose', 'verbose output')
|
|
1722
1727
|
.option('--poll-auth', 'wait for sign-in to complete (polling every 5s, up to 5 minutes) instead of exiting, then continue recording')
|
|
1723
1728
|
.option('--remote', 'trigger the GitHub Actions recording workflow for this project remotely instead of recording locally')
|
|
1729
|
+
.option('--languages <langs>', 'record/render only these languages (comma-separated, e.g. fi,en)')
|
|
1724
1730
|
.allowUnknownOption(true)
|
|
1725
1731
|
.action(async () => {
|
|
1726
1732
|
const parsed = parseRecordCliArgs(getSubcommandArgv('record'));
|
|
1727
1733
|
// `--remote` is a pure dispatch: it fires the project's GitHub Actions
|
|
1728
1734
|
// recording workflow and exits, so there is no local Playwright run. A
|
|
1729
|
-
// pass-through `--grep` becomes the remote recording filter
|
|
1735
|
+
// pass-through `--grep` becomes the remote recording filter, and
|
|
1736
|
+
// `--languages` limits which language versions are recorded.
|
|
1730
1737
|
if (parsed.remote) {
|
|
1731
|
-
await triggerRemoteRun(parsed.configPath, extractGrep(parsed.otherArgs));
|
|
1738
|
+
await triggerRemoteRun(parsed.configPath, extractGrep(parsed.otherArgs), parsed.languages);
|
|
1732
1739
|
return;
|
|
1733
1740
|
}
|
|
1734
1741
|
let playwrightFailure = null;
|
|
1735
1742
|
try {
|
|
1736
|
-
await run('record', parsed.otherArgs, parsed.configPath, parsed.verbose, false, parsed.pollAuth);
|
|
1743
|
+
await run('record', parsed.otherArgs, parsed.configPath, parsed.verbose, false, parsed.pollAuth, parsed.languages);
|
|
1737
1744
|
}
|
|
1738
1745
|
catch (error) {
|
|
1739
1746
|
if (!(error instanceof Error))
|
|
@@ -1966,11 +1973,12 @@ function getSubcommandArgv(command) {
|
|
|
1966
1973
|
const commandIndex = argv.indexOf(command);
|
|
1967
1974
|
return commandIndex === -1 ? [] : argv.slice(commandIndex + 1);
|
|
1968
1975
|
}
|
|
1969
|
-
function parseRecordCliArgs(args) {
|
|
1976
|
+
export function parseRecordCliArgs(args) {
|
|
1970
1977
|
let configPath;
|
|
1971
1978
|
let verbose = false;
|
|
1972
1979
|
let pollAuth = false;
|
|
1973
1980
|
let remote = false;
|
|
1981
|
+
let languages;
|
|
1974
1982
|
const otherArgs = [];
|
|
1975
1983
|
for (let i = 0; i < args.length; i++) {
|
|
1976
1984
|
const arg = args[i];
|
|
@@ -1985,6 +1993,20 @@ function parseRecordCliArgs(args) {
|
|
|
1985
1993
|
configPath = nextArg;
|
|
1986
1994
|
i++;
|
|
1987
1995
|
}
|
|
1996
|
+
else if (arg === '--languages' || arg === '--language') {
|
|
1997
|
+
// screenci-only flag: parsed out so it is not forwarded to Playwright.
|
|
1998
|
+
const nextArg = args[i + 1];
|
|
1999
|
+
if (nextArg === undefined) {
|
|
2000
|
+
logger.error('Error: --languages requires a comma-separated value');
|
|
2001
|
+
process.exit(1);
|
|
2002
|
+
}
|
|
2003
|
+
languages = nextArg;
|
|
2004
|
+
i++;
|
|
2005
|
+
}
|
|
2006
|
+
else if (arg.startsWith('--languages=') ||
|
|
2007
|
+
arg.startsWith('--language=')) {
|
|
2008
|
+
languages = arg.slice(arg.indexOf('=') + 1);
|
|
2009
|
+
}
|
|
1988
2010
|
else if (arg === '--verbose' || arg === '-v') {
|
|
1989
2011
|
verbose = true;
|
|
1990
2012
|
}
|
|
@@ -2003,6 +2025,7 @@ function parseRecordCliArgs(args) {
|
|
|
2003
2025
|
verbose,
|
|
2004
2026
|
pollAuth,
|
|
2005
2027
|
remote,
|
|
2028
|
+
languages,
|
|
2006
2029
|
otherArgs,
|
|
2007
2030
|
};
|
|
2008
2031
|
}
|
|
@@ -2053,7 +2076,85 @@ function validateArgs(args) {
|
|
|
2053
2076
|
}
|
|
2054
2077
|
}
|
|
2055
2078
|
}
|
|
2056
|
-
|
|
2079
|
+
/**
|
|
2080
|
+
* Fetch the project's current Studio text-field overrides so they can be
|
|
2081
|
+
* injected as SCREENCI_TEXT_OVERRIDES before a recording. On-screen `text`
|
|
2082
|
+
* fields render during the recording (they cannot be patched at render time),
|
|
2083
|
+
* so any Studio edits must be present here; code-declared seeds are the
|
|
2084
|
+
* fallback. Best-effort: any failure returns an empty env so the SDK uses the
|
|
2085
|
+
* code seeds, and a recording is never blocked by this fetch.
|
|
2086
|
+
*/
|
|
2087
|
+
async function fetchTextOverridesEnv(configPath, languages, verbose) {
|
|
2088
|
+
try {
|
|
2089
|
+
const { screenciConfig, secret, apiUrl } = await requireScreenCISecret(configPath, { interactive: false });
|
|
2090
|
+
const params = new URLSearchParams({
|
|
2091
|
+
projectName: screenciConfig.projectName,
|
|
2092
|
+
});
|
|
2093
|
+
if (languages)
|
|
2094
|
+
params.set('languages', languages);
|
|
2095
|
+
const res = await fetch(`${apiUrl}/cli/text-overrides?${params.toString()}`, { headers: { 'X-ScreenCI-Secret': secret } });
|
|
2096
|
+
if (!res.ok) {
|
|
2097
|
+
if (verbose) {
|
|
2098
|
+
logger.warn(`Could not fetch Studio text overrides (${res.status}); using code-declared values.`);
|
|
2099
|
+
}
|
|
2100
|
+
return {};
|
|
2101
|
+
}
|
|
2102
|
+
const body = (await res.json());
|
|
2103
|
+
const overrides = body.overrides;
|
|
2104
|
+
if (overrides === undefined ||
|
|
2105
|
+
overrides === null ||
|
|
2106
|
+
typeof overrides !== 'object' ||
|
|
2107
|
+
Object.keys(overrides).length === 0) {
|
|
2108
|
+
return {};
|
|
2109
|
+
}
|
|
2110
|
+
return { [SCREENCI_TEXT_OVERRIDES_ENV]: JSON.stringify(overrides) };
|
|
2111
|
+
}
|
|
2112
|
+
catch (error) {
|
|
2113
|
+
if (verbose) {
|
|
2114
|
+
logger.warn(`Could not fetch Studio text overrides; using code-declared values.${error instanceof Error ? ` (${error.message})` : ''}`);
|
|
2115
|
+
}
|
|
2116
|
+
return {};
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
/**
|
|
2120
|
+
* Fetch the project's current Studio record-option overrides so they can be
|
|
2121
|
+
* injected as SCREENCI_RECORD_OPTIONS before a recording. Record options (aspect
|
|
2122
|
+
* ratio, quality, fps) change the captured viewport/encode, so any Studio edits
|
|
2123
|
+
* must be present here; code-declared values are the fallback. Best-effort: any
|
|
2124
|
+
* failure returns an empty env so the SDK uses the code values, and a recording
|
|
2125
|
+
* is never blocked by this fetch.
|
|
2126
|
+
*/
|
|
2127
|
+
async function fetchRecordOptionsEnv(configPath, verbose) {
|
|
2128
|
+
try {
|
|
2129
|
+
const { screenciConfig, secret, apiUrl } = await requireScreenCISecret(configPath, { interactive: false });
|
|
2130
|
+
const params = new URLSearchParams({
|
|
2131
|
+
projectName: screenciConfig.projectName,
|
|
2132
|
+
});
|
|
2133
|
+
const res = await fetch(`${apiUrl}/cli/record-options?${params.toString()}`, { headers: { 'X-ScreenCI-Secret': secret } });
|
|
2134
|
+
if (!res.ok) {
|
|
2135
|
+
if (verbose) {
|
|
2136
|
+
logger.warn(`Could not fetch Studio record options (${res.status}); using code-declared values.`);
|
|
2137
|
+
}
|
|
2138
|
+
return {};
|
|
2139
|
+
}
|
|
2140
|
+
const body = (await res.json());
|
|
2141
|
+
const recordOptions = body.recordOptions;
|
|
2142
|
+
if (recordOptions === undefined ||
|
|
2143
|
+
recordOptions === null ||
|
|
2144
|
+
typeof recordOptions !== 'object' ||
|
|
2145
|
+
Object.keys(recordOptions).length === 0) {
|
|
2146
|
+
return {};
|
|
2147
|
+
}
|
|
2148
|
+
return { [SCREENCI_RECORD_OPTIONS_ENV]: JSON.stringify(recordOptions) };
|
|
2149
|
+
}
|
|
2150
|
+
catch (error) {
|
|
2151
|
+
if (verbose) {
|
|
2152
|
+
logger.warn(`Could not fetch Studio record options; using code-declared values.${error instanceof Error ? ` (${error.message})` : ''}`);
|
|
2153
|
+
}
|
|
2154
|
+
return {};
|
|
2155
|
+
}
|
|
2156
|
+
}
|
|
2157
|
+
async function run(command, additionalArgs, customConfigPath, verbose = false, mockRecord = false, pollAuth = false, languages) {
|
|
2057
2158
|
const configPath = resolveScreenCIConfigPathOrExit(customConfigPath);
|
|
2058
2159
|
if (command === 'test' || process.env.SCREENCI_RECORDING !== 'true') {
|
|
2059
2160
|
await loadEnvFileFromConfigSource(configPath, false);
|
|
@@ -2070,11 +2171,25 @@ async function run(command, additionalArgs, customConfigPath, verbose = false, m
|
|
|
2070
2171
|
const screenciDir = resolve(dirname(configPath), '.screenci');
|
|
2071
2172
|
clearRecordingDirectories(screenciDir);
|
|
2072
2173
|
}
|
|
2174
|
+
// Studio text-field overrides are injected for the record command only: they
|
|
2175
|
+
// resolve in the SDK's `text` fixture before the recording runs. `test` (the
|
|
2176
|
+
// preview run) keeps code-declared values.
|
|
2177
|
+
const textOverridesEnv = command === 'record'
|
|
2178
|
+
? await fetchTextOverridesEnv(configPath, languages, verbose)
|
|
2179
|
+
: {};
|
|
2180
|
+
// Studio record-option overrides are likewise injected for record only: they
|
|
2181
|
+
// resolve in the SDK's `recordOptions` fixture before the capture runs.
|
|
2182
|
+
const recordOptionsEnv = command === 'record' ? await fetchRecordOptionsEnv(configPath, verbose) : {};
|
|
2073
2183
|
const envForChild = { ...process.env };
|
|
2074
2184
|
await validateUniqueDiscoveredTestTitles(configPath, additionalArgs, {
|
|
2075
2185
|
...envForChild,
|
|
2076
2186
|
SCREENCI_CONFIG_DIR: dirname(configPath),
|
|
2077
2187
|
...(command === 'record' ? { SCREENCI_RECORDING: 'true' } : {}),
|
|
2188
|
+
...(command === 'record' && languages
|
|
2189
|
+
? { [SCREENCI_LANGUAGES_ENV]: languages }
|
|
2190
|
+
: {}),
|
|
2191
|
+
...textOverridesEnv,
|
|
2192
|
+
...recordOptionsEnv,
|
|
2078
2193
|
...(command === 'test' && !mockRecord
|
|
2079
2194
|
? { [SCREENCI_DISABLE_RECORDING_TIMINGS_ENV]: 'true' }
|
|
2080
2195
|
: {}),
|
|
@@ -2101,6 +2216,14 @@ async function run(command, additionalArgs, customConfigPath, verbose = false, m
|
|
|
2101
2216
|
SCREENCI_CONFIG_DIR: dirname(configPath),
|
|
2102
2217
|
// Enable recording only for record command
|
|
2103
2218
|
...(command === 'record' ? { SCREENCI_RECORDING: 'true' } : {}),
|
|
2219
|
+
// Per-language filter: the builder records only these languages.
|
|
2220
|
+
...(command === 'record' && languages
|
|
2221
|
+
? { [SCREENCI_LANGUAGES_ENV]: languages }
|
|
2222
|
+
: {}),
|
|
2223
|
+
// Studio text-field overrides resolved from the backend (record only).
|
|
2224
|
+
...textOverridesEnv,
|
|
2225
|
+
// Studio record-option overrides resolved from the backend (record only).
|
|
2226
|
+
...recordOptionsEnv,
|
|
2104
2227
|
...(command === 'test' && !mockRecord
|
|
2105
2228
|
? { [SCREENCI_DISABLE_RECORDING_TIMINGS_ENV]: 'true' }
|
|
2106
2229
|
: {}),
|