Skip to content

Commit 665ad24

Browse files
authored
fix: e2e related tsconfig and eslint config (#3057)
1 parent c8c809c commit 665ad24

File tree

7 files changed

+192
-125
lines changed

7 files changed

+192
-125
lines changed

e2e/auth.spec.ts renamed to e2e/tests/auth.spec.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,9 @@
1515
* limitations under the License.
1616
*/
1717

18+
import { getAPISIXConf } from '@e2e/utils/common';
19+
import { test } from '@e2e/utils/test';
1820
import { expect } from '@playwright/test';
19-
import { test } from '@utils/test';
20-
21-
import { getAPISIXConf } from './utils/common';
2221

2322
// use empty storage state to avoid auth
2423
test.use({ storageState: { cookies: [], origins: [] } });

tsconfig.e2e.json renamed to e2e/tsconfig.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,17 @@
1515
"esModuleInterop": true,
1616
"skipLibCheck": true,
1717
"noImplicitAny": false,
18+
"verbatimModuleSyntax": true,
1819
"paths": {
19-
"@utils/*": [
20-
"./e2e/utils/*"
20+
"@e2e/*": [
21+
"./*"
22+
],
23+
"@/*": [
24+
"../src/*"
2125
]
2226
}
2327
},
2428
"include": [
25-
"e2e/**/*.ts",
29+
"./**/*.ts",
2630
]
2731
}

e2e/utils/req.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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+
import { type APIRequestContext, request } from '@playwright/test';
18+
import axios, { type AxiosAdapter } from 'axios';
19+
import { stringify } from 'qs';
20+
21+
import { API_HEADER_KEY, API_PREFIX, BASE_PATH } from '@/config/constant';
22+
23+
import { getAPISIXConf } from './common';
24+
import { env } from './env';
25+
26+
export const getPlaywrightRequestAdapter = (
27+
ctx: APIRequestContext
28+
): AxiosAdapter => {
29+
return async (config) => {
30+
const { url, data, baseURL } = config;
31+
if (typeof url === 'undefined') {
32+
throw new Error('Need to provide a url');
33+
}
34+
35+
type Payload = Parameters<APIRequestContext['fetch']>[1];
36+
const payload: Payload = {
37+
headers: config.headers,
38+
method: config.method,
39+
failOnStatusCode: true,
40+
data,
41+
};
42+
const urlWithBase = `${baseURL}${url}`;
43+
const res = await ctx.fetch(urlWithBase, payload);
44+
45+
try {
46+
return {
47+
...res,
48+
data: await res.json(),
49+
config,
50+
status: res.status(),
51+
statusText: res.statusText(),
52+
headers: res.headers(),
53+
};
54+
} finally {
55+
await res.dispose();
56+
}
57+
};
58+
};
59+
60+
export const getE2eReq = async (ctx: APIRequestContext) => {
61+
const { adminKey } = await getAPISIXConf();
62+
const API_URL = env.E2E_TARGET_URL.slice(0, -BASE_PATH.length - 1);
63+
64+
return axios.create({
65+
adapter: getPlaywrightRequestAdapter(ctx),
66+
baseURL: `${API_URL}${API_PREFIX}`,
67+
paramsSerializer: (p) =>
68+
stringify(p, {
69+
arrayFormat: 'repeat',
70+
}),
71+
headers: { [API_HEADER_KEY]: adminKey },
72+
});
73+
};
74+
75+
export const e2eReq = await getE2eReq(await request.newContext());

e2e/utils/test.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17+
import { existsSync } from 'node:fs';
18+
import path from 'node:path';
19+
1720
import { test as baseTest } from '@playwright/test';
21+
1822
import { getAPISIXConf } from './common';
19-
import path from 'node:path';
20-
import { existsSync } from 'node:fs';
2123
import { env } from './env';
2224

