Merge pull request #7419 from hsm-lv/fix-event

chore:刷新动作参数调整(默认不传数据)
This commit is contained in:
hsm-lv 2023-07-10 19:38:06 +08:00 committed by GitHub
commit f05c4681d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 6545 additions and 62 deletions

View File

@ -3885,6 +3885,7 @@ itemAction 里的 onClick 还能通过 `data` 参数拿到当前行的数据,
| 动作名称 | 动作配置 | 说明 |
| -------- | --------------- | ------------ |
| reload | - | 刷新列表请求 |
| setValue | `value: object` | 更新列表记录 |
value 结构说明:
@ -3894,6 +3895,378 @@ value 结构说明:
| items 或 rows | `item[]` | | 列表记录 |
| count 或 total | `number` | | 记录总数 |
### reload
#### 只做刷新
重新发送`api`请求,刷新 CRUD 时,只配置`componentId`目标组件 ID 即可。
```schema
{
"type": "page",
"data": {
"name": "amis",
"age": 18,
"date": "2023-6-6"
},
"body": [
{
"type": "button",
"label": "刷新CRUD数据加载请求",
level: 'primary',
"className": "mb-2",
"onEvent": {
"click": {
"actions": [
{
"componentId": "crud_reload1",
"actionType": "reload"
}
]
}
}
},
{
"type": "crud",
"api": "/api/mock2/sample",
"id": "crud_reload1",
"syncLocation": false,
"columns": [
{
"name": "id",
"label": "ID"
},
{
"name": "engine",
"label": "Rendering engine"
},
{
"name": "browser",
"label": "Browser"
},
{
"name": "platform",
"label": "Platform(s)"
},
{
"name": "version",
"label": "Engine version"
},
{
"name": "grade",
"label": "CSS grade"
},
{
"type": "operation",
"label": "操作",
"buttons": [
{
"label": "详情",
"type": "button",
"level": "link",
"actionType": "dialog",
"dialog": {
"title": "查看详情",
"body": {
"type": "form",
"body": [
{
"type": "input-text",
"name": "engine",
"label": "Engine"
},
{
"type": "input-text",
"name": "browser",
"label": "Browser"
},
{
"type": "input-text",
"name": "platform",
"label": "platform"
},
{
"type": "input-text",
"name": "version",
"label": "version"
},
{
"type": "control",
"label": "grade",
"body": {
"type": "tag",
"label": "${grade}",
"displayMode": "normal",
"color": "active"
}
}
]
}
}
},
{
"label": "删除",
"type": "button",
"level": "link",
"className": "text-danger",
"disabledOn": "this.grade === 'A'"
}
]
}
]
}
]
}
```
#### 追加请求参数并刷新
刷新 CRUD 时,如果配置了`data`,将发送`data`给目标 CRUD 组件,并将该数据合并到目标 CRUD 组件的数据域中,然后触发目标组件的刷新操作,即 CRUD 数据拉取接口将自动追加`data`参数到请求中。
```schema
{
"type": "page",
"data": {
"name": "amis",
"age": 18,
"date": "2023-6-6"
},
"body": [
{
"type": "button",
"label": "刷新CRUD数据加载请求同时追加参数date",
level: 'primary',
"className": "mb-2",
"onEvent": {
"click": {
"actions": [
{
"componentId": "crud_reload2",
"actionType": "reload",
data: {
date: "${date}"
}
}
]
}
}
},
{
"type": "crud",
"api": "/api/mock2/sample",
"id": "crud_reload2",
"syncLocation": false,
"columns": [
{
"name": "id",
"label": "ID"
},
{
"name": "engine",
"label": "Rendering engine"
},
{
"name": "browser",
"label": "Browser"
},
{
"name": "platform",
"label": "Platform(s)"
},
{
"name": "version",
"label": "Engine version"
},
{
"name": "grade",
"label": "CSS grade"
},
{
"type": "operation",
"label": "操作",
"buttons": [
{
"label": "详情",
"type": "button",
"level": "link",
"actionType": "dialog",
"dialog": {
"title": "查看详情",
"body": {
"type": "form",
"body": [
{
"type": "input-text",
"name": "engine",
"label": "Engine"
},
{
"type": "input-text",
"name": "browser",
"label": "Browser"
},
{
"type": "input-text",
"name": "platform",
"label": "platform"
},
{
"type": "input-text",
"name": "version",
"label": "version"
},
{
"type": "control",
"label": "grade",
"body": {
"type": "tag",
"label": "${grade}",
"displayMode": "normal",
"color": "active"
}
}
]
}
}
},
{
"label": "删除",
"type": "button",
"level": "link",
"className": "text-danger",
"disabledOn": "this.grade === 'A'"
}
]
}
]
}
]
}
```
通过`&: $$`追加触发事件的按钮所在数据域的所有数据,即`name、age、date`。
```schema
{
"type": "page",
"data": {
"name": "amis",
"age": 18,
"date": "2023-6-6"
},
"body": [
{
"type": "button",
"label": "刷新CRUD数据加载请求同时追加按钮所在数据域的所有数据",
level: 'primary',
"className": "mb-2",
"onEvent": {
"click": {
"actions": [
{
"componentId": "crud_reload2",
"actionType": "reload",
data: {
"&": "$$"
}
}
]
}
}
},
{
"type": "crud",
"api": "/api/mock2/sample",
"id": "crud_reload2",
"syncLocation": false,
"columns": [
{
"name": "id",
"label": "ID"
},
{
"name": "engine",
"label": "Rendering engine"
},
{
"name": "browser",
"label": "Browser"
},
{
"name": "platform",
"label": "Platform(s)"
},
{
"name": "version",
"label": "Engine version"
},
{
"name": "grade",
"label": "CSS grade"
},
{
"type": "operation",
"label": "操作",
"buttons": [
{
"label": "详情",
"type": "button",
"level": "link",
"actionType": "dialog",
"dialog": {
"title": "查看详情",
"body": {
"type": "form",
"body": [
{
"type": "input-text",
"name": "engine",
"label": "Engine"
},
{
"type": "input-text",
"name": "browser",
"label": "Browser"
},
{
"type": "input-text",
"name": "platform",
"label": "platform"
},
{
"type": "input-text",
"name": "version",
"label": "version"
},
{
"type": "control",
"label": "grade",
"body": {
"type": "tag",
"label": "${grade}",
"displayMode": "normal",
"color": "active"
}
}
]
}
}
},
{
"label": "删除",
"type": "button",
"level": "link",
"className": "text-danger",
"disabledOn": "this.grade === 'A'"
}
]
}
]
}
]
}
```
### setValue
#### 更新列表记录

View File

@ -1691,7 +1691,9 @@ Form 支持轮询初始化接口,步骤如下:
### reload
通过`reload`来重新请求表单的初始化接口,实现表单刷新。
#### 只做刷新
重新发送`initApi`请求,刷新 Form 时,只配置`componentId`目标组件 ID 即可。
```schema: scope="body"
[
@ -1731,6 +1733,56 @@ Form 支持轮询初始化接口,步骤如下:
]
```
#### 发送数据并刷新
刷新 Form 组件时,如果配置了`data`,将发送`data`给目标组件,并将该数据合并到目标组件的数据域中。
```schema: scope="body"
[
{
"type": "button",
"label": "刷新Form数据加载请求并将我的年龄设置为18",
className: "mb-2",
"onEvent": {
"click": {
"actions": [
{
"actionType": "reload",
"componentId": "form_reload2",
"data": {
age: 18
}
}
]
}
}
},
{
"type": "form",
"id": "form_reload2",
"debug": true,
"initApi": "/api/mock2/form/initData",
"body": [
{
"type": "input-text",
"name": "name",
"label": "姓名:"
},
{
"name": "author",
"type": "input-text",
"label": "作者:"
},
{
"name": "age",
"type": "input-text",
"label": "年龄:"
}
]
}
]
```
### reset
通过`reset`将表单数据重置为初始数据,初始数据可以是静态数据或初始化接口返回的数据。

View File

