mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-19 14:12:52 +00:00
# Which Problems Are Solved Replaces Turbo by Nx and lays the foundation for the next CI improvements. It enables using Nx Cloud to speed the up the pipelines that affect any node package. It streamlines the dev experience for frontend and backend developers by providing the following commands: | Task | Command | Notes | |------|---------|--------| | **Production** | `nx run PROJECT:prod` | Production server | | **Develop** | `nx run PROJECT:dev` | Hot reloading development server | | **Test** | `nx run PROJECT:test` | Run all tests | | **Lint** | `nx run PROJECT:lint` | Check code style | | **Lint Fix** | `nx run PROJECT:lint-fix` | Auto-fix style issues | The following values can be used for PROJECT: - @zitadel/zitadel (root commands) - @zitadel/api, - @zitadel/login, - @zitadel/console, - @zitadel/docs, - @zitadel/client - @zitadel/proto The project names and folders are streamlined: | Old Folder | New Folder | | --- | --- | | ./e2e | ./tests/functional-ui | | ./load-test | ./benchmark | | ./build/zitadel | ./apps/api | | ./console | ./apps/console (postponed so the PR is reviewable) | Also, all references to the TypeScript repo are removed so we can archive it. # How the Problems Are Solved - Ran `npx nx@latest init` - Replaced all turbo.json by project.json and fixed the target configs - Removed Turbo dependency - All JavaScript related code affected by a PRs changes is quality-checked using the `nx affected` command - We move PR checks that are runnable using Nx into the `check` workflow. For workflows where we don't use Nx, yet, we restore previously built dependency artifacts from Nx. - We only use a single and easy to understand dev container - The CONTRIBUTING.md is streamlined - The setup with a generated client pat is orchestrated with Nx - Everything related to the TypeScript repo is updated or removed. A **Deploy with Vercel** button is added to the docs and the CONTRIBUTING.md. # Additional Changes - NPM package names have a consistent pattern. - Docker bake is removed. The login container is built and released like the core container. - The integration tests build the login container before running, so they don't rely on the login container action anymore. This fixes consistently failing checks on PRs from forks. - The docs build in GitHub actions is removed, as we already build on Vercel. # Additional Context - Internal discussion: https://zitadel.slack.com/archives/C087ADF8LRX/p1756277884928169 - Workflow dispatch test: https://github.com/zitadel/zitadel/actions/runs/17760122959 --------- Co-authored-by: Florian Forster <[email protected]> Co-authored-by: Tim Möhlmann <[email protected]> Co-authored-by: Copilot <[email protected]>
171 lines
6.2 KiB
TypeScript
171 lines
6.2 KiB
TypeScript
import { apiAuth } from '../../support/api/apiauth';
|
|
import { resetInstanceFeatures } from '../../support/api/features';
|
|
import { login, User } from '../../support/login/users';
|
|
|
|
describe('features settings', () => {
|
|
const featuresPath = '/instance?id=features';
|
|
|
|
beforeEach(() => {
|
|
cy.context().as('ctx');
|
|
cy.visit(featuresPath);
|
|
});
|
|
|
|
describe('UI and Display Tests', () => {
|
|
it('should display features page with correct elements', () => {
|
|
// Check page title contains relevant text (flexible for translation issues)
|
|
cy.get('h2').should('be.visible').and('contain.text', 'Feature');
|
|
cy.get('.events-desc').should('be.visible');
|
|
|
|
// Check info link
|
|
cy.get('a[href*="feature-service"]').should('be.visible').and('have.attr', 'target', '_blank');
|
|
|
|
// Check reset button is always present
|
|
cy.get('[data-e2e="reset-features-button"]').should('be.visible');
|
|
});
|
|
|
|
it('should display feature toggles', () => {
|
|
cy.get('cnsl-card').should('be.visible');
|
|
cy.get('.features').should('be.visible');
|
|
|
|
// Check that feature toggles are present
|
|
cy.get('cnsl-feature-toggle').should('have.length.greaterThan', 0);
|
|
cy.get('cnsl-login-v2-feature-toggle').should('be.visible');
|
|
});
|
|
|
|
it('should maintain feature states after page reload', () => {
|
|
// Wait for features to load
|
|
cy.get('cnsl-feature-toggle').should('be.visible');
|
|
|
|
// Get the count of feature toggles before reload
|
|
cy.get('cnsl-feature-toggle').then(($toggles) => {
|
|
const initialCount = $toggles.length;
|
|
|
|
// Reload page
|
|
cy.reload();
|
|
|
|
// Wait for features to load again
|
|
cy.get('cnsl-feature-toggle').should('be.visible');
|
|
|
|
// Verify that the same number of toggles are still present
|
|
cy.get('cnsl-feature-toggle').should('have.length', initialCount);
|
|
|
|
// Verify that toggles are still functional
|
|
cy.get('cnsl-feature-toggle')
|
|
.first()
|
|
.within(() => {
|
|
cy.get('mat-button-toggle').should('be.visible');
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should handle API errors gracefully', () => {
|
|
// Intercept API calls and force them to fail
|
|
cy.intercept('POST', '**/features*', {
|
|
statusCode: 500,
|
|
body: { message: 'Internal server error' },
|
|
}).as('featureError');
|
|
|
|
// Try to toggle a feature
|
|
cy.get('cnsl-feature-toggle')
|
|
.first()
|
|
.within(() => {
|
|
cy.get('mat-button-toggle').first().click();
|
|
});
|
|
|
|
// Wait for the error response (optional since it might not always trigger)
|
|
cy.get('body').then(() => {
|
|
// Just verify that the page is still functional
|
|
cy.get('cnsl-feature-toggle').should('be.visible');
|
|
});
|
|
});
|
|
|
|
describe('permissions', () => {
|
|
it('should show appropriate elements for admin users', () => {
|
|
// Admin should see reset button
|
|
cy.get('[data-e2e="reset-features-button"]').should('be.visible');
|
|
|
|
// Admin should see all feature toggles
|
|
cy.get('cnsl-feature-toggle').should('have.length.greaterThan', 0);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Feature Modification Tests', () => {
|
|
afterEach(() => {
|
|
// Reset features after each feature modification test to ensure clean state
|
|
apiAuth().then((api) => {
|
|
resetInstanceFeatures(api);
|
|
});
|
|
});
|
|
|
|
it('should be able to toggle a feature', () => {
|
|
// Wait for features to load
|
|
cy.get('cnsl-feature-toggle').should('be.visible');
|
|
|
|
// Get the first feature toggle and check its initial state
|
|
cy.get('cnsl-feature-toggle')
|
|
.first()
|
|
.within(() => {
|
|
// Ensure we always trigger a state change by clicking an unchecked button
|
|
cy.get('mat-button-toggle').then(($allButtons) => {
|
|
const uncheckedButtons = $allButtons.not('.mat-button-toggle-checked');
|
|
|
|
if (uncheckedButtons.length > 0) {
|
|
// Click an unchecked button to enable it
|
|
const targetButton = uncheckedButtons.first();
|
|
cy.wrap(targetButton).click();
|
|
|
|
// Verify the toggle reflected the new state
|
|
cy.wrap(targetButton).should('have.class', 'mat-button-toggle-checked');
|
|
} else {
|
|
// All buttons are checked, click the first one to uncheck it
|
|
const targetButton = $allButtons.first();
|
|
cy.wrap(targetButton).click();
|
|
|
|
// Verify the toggle reflected the new state (should be unchecked now)
|
|
cy.wrap(targetButton).should('not.have.class', 'mat-button-toggle-checked');
|
|
}
|
|
});
|
|
});
|
|
// Check for success toast since we made a real change
|
|
cy.shouldConfirmSuccess();
|
|
});
|
|
|
|
it('should reset features when reset button is clicked', () => {
|
|
// Change a feature first to have something to reset
|
|
cy.get('cnsl-feature-toggle')
|
|
.first()
|
|
.within(() => {
|
|
// Check current state and click the opposite to ensure we trigger a change
|
|
cy.get('mat-button-toggle').then(($buttons) => {
|
|
const checkedButton = $buttons.filter('.mat-button-toggle-checked');
|
|
const uncheckedButtons = $buttons.not('.mat-button-toggle-checked');
|
|
|
|
if (uncheckedButtons.length > 0) {
|
|
// Click an unchecked button to enable it
|
|
cy.wrap(uncheckedButtons.first()).click();
|
|
// Verify the change was applied
|
|
cy.wrap(uncheckedButtons.first()).should('have.class', 'mat-button-toggle-checked');
|
|
} else {
|
|
// All buttons are checked, click the first one to uncheck it
|
|
cy.wrap(checkedButton.first()).click();
|
|
// Verify the change was applied
|
|
cy.wrap(checkedButton.first()).should('not.have.class', 'mat-button-toggle-checked');
|
|
}
|
|
});
|
|
});
|
|
// Check for success toast since we made a real change
|
|
cy.shouldConfirmSuccess();
|
|
|
|
// Click the reset button
|
|
cy.get('[data-e2e="reset-features-button"]').click();
|
|
|
|
// Check for success toast from reset operation
|
|
cy.shouldConfirmSuccess();
|
|
|
|
// Verify features are still loaded and functional after UI reset
|
|
cy.get('cnsl-feature-toggle').should('be.visible');
|
|
});
|
|
});
|
|
});
|