.and('have.class', 'ng-invalid');
// Check that error message was printed under name input field
- cy.get('#bid + .invalid-feedback').should('have.text', 'The value is not valid.');
+ cy.get('#bid + .invalid-feedback').should(
+ 'have.text',
+ 'Bucket names must be 3 to 63 characters long.'
+ );
// Test invalid owner input
// select some valid option. The owner drop down error message will not appear unless a valid user was selected at
<span class="invalid-feedback"
*ngIf="bucketForm.showError('bid', frm, 'bucketNameExists')"
i18n>The chosen name is already in use.</span>
+ <span class="invalid-feedback"
+ *ngIf="bucketForm.showError('bid', frm, 'containsUpperCase')"
+ i18n>Bucket names must not contain uppercase characters or underscores.</span>
+ <span class="invalid-feedback"
+ *ngIf="bucketForm.showError('bid', frm, 'lowerCaseOrNumber')"
+ i18n>Each label must start and end with a lowercase letter or a number.</span>
+ <span class="invalid-feedback"
+ *ngIf="bucketForm.showError('bid', frm, 'ipAddress')"
+ i18n>Bucket names cannot be formatted as IP address.</span>
+ <span class="invalid-feedback"
+ *ngIf="bucketForm.showError('bid', frm, 'onlyLowerCaseAndNumbers')"
+ i18n>Bucket names can only contain lowercase letters, numbers, and hyphens.</span>
+ <span class="invalid-feedback"
+ *ngIf="bucketForm.showError('bid', frm, 'shouldBeInRange')"
+ i18n>Bucket names must be 3 to 63 characters long.</span>
</div>
</div>
});
describe('bucketNameValidator', () => {
- const testValidator = (name: string, valid: boolean) => {
+ const testValidator = (name: string, valid: boolean, expectedError?: string) => {
rgwBucketServiceGetSpy.and.returnValue(throwError('foo'));
formHelper.setValue('bid', name, true);
- tick(500);
+ tick();
if (valid) {
formHelper.expectValid('bid');
} else {
- formHelper.expectError('bid', 'bucketNameInvalid');
+ formHelper.expectError('bid', expectedError);
}
};
}));
it('bucket names cannot be formatted as IP address', fakeAsync(() => {
- testValidator('172.10.4.51', false);
+ const testIPs = ['1.1.1.01', '001.1.1.01', '127.0.0.1'];
+ for (const ip of testIPs) {
+ testValidator(ip, false, 'ipAddress');
+ }
}));
it('bucket name must be >= 3 characters long (1/2)', fakeAsync(() => {
- testValidator('ab', false);
+ testValidator('ab', false, 'shouldBeInRange');
}));
it('bucket name must be >= 3 characters long (2/2)', fakeAsync(() => {
}));
it('bucket name must be <= than 63 characters long (1/2)', fakeAsync(() => {
- testValidator(_.repeat('a', 64), false);
+ testValidator(_.repeat('a', 64), false, 'shouldBeInRange');
}));
it('bucket name must be <= than 63 characters long (2/2)', fakeAsync(() => {
}));
it('bucket names must not contain uppercase characters or underscores (1/2)', fakeAsync(() => {
- testValidator('iAmInvalid', false);
+ testValidator('iAmInvalid', false, 'containsUpperCase');
+ }));
+
+ it('bucket names can only contain lowercase letters, numbers, and hyphens', fakeAsync(() => {
+ testValidator('$$$', false, 'onlyLowerCaseAndNumbers');
}));
it('bucket names must not contain uppercase characters or underscores (2/2)', fakeAsync(() => {
- testValidator('i_am_invalid', false);
+ testValidator('i_am_invalid', false, 'containsUpperCase');
+ }));
+
+ it('bucket names must start and end with letters or numbers', fakeAsync(() => {
+ testValidator('abcd-', false, 'lowerCaseOrNumber');
}));
it('bucket names with invalid labels (1/3)', fakeAsync(() => {
- testValidator('abc.1def.Ghi2', false);
+ testValidator('abc.1def.Ghi2', false, 'containsUpperCase');
}));
it('bucket names with invalid labels (2/3)', fakeAsync(() => {
- testValidator('abc.1_xy', false);
+ testValidator('abc.1_xy', false, 'containsUpperCase');
}));
it('bucket names with invalid labels (3/3)', fakeAsync(() => {
- testValidator('abc.*def', false);
+ testValidator('abc.*def', false, 'lowerCaseOrNumber');
}));
it('bucket names must be a series of one or more labels and can contain lowercase letters, numbers, and hyphens (1/3)', fakeAsync(() => {
return observableOf(null);
}
const constraints = [];
+ let errorName: string;
// - Bucket names cannot be formatted as IP address.
constraints.push(() => {
const ipv4Rgx = /^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/i;
const ipv6Rgx = /^(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}$/i;
const name = this.bucketForm.get('bid').value;
- let notAnIP = true;
+ let notIP = true;
if (ipv4Rgx.test(name) || ipv6Rgx.test(name)) {
- notAnIP = false;
+ errorName = 'ipAddress';
+ notIP = false;
}
- return notAnIP;
+ return notIP;
});
// - Bucket names can be between 3 and 63 characters long.
- constraints.push((name: string) => _.inRange(name.length, 3, 64));
+ constraints.push((name: string) => {
+ if (!_.inRange(name.length, 3, 64)) {
+ errorName = 'shouldBeInRange';
+ return false;
+ }
+ return true;
+ });
// - Bucket names must not contain uppercase characters or underscores.
// - Bucket names must start with a lowercase letter or number.
// - Bucket names must be a series of one or more labels. Adjacent
return _.every(labels, (label) => {
// Bucket names must not contain uppercase characters or underscores.
if (label !== _.toLower(label) || label.includes('_')) {
+ errorName = 'containsUpperCase';
return false;
}
// Bucket names can contain lowercase letters, numbers, and hyphens.
if (!/[0-9a-z-]/.test(label)) {
+ errorName = 'onlyLowerCaseAndNumbers';
return false;
}
// Each label must start and end with a lowercase letter or a number.
- return _.every([0, label.length], (index) => {
+ return _.every([0, label.length - 1], (index) => {
+ errorName = 'lowerCaseOrNumber';
return /[a-z]/.test(label[index]) || _.isInteger(_.parseInt(label[index]));
});
});
if (!_.every(constraints, (func: Function) => func(control.value))) {
return observableTimer().pipe(
map(() => {
- return { bucketNameInvalid: true };
+ switch (errorName) {
+ case 'onlyLowerCaseAndNumbers':
+ return { onlyLowerCaseAndNumbers: true };
+ case 'shouldBeInRange':
+ return { shouldBeInRange: true };
+ case 'ipAddress':
+ return { ipAddress: true };
+ case 'containsUpperCase':
+ return { containsUpperCase: true };
+ case 'lowerCaseOrNumber':
+ return { lowerCaseOrNumber: true };
+ default:
+ return { bucketNameInvalid: true };
+ }
})
);
}