@ -342,29 +342,70 @@ Page 默认将页面分为几个区域,分别是**内容区(`body`**、**
### reload
#### 只做刷新
重新发送`initApi`请求,刷新 Page 时,只配置`componentId`目标组件 ID 即可。
```schema
{
"type": "page",
"id": "page01",
"id": "page_reload_1",
"initApi": "/api/mock2/page/initData",
"body": [
{
"type": "tpl",
"tpl": "当前时间是:${date}"
},
{
"type": "button",
"label": "刷新请求",
"label": "刷新Page数据加载请求",
"className": "mb-2",
"onEvent": {
"click": {
"actions": [
{
"componentId": "page01",
"componentId": "page_reload_1",
"actionType": "reload"
}
]
}
}
},
{
"type": "tpl",
"tpl": "当前时间是:${date}"
}
]
}
```
#### 发送数据并刷新
刷新 Page 组件时,如果配置了`data`,将发送`data`给目标组件,并将该数据合并到目标组件的数据域中。
```schema
{
"type": "page",
"id": "page_reload_2",
"initApi": "/api/mock2/page/initData",
"body": [
{
"type": "button",
"label": "刷新Page数据加载请求并将我的年龄设置为18",
"className": "mb-2",
"onEvent": {
"click": {
"actions": [
{
"componentId": "page_reload_2",
"actionType": "reload",
"data": {
"age": 18
}
}
]
}
}
},
{
"type": "tpl",
"tpl": "当前时间是:${date} 我的年龄:${age|default:'-'}"
}
]
}
@ -378,13 +419,10 @@ Page 默认将页面分为几个区域,分别是**内容区(`body`**、**
"id": "page02",
"initApi": "/api/mock2/page/initData",
"body": [
{
"type": "tpl",
"tpl": "当前时间是:${date}"
},
{
"type": "button",
"label": "更新数据",
"className": "mb-2",
"onEvent": {
"click": {
"actions": [
@ -398,6 +436,10 @@ Page 默认将页面分为几个区域,分别是**内容区(`body`**、**
]
}
}
},
{
"type": "tpl",
"tpl": "当前时间是:${date}"
}
]
}

View File

@ -844,7 +844,9 @@ schemaApi 接口请求完成。
### reload
重新请求 api 接口,并刷新。
#### 只做刷新
重新发送`api`请求,刷新 Page 时,只配置`componentId`目标组件 ID 即可。
```schema: scope="body"
[
@ -872,6 +874,39 @@ schemaApi 接口请求完成。
]
```
#### 发送数据并刷新
刷新 Service 组件时,如果配置了`data`,将发送`data`给目标组件,并将该数据合并到目标组件的数据域中。
```schema: scope="body"
[
{
"type": "button",
"label": "刷新请求",
"onEvent": {
"click": {
"actions": [
{
"componentId": "service-reload",
"actionType": "reload",
"data": {
"date": "${NOW()}"
}
}
]
}
}
},
{
"type": "service",
"id": "service-reload",
"name": "service-reload",
"api": "/api/mock2/number/random",
"body": "现在是:${random}, 当前时间:${date}"
}
]
```
### rebuild
重新构建,基于 args 传参和 schemaApi 绑定变量,让 service 获取不同的 schema。

View File

@ -1374,9 +1374,13 @@ run action ajax
| subject | `string` | - | 邮件主题,可用 ${xxx} 取值 |
| body | `string` | - | 邮件正文,可用 ${xxx} 取值 |
### 刷新
### 刷新组件请求
通过配置`actionType: 'reload'`实现对指定组件的刷新(重新加载)操作,仅支持`form`、`wizard`、`service`、`page`、`app`、`chart`、`crud`,以及支持动态数据的`输入类`组件,详见组件的`动作表`。更多示例请查看[刷新示例](../../../examples/action/reload/form)。
通过配置`actionType: 'reload'`刷新指定组件的数据请求,支持数据容器类组件(`form`、`wizard`、`service`、`page`、`app`、`chart`、`crud`)以及支持动态数据的`输入类`组件,详见组件的`动作表`。更多示例请查看[刷新示例](../../../examples/action/reload/form)。
#### 刷新输入类组件
针对支持远程数据的输入类组件,支持刷新目标组件的数据请求。
```schema
{
@ -1384,7 +1388,7 @@ run action ajax
body: [
{
type: 'button',
label: '刷新',
label: '刷新下拉框',
className: 'mb-2',
level: 'primary',
onEvent: {
@ -1392,7 +1396,7 @@ run action ajax
actions: [
{
actionType: 'reload',
componentId: 'form-reload'
componentId: 'select-reload'
}
]
}
@ -1400,17 +1404,14 @@ run action ajax
},
{
type: 'form',
id: 'form-reload',
name: 'form-reload',
initApi:
'https://3xsw4ap8wah59.cfc-execute.bj.baidubce.com/api/amis-mock/mock2/page/initData',
title: '表单',
body: [
{
type: 'input-text',
id: 'date-input-01',
name: 'date',
label: '时间戳'
type: 'select',
id: 'select-reload',
name: 'select',
label: '选项',
"source": "/api/mock2/form/getOptions?waitSeconds=1"
}
]
}
@ -1418,6 +1419,175 @@ run action ajax
}
```
#### 刷新 CRUD
刷新 CRUD 时,如果配置了`data`,将发送`data`给目标 CRUD 组件,并将该数据合并到目标 CRUD 组件的数据域中,然后触发目标组件的刷新操作,即 CRUD 数据拉取接口将自动追加`data`参数到请求中,更多示例可以查看[CRUD reload](../../components/crud#reload)。
```schema
{
"type": "page",
"data": {
"name": "amis",
"age": 18,
"date": "2023-6-6"
},
"body": [
{
"type": "button",
"label": "刷新CRUD数据加载请求同时追加参数",
level: 'primary',
"className": "mb-2",
"onEvent": {
"click": {
"actions": [
{
"componentId": "crud_reload",
"actionType": "reload",
data: {
author: "${author}"
}
}
]
}
}
},
{
"type": "crud",
"api": "/api/mock2/sample",
"id": "crud_reload",
"syncLocation": false,
"columns": [
{
"name": "id",
"label": "ID"
},
{
"name": "engine",
"label": "Rendering engine"
},
{
"name": "browser",
"label": "Browser"
},
{
"name": "platform",
"label": "Platform(s)"
},
{
"name": "version",
"label": "Engine version"
},
{
"name": "grade",
"label": "CSS grade"
},
{
"type": "operation",
"label": "操作",
"buttons": [
{
"label": "详情",
"type": "button",
"level": "link",
"actionType": "dialog",
"dialog": {
"title": "查看详情",
"body": {
"type": "form",
"body": [
{
"type": "input-text",
"name": "engine",
"label": "Engine"
},
{
"type": "input-text",
"name": "browser",
"label": "Browser"
},
{
"type": "input-text",
"name": "platform",
"label": "platform"
},
{
"type": "input-text",
"name": "version",
"label": "version"
},
{
"type": "control",
"label": "grade",
"body": {
"type": "tag",
"label": "${grade}",
"displayMode": "normal",
"color": "active"
}
}
]
}
}
},
{
"label": "删除",
"type": "button",
"level": "link",
"className": "text-danger",
"disabledOn": "this.grade === 'A'"
}
]
}
]
}
]
}
```
#### 刷新其他数据容器类组件
刷新容器类组件(`form`、`wizard`、`service`、`page`、`app`、`chart`)时,如果配置了`data`,将发送`data`给目标组件,并将该数据合并到目标组件的数据域中。
```schema
{
"type": "page",
"body": [
{
"type": "button",
"label": "刷新Service数据加载请求同时把年龄更新为18",
level: 'primary',
"className": "mb-2",
"onEvent": {
"click": {
"actions": [
{
"componentId": "service_reload",
"actionType": "reload",
data: {
age: "18"
}
}
]
}
}
},
{
"type": "service",
"api": "/api/mock2/form/initData",
"body": [
{
"type": "tpl",
"tpl": "我的名字:${name}, 我的年龄:${age|default:'-'}",
"wrapperComponent": "",
"inline": false
}
],
"id": "service_reload"
}
]
}
```
**动作属性**
| 属性名 | 类型 | 默认值 | 说明 |
@ -1430,12 +1600,14 @@ run action ajax
| ----------- | -------- | ------ | --------------------- |
| componentId | `string` | - | 指定刷新的目标组件 id |
### 控制状态
### 修改组件状态
> 1.8.0 及以上版本
通过配置`actionType: 'show'`或`'hidden'`或`'enabled'`或`'disabled'`或`'static'`或`'nostatic'`实现对指定组件的显示、隐藏、启用、禁用,仅支持实现了对应状态控制功能的数据`输入类`组件。
#### 显示与隐藏
```schema
{
type: 'page',
@ -1450,7 +1622,7 @@ run action ajax
actions: [
{
actionType: 'show',
componentId: 'form_disable'
componentId: 'form_hidden'
}
]
}
@ -1466,12 +1638,36 @@ run action ajax
actions: [
{
actionType: 'hidden',
componentId: 'form_disable'
componentId: 'form_hidden'
}
]
}
}
},
{
type: 'form',
id: 'form_hidden',
title: '表单',
body: [
{
"type": "input-text",
"name": "text",
"label": "输入框",
"mode": "horizontal",
"value": "text"
}
]
}
]
}
```
#### 启用与禁用
```schema
{
type: 'page',
body: [
{
type: 'button',
id: 'b_dis',
@ -1506,38 +1702,6 @@ run action ajax
}
}
},
{
type: 'button',
label: '静态展示表单',
level: 'primary',
className: 'mr-2 mb-2',
onEvent: {
click: {
actions: [
{
actionType: 'static',
componentId: 'form_disable'
}
]
}
}
},
{
type: 'button',
label: '非静态展示表单',
level: 'primary',
className: 'mr-2 mb-2',
onEvent: {
click: {
actions: [
{
actionType: 'nonstatic',
componentId: 'form_disable'
}
]
}
}
},
{
type: 'form',
id: 'form_disable',
@ -1593,13 +1757,69 @@ run action ajax
}
```
#### 静态展示与编辑态
```schema
{
type: 'page',
body: [
{
type: 'button',
label: '静态展示表单',
level: 'primary',
className: 'mr-2 mb-2',
onEvent: {
click: {
actions: [
{
actionType: 'static',
componentId: 'form_static'
}
]
}
}
},
{
type: 'button',
label: '非静态展示表单',
level: 'primary',
className: 'mr-2 mb-2',
onEvent: {
click: {
actions: [
{
actionType: 'nonstatic',
componentId: 'form_static'
}
]
}
}
},
{
type: 'form',
id: 'form_static',
title: '表单',
body: [
{
"type": "input-text",
"name": "text",
"label": "输入框",
"mode": "horizontal",
"value": "text"
}
]
}
]
}
```
**其他属性**
| 属性名 | 类型 | 默认值 | 说明 |
| ----------- | -------- | ------ | ------------------------------------ |
| componentId | `string` | - | 指定启用/禁用/显示/隐藏的目标组件 id |
### 更新数据
### 更新组件数据
> 1.8.0 及以上版本

View File

@ -285,7 +285,7 @@ export const runAction = async (
{
...actionConfig,
args,
data,
data: actionConfig.actionType === 'reload' ? actionData : data, // 如果是刷新动作则只传action.data
...key
},
renderer,

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,634 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`doAction:page reload 1`] = `
<div>
<div
class="cxd-Page"
>
<div
class="cxd-Page-content"
>
<div
class="cxd-Page-main"
>
<div
class="cxd-Page-body"
role="page-body"
>
<button
class="cxd-Button cxd-Button--primary cxd-Button--size-default mb-2"
type="button"
>
<span>
刷新Page数据加载请求
</span>
</button>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
我的标题:
</span>
</span>
</span>
</label>
<div
class="cxd-Form-control cxd-TextControl"
>
<div
class="cxd-TextControl-input"
>
<input
autocomplete="off"
class=""
name="title"
placeholder=""
size="10"
type="text"
value="Test Page Component"
/>
</div>
</div>
</div>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
我的年龄:
</span>
</span>
</span>
</label>
<div
class="cxd-Form-control cxd-TextControl"
>
<div
class="cxd-TextControl-input"
>
<input
autocomplete="off"
class=""
name="age"
placeholder=""
size="10"
type="text"
value=""
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`doAction:page reload 2`] = `
<div>
<div
class="cxd-Page"
>
<div
class="cxd-Page-content"
>
<div
class="cxd-Page-main"
>
<div
class="cxd-Page-body"
role="page-body"
>
<div
class="cxd-Spinner-overlay in"
/>
<div
class="cxd-Spinner cxd-Spinner--overlay in"
data-testid="spinner"
>
<div
class="cxd-Spinner-icon cxd-Spinner-icon--lg cxd-Spinner-icon--default"
/>
</div>
<button
class="cxd-Button cxd-Button--primary cxd-Button--size-default mb-2"
type="button"
>
<span>
刷新Page数据加载请求
</span>
</button>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
我的标题:
</span>
</span>
</span>
</label>
<div
class="cxd-Form-control cxd-TextControl"
>
<div
class="cxd-TextControl-input"
>
<input
autocomplete="off"
class=""
name="title"
placeholder=""
size="10"
type="text"
value="Test Page Component"
/>
</div>
</div>
</div>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
我的年龄:
</span>
</span>
</span>
</label>
<div
class="cxd-Form-control cxd-TextControl"
>
<div
class="cxd-TextControl-input"
>
<input
autocomplete="off"
class=""
name="age"
placeholder=""
size="10"
type="text"
value=""
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`doAction:page reload with data 1`] = `
<div>
<div
class="cxd-Page"
>
<div
class="cxd-Page-content"
>
<div
class="cxd-Page-main"
>
<div
class="cxd-Page-body"
role="page-body"
>
<button
class="cxd-Button cxd-Button--primary cxd-Button--size-default mb-2"
type="button"
>
<span>
刷新Page数据加载请求同时把年龄更新为18
</span>
</button>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
我的标题:
</span>
</span>
</span>
</label>
<div
class="cxd-Form-control cxd-TextControl"
>
<div
class="cxd-TextControl-input"
>
<input
autocomplete="off"
class=""
name="title"
placeholder=""
size="10"
type="text"
value="Test Page Component"
/>
</div>
</div>
</div>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
我的年龄:
</span>
</span>
</span>
</label>
<div
class="cxd-Form-control cxd-TextControl"
>
<div
class="cxd-TextControl-input"
>
<input
autocomplete="off"
class=""
name="age"
placeholder=""
size="10"
type="text"
value=""
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`doAction:page reload with data 2`] = `
<div>
<div
class="cxd-Page"
>
<div
class="cxd-Page-content"
>
<div
class="cxd-Page-main"
>
<div
class="cxd-Page-body"
role="page-body"
>
<div
class="cxd-Spinner-overlay in"
/>
<div
class="cxd-Spinner cxd-Spinner--overlay in"
data-testid="spinner"
>
<div
class="cxd-Spinner-icon cxd-Spinner-icon--lg cxd-Spinner-icon--default"
/>
</div>
<button
class="cxd-Button cxd-Button--primary cxd-Button--size-default mb-2"
type="button"
>
<span>
刷新Page数据加载请求同时把年龄更新为18
</span>
</button>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
我的标题:
</span>
</span>
</span>
</label>
<div
class="cxd-Form-control cxd-TextControl"
>
<div
class="cxd-TextControl-input"
>
<input
autocomplete="off"
class=""
name="title"
placeholder=""
size="10"
type="text"
value="Test Page Component"
/>
</div>
</div>
</div>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
我的年龄:
</span>
</span>
</span>
</label>
<div
class="cxd-Form-control cxd-TextControl"
>
<div
class="cxd-TextControl-input"
>
<input
autocomplete="off"
class=""
name="age"
placeholder=""
size="10"
type="text"
value="18"
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`doAction:page reload with data(same name) 1`] = `
<div>
<div
class="cxd-Page"
>
<div
class="cxd-Page-content"
>
<div
class="cxd-Page-main"
>
<div
class="cxd-Page-body"
role="page-body"
>
<button
class="cxd-Button cxd-Button--primary cxd-Button--size-default mb-2"
type="button"
>
<span>
刷新Page数据加载请求请求返回的date会覆盖动作传递的date
</span>
</button>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
我的标题:
</span>
</span>
</span>
</label>
<div
class="cxd-Form-control cxd-TextControl"
>
<div
class="cxd-TextControl-input"
>
<input
autocomplete="off"
class=""
name="title"
placeholder=""
size="10"
type="text"
value="Test Page Component"
/>
</div>
</div>
</div>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
日期:
</span>
</span>
</span>
</label>
<div
class="cxd-Form-control cxd-TextControl"
>
<div
class="cxd-TextControl-input"
>
<input
autocomplete="off"
class=""
name="date"
placeholder=""
size="10"
type="text"
value="2017-10-13"
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`doAction:page reload with data(same name) 2`] = `
<div>
<div
class="cxd-Page"
>
<div
class="cxd-Page-content"
>
<div
class="cxd-Page-main"
>
<div
class="cxd-Page-body"
role="page-body"
>
<div
class="cxd-Spinner-overlay"
/>
<div
class="cxd-Spinner cxd-Spinner--overlay"
data-testid="spinner"
>
<div
class="cxd-Spinner-icon cxd-Spinner-icon--lg cxd-Spinner-icon--default"
/>
</div>
<button
class="cxd-Button cxd-Button--primary cxd-Button--size-default mb-2"
type="button"
>
<span>
刷新Page数据加载请求请求返回的date会覆盖动作传递的date
</span>
</button>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
我的标题:
</span>
</span>
</span>
</label>
<div
class="cxd-Form-control cxd-TextControl"
>
<div
class="cxd-TextControl-input"
>
<input
autocomplete="off"
class=""
name="title"
placeholder=""
size="10"
type="text"
value="Test Page Component"
/>
</div>
</div>
</div>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
日期:
</span>
</span>
</span>
</label>
<div
class="cxd-Form-control cxd-TextControl"
>
<div
class="cxd-TextControl-input"
>
<input
autocomplete="off"
class=""
name="date"
placeholder=""
size="10"
type="text"
value="2017-10-13"
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;

View File

@ -0,0 +1,578 @@
import React = require('react');
import * as renderer from 'react-test-renderer';
import {fireEvent, render, waitFor} from '@testing-library/react';
import '../../../src';
import {render as amisRender} from '../../../src';
import {makeEnv} from '../../helper';
test('doAction:crud reload', async () => {
const notify = jest.fn();
const fetcher = jest.fn().mockImplementation(() =>
Promise.resolve({
data: {
status: 0,
msg: 'ok',
data: {
count: 171,
rows: [
{
engine: 'Trident - pbz7l',
browser: 'Internet Explorer 4.0',
platform: 'Win 95+',
version: '4',
grade: 'X',
badgeText: '默认',
id: 1
},
{
engine: 'Trident - tir4m8',
browser: 'Internet Explorer 5.0',
platform: 'Win 95+',
version: '5',
grade: 'C',
badgeText: '危险',
id: 2
},
{
engine: 'Trident - wcn6f',
browser: 'Internet Explorer 5.5',
platform: 'Win 95+',
version: '5.5',
grade: 'A',
id: 3
},
{
engine: 'Trident - uwmcbf',
browser: 'Internet Explorer 6',
platform: 'Win 98+',
version: '6',
grade: 'A',
id: 4
},
{
engine: 'Trident - yjgst7',
browser: 'Internet Explorer 7',
platform: 'Win XP SP2+',
version: '7',
grade: 'A',
id: 5
},
{
engine: 'Trident - w9ee2k',
browser: 'AOL browser (AOL desktop)',
platform: 'Win XP',
version: '6',
grade: 'A',
id: 6
},
{
engine: 'Gecko - hi6cd',
browser: 'Firefox 1.0',
platform: 'Win 98+ / OSX.2+',
version: '1.7',
grade: 'A',
id: 7
},
{
engine: 'Gecko - 4kxz6',
browser: 'Firefox 1.5',
platform: 'Win 98+ / OSX.2+',
version: '1.8',
grade: 'A',
id: 8
},
{
engine: 'Gecko - x0u91o',
browser: 'Firefox 2.0',
platform: 'Win 98+ / OSX.2+',
version: '1.8',
grade: 'A',
id: 9
},
{
engine: 'Gecko - iou01',
browser: 'Firefox 3.0',
platform: 'Win 2k+ / OSX.3+',
version: '1.9',
grade: 'A',
id: 10
}
]
}
}
})
);
const {container, getByText} = render(
amisRender(
{
type: 'page',
data: {
name: 'amis',
age: 18,
date: '2023-6-6'
},
body: [
{
type: 'button',
label: '刷新CRUD数据加载请求',
level: 'primary',
className: 'mb-2',
onEvent: {
click: {
actions: [
{
componentId: 'crud_reload',
actionType: 'reload'
}
]
}
}
},
{
type: 'crud',
api: '/api/mock2/sample',
id: 'crud_reload',
syncLocation: false,
columns: [
{
name: 'id',
label: 'ID'
},
{
name: 'engine',
label: 'Rendering engine'
},
{
name: 'browser',
label: 'Browser'
},
{
name: 'platform',
label: 'Platform(s)'
},
{
name: 'version',
label: 'Engine version'
},
{
name: 'grade',
label: 'CSS grade'
},
{
type: 'operation',
label: '操作',
buttons: [
{
label: '详情',
type: 'button',
level: 'link',
actionType: 'dialog',
dialog: {
title: '查看详情',
body: {
type: 'form',
body: [
{
type: 'input-text',
name: 'engine',
label: 'Engine'
},
{
type: 'input-text',
name: 'browser',
label: 'Browser'
},
{
type: 'input-text',
name: 'platform',
label: 'platform'
},
{
type: 'input-text',
name: 'version',
label: 'version'
},
{
type: 'control',
label: 'grade',
body: {
type: 'tag',
label: '${grade}',
displayMode: 'normal',
color: 'active'
}
}
]
}
}
},
{
label: '删除',
type: 'button',
level: 'link',
className: 'text-danger',
disabledOn: "this.grade === 'A'"
}
]
}
]
}
]
},
{},
makeEnv({
notify,
fetcher
})
)
);
await waitFor(() => {
expect(getByText('刷新CRUD数据加载请求')).toBeInTheDocument();
});
fireEvent.click(getByText(/刷新CRUD数据加载请求/));
await waitFor(() => {
expect(fetcher).toHaveBeenCalledTimes(2);
expect(fetcher.mock.calls[0][0].url).toEqual(
'/api/mock2/sample?page=1&perPage=10'
);
expect(fetcher.mock.calls[1][0].url).toEqual(
'/api/mock2/sample?page=1&perPage=10'
);
});
expect(container).toMatchSnapshot();
});
test('doAction:crud reload with data1', async () => {
const notify = jest.fn();
const fetcher = jest.fn().mockImplementation(() =>
Promise.resolve({
data: {
status: 0,
msg: 'ok',
data: {
name: 'Amis Renderer',
author: 'fex',
date: 1688714086
}
}
})
);
const {container, getByText} = render(
amisRender(
{
type: 'page',
data: {
name: 'amis',
age: 18,
date: '2023-6-6'
},
body: [
{
type: 'button',
label: '刷新CRUD数据加载请求同时追加参数date',
level: 'primary',
className: 'mb-2',
onEvent: {
click: {
actions: [
{
componentId: 'crud_reload',
actionType: 'reload',
data: {
date: '${date}'
}
}
]
}
}
},
{
type: 'crud',
api: '/api/mock2/sample',
id: 'crud_reload',
syncLocation: false,
columns: [
{
name: 'id',
label: 'ID'
},
{
name: 'engine',
label: 'Rendering engine'
},
{
name: 'browser',
label: 'Browser'
},
{
name: 'platform',
label: 'Platform(s)'
},
{
name: 'version',
label: 'Engine version'
},
{
name: 'grade',
label: 'CSS grade'
},
{
type: 'operation',
label: '操作',
buttons: [
{
label: '详情',
type: 'button',
level: 'link',
actionType: 'dialog',
dialog: {
title: '查看详情',
body: {
type: 'form',
body: [
{
type: 'input-text',
name: 'engine',
label: 'Engine'
},
{
type: 'input-text',
name: 'browser',
label: 'Browser'
},
{
type: 'input-text',
name: 'platform',
label: 'platform'
},
{
type: 'input-text',
name: 'version',
label: 'version'
},
{
type: 'control',
label: 'grade',
body: {
type: 'tag',
label: '${grade}',
displayMode: 'normal',
color: 'active'
}
}
]
}
}
},
{
label: '删除',
type: 'button',
level: 'link',
className: 'text-danger',
disabledOn: "this.grade === 'A'"
}
]
}
]
}
]
},
{},
makeEnv({
notify,
fetcher
})
)
);
await waitFor(() => {
expect(
getByText('刷新CRUD数据加载请求同时追加参数date')
).toBeInTheDocument();
});
fireEvent.click(getByText(/刷新CRUD数据加载请求同时追加参数date/));
await waitFor(() => {
expect(fetcher).toHaveBeenCalledTimes(2);
expect(fetcher.mock.calls[0][0].url).toEqual(
'/api/mock2/sample?page=1&perPage=10'
);
expect(fetcher.mock.calls[1][0].url).toEqual(
'/api/mock2/sample?page=1&date=2023-6-6&perPage=10'
);
});
expect(container).toMatchSnapshot();
});
test('doAction:crud reload with data2', async () => {
const notify = jest.fn();
const fetcher = jest.fn().mockImplementation(() =>
Promise.resolve({
data: {
status: 0,
msg: 'ok',
data: {
name: 'Amis Renderer',
author: 'fex',
date: 1688714086
}
}
})
);
const {container, getByText} = render(
amisRender(
{
type: 'page',
data: {
name: 'amis',
age: 18,
date: '2023-6-6'
},
body: [
{
type: 'button',
label: '刷新CRUD数据加载请求同时追加按钮所在数据域的所有数据',
level: 'primary',
className: 'mb-2',
onEvent: {
click: {
actions: [
{
componentId: 'crud_reload',
actionType: 'reload',
data: {
'&': '$$',
'author': 'fex'
}
}
]
}
}
},
{
type: 'crud',
api: '/api/mock2/sample',
id: 'crud_reload',
syncLocation: false,
columns: [
{
name: 'id',
label: 'ID'
},
{
name: 'engine',
label: 'Rendering engine'
},
{
name: 'browser',
label: 'Browser'
},
{
name: 'platform',
label: 'Platform(s)'
},
{
name: 'version',
label: 'Engine version'
},
{
name: 'grade',
label: 'CSS grade'
},
{
type: 'operation',
label: '操作',
buttons: [
{
label: '详情',
type: 'button',
level: 'link',
actionType: 'dialog',
dialog: {
title: '查看详情',
body: {
type: 'form',
body: [
{
type: 'input-text',
name: 'engine',
label: 'Engine'
},
{
type: 'input-text',
name: 'browser',
label: 'Browser'
},
{
type: 'input-text',
name: 'platform',
label: 'platform'
},
{
type: 'input-text',
name: 'version',
label: 'version'
},
{
type: 'control',
label: 'grade',
body: {
type: 'tag',
label: '${grade}',
displayMode: 'normal',
color: 'active'
}
}
]
}
}
},
{
label: '删除',
type: 'button',
level: 'link',
className: 'text-danger',
disabledOn: "this.grade === 'A'"
}
]
}
]
}
]
},
{},
makeEnv({
notify,
fetcher
})
)
);
await waitFor(() => {
expect(
getByText('刷新CRUD数据加载请求同时追加按钮所在数据域的所有数据')
).toBeInTheDocument();
});
fireEvent.click(
getByText(/刷新CRUD数据加载请求同时追加按钮所在数据域的所有数据/)
);
await waitFor(() => {
expect(fetcher).toHaveBeenCalledTimes(2);
expect(fetcher.mock.calls[0][0].url).toEqual(
'/api/mock2/sample?page=1&perPage=10'
);
expect(fetcher.mock.calls[1][0].url).toEqual(
'/api/mock2/sample?page=1&name=amis&age=18&date=2023-6-6&author=fex&perPage=10'
);
});
expect(container).toMatchSnapshot();
});

View File

@ -939,6 +939,818 @@ exports[`doAction:form reload 2`] = `
</div>
`;
exports[`doAction:form reload with data 1`] = `
<div>
<div
class="cxd-Page"
>
<div
class="cxd-Page-content"
>
<div
class="cxd-Page-main"
>
<div
class="cxd-Page-body"
role="page-body"
>
<button
class="cxd-Button cxd-Button--default cxd-Button--size-default mb-2"
type="button"
>
<span>
刷新表单
</span>
</button>
<div
class="cxd-Panel cxd-Panel--default cxd-Panel--form"
style="position: relative;"
>
<div
class="cxd-Panel-heading"
>
<h3
class="cxd-Panel-title"
>
<span
class="cxd-TplField"
>
<span>
表单
</span>
</span>
</h3>
</div>
<div
class="cxd-Panel-body"
>
<form
class="cxd-Form cxd-Form--normal"
novalidate=""
>
<input
style="display: none;"
type="submit"
/>
<div
class="cxd-JsonField cxd-Form--debug"
>
<div
class="react-json-view"
style="font-family: monospace; cursor: default; background-color: rgba(0, 0, 0, 0); position: relative;"
>
<div
class="pretty-json-container object-container"
>
<div
class="object-content"
>
<div
class="object-key-val"
>
<span>
<span
style="display: inline-block; cursor: pointer;"
>
<div
class="icon-container"
style="display: inline-block; width: 17px;"
>
<span
class="collapsed-icon"
>
<svg
fill="#2aa198"
height="1em"
style="vertical-align: middle; color: rgb(42, 161, 152); height: 1em; width: 1em;"
viewBox="0 0 1792 1792"
width="1em"
>
<path
d="M1344 800v64q0 14-9 23t-23 9h-352v352q0 14-9 23t-23 9h-64q-14 0-23-9t-9-23v-352h-352q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h352v-352q0-14 9-23t23-9h64q14 0 23 9t9 23v352h352q14 0 23 9t9 23zm128 448v-832q0-66-47-113t-113-47h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113zm128-832v832q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q119 0 203.5 84.5t84.5 203.5z"
/>
</svg>
</span>
</div>
<span />
<span
style="display: inline-block; cursor: pointer; font-weight: bold; color: rgb(0, 43, 54);"
>
{
</span>
</span>
</span>
<span
class="brace-row"
>
<span
style="display: inline-block; cursor: pointer; font-weight: bold; color: rgb(0, 43, 54); padding-left: 0px;"
>
}
</span>
<div
class="object-meta-data"
style="display: inline-block; padding: 0px 0px 0px 10px;"
>
<span
class="object-size"
style="color: rgba(0, 0, 0, 0.3); border-radius: 3px; font-style: italic; margin: 0px 6px 0px 0px; cursor: default;"
>
0
item
s
</span>
</div>
</span>
</div>
</div>
</div>
</div>
</div>
<div
class="cxd-Spinner-overlay in"
/>
<div
class="cxd-Spinner cxd-Spinner--overlay in"
data-testid="spinner"
>
<div
class="cxd-Spinner-icon cxd-Spinner-icon--default"
/>
</div>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
姓名:
</span>
</span>
</span>
</label>
<div
class="cxd-Form-control cxd-TextControl is-disabled"
>
<div
class="cxd-TextControl-input"
>
<input
autocomplete="off"
class=""
disabled=""
name="name"
placeholder=""
size="10"
type="text"
value=""
/>
</div>
</div>
</div>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
作者:
</span>
</span>
</span>
</label>
<div
class="cxd-Form-control cxd-TextControl is-disabled"
>
<div
class="cxd-TextControl-input"
>
<input
autocomplete="off"
class=""
disabled=""
name="author"
placeholder=""
size="10"
type="text"
value="amis"
/>
</div>
</div>
</div>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
年龄:
</span>
</span>
</span>
</label>
<div
class="cxd-Form-control cxd-TextControl is-disabled"
>
<div
class="cxd-TextControl-input"
>
<input
autocomplete="off"
class=""
disabled=""
name="age"
placeholder=""
size="10"
type="text"
value=""
/>
</div>
</div>
</div>
</form>
</div>
<div
class="cxd-Panel-footerWrap"
>
<div
class="cxd-Panel-btnToolbar cxd-Panel-footer"
>
<div
class="cxd-Button cxd-Button--primary cxd-Button--size-default is-disabled"
disabled=""
>
<span>
提交
</span>
</div>
</div>
</div>
<div
class="resize-sensor"
style="position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; overflow: scroll; z-index: -1; visibility: hidden;"
>
<div
class="resize-sensor-expand"
style="position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;"
>
<div
style="position: absolute; left: 0px; top: 0px; width: 10px; height: 10px;"
/>
</div>
<div
class="resize-sensor-shrink"
style="position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;"
>
<div
style="position: absolute; left: 0; top: 0; width: 200%; height: 200%"
/>
</div>
<div
class="resize-sensor-appear"
style="position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;animation-name: apearSensor; animation-duration: 0.2s;"
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`doAction:form reload with data 2`] = `
<div>
<div
class="cxd-Page"
>
<div
class="cxd-Page-content"
>
<div
class="cxd-Page-main"
>
<div
class="cxd-Page-body"
role="page-body"
>
<button
class="cxd-Button cxd-Button--default cxd-Button--size-default mb-2"
type="button"
>
<span>
刷新表单
</span>
</button>
<div
class="cxd-Panel cxd-Panel--default cxd-Panel--form"
style="position: relative;"
>
<div
class="cxd-Panel-heading"
>
<h3
class="cxd-Panel-title"
>
<span
class="cxd-TplField"
>
<span>
表单
</span>
</span>
</h3>
</div>
<div
class="cxd-Panel-body"
>
<form
class="cxd-Form cxd-Form--normal"
novalidate=""
>
<input
style="display: none;"
type="submit"
/>
<div
class="cxd-JsonField cxd-Form--debug"
>
<div
class="react-json-view"
style="font-family: monospace; cursor: default; background-color: rgba(0, 0, 0, 0); position: relative;"
>
<div
class="pretty-json-container object-container"
>
<div
class="object-content"
>
<div
class="object-key-val"
>
<span>
<span
style="display: inline-block; cursor: pointer;"
>
<div
class="icon-container"
style="display: inline-block; width: 17px;"
>
<span
class="expanded-icon"
>
<svg
fill="#586e75"
height="1em"
style="vertical-align: middle; color: rgb(88, 110, 117); height: 1em; width: 1em;"
viewBox="0 0 1792 1792"
width="1em"
>
<path
d="M1344 800v64q0 14-9 23t-23 9h-832q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h832q14 0 23 9t9 23zm128 448v-832q0-66-47-113t-113-47h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113zm128-832v832q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q119 0 203.5 84.5t84.5 203.5z"
/>
</svg>
</span>
</div>
<span />
<span
style="display: inline-block; cursor: pointer; font-weight: bold; color: rgb(0, 43, 54);"
>
{
</span>
</span>
<div
class="object-meta-data"
style="display: inline-block; padding: 0px 0px 0px 10px;"
>
<span
class="object-size"
style="color: rgba(0, 0, 0, 0.3); border-radius: 3px; font-style: italic; margin: 0px 6px 0px 0px; cursor: default;"
>
4
item
s
</span>
</div>
</span>
<div
class="pushed-content object-container"
>
<div
class="object-content"
style="margin-left: 6px;"
>
<div
class="variable-row"
style="border-left: 1px solid rgb(235, 235, 235); padding: 3px 5px 3px 20px;"
>
<span>
<span
class="object-key"
style="display: inline-block; color: rgb(0, 43, 54); letter-spacing: 0.5px; font-style: none; vertical-align: top; opacity: 0.85;"
>
<span
style="vertical-align: top;"
>
"
</span>
<span
style="display: inline-block;"
>
name
</span>
<span
style="vertical-align: top;"
>
"
</span>
</span>
<span
style="display: inline-block; margin: 0px 5px; color: rgb(0, 43, 54); vertical-align: top;"
>
:
</span>
</span>
<div
class="variable-value"
style="display: inline-block; padding-right: 6px; position: relative; cursor: default;"
>
<div
style="display: inline-block; color: rgb(203, 75, 22);"
>
<span
class="string-value"
style="cursor: default;"
>
"
Amis Renderer
"
</span>
</div>
</div>
</div>
<div
class="variable-row"
style="border-left: 1px solid rgb(235, 235, 235); padding: 3px 5px 3px 20px;"
>
<span>
<span
class="object-key"
style="display: inline-block; color: rgb(0, 43, 54); letter-spacing: 0.5px; font-style: none; vertical-align: top; opacity: 0.85;"
>
<span
style="vertical-align: top;"
>
"
</span>
<span
style="display: inline-block;"
>
author
</span>
<span
style="vertical-align: top;"
>
"
</span>
</span>
<span
style="display: inline-block; margin: 0px 5px; color: rgb(0, 43, 54); vertical-align: top;"
>
:
</span>
</span>
<div
class="variable-value"
style="display: inline-block; padding-right: 6px; position: relative; cursor: default;"
>
<div
style="display: inline-block; color: rgb(203, 75, 22);"
>
<span
class="string-value"
style="cursor: default;"
>
"
fex
"
</span>
</div>
</div>
</div>
<div
class="variable-row"
style="border-left: 1px solid rgb(235, 235, 235); padding: 3px 5px 3px 20px;"
>
<span>
<span
class="object-key"
style="display: inline-block; color: rgb(0, 43, 54); letter-spacing: 0.5px; font-style: none; vertical-align: top; opacity: 0.85;"
>
<span
style="vertical-align: top;"
>
"
</span>
<span
style="display: inline-block;"
>
date
</span>
<span
style="vertical-align: top;"
>
"
</span>
</span>
<span
style="display: inline-block; margin: 0px 5px; color: rgb(0, 43, 54); vertical-align: top;"
>
:
</span>
</span>
<div
class="variable-value"
style="display: inline-block; padding-right: 6px; position: relative; cursor: default;"
>
<div
style="display: inline-block; color: rgb(38, 139, 210);"
>
1688714086
</div>
</div>
</div>
<div
class="variable-row"
style="border-left: 1px solid rgb(235, 235, 235); padding: 3px 5px 3px 20px;"
>
<span>
<span
class="object-key"
style="display: inline-block; color: rgb(0, 43, 54); letter-spacing: 0.5px; font-style: none; vertical-align: top; opacity: 0.85;"
>
<span
style="vertical-align: top;"
>
"
</span>
<span
style="display: inline-block;"
>
age
</span>
<span
style="vertical-align: top;"
>
"
</span>
</span>
<span
style="display: inline-block; margin: 0px 5px; color: rgb(0, 43, 54); vertical-align: top;"
>
:
</span>
</span>
<div
class="variable-value"
style="display: inline-block; padding-right: 6px; position: relative; cursor: default;"
>
<div
style="display: inline-block; color: rgb(38, 139, 210);"
>
18
</div>
</div>
</div>
</div>
</div>
<span
class="brace-row"
>
<span
style="display: inline-block; cursor: pointer; font-weight: bold; color: rgb(0, 43, 54); padding-left: 3px;"
>
}
</span>
</span>
</div>
</div>
</div>
</div>
</div>
<div
class="cxd-Spinner-overlay"
/>
<div
class="cxd-Spinner cxd-Spinner--overlay"
data-testid="spinner"
>
<div
class="cxd-Spinner-icon cxd-Spinner-icon--default"
/>
</div>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
姓名:
</span>
</span>
</span>
</label>
<div
class="cxd-Form-control cxd-TextControl"
>
<div
class="cxd-TextControl-input"
>
<input
autocomplete="off"
class=""
name="name"
placeholder=""
size="10"
type="text"
value="Amis Renderer"
/>
</div>
</div>
</div>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
作者:
</span>
</span>
</span>
</label>
<div
class="cxd-Form-control cxd-TextControl"
>
<div
class="cxd-TextControl-input"
>
<input
autocomplete="off"
class=""
name="author"
placeholder=""
size="10"
type="text"
value="fex"
/>
</div>
</div>
</div>
<div
class="cxd-Form-item cxd-Form-item--normal"
data-role="form-item"
>
<label
class="cxd-Form-label"
>
<span>
<span
class="cxd-TplField"
>
<span>
年龄:
</span>
</span>
</span>
</label>
<div
class="cxd-Form-control cxd-TextControl"
>
<div
class="cxd-TextControl-input"
>
<input
autocomplete="off"
class=""
name="age"
placeholder=""
size="10"
type="text"
value="18"
/>
</div>
</div>
</div>
</form>
</div>
<div
class="cxd-Panel-footerWrap"
>
<div
class="cxd-Panel-btnToolbar cxd-Panel-footer"
>
<button
class="cxd-Button cxd-Button--primary cxd-Button--size-default"
type="submit"
>
<span>
提交
</span>
</button>
</div>
</div>
<div
class="resize-sensor"
style="position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; overflow: scroll; z-index: -1; visibility: hidden;"
>
<div
class="resize-sensor-expand"
style="position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;"
>
<div
style="position: absolute; left: 0px; top: 0px; width: 10px; height: 10px;"
/>
</div>
<div
class="resize-sensor-shrink"
style="position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;"
>
<div
style="position: absolute; left: 0; top: 0; width: 200%; height: 200%"
/>
</div>
<div
class="resize-sensor-appear"
style="position: absolute; left: 0; top: 0; right: 0; bottom: 0; overflow: scroll; z-index: -1; visibility: hidden;animation-name: apearSensor; animation-duration: 0.2s;"
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`doAction:form reset 1`] = `
<div>
<div