23-
export const test = baseTest.extend<{}, { workerStorageState: string }>({
25+
export const test = baseTest.extend<object, { workerStorageState: string }>({
2426
storageState: ({ workerStorageState }, use) => use(workerStorageState),
2527
workerStorageState: [
2628
async ({ browser }, use) => {
@@ -54,7 +56,6 @@ export const test = baseTest.extend<{}, { workerStorageState: string }>({
5456
.click();
5557

5658
await page.reload();
57-
await page.waitForLoadState('networkidle');
5859
}
5960

6061
await page.context().storageState({ path: fileName });

eslint.config.ts

Lines changed: 103 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -32,18 +32,20 @@ const importRules = tseslint.config({
3232
plugins: {
3333
'unused-imports': unusedImports,
3434
'simple-import-sort': simpleImportSort,
35-
'import': importPlugin,
35+
import: importPlugin,
3636
},
3737
rules: {
38+
...importPlugin.flatConfigs?.recommended.rules,
39+
...importPlugin.flatConfigs?.typescript.rules,
3840
'no-unused-vars': 'off',
3941
'unused-imports/no-unused-imports': 'error',
4042
'unused-imports/no-unused-vars': [
4143
'warn',
4244
{
43-
'vars': 'all',
44-
'varsIgnorePattern': '^_',
45-
'args': 'after-used',
46-
'argsIgnorePattern': '^_',
45+
vars: 'all',
46+
varsIgnorePattern: '^_',
47+
args: 'after-used',
48+
argsIgnorePattern: '^_',
4749
},
4850
],
4951
'simple-import-sort/imports': 'error',
@@ -53,18 +55,48 @@ const importRules = tseslint.config({
5355
'import/no-duplicates': 'error',
5456
'import/no-unresolved': 'off',
5557
'import/no-named-as-default-member': 'off',
56-
}
57-
})
58+
},
59+
});
5860

59-
const e2eRules = tseslint.config({
60-
extends: [importRules],
61-
...playwright.configs['flat/recommended'],
62-
files: ['e2e/**/*.spec.ts'],
61+
const commonRules = tseslint.config({
62+
extends: [
63+
js.configs.recommended,
64+
...tseslint.configs.recommended,
65+
importRules,
66+
],
67+
plugins: {
68+
headers: headers,
69+
},
6370
rules: {
64-
...playwright.configs['flat/recommended'].rules,
71+
'headers/header-format': [
72+
'error',
73+
{
74+
source: 'file',
75+
path: '.actions/ASFLicenseHeader.txt',
76+
},
77+
],
78+
quotes: [
79+
'error',
80+
'single',
81+
{
82+
avoidEscape: true,
83+
allowTemplateLiterals: false,
84+
},
85+
],
6586
},
6687
});
6788

89+
const e2eRules = tseslint.config(
90+
{
91+
extends: [commonRules],
92+
files: ['e2e/**/*.ts'],
93+
},
94+
{
95+
files: ['e2e/**/*.spec.ts'],
96+
...playwright.configs['flat/recommended'],
97+
}
98+
);
99+
68100
const i18nRules = tseslint.config({
69101
files: ['src/**/*.{ts,tsx,js}'],
70102
plugins: {
@@ -74,10 +106,7 @@ const i18nRules = tseslint.config({
74106
rules: {
75107
...i18next.configs['flat/recommended'].rules,
76108
'i18n/no-unknown-key': 'error',
77-
'i18n/no-text-as-children': [
78-
'error',
79-
{ ignorePattern: '^\\s?[/.]\\s?$' },
80-
],
109+
'i18n/no-text-as-children': ['error', { ignorePattern: '^\\s?[/.]\\s?$' }],
81110
'i18n/no-text-as-attribute': ['error', { attributes: ['alt', 'title'] }],
82111
'i18n/interpolation-data': [
83112
'error',
@@ -95,104 +124,67 @@ const i18nRules = tseslint.config({
95124
functionName: 't',
96125
},
97126
},
98-
})
127+
});
128+
129+
const srcRules = tseslint.config({
130+
extends: [commonRules],
131+
files: ['src/**/*.{ts,tsx}', 'eslint.config.ts'],
132+
languageOptions: {
133+
ecmaVersion: 2020,
134+
globals: globals.browser,
135+
sourceType: 'module',
136+
},
137+
plugins: {
138+
'react-hooks': reactHooks,
139+
'react-refresh': reactRefresh,
140+
react: react,
141+
},
142+
settings: {
143+
react: {
144+
version: 'detect',
145+
},
146+
},
147+
rules: {
148+
...react.configs.flat.recommended.rules,
149+
...react.configs.flat['jsx-runtime'].rules,
150+
...reactHooks.configs.recommended.rules,
151+
'no-console': 'warn',
152+
'react-refresh/only-export-components': [
153+
'warn',
154+
{ allowConstantExport: true },
155+
],
156+
'react/jsx-curly-brace-presence': [
157+
'error',
158+
{
159+
props: 'never',
160+
children: 'never',
161+
},
162+
],
163+
'react/no-unescaped-entities': [
164+
'error',
165+
{
166+
forbid: ['>', '}'],
167+
},
168+
],
169+
'react/no-children-prop': [
170+
'error',
171+
{
172+
allowFunctions: true,
173+
},
174+
],
175+
'react/self-closing-comp': [
176+
'error',
177+
{
178+
component: true,
179+
html: true,
180+
},
181+
],
182+
},
183+
});
99184

100185
export default tseslint.config(
101186
{ ignores: ['dist', 'src/routeTree.gen.ts'] },
102187
e2eRules,
103188
i18nRules,
104-
{
105-
extends: [js.configs.recommended, ...tseslint.configs.recommended, importRules],
106-
files: ['src/**/*.{ts,tsx}', 'eslint.config.ts'],
107-
languageOptions: {
108-
ecmaVersion: 2020,
109-
globals: globals.browser,
110-
sourceType: 'module',
111-
},
112-
plugins: {
113-
'react-hooks': reactHooks,
114-
'react-refresh': reactRefresh,
115-
react: react,
116-
'unused-imports': unusedImports,
117-
'simple-import-sort': simpleImportSort,
118-
import: importPlugin,
119-
headers: headers,
120-
},
121-
settings: {
122-
react: {
123-
version: 'detect',
124-
},
125-
},
126-
rules: {
127-
...react.configs.flat.recommended.rules,
128-
...react.configs.flat['jsx-runtime'].rules,
129-
...reactHooks.configs.recommended.rules,
130-
...importPlugin.flatConfigs?.recommended.rules,
131-
...importPlugin.flatConfigs?.typescript.rules,
132-
'no-console': 'warn',
133-
'no-unused-vars': 'off',
134-
'unused-imports/no-unused-imports': 'error',
135-
'unused-imports/no-unused-vars': [
136-
'warn',
137-
{
138-
vars: 'all',
139-
varsIgnorePattern: '^_',
140-
args: 'after-used',
141-
argsIgnorePattern: '^_',
142-
},
143-
],
144-
'simple-import-sort/imports': 'error',
145-
'simple-import-sort/exports': 'error',
146-
'import/first': 'error',
147-
'import/newline-after-import': 'error',
148-
'import/no-duplicates': 'error',
149-
'import/no-unresolved': 'off',
150-
'import/no-named-as-default-member': 'off',
151-
'react-refresh/only-export-components': [
152-
'warn',
153-
{ allowConstantExport: true },
154-
],
155-
'react/jsx-curly-brace-presence': [
156-
'error',
157-
{
158-
props: 'never',
159-
children: 'never',
160-
},
161-
],
162-
'react/no-unescaped-entities': [
163-
'error',
164-
{
165-
forbid: ['>', '}'],
166-
},
167-
],
168-
'react/no-children-prop': [
169-
'error',
170-
{
171-
allowFunctions: true,
172-
},
173-
],
174-
'react/self-closing-comp': [
175-
'error',
176-
{
177-
component: true,
178-
html: true,
179-
},
180-
],
181-
'headers/header-format': [
182-
'error',
183-
{
184-
source: 'file',
185-
path: '.actions/ASFLicenseHeader.txt',
186-
},
187-
],
188-
'quotes': [
189-
'error',
190-
'single',
191-
{
192-
'avoidEscape': true,
193-
'allowTemplateLiterals': false
194-
}
195-
],
196-
},
197-
}
189+
srcRules
198190
);

0 commit comments

Comments
 (0)