Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5,518 changes: 2,096 additions & 3,422 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions react/.env.mock
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
FRONT_MOCK_ENABLE=true
1 change: 1 addition & 0 deletions react/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ dist-ssr
*.local
coverage/
junit-report.xml
test-reports/

# Editor directories and files
.vscode/*
Expand Down
45 changes: 45 additions & 0 deletions react/mrc.e2e.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright The Microcks Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { CoverageReportOptions } from 'monocart-coverage-reports';

export const coverageOptions: CoverageReportOptions = {
enabled: process.env.CI ?? process.env.ENABLED_COVERAGE,
name: 'Playwright Coverage Report',
outputDir: './test-reports/e2e/coverage',
baseDir: './src/',
reports: [
'text',
'text-summary',
['html', { subdir: 'html-coverage' }],
['lcovonly', { file: 'lcov-coverage.info' }],
['cobertura', { file: 'cobertura-coverage.xml' }],
],
sourceFilter: {
'**/node_modules/**': false,
'**/mocks/**': false,
'**/*.{test,spec,steps}.{js,jsx,ts,tsx}': false,
'vitest.setup.ts': false,
'**/*.{js,jsx,ts,tsx}': true,
},
watermarks: {
statements: [80, 90],
branches: [70, 80],
functions: [80, 90],
lines: [80, 90],
bytes: [80, 90],
},
};
20 changes: 16 additions & 4 deletions react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,17 @@
"lint:prettier": "prettier \"src/**/*.!(js|jsx|mjs|ts|tsx|scss|css)\" --check --ignore-unknown",
"lint:prettier:fix": "prettier \"src/**/*.!(js|jsx|mjs|ts|tsx|scss|css)\" --write --ignore-unknown",
"lint:tsc": "tsc --noEmit",
"test": "vitest run",
"test:watch": "vitest",
"test": "node scripts/test.js",
"test:unit": "vitest run",
"test:unit:watch": "vitest",
"test:e2e": "node scripts/playwright.js test",
"test:e2e:watch": "node scripts/playwright.js test --watch",
"test:e2e:ui": "node scripts/playwright.js test --ui",
"orval": "orval --config orval.config.ts",
"add-license-header": "node scripts/addLicenseHeader.js"
"add-license-header": "node scripts/addLicenseHeader.js",
"playwright:install": "playwright install",
"playwright:show-report": "playwright show-report",
"playwright:codegen": "playwright codegen"
},
"dependencies": {
"@pplancq/svg-react": "^2.0.2",
Expand All @@ -35,10 +42,13 @@
"tw-animate-css": "^1.2.8"
},
"devDependencies": {
"@msw/playwright": "^0.4.2",
"@playwright/test": "^1.57.0",
"@pplancq/eslint-config": "^4.2.0",
"@pplancq/prettier-config": "^1.2.6",
"@pplancq/stylelint-config": "^4.0.1",
"@rsbuild/core": "^1.3.22",
"@rsbuild/plugin-eslint": "^1.2.0",
"@rsbuild/plugin-react": "^1.3.2",
"@tailwindcss/postcss": "^4.1.10",
"@testing-library/jest-dom": "^6.6.3",
Expand All @@ -52,12 +62,14 @@
"concurrently": "^9.1.2",
"eslint": "^9.30.0",
"eslint-plugin-prettier": "^5.5.0",
"glob": "^11.0.3",
"jsdom": "^26.1.0",
"monocart-coverage-reports": "^2.12.9",
"msw": "^2.10.2",
"nodemon": "^3.1.11",
"orval": "^7.17.0",
"prettier": "^3.5.3",
"stylelint-prettier": "^5.0.3",
"stylelint-webpack-plugin": "^5.0.1",
"typescript": "~5.7.2",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.2.4"
Expand Down
60 changes: 60 additions & 0 deletions react/playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright The Microcks Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { defineConfig, devices } from '@playwright/test';

const appUrl = 'http://localhost:3000';

export default defineConfig({
testDir: 'tests',
outputDir: './test-reports/e2e/test-results',
fullyParallel: true,
forbidOnly: Boolean(process.env.CI),
retries: process.env.CI ? 2 : undefined,
workers: process.env.CI ? 1 : undefined,
reporter: [
['list'],
['html', { open: 'never', outputFolder: 'test-reports/e2e/html-report' }],
['junit', { outputFile: 'test-reports/e2e/junit-report.xml' }],
],
globalSetup: 'tests/utils/playwright.globalSetup.ts',
globalTeardown: 'tests/utils/playwright.globalTeardown.ts',
use: {
baseURL: appUrl,
trace: 'retain-on-failure',
screenshot: 'only-on-failure',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'firefox',
use: { ...devices['Firefox Desktop'] },
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
],
webServer: {
command: 'npm run build -- --env-mode test && npm run preview',
url: appUrl,
stdout: 'pipe',
reuseExistingServer: !process.env.CI,
},
});
95 changes: 72 additions & 23 deletions react/rsbuild.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,32 +14,81 @@
* limitations under the License.
*/

import { defineConfig } from '@rsbuild/core';
import { defineConfig, loadEnv } from '@rsbuild/core';
import { pluginEslint } from '@rsbuild/plugin-eslint';
import { pluginReact } from '@rsbuild/plugin-react';
import StylelintPlugin from 'stylelint-webpack-plugin';
import packageJson from './package.json';

export default defineConfig({
plugins: [pluginReact()],
source: {
entry: {
index: 'src/main.ts',
const resolveModule = (module: string) => {
try {
require.resolve(module);
return true;
} catch {
return false;
}
};

const { publicVars } = loadEnv({ prefixes: [process.env.ENV_PREFIX ?? 'FRONT_'] });

const publicUrl = process.env.PUBLIC_URL ?? (packageJson as { homepage?: string }).homepage ?? '/';
const publicPath = new URL(publicUrl.endsWith('/') ? publicUrl : `${publicUrl}/`, 'http://localhost').pathname;
const disableSourceMap = (process.env.DISABLE_SOURCE_MAP ?? 'false') === 'true' ? false : 'source-map';
const disableStyleLintPlugin =
(process.env.DISABLE_STYLELINT_PLUGIN ?? 'false') === 'true' || !resolveModule('stylelint');

export default defineConfig(({ env }) => {
const isProduction = env === 'production';

return {
plugins: [
pluginReact(),
!isProduction &&
pluginEslint({
enable: (process.env.DISABLE_ESLINT_PLUGIN ?? 'false') === 'true' || !resolveModule('eslint'),
}),
].filter(Boolean),
source: {
entry: {
index: 'src/main.ts',
},
define: publicVars,
},
},
output: {
distPath: {
root: 'dist',
output: {
assetPrefix: publicPath,
sourceMap: {
js: isProduction ? disableSourceMap : 'cheap-module-source-map',
css: (process.env.DISABLE_SOURCE_MAP ?? 'false') !== 'true',
},
distPath: {
root: 'dist',
},
copy: [
{
from: 'public',
to: '.',
},
],
},
server: {
port: parseInt(process.env.PORT ?? '3000', 10),
open: (process.env.BROWSER ?? 'false') === 'true',
},
copy: [
{
from: 'public',
to: '.',
tools: {
rspack: {
plugins: [
!disableStyleLintPlugin &&
new StylelintPlugin({
extensions: ['css', 'scss', 'sass'],
stylelintPath: require.resolve('stylelint'),
failOnError: isProduction,
context: 'src',
}),
].filter(Boolean),
},
],
},
server: {
port: 3000,
open: false,
},
html: {
template: './index.html',
},
},
html: {
template: './index.html',
},
};
});
55 changes: 55 additions & 0 deletions react/scripts/playwright.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright The Microcks Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { spawnSync } from 'node:child_process';
import { platform } from 'node:process';

const runCommand = (cmd, args = []) => {
console.info(`> ${cmd} ${args.join(' ')}`);
const result = spawnSync(cmd, args, { cwd: process.cwd(), stdio: 'inherit', shell: platform === 'win32' });
if (result.status !== 0) {
throw result;
}
};

const main = async () => {
const args = process.argv.slice(2);

let playwrightArgs = [...args];

if (args.indexOf('--watch') !== -1) {
const filteredArgs = args.filter(a => a !== '--watch');
runCommand('npx', [
'nodemon',
'--watch',
'./tests/',
'--ext',
'js,jx,ts,tsx',
'--exec',
['node', 'scripts/playwright.js', ...filteredArgs].join(' '),
]);
return;
}

if (playwrightArgs.indexOf('--coverage') !== -1) {
process.env.ENABLED_COVERAGE = 'true';
playwrightArgs = playwrightArgs.filter(p => p !== '--coverage');
}

runCommand('npx', ['playwright', ...playwrightArgs]);
};

main().catch(e => process.exit(e.status));
36 changes: 36 additions & 0 deletions react/scripts/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright The Microcks Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// eslint-disable-next-line import/no-extraneous-dependencies
import concurrently from 'concurrently';

const args = process.argv.slice(2);

let commands = ['npm:test:unit', 'npm:test:e2e'];

if (args.includes('--coverage')) {
commands = commands.map(command => `${command} -- --coverage`);
}

const { result } = concurrently(commands, {
prefixColors: 'auto',
maxProcesses: 1,
});

result.then(
() => process.exit(0),
() => process.exit(1),
);
27 changes: 27 additions & 0 deletions react/tests/demo.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright The Microcks Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { expect } from '@playwright/test';
import { describe, it } from './fixture/playwright.fixture';

describe('Demo Test Suite', () => {
it('should load the homepage and check title', async ({ page }) => {
await page.goto('/');
const title = page.getByRole('heading', { name: 'Welcome to hub.microcks.io', level: 1 });

await expect(title).toBeVisible();
});
});
Loading