Skip to content

Commit fd5afe4

Browse files
authored
feat(plugin): allowing basic-auth to dynamically adapt to the BE rules (#2086)
1 parent 0972f16 commit fd5afe4

File tree

4 files changed

+135
-5
lines changed

4 files changed

+135
-5
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
/* eslint-disable no-undef */
18+
19+
context('Create and delete consumer with basic-auth plugin form', () => {
20+
const selector = {
21+
empty: '.ant-empty-normal',
22+
username: '#username',
23+
password: '#password',
24+
description: '#desc',
25+
pluginCard: '.ant-card',
26+
drawer: '.ant-drawer-content',
27+
disabledSwitcher: '#disable',
28+
notification: '.ant-notification-notice-message',
29+
notificationCloseIcon: '.ant-notification-close-icon',
30+
monacoViewZones: '.view-zones',
31+
alert: '.ant-form-item-explain-error [role=alert]'
32+
};
33+
34+
const data = {
35+
consumerName: 'test_consumer',
36+
description: 'desc_by_autotest',
37+
createConsumerSuccess: 'Create Consumer Successfully',
38+
deleteConsumerSuccess: 'Delete Consumer Successfully',
39+
username: 'root',
40+
password: '1234',
41+
};
42+
43+
beforeEach(() => {
44+
cy.login();
45+
});
46+
47+
it('creates consumer with basic-auth form', function () {
48+
cy.visit('/');
49+
cy.contains('Consumer').click();
50+
cy.get(selector.empty).should('be.visible');
51+
cy.contains('Create').click();
52+
// basic information
53+
cy.get(selector.username).type(data.consumerName);
54+
cy.get(selector.description).type(data.description);
55+
cy.contains('Next').click();
56+
57+
// config auth plugin
58+
cy.contains(selector.pluginCard, 'key-auth').within(() => {
59+
cy.contains('Enable').click({
60+
force: true,
61+
});
62+
});
63+
cy.focused(selector.drawer).should('exist');
64+
cy.get(selector.monacoViewZones).should('exist');
65+
cy.get(selector.disabledSwitcher).click();
66+
67+
// edit monaco
68+
cy.window().then((window) => {
69+
window.monacoEditor.setValue(JSON.stringify({ key: 'test' }));
70+
cy.contains('button', 'Submit').click();
71+
});
72+
73+
cy.contains(selector.pluginCard, 'basic-auth').within(() => {
74+
cy.contains('Enable').click({
75+
force: true,
76+
});
77+
});
78+
79+
cy.focused(selector.drawer).should('exist');
80+
81+
// config basic-auth form without username and password
82+
cy.get(selector.username).click();
83+
cy.get(selector.alert).contains('Please enter username');
84+
cy.get(selector.password).click();
85+
cy.get(selector.alert).contains('Please enter password');
86+
cy.get(selector.drawer).within(() => {
87+
cy.contains('Submit').click({
88+
force: true,
89+
});
90+
});
91+
cy.get(selector.notification).should('contain', 'Invalid plugin data');
92+
cy.get(selector.notificationCloseIcon).click();
93+
94+
// config basic-auth form with username and password
95+
cy.get(selector.username).type(data.username);
96+
cy.get(selector.password).type(data.password);
97+
cy.get(selector.alert).should('not.exist');
98+
cy.get(selector.disabledSwitcher).click();
99+
cy.get(selector.drawer).within(() => {
100+
cy.contains('Submit').click({
101+
force: true,
102+
});
103+
});
104+
cy.get(selector.drawer).should('not.exist');
105+
106+
cy.contains('button', 'Next').click();
107+
cy.contains('button', 'Submit').click();
108+
cy.get(selector.notification).should('contain', data.createConsumerSuccess);
109+
});
110+
111+
it('delete the consumer', function () {
112+
cy.visit('/consumer/list');
113+
cy.contains(data.consumerName).should('be.visible').siblings().contains('Delete').click();
114+
cy.contains('button', 'Confirm').click();
115+
cy.get(selector.notification).should('contain', data.deleteConsumerSuccess);
116+
});
117+
});

web/src/components/Plugin/PluginDetail.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,8 @@ const PluginDetail: React.FC<Props> = ({
107107
const [UIForm] = Form.useForm();
108108
const data = initialData[name] || {};
109109
const pluginType = pluginList.find((item) => item.name === name)?.originType;
110-
const pluginSchema = pluginList.find((item) => item.name === name)?.schema;
110+
const schemaName = name === 'basic-auth' ? 'consumer_schema' : 'schema';
111+
const pluginSchema = pluginList.find((item) => item.name === name)?.[schemaName];
111112
const [content, setContent] = useState<string>(JSON.stringify(data, null, 2));
112113
const [monacoMode, setMonacoMode] = useState<PluginComponent.MonacoLanguage>(monacoModeList.JSON);
113114
const modeOptions: { label: string; value: string }[] = [

web/src/components/Plugin/UI/basic-auth.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { Form, Input } from 'antd';
2020

2121
type Props = {
2222
form: FormInstance;
23+
schema: Record<string, any> | undefined;
2324
ref?: any;
2425
};
2526

@@ -32,13 +33,24 @@ export const FORM_ITEM_LAYOUT = {
3233
},
3334
};
3435

35-
const BasicAuth: React.FC<Props> = ({ form }) => {
36+
const BasicAuth: React.FC<Props> = ({ form, schema }) => {
37+
const required: string[] = schema?.required;
3638
return (
3739
<Form form={form} {...FORM_ITEM_LAYOUT}>
38-
<Form.Item label="username" name="username" required>
40+
<Form.Item
41+
label="username"
42+
name="username"
43+
rules={[{ required: required.indexOf('username') > -1 }]}
44+
validateTrigger={['onChange', 'onBlur', 'onClick']}
45+
>
3946
<Input></Input>
4047
</Form.Item>
41-
<Form.Item label="password" name="password" required>
48+
<Form.Item
49+
label="password"
50+
name="password"
51+
rules={[{ required: required.indexOf('password') > -1 }]}
52+
validateTrigger={['onChange', 'onBlur', 'onClick']}
53+
>
4254
<Input></Input>
4355
</Form.Item>
4456
</Form>

web/src/components/Plugin/UI/plugin.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export const PluginForm: React.FC<Props> = ({ name, schema, renderForm, form })
6262
case 'api-breaker':
6363
return <ApiBreaker form={form} schema={schema} />
6464
case 'basic-auth':
65-
return <BasicAuth form={form} />;
65+
return <BasicAuth form={form} schema={schema} />;
6666
case 'limit-count':
6767
return <LimitCount form={form} schema={schema} />
6868
case 'cors':

0 commit comments

Comments
 (0)