test(override-rules): add component tests for service id resolution

Attempt at testing components via cypress
This commit is contained in:
fallenbagel
2026-04-18 19:16:28 +08:00
parent aa15c3a3ea
commit 08bb6cdc00
9 changed files with 2492 additions and 18 deletions

View File

@@ -81,3 +81,46 @@ jobs:
# Fix test titles in cypress dashboard
COMMIT_INFO_MESSAGE: ${{github.event.pull_request.title}}
COMMIT_INFO_SHA: ${{github.event.pull_request.head.sha}}
cypress-component:
name: Cypress Component Tests
runs-on: ubuntu-24.04
steps:
- name: Checkout
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd
with:
persist-credentials: false
- name: Set up Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444
with:
node-version-file: package.json
package-manager-cache: false
- name: Pnpm Setup
uses: pnpm/action-setup@41ff72655975bd51cab0327fa583b6e92b6d3061
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Setup cypress cache
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
with:
path: ~/.cache/Cypress
key: ${{ runner.os }}-cypress-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-cypress-store-
- name: Install Cypress binary
env:
CYPRESS_CACHE_FOLDER: ~/.cache/Cypress
run: pnpm exec cypress install
- name: Cypress component run
uses: cypress-io/github-action@f790eee7a50d9505912f50c2095510be7de06aa7
with:
install: false
component: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CYPRESS_COMPONENT_BUILD: 1

View File

@@ -6,6 +6,14 @@ export default defineConfig({
baseUrl: 'http://localhost:5055',
video: true,
},
component: {
devServer: {
framework: 'next',
bundler: 'webpack',
},
supportFile: 'cypress/support/component.ts',
indexHtmlFile: 'cypress/support/component-index.html',
},
env: {
ADMIN_EMAIL: 'admin@seerr.dev',
ADMIN_PASSWORD: 'test1234',

View File

@@ -0,0 +1,135 @@
import OverrideRuleModal from '@app/components/Settings/OverrideRule/OverrideRuleModal';
import type OverrideRule from '@server/entity/OverrideRule';
import type { RadarrSettings, SonarrSettings } from '@server/lib/settings';
import { IntlProvider } from 'react-intl';
import { ToastProvider } from 'react-toast-notifications';
const Wrapper = ({ children }: { children: React.ReactNode }) => (
<IntlProvider locale="en">
<ToastProvider>{children}</ToastProvider>
</IntlProvider>
);
const mockTestResponse = {
profiles: [{ id: 1, name: 'HD-1080p' }],
rootFolders: [{ id: 1, path: '/movies' }],
tags: [],
};
describe('OverrideRuleModal', () => {
beforeEach(() => {
cy.intercept('POST', '/api/v1/settings/radarr/test', mockTestResponse).as(
'radarrTest'
);
cy.intercept('POST', '/api/v1/settings/sonarr/test', mockTestResponse).as(
'sonarrTest'
);
cy.intercept('GET', '/api/v1/settings/main', { originalLanguage: 'en' });
});
it('enables dropdowns when radarrServiceId does not match array index', () => {
const radarrServices = [
{
id: 3,
name: 'Radarr',
hostname: 'localhost',
port: 7878,
apiKey: 'test',
},
] as RadarrSettings[];
const rule = {
radarrServiceId: 3,
} as Partial<OverrideRule> as OverrideRule;
cy.mount(
<Wrapper>
<OverrideRuleModal
rule={rule}
radarrServices={radarrServices}
sonarrServices={[]}
onClose={() => {}}
/>
</Wrapper>
);
cy.wait('@radarrTest');
cy.get('#rootFolderRule').should('not.be.disabled');
cy.get('#profileIdRule').should('not.be.disabled');
});
it('enables dropdowns when sonarrServiceId does not match array index', () => {
const sonarrServices = [
{
id: 5,
name: 'Sonarr',
hostname: 'localhost',
port: 8989,
apiKey: 'test',
},
] as SonarrSettings[];
const rule = {
sonarrServiceId: 5,
} as Partial<OverrideRule> as OverrideRule;
cy.mount(
<Wrapper>
<OverrideRuleModal
rule={rule}
radarrServices={[]}
sonarrServices={sonarrServices}
onClose={() => {}}
/>
</Wrapper>
);
cy.wait('@sonarrTest');
cy.get('#rootFolderRule').should('not.be.disabled');
cy.get('#profileIdRule').should('not.be.disabled');
});
it('populates root folder and quality profile options after service resolves', () => {
const radarrServices = [
{
id: 3,
name: 'Radarr',
hostname: 'localhost',
port: 7878,
apiKey: 'test',
},
] as RadarrSettings[];
const rule = {
radarrServiceId: 3,
} as Partial<OverrideRule> as OverrideRule;
cy.mount(
<Wrapper>
<OverrideRuleModal
rule={rule}
radarrServices={radarrServices}
sonarrServices={[]}
onClose={() => {}}
/>
</Wrapper>
);
cy.wait('@radarrTest');
cy.get('#rootFolderRule').should('contain', '/movies');
cy.get('#profileIdRule').should('contain', 'HD-1080p');
});
it('keeps dropdowns disabled when no service is selected', () => {
cy.mount(
<Wrapper>
<OverrideRuleModal
rule={null}
radarrServices={[]}
sonarrServices={[]}
onClose={() => {}}
/>
</Wrapper>
);
cy.get('#rootFolderRule').should('be.disabled');
cy.get('#profileIdRule').should('be.disabled');
});
});

View File

@@ -0,0 +1,12 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Component Testing</title>
</head>
<body>
<div data-cy-root></div>
</body>
</html>

View File

@@ -0,0 +1,13 @@
/* eslint-disable @typescript-eslint/no-namespace */
import { mount } from '@cypress/react';
declare global {
namespace Cypress {
interface Chainable {
mount: typeof mount;
}
}
}
Cypress.Commands.add('mount', mount);

View File

@@ -1,4 +1,5 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"target": "es5",
"lib": ["es5", "dom"],
@@ -6,5 +7,5 @@
"resolveJsonModule": true,
"esModuleInterop": true
},
"include": ["**/*.ts"]
"include": ["**/*.ts", "**/*.tsx"]
}

View File

@@ -20,6 +20,13 @@ module.exports = {
use: ['@svgr/webpack'],
});
if (process.env.CYPRESS_COMPONENT_BUILD) {
config.resolve.alias = {
...config.resolve.alias,
'country-flag-icons/3x2/flags.css': false,
};
}
return config;
},
experimental: {

View File

@@ -119,6 +119,8 @@
"devDependencies": {
"@commitlint/cli": "17.4.4",
"@commitlint/config-conventional": "17.4.4",
"@cypress/react": "^9.0.2",
"@cypress/webpack-dev-server": "^4.1.1",
"@eslint/js": "9.39.3",
"@next/eslint-plugin-next": "^16.1.6",
"@tailwindcss/aspect-ratio": "^0.4.2",
@@ -170,6 +172,7 @@
"jiti": "^2.6.1",
"lint-staged": "13.1.2",
"nodemon": "3.1.11",
"null-loader": "^4.0.1",
"postcss": "^8.5.6",
"prettier": "3.8.1",
"prettier-plugin-organize-imports": "4.3.0",

2286
pnpm-lock.yaml generated
View File

File diff suppressed because it is too large Load Diff