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
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ async function renderValidationEditor(
validation={validation}
generateValidationRules={() => {}}
isRulesGenerationInProgress={false}
isSavingInProgress={false}
isEditable
isEditingEnabled
{...props}
Expand All @@ -44,6 +45,8 @@ async function renderValidationEditor(
);
}

const updateValidationTestId = 'update-validation-button';

describe('ValidationEditor [Component]', function () {
context(
'when it is an editable mode but editing is not yet enabled',
Expand Down Expand Up @@ -173,10 +176,73 @@ describe('ValidationEditor [Component]', function () {
});
});

it('allows to generate rules', function () {
it('disables the ability to generate rules', function () {
const generateBtn = screen.getByTestId('generate-rules-button');
expect(generateBtn).to.be.visible;
expect(generateBtn).to.have.attribute('aria-disabled', 'true');
});
});

context('when the validator is not changed', function () {
beforeEach(async function () {
await renderValidationEditor({
validation: {
validator: '{}',
validationAction: 'error',
validationLevel: 'moderate',
isChanged: false,
syntaxError: null,
error: null,
},
});
});

it('does not allow applying the rules', function () {
const applyBtn = screen.queryByTestId(updateValidationTestId);
expect(applyBtn).to.not.exist;
});
});

context('when the validator is changed', function () {
beforeEach(async function () {
await renderValidationEditor({
validation: {
validator: '{}',
validationAction: 'error',
validationLevel: 'moderate',
isChanged: true,
syntaxError: null,
error: null,
},
});
});

it('allows to apply changes', function () {
const applyBtn = screen.getByTestId(updateValidationTestId);
expect(applyBtn).to.be.visible;
expect(applyBtn).to.have.attribute('aria-disabled', 'false');
});
});

context('when the validation saving is in progress', function () {
beforeEach(async function () {
await renderValidationEditor({
validation: {
validator: '{}',
validationAction: 'error',
validationLevel: 'moderate',
isChanged: true,
syntaxError: null,
error: null,
},
isSavingInProgress: true,
});
});

it('disables the apply button and shows a spin loader', function () {
const applyBtn = screen.queryByTestId(updateValidationTestId);
expect(applyBtn).to.be.visible;
expect(applyBtn).to.have.attribute('aria-disabled', 'true');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ type ValidationEditorProps = {
isEditable: boolean;
isEditingEnabled: boolean;
isRulesGenerationInProgress: boolean;
isSavingInProgress: boolean;
};

/**
Expand All @@ -171,6 +172,7 @@ export const ValidationEditor: React.FunctionComponent<
isEditable,
isEditingEnabled,
isRulesGenerationInProgress,
isSavingInProgress,
}) => {
const enableExportSchema = usePreference('enableExportSchema');
const track = useTelemetry();
Expand Down Expand Up @@ -343,6 +345,8 @@ export const ValidationEditor: React.FunctionComponent<
onClick={() => {
void onClickApplyValidation();
}}
isLoading={isSavingInProgress}
loadingIndicator={<SpinLoader title="Updating validation…" />}
disabled={!!syntaxError}
>
Apply
Expand Down Expand Up @@ -372,6 +376,7 @@ const mapStateToProps = (state: RootState) => ({
validation: state.validation,
namespace: state.namespace.ns,
isRulesGenerationInProgress: state.rulesGeneration.isInProgress,
isSavingInProgress: state.validation.isSaving,
});

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ describe('validation module', function () {
validationAction: 'error',
validationLevel: 'strict',
isChanged: false,
isSaving: false,
syntaxError: null,
error: null,
});
Expand Down Expand Up @@ -131,6 +132,7 @@ describe('validation module', function () {

expect(validation).to.deep.equal({
isChanged: false,
isSaving: false,
prevValidation: {
validator,
validationAction: 'warn',
Expand Down Expand Up @@ -159,6 +161,7 @@ describe('validation module', function () {
validationAction: 'error',
validationLevel: 'strict',
isChanged: false,
isSaving: false,
syntaxError: null,
error: {
message: 'Validation save failed!',
Expand Down
50 changes: 50 additions & 0 deletions packages/compass-schema-validation/src/modules/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export type ValidationLevel = 'off' | 'moderate' | 'strict';
export const enum ValidationActions {
ValidatorChanged = 'compass-schema-validation/validation/ValidatorChanged',
ValidationCanceled = 'compass-schema-validation/validation/ValidationCanceled',
ValidationSaveStarted = 'compass-schema-validation/validation/ValidationSaveStarted',
ValidationSaveEnded = 'compass-schema-validation/validation/ValidationSaveEnded',
ValidationSaveFailed = 'compass-schema-validation/validation/ValidationSaveFailed',
ValidationFetched = 'compass-schema-validation/validation/ValidationFetched',
EmptyValidationFetched = 'compass-schema-validation/validation/EmptyValidationFetched',
Expand All @@ -35,6 +37,14 @@ export interface ValidationCanceledAction {
type: ValidationActions.ValidationCanceled;
}

interface ValidationSaveStartedAction {
type: ValidationActions.ValidationSaveStarted;
}

interface ValidationSaveEndedAction {
type: ValidationActions.ValidationSaveEnded;
}

interface ValidationSaveFailedAction {
type: ValidationActions.ValidationSaveFailed;
error: { message: string };
Expand Down Expand Up @@ -86,6 +96,7 @@ export interface Validation {

export interface ValidationState extends Validation {
isChanged: boolean;
isSaving: boolean;
syntaxError: null | { message: string };
error: null | { message: string };
prevValidation?: Validation;
Expand All @@ -99,6 +110,7 @@ export const INITIAL_STATE: ValidationState = {
validationAction: 'error',
validationLevel: 'strict',
isChanged: false,
isSaving: false,
syntaxError: null,
error: null,
};
Expand Down Expand Up @@ -165,6 +177,31 @@ export default function reducer(
};
}

if (
isAction<ValidationSaveStartedAction>(
action,
ValidationActions.ValidationSaveStarted
)
) {
return {
...state,
error: null,
isSaving: true,
};
}

if (
isAction<ValidationSaveEndedAction>(
action,
ValidationActions.ValidationSaveEnded
)
) {
return {
...state,
isSaving: false,
};
}

if (
isAction<ValidationSaveFailedAction>(
action,
Expand Down Expand Up @@ -369,6 +406,14 @@ export const emptyValidationFetched = ({
validationTemplate,
});

export const validationSaveStarted = (): ValidationSaveStartedAction => ({
type: ValidationActions.ValidationSaveStarted,
});

export const validationSaveEnded = (): ValidationSaveEndedAction => ({
type: ValidationActions.ValidationSaveEnded,
});

export const validationCanceled = (): ValidationCanceledAction => ({
type: ValidationActions.ValidationCanceled,
});
Expand Down Expand Up @@ -446,6 +491,9 @@ export const saveValidation = (
validation_level: validation.validationLevel,
};
track('Schema Validation Updated', trackEvent, connectionInfoRef.current);

dispatch(validationSaveStarted());

try {
await dataService.updateCollection(
`${namespace.database}.${namespace.collection}`,
Expand All @@ -463,6 +511,8 @@ export const saveValidation = (
dispatch(disableEditRules());
} catch (error) {
dispatch(validationSaveFailed(error as Error));
} finally {
dispatch(validationSaveEnded());
}
};
};
Expand Down
2 changes: 2 additions & 0 deletions packages/compass-schema-validation/src/stores/store.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ describe('Schema Validation Store', function () {
error: null,
syntaxError: null,
isChanged: false,
isSaving: false,
prevValidation: {
validator,
validationAction: 'warn',
Expand All @@ -242,6 +243,7 @@ describe('Schema Validation Store', function () {
error: { message: 'Validation fetch failed!' },
syntaxError: null,
isChanged: true,
isSaving: false,
prevValidation: {
validator: '{}',
validationAction: 'error',
Expand Down
Loading