View File

@ -454,6 +454,107 @@ test('doAction:form reload', async () => {
expect(container).toMatchSnapshot();
});
test('doAction:form reload with data', async () => {
const notify = jest.fn();
const fetcher = jest.fn().mockImplementation(() =>
Promise.resolve({
data: {
status: 0,
msg: 'ok',
data: {
name: 'Amis Renderer',
author: 'fex',
date: 1688714086
}
}
})
);
const {container, getByText} = render(
amisRender(
{
type: 'page',
body: [
{
type: 'button',
label: '刷新表单',
className: 'mb-2',
onEvent: {
click: {
actions: [
{
actionType: 'reload',
componentId: 'form_reload',
data: {
age: 18
}
}
]
}
}
},
{
type: 'form',
id: 'form_reload',
debug: true,
initApi: '/api/mock2/form/initData',
body: [
{
type: 'input-text',
name: 'name',
label: '姓名:'
},
{
name: 'author',
type: 'input-text',
label: '作者:'
},
{
name: 'age',
type: 'input-text',
label: '年龄:'
}
]
}
]
},
{},
makeEnv({
notify,
fetcher
})
)
);
fireEvent.change(container.querySelector('[name="author"]')!, {
target: {value: 'amis'}
});
await waitFor(() => {
expect((container.querySelector('[name="author"]') as any)?.value).toEqual(
'amis'
);
});
expect(container).toMatchSnapshot();
await waitFor(() => {
expect(getByText('刷新表单')).toBeInTheDocument();
});
fireEvent.click(getByText(/刷新表单/));
await waitFor(() => {
expect((container.querySelector('[name="author"]') as any)?.value).toEqual(
'fex'
);
expect((container.querySelector('[name="age"]') as any)?.value).toEqual(
'18'
);
});
expect(container).toMatchSnapshot();
});
test('doAction:form reset', async () => {
const notify = jest.fn();
const fetcher = jest.fn().mockImplementation(() =>

View File

@ -0,0 +1,285 @@
import React = require('react');
import * as renderer from 'react-test-renderer';
import {fireEvent, render, waitFor} from '@testing-library/react';
import '../../../src';
import {render as amisRender} from '../../../src';
import {makeEnv} from '../../helper';
test('doAction:page reload', async () => {
const notify = jest.fn();
const fetcher = jest.fn().mockImplementation(() =>
Promise.resolve({
data: {
status: 0,
msg: 'ok',
data: {
title: 'Test Page Component',
date: '2017-10-13'
}
}
})
);
const {container, getByText} = render(
amisRender(
{
type: 'page',
initApi: '/api/mock2/page/initData',
id: 'page_reload',
body: [
{
type: 'button',
label: '刷新Page数据加载请求',
level: 'primary',
className: 'mb-2',
onEvent: {
click: {
actions: [
{
componentId: 'page_reload',
actionType: 'reload'
}
]
}
}
},
{
type: 'input-text',
label: '我的标题:',
name: 'title'
},
{
type: 'input-text',
label: '我的年龄:',
name: 'age'
}
]
},
{},
makeEnv({
notify,
fetcher
})
)
);
await waitFor(() => {
expect(getByText('刷新Page数据加载请求')).toBeInTheDocument();
expect(
container.querySelector('[name="title"][value="Test Page Component"]')
).toBeInTheDocument();
expect(
container.querySelector('[name="age"][value=""]')
).toBeInTheDocument();
expect(
container.querySelector('[data-testid="spinner"]')
).not.toBeInTheDocument();
});
expect(container).toMatchSnapshot();
fireEvent.click(getByText(/刷新Page数据加载请求/));
await waitFor(() => {
expect(fetcher).toHaveBeenCalledTimes(2);
expect(fetcher.mock.calls[0][0].url).toEqual('/api/mock2/page/initData');
expect(fetcher.mock.calls[1][0].url).toEqual('/api/mock2/page/initData');
expect(
container.querySelector('[name="title"][value="Test Page Component"]')
).toBeInTheDocument();
expect(
container.querySelector('[name="age"][value=""]')
).toBeInTheDocument();
});
expect(container).toMatchSnapshot();
});
test('doAction:page reload with data', async () => {
const notify = jest.fn();
const fetcher = jest.fn().mockImplementation(() =>
Promise.resolve({
data: {
status: 0,
msg: 'ok',
data: {
title: 'Test Page Component',
date: '2017-10-13'
}
}
})
);
const {container, getByText} = render(
amisRender(
{
type: 'page',
initApi: '/api/mock2/page/initData',
id: 'page_reload',
body: [
{
type: 'button',
label: '刷新Page数据加载请求同时把年龄更新为18',
level: 'primary',
className: 'mb-2',
onEvent: {
click: {
actions: [
{
componentId: 'page_reload',
actionType: 'reload',
data: {
age: '18'
}
}
]
}
}
},
{
type: 'input-text',
label: '我的标题:',
name: 'title'
},
{
type: 'input-text',
label: '我的年龄:',
name: 'age'
}
]
},
{},
makeEnv({
notify,
fetcher
})
)
);
await waitFor(() => {
expect(
getByText('刷新Page数据加载请求同时把年龄更新为18')
).toBeInTheDocument();
expect(
container.querySelector('[name="title"][value="Test Page Component"]')
).toBeInTheDocument();
expect(
container.querySelector('[name="age"][value=""]')
).toBeInTheDocument();
expect(
container.querySelector('[data-testid="spinner"]')
).not.toBeInTheDocument();
});
expect(container).toMatchSnapshot();
fireEvent.click(getByText(/刷新Page数据加载请求同时把年龄更新为18/));
await waitFor(() => {
expect(fetcher).toHaveBeenCalledTimes(2);
expect(fetcher.mock.calls[0][0].url).toEqual('/api/mock2/page/initData');
expect(fetcher.mock.calls[1][0].url).toEqual('/api/mock2/page/initData');
expect(
container.querySelector('[name="title"][value="Test Page Component"]')
).toBeInTheDocument();
expect(
container.querySelector('[name="age"][value="18"]')
).toBeInTheDocument();
});
expect(container).toMatchSnapshot();
});
test('doAction:page reload with data(same name)', async () => {
const notify = jest.fn();
const fetcher = jest.fn().mockImplementation(() =>
Promise.resolve({
data: {
status: 0,
msg: 'ok',
data: {
title: 'Test Page Component',
date: '2017-10-13'
}
}
})
);
const {container, getByText} = render(
amisRender(
{
type: 'page',
initApi: '/api/mock2/page/initData',
id: 'page_reload',
body: [
{
type: 'button',
label: '刷新Page数据加载请求请求返回的date会覆盖动作传递的date',
level: 'primary',
className: 'mb-2',
onEvent: {
click: {
actions: [
{
componentId: 'page_reload',
actionType: 'reload',
data: {
date: '2023-07-07'
}
}
]
}
}
},
{
type: 'input-text',
label: '我的标题:',
name: 'title'
},
{
type: 'input-text',
label: '日期:',
name: 'date'
}
]
},
{},
makeEnv({
notify,
fetcher
})
)
);
await waitFor(() => {
expect(
getByText('刷新Page数据加载请求请求返回的date会覆盖动作传递的date')
).toBeInTheDocument();
expect(
container.querySelector('[name="title"][value="Test Page Component"]')
).toBeInTheDocument();
expect(
container.querySelector('[name="date"][value="2017-10-13"]')
).toBeInTheDocument();
expect(
container.querySelector('[data-testid="spinner"]')
).not.toBeInTheDocument();
});
expect(container).toMatchSnapshot();
fireEvent.click(
getByText(/刷新Page数据加载请求请求返回的date会覆盖动作传递的date/)
);
await waitFor(() => {
expect(fetcher).toHaveBeenCalledTimes(2);
expect(fetcher.mock.calls[0][0].url).toEqual('/api/mock2/page/initData');
expect(fetcher.mock.calls[1][0].url).toEqual('/api/mock2/page/initData');
expect(
container.querySelector('[name="title"][value="Test Page Component"]')
).toBeInTheDocument();
expect(
container.querySelector('[name="date"][value="2017-10-13"]')
).toBeInTheDocument();
});
expect(container).toMatchSnapshot();
});

View File

@ -0,0 +1,515 @@
import React = require('react');
import * as renderer from 'react-test-renderer';
import {fireEvent, render, waitFor} from '@testing-library/react';
import '../../../src';
import {render as amisRender} from '../../../src';
import {makeEnv, replaceReactAriaIds, wait} from '../../helper';
test('doAction:service reload', async () => {
const notify = jest.fn();
const fetcher = jest.fn().mockImplementation(() =>
Promise.resolve({
data: {
status: 0,
msg: 'ok',
data: {
name: 'Amis Renderer',
author: 'fex',
date: 1688871102,
info: ''
}
}
})
);
const {container, getByText} = render(
amisRender(
{
type: 'page',
body: [
{
type: 'form',
body: [
{
type: 'input-text',
label: '名字:',
name: 'name',
value: 'amis'
},
{
type: 'input-text',
label: '年龄:',
name: 'age',
value: 18
},
{
type: 'button',
label: '刷新Service数据加载请求',
level: 'primary',
className: 'mb-2',
onEvent: {
click: {
actions: [
{
componentId: 'service_reload',
actionType: 'reload'
}
]
}
}
}
]
},
{
type: 'service',
api: '/api/mock2/form/initData',
body: [
{
type: 'input-text',
label: '我的名字:',
name: 'name'
},
{
type: 'input-text',
label: '我的年龄:',
name: 'age'
}
],
id: 'service_reload'
}
]
},
{},
makeEnv({
notify,
fetcher
})
)
);
await waitFor(() => {
expect(getByText('刷新Service数据加载请求')).toBeInTheDocument();
expect(
container.querySelector('[name="name"][value="Amis Renderer"]')
).toBeInTheDocument();
expect(
container.querySelector('[name="age"][value=""]')
).toBeInTheDocument();
expect(
container.querySelector('[data-testid="spinner"]')
).not.toBeInTheDocument();
});
replaceReactAriaIds(container);
expect(container).toMatchSnapshot();
fireEvent.click(getByText(/刷新Service数据加载请求/));
await waitFor(() => {
expect(fetcher).toHaveBeenCalledTimes(2);
expect(fetcher.mock.calls[0][0].url).toEqual('/api/mock2/form/initData');
expect(fetcher.mock.calls[1][0].url).toEqual('/api/mock2/form/initData');
expect(
container.querySelector('[name="name"][value="Amis Renderer"]')
).toBeInTheDocument();
expect(
container.querySelector('[name="age"][value=""]')
).toBeInTheDocument();
});
expect(container).toMatchSnapshot();
});
test('doAction:service reload with data', async () => {
const notify = jest.fn();
const fetcher = jest.fn().mockImplementation(() =>
Promise.resolve({
data: {
status: 0,
msg: 'ok',
data: {
name: 'Amis Renderer',
author: 'fex',
date: 1688871102,
info: ''
}
}
})
);
const {container, getByText} = render(
amisRender(
{
type: 'page',
body: [
{
type: 'button',
label: '刷新Service数据加载请求同时把年龄更新为18',
level: 'primary',
className: 'mb-2',
onEvent: {
click: {
actions: [
{
componentId: 'service_reload',
actionType: 'reload',
data: {
age: '18'
}
}
]
}
}
},
{
type: 'service',
api: '/api/mock2/form/initData',
body: [
{
type: 'input-text',
label: '我的名字:',
name: 'name'
},
{
type: 'input-text',
label: '我的年龄:',
name: 'age'
}
],
id: 'service_reload'
}
]
},
{},
makeEnv({
notify,
fetcher
})
)
);
await waitFor(() => {
expect(
getByText('刷新Service数据加载请求同时把年龄更新为18')
).toBeInTheDocument();
expect(
container.querySelector('[name="name"][value="Amis Renderer"]')
).toBeInTheDocument();
expect(
container.querySelector('[name="age"][value=""]')
).toBeInTheDocument();
expect(
container.querySelector('[data-testid="spinner"]')
).not.toBeInTheDocument();
});
replaceReactAriaIds(container);
expect(container).toMatchSnapshot();
fireEvent.click(getByText(/刷新Service数据加载请求同时把年龄更新为18/));
await waitFor(() => {
expect(fetcher).toHaveBeenCalledTimes(2);
expect(fetcher.mock.calls[0][0].url).toEqual('/api/mock2/form/initData');
expect(fetcher.mock.calls[1][0].url).toEqual('/api/mock2/form/initData');
expect(
container.querySelector('[name="name"][value="Amis Renderer"]')
).toBeInTheDocument();
expect(
container.querySelector('[name="age"][value="18"]')
).toBeInTheDocument();
});
expect(container).toMatchSnapshot();
});
test('doAction:service(schemaApi) reload', async () => {
const notify = jest.fn();
const fetcher = jest.fn().mockImplementation(() =>
Promise.resolve({
data: {
status: 0,
msg: 'ok',
data: {
controls: [
{
type: 'input-text',
label: '我的名字:',
name: 'name'
},
{
type: 'input-text',
label: '我的年龄:',
name: 'age'
}
]
}
}
})
);
const {container, getByText} = render(
amisRender(
{
type: 'page',
body: [
{
type: 'button',
label: '刷新Service数据加载请求',
level: 'primary',
className: 'mb-2',
onEvent: {
click: {
actions: [
{
componentId: 'service_reload',
actionType: 'reload'
}
]
}
}
},
{
type: 'service',
schemaApi: '/api/schemaApi',
id: 'service_reload'
}
]
},
{},
makeEnv({
notify,
fetcher
})
)
);
await waitFor(() => {
expect(getByText('刷新Service数据加载请求')).toBeInTheDocument();
expect(
container.querySelector('[name="name"][value=""]')
).toBeInTheDocument();
expect(
container.querySelector('[name="age"][value=""]')
).toBeInTheDocument();
expect(
container.querySelector('[data-testid="spinner"]')
).not.toBeInTheDocument();
});
replaceReactAriaIds(container);
expect(container).toMatchSnapshot();
fireEvent.click(getByText(/刷新Service数据加载请求/));
await waitFor(() => {
expect(fetcher).toHaveBeenCalledTimes(2);
expect(fetcher.mock.calls[0][0].url).toEqual('/api/schemaApi?_replace=1');
expect(fetcher.mock.calls[1][0].url).toEqual('/api/schemaApi?_replace=1');
expect(
container.querySelector('[name="name"][value=""]')
).toBeInTheDocument();
expect(
container.querySelector('[name="age"][value=""]')
).toBeInTheDocument();
});
expect(container).toMatchSnapshot();
});
test('doAction:service(schemaApi) reload with data', async () => {
const notify = jest.fn();
const fetcher = jest.fn().mockImplementation(() =>
Promise.resolve({
data: {
status: 0,
msg: 'ok',
data: {
controls: [
{
type: 'input-text',
label: '我的名字:',
name: 'name'
},
{
type: 'input-text',
label: '我的年龄:',
name: 'age'
}
]
}
}
})
);
const {container, getByText} = render(
amisRender(
{
type: 'page',
body: [
{
type: 'button',
label: '刷新Service数据加载请求同时把年龄更新为18',
level: 'primary',
className: 'mb-2',
onEvent: {
click: {
actions: [
{
componentId: 'service_reload',
actionType: 'reload',
data: {
age: '18'
}
}
]
}
}
},
{
type: 'service',
schemaApi: '/api/schemaApi',
id: 'service_reload'
}
]
},
{},
makeEnv({
notify,
fetcher
})
)
);
await waitFor(() => {
expect(
getByText('刷新Service数据加载请求同时把年龄更新为18')
).toBeInTheDocument();
expect(
container.querySelector('[name="name"][value=""]')
).toBeInTheDocument();
expect(
container.querySelector('[name="age"][value=""]')
).toBeInTheDocument();
expect(
container.querySelector('[data-testid="spinner"]')
).not.toBeInTheDocument();
});
replaceReactAriaIds(container);
expect(container).toMatchSnapshot();
fireEvent.click(getByText(/刷新Service数据加载请求同时把年龄更新为18/));
await waitFor(() => {
expect(fetcher).toHaveBeenCalledTimes(2);
expect(fetcher.mock.calls[0][0].url).toEqual('/api/schemaApi?_replace=1');
expect(fetcher.mock.calls[1][0].url).toEqual('/api/schemaApi?_replace=1');
expect(
container.querySelector('[name="name"][value=""]')
).toBeInTheDocument();
expect(
container.querySelector('[name="age"][value="18"]')
).toBeInTheDocument();
});
expect(container).toMatchSnapshot();
});
test('doAction:service(schemaApi+data) reload with data', async () => {
const notify = jest.fn();
const fetcher = jest.fn().mockImplementation(() =>
Promise.resolve({
data: {
status: 0,
msg: 'ok',
data: {
data: {
name: 'amis',
age: 20
},
controls: [
{
type: 'input-text',
label: '我的名字:',
name: 'name'
},
{
type: 'input-text',
label: '我的年龄:',
name: 'age'
}
]
}
}
})
);
const {container, getByText} = render(
amisRender(
{
type: 'page',
body: [
{
type: 'button',
label: '刷新Service数据加载请求同时把年龄更新为18',
level: 'primary',
className: 'mb-2',
onEvent: {
click: {
actions: [
{
componentId: 'service_reload',
actionType: 'reload',
data: {
age: '18'
}
}
]
}
}
},
{
type: 'service',
schemaApi: '/api/schemaApi',
id: 'service_reload'
}
]
},
{},
makeEnv({
notify,
fetcher
})
)
);
await waitFor(() => {
expect(
getByText('刷新Service数据加载请求同时把年龄更新为18')
).toBeInTheDocument();
expect(
container.querySelector('[name="name"][value="amis"]')
).toBeInTheDocument();
expect(
container.querySelector('[name="age"][value="20"]')
).toBeInTheDocument();
expect(
container.querySelector('[data-testid="spinner"]')
).not.toBeInTheDocument();
});
replaceReactAriaIds(container);
expect(container).toMatchSnapshot();
fireEvent.click(getByText(/刷新Service数据加载请求同时把年龄更新为18/));
await waitFor(() => {
expect(fetcher).toHaveBeenCalledTimes(2);
expect(fetcher.mock.calls[0][0].url).toEqual('/api/schemaApi?_replace=1');
expect(fetcher.mock.calls[1][0].url).toEqual('/api/schemaApi?_replace=1');
expect(
container.querySelector('[name="name"][value="amis"]')
).toBeInTheDocument();
expect(
container.querySelector('[name="age"][value="18"]')
).toBeInTheDocument();
});
expect(container).toMatchSnapshot();
});