From 53170c54186281982b686bf9e73ae889dbd82791 Mon Sep 17 00:00:00 2001 From: lvxiaojiao Date: Fri, 7 Jul 2023 16:49:21 +0800 Subject: [PATCH] =?UTF-8?q?chore:=E5=88=B7=E6=96=B0=E5=8A=A8=E4=BD=9C?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E8=B0=83=E6=95=B4=EF=BC=88=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E4=B8=8D=E4=BC=A0=E6=95=B0=E6=8D=AE=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh-CN/components/crud.md | 373 +++++ docs/zh-CN/components/form/index.md | 54 +- docs/zh-CN/components/page.md | 64 +- docs/zh-CN/components/service.md | 37 +- docs/zh-CN/concepts/event-action.md | 316 +++- packages/amis-core/src/actions/Action.ts | 2 +- .../__snapshots__/crud.test.tsx.snap | 1456 +++++++++++++++++ .../__snapshots__/page.test.tsx.snap | 634 +++++++ .../__snapshots__/service.test.tsx.snap | 1380 ++++++++++++++++ .../event-action/renderers/crud.test.tsx | 578 +++++++ .../form/__snapshots__/form.test.tsx.snap | 812 +++++++++ .../event-action/renderers/form/form.test.tsx | 101 ++ .../event-action/renderers/page.test.tsx | 285 ++++ .../event-action/renderers/service.test.tsx | 515 ++++++ 14 files changed, 6545 insertions(+), 62 deletions(-) create mode 100644 packages/amis/__tests__/event-action/renderers/__snapshots__/crud.test.tsx.snap create mode 100644 packages/amis/__tests__/event-action/renderers/__snapshots__/page.test.tsx.snap create mode 100644 packages/amis/__tests__/event-action/renderers/__snapshots__/service.test.tsx.snap create mode 100644 packages/amis/__tests__/event-action/renderers/crud.test.tsx create mode 100644 packages/amis/__tests__/event-action/renderers/page.test.tsx create mode 100644 packages/amis/__tests__/event-action/renderers/service.test.tsx diff --git a/docs/zh-CN/components/crud.md b/docs/zh-CN/components/crud.md index 8a8361e17..599e387df 100755 --- a/docs/zh-CN/components/crud.md +++ b/docs/zh-CN/components/crud.md @@ -3884,6 +3884,7 @@ itemAction 里的 onClick 还能通过 `data` 参数拿到当前行的数据, | 动作名称 | 动作配置 | 说明 | | -------- | --------------- | ------------ | +| reload | - | 刷新列表请求 | | setValue | `value: object` | 更新列表记录 | value 结构说明: @@ -3893,6 +3894,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 #### 更新列表记录 diff --git a/docs/zh-CN/components/form/index.md b/docs/zh-CN/components/form/index.md index 1c4d3448a..35cc6a4fa 100755 --- a/docs/zh-CN/components/form/index.md +++ b/docs/zh-CN/components/form/index.md @@ -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`将表单数据重置为初始数据,初始数据可以是静态数据或初始化接口返回的数据。 diff --git a/docs/zh-CN/components/page.md b/docs/zh-CN/components/page.md index 79c2f3ea9..64343bc1e 100755 --- a/docs/zh-CN/components/page.md +++ b/docs/zh-CN/components/page.md @@ -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}" } ] } diff --git a/docs/zh-CN/components/service.md b/docs/zh-CN/components/service.md index c9d792533..550f20924 100755 --- a/docs/zh-CN/components/service.md +++ b/docs/zh-CN/components/service.md @@ -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。 diff --git a/docs/zh-CN/concepts/event-action.md b/docs/zh-CN/concepts/event-action.md index d330717a0..7e375e9f1 100644 --- a/docs/zh-CN/concepts/event-action.md +++ b/docs/zh-CN/concepts/event-action.md @@ -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 及以上版本 diff --git a/packages/amis-core/src/actions/Action.ts b/packages/amis-core/src/actions/Action.ts index c4b4fcbd6..f90a336eb 100644 --- a/packages/amis-core/src/actions/Action.ts +++ b/packages/amis-core/src/actions/Action.ts @@ -285,7 +285,7 @@ export const runAction = async ( { ...actionConfig, args, - data, + data: actionConfig.actionType === 'reload' ? actionData : data, // 如果是刷新动作,则只传action.data ...key }, renderer, diff --git a/packages/amis/__tests__/event-action/renderers/__snapshots__/crud.test.tsx.snap b/packages/amis/__tests__/event-action/renderers/__snapshots__/crud.test.tsx.snap new file mode 100644 index 000000000..283c04d8c --- /dev/null +++ b/packages/amis/__tests__/event-action/renderers/__snapshots__/crud.test.tsx.snap @@ -0,0 +1,1456 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`doAction:crud reload 1`] = ` +
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + +
+
+ + + ID + + +
+
+
+
+ + + Rendering engine + + +
+
+
+
+ + + Browser + + +
+
+
+
+ + + Platform(s) + + +
+
+
+
+ + + Engine version + + +
+
+
+
+ + + CSS grade + + +
+
+
+
+ + + 操作 + + +
+
+
+ +
+
+`; + +exports[`doAction:crud reload with data1 1`] = ` +
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + +
+
+ + + ID + + +
+
+
+
+ + + Rendering engine + + +
+
+
+
+ + + Browser + + +
+
+
+
+ + + Platform(s) + + +
+
+
+
+ + + Engine version + + +
+
+
+
+ + + CSS grade + + +
+
+
+
+ + + 操作 + + +
+
+
+ +
+
+`; + +exports[`doAction:crud reload with data2 1`] = ` +
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+
+
+ + + + + + + + + + + + + + + +
+
+ + + ID + + +
+
+
+
+ + + Rendering engine + + +
+
+
+
+ + + Browser + + +
+
+
+
+ + + Platform(s) + + +
+
+
+
+ + + Engine version + + +
+
+
+
+ + + CSS grade + + +
+
+
+
+ + + 操作 + + +
+
+
+ +
+
+`; diff --git a/packages/amis/__tests__/event-action/renderers/__snapshots__/page.test.tsx.snap b/packages/amis/__tests__/event-action/renderers/__snapshots__/page.test.tsx.snap new file mode 100644 index 000000000..c957494cd --- /dev/null +++ b/packages/amis/__tests__/event-action/renderers/__snapshots__/page.test.tsx.snap @@ -0,0 +1,634 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`doAction:page reload 1`] = ` +
+
+
+
+
+ +
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+`; + +exports[`doAction:page reload 2`] = ` +
+
+
+
+
+
+
+
+
+ +
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+`; + +exports[`doAction:page reload with data 1`] = ` +
+
+
+
+
+ +
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+`; + +exports[`doAction:page reload with data 2`] = ` +
+
+
+
+
+
+
+
+
+ +
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+`; + +exports[`doAction:page reload with data(same name) 1`] = ` +
+
+
+
+
+ +
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+`; + +exports[`doAction:page reload with data(same name) 2`] = ` +
+
+
+
+
+
+
+
+
+ +
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+`; diff --git a/packages/amis/__tests__/event-action/renderers/__snapshots__/service.test.tsx.snap b/packages/amis/__tests__/event-action/renderers/__snapshots__/service.test.tsx.snap new file mode 100644 index 000000000..c063ae5e9 --- /dev/null +++ b/packages/amis/__tests__/event-action/renderers/__snapshots__/service.test.tsx.snap @@ -0,0 +1,1380 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`doAction:service reload 1`] = ` +
+
+
+
+
+
+
+

+ + + 表单 + + +

+
+
+
+ +
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+ +
+
+ +
+
+
+`; + +exports[`doAction:service reload 2`] = ` +
+
+
+
+
+
+
+

+ + + 表单 + + +

+
+
+
+ +
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+ +
+
+ +
+`; + +exports[`doAction:service reload with data 1`] = ` +
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+`; + +exports[`doAction:service reload with data 2`] = ` +
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`doAction:service(schemaApi) reload 1`] = ` +
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+`; + +exports[`doAction:service(schemaApi) reload 2`] = ` +
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`doAction:service(schemaApi) reload with data 1`] = ` +
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+`; + +exports[`doAction:service(schemaApi) reload with data 2`] = ` +
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`doAction:service(schemaApi+data) reload with data 1`] = ` +
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+`; + +exports[`doAction:service(schemaApi+data) reload with data 2`] = ` +
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+`; diff --git a/packages/amis/__tests__/event-action/renderers/crud.test.tsx b/packages/amis/__tests__/event-action/renderers/crud.test.tsx new file mode 100644 index 000000000..fbd84f63e --- /dev/null +++ b/packages/amis/__tests__/event-action/renderers/crud.test.tsx @@ -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(); +}); diff --git a/packages/amis/__tests__/event-action/renderers/form/__snapshots__/form.test.tsx.snap b/packages/amis/__tests__/event-action/renderers/form/__snapshots__/form.test.tsx.snap index 885454616..63df235e2 100644 --- a/packages/amis/__tests__/event-action/renderers/form/__snapshots__/form.test.tsx.snap +++ b/packages/amis/__tests__/event-action/renderers/form/__snapshots__/form.test.tsx.snap @@ -939,6 +939,818 @@ exports[`doAction:form reload 2`] = `
`; +exports[`doAction:form reload with data 1`] = ` +
+
+
+
+
+ +
+
+

+ + + 表单 + + +

+
+
+
+ +
+
+
+
+
+ + +
+ + + + + +
+ + + { + + +
+ + + } + + + +
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+ +
+
+ +
+ +
+
+
+`; + +exports[`doAction:form reload with data 2`] = ` +
+
+
+
+
+ +
+
+

+ + + 表单 + + +

+
+
+
+ +
+
+
+
+
+ + +
+ + + + + +
+ + + { + + + +
+
+
+
+ + + + " + + + name + + + " + + + + : + + +
+
+ + " + Amis Renderer + " + +
+
+
+
+ + + + " + + + author + + + " + + + + : + + +
+
+ + " + fex + " + +
+
+
+
+ + + + " + + + date + + + " + + + + : + + +
+
+ 1688714086 +
+
+
+
+ + + + " + + + age + + + " + + + + : + + +
+
+ 18 +
+
+
+
+
+ + + } + + +
+
+
+
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+ +
+
+ +
+ +
+
+
+`; + exports[`doAction:form reset 1`] = `
{ 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(() => diff --git a/packages/amis/__tests__/event-action/renderers/page.test.tsx b/packages/amis/__tests__/event-action/renderers/page.test.tsx new file mode 100644 index 000000000..02f4714e7 --- /dev/null +++ b/packages/amis/__tests__/event-action/renderers/page.test.tsx @@ -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(); +}); diff --git a/packages/amis/__tests__/event-action/renderers/service.test.tsx b/packages/amis/__tests__/event-action/renderers/service.test.tsx new file mode 100644 index 000000000..672adaa9b --- /dev/null +++ b/packages/amis/__tests__/event-action/renderers/service.test.tsx @@ -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(); +});