openyida 2026.5.9-beta.9 → 2026.5.9

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  <div align="center">
2
2
 
3
- ![OpenYida](https://img.alicdn.com/imgextra/i4/O1CN017uyK3q1UUfbv7Z8oh_!!6000000002521-2-tps-2648-1382.png)
3
+ ![OpenYida](https://img.alicdn.com/imgextra/i3/O1CN01SKWbWu1aPzGXh293W_!!6000000003323-2-tps-1672-941.png)
4
4
 
5
5
  # OpenYida
6
6
 
@@ -199,6 +199,40 @@ openyida get-permission APP_XXX FORM_XXX
199
199
 
200
200
  When creating or updating test data with `openyida data`, Yida date fields must use 13-digit millisecond timestamps, for example `"dateField_xxx": 1719705600000`. Do not submit `YYYY-MM-DD` strings for `DateField` or `CascadeDateField` values.
201
201
 
202
+ ### Real Environment E2E
203
+
204
+ Most checks should stay offline, but OpenYida also includes an explicit real-environment smoke path for release and nightly validation:
205
+
206
+ ```bash
207
+ OPENYIDA_E2E=1 npm run test:e2e:real
208
+ OPENYIDA_E2E=1 npm run test:e2e:real:full
209
+ npm run test:e2e:real:skills
210
+ ```
211
+
212
+ The runner creates a disposable app, form, and custom page with an `OY_E2E_*` prefix, then verifies login, app listing, schema fetch, data query, and page publish. It writes a registry to `project/.cache/e2e-real/` so created resources can be audited later. To inject CI cookies without relying on a local login cache, pass `OPENYIDA_E2E_COOKIES_BASE64` as a base64 encoded cookie array or `{ "cookies": [...] }` object.
213
+
214
+ `test:e2e:real:full` extends the smoke path into a broad deterministic feature matrix: auth/env, app update, form update and option mutation, page build/compile/generate/publish, data create/get/update/query, permission read, page config and short URL check, report create/append, dashboard skill verification, export/import, batch, task-center, formula/doctor/sample/CDN config, and local connector parsing/template generation. AI-backed commands such as `flash-to-prd` are available as the optional `ai` stage because they depend on remote model availability.
215
+
216
+ `test:e2e:real:skills` enforces coverage for every directory under `yida-skills/skills/`. Each skill must be classified as real E2E, offline/unit, opt-in, or deprecated with an explicit reason. This prevents new skills from quietly bypassing the real-environment test plan.
217
+
218
+ Each successful full run leaves a human-inspectable result app in the target organization. The final step publishes a dedicated `Full E2E Dashboard` custom page, renames the app to `OY_E2E_*_PASSED` by default, and prints direct links for the app, form, dashboard page, and report; the same links are saved under `resultApp` in the registry JSON.
219
+
220
+ Useful options:
221
+
222
+ | Env var | Purpose |
223
+ |---------|---------|
224
+ | `OPENYIDA_E2E_PREFIX` | Override the disposable resource name prefix |
225
+ | `OPENYIDA_E2E_CORP_ID` | Switch to the dedicated test organization before creating resources |
226
+ | `OPENYIDA_E2E_RESULT_APP_NAME` | Override the final app name shown as the full-run result |
227
+ | `OPENYIDA_E2E_BASE_URL` | Override the Yida base URL for private deployments |
228
+ | `OPENYIDA_E2E_FIELDS_FILE` | Use a custom form fields fixture |
229
+ | `OPENYIDA_E2E_PAGE_SOURCE` | Use a custom page source for publish verification |
230
+ | `OPENYIDA_E2E_SKIP_PUBLISH=1` | Skip custom page creation and publish |
231
+ | `OPENYIDA_E2E_REGISTRY_DIR` | Write registries outside `project/.cache/e2e-real/` |
232
+ | `OPENYIDA_E2E_FULL_STAGES` | Comma-separated stage list for `test:e2e:real:full`; use `all` or omit for the default broad matrix |
233
+
234
+ Use `npm run test:e2e:real:cleanup` to list recorded disposable resources. OpenYida does not yet expose a safe app/form deletion command, so cleanup is intentionally a registry-backed audit step rather than an automatic destructive action.
235
+
202
236
  ### Connectors, Integrations, and Reports
203
237
 
204
238
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openyida",
3
- "version": "2026.5.9-beta.9",
3
+ "version": "2026.5.9",
4
4
  "description": "OpenYida CLI - 宜搭低代码 AI 开发工具(安装即用,零配置)",
5
5
  "bin": {
6
6
  "openyida": "bin/yida.js",
@@ -22,6 +22,10 @@
22
22
  "scripts": {
23
23
  "test": "jest",
24
24
  "test:unit": "jest",
25
+ "test:e2e:real": "node scripts/e2e-real/runner.js",
26
+ "test:e2e:real:full": "node scripts/e2e-real/full-runner.js",
27
+ "test:e2e:real:skills": "node scripts/e2e-real/skill-coverage.js",
28
+ "test:e2e:real:cleanup": "node scripts/e2e-real/cleanup.js",
25
29
  "test:coverage": "jest --coverage",
26
30
  "lint": "eslint bin/ lib/ scripts/ tests/ --ext .js",
27
31
  "lint:fix": "eslint bin/ lib/ scripts/ tests/ --ext .js --fix",
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env node
2
+
3
+ 'use strict';
4
+
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+
8
+ const ROOT = path.resolve(__dirname, '..', '..');
9
+ const DEFAULT_REGISTRY_DIR = path.join(ROOT, 'project', '.cache', 'e2e-real');
10
+
11
+ function getRegistryDir(env = process.env) {
12
+ return env.OPENYIDA_E2E_REGISTRY_DIR || DEFAULT_REGISTRY_DIR;
13
+ }
14
+
15
+ function listRegistries(registryDir = getRegistryDir()) {
16
+ if (!fs.existsSync(registryDir)) {return [];}
17
+ return fs.readdirSync(registryDir)
18
+ .filter((file) => file.endsWith('.json'))
19
+ .map((file) => {
20
+ const registryPath = path.join(registryDir, file);
21
+ const registry = JSON.parse(fs.readFileSync(registryPath, 'utf8'));
22
+ return { registryPath, registry };
23
+ })
24
+ .sort((a, b) => String(a.registry.startedAt || '').localeCompare(String(b.registry.startedAt || '')));
25
+ }
26
+
27
+ function printSummary(items) {
28
+ if (items.length === 0) {
29
+ console.log('No real E2E registries found.');
30
+ return;
31
+ }
32
+
33
+ for (const item of items) {
34
+ const registry = item.registry;
35
+ console.log(`\n${registry.runId || path.basename(item.registryPath)} [${registry.status || 'unknown'}]`);
36
+ console.log(`Registry: ${item.registryPath}`);
37
+ for (const resource of registry.resources || []) {
38
+ const id = resource.appType || resource.formUuid || resource.pageId || 'unknown';
39
+ const secondary = resource.formUuid || resource.pageId || '';
40
+ console.log(`- ${resource.type}: ${id}${secondary && secondary !== id ? ` / ${secondary}` : ''} ${resource.name || ''}`);
41
+ }
42
+ }
43
+
44
+ console.log('\nOpenYida does not yet expose a safe app/form deletion command, so this script lists disposable resources recorded by real E2E runs for manual cleanup.');
45
+ }
46
+
47
+ function run(options = {}) {
48
+ const registryDir = options.registryDir || getRegistryDir(options.env || process.env);
49
+ const items = listRegistries(registryDir);
50
+ printSummary(items);
51
+ return items;
52
+ }
53
+
54
+ if (require.main === module) {
55
+ try {
56
+ run();
57
+ } catch (error) {
58
+ console.error(error.message);
59
+ process.exit(1);
60
+ }
61
+ }
62
+
63
+ module.exports = {
64
+ getRegistryDir,
65
+ listRegistries,
66
+ run,
67
+ };
@@ -0,0 +1,18 @@
1
+ [
2
+ {
3
+ "type": "TextField",
4
+ "label": "E2E Text",
5
+ "required": true,
6
+ "placeholder": "Created by OpenYida real E2E"
7
+ },
8
+ {
9
+ "type": "NumberField",
10
+ "label": "E2E Number",
11
+ "placeholder": "123"
12
+ },
13
+ {
14
+ "type": "SelectField",
15
+ "label": "E2E Status",
16
+ "options": ["New", "Done"]
17
+ }
18
+ ]