+
Register a new domain name
diff --git a/src/app/domainregister/domainregister.component.spec.ts b/src/app/domainregister/domainregister.component.spec.ts
new file mode 100644
index 000000000..cfdeca57c
--- /dev/null
+++ b/src/app/domainregister/domainregister.component.spec.ts
@@ -0,0 +1,111 @@
+// --------- BEGIN RUNBOX LICENSE ---------
+// Copyright (C) 2016-2026 Runbox Solutions AS (runbox.com).
+//
+// This file is part of Runbox 7.
+//
+// Runbox 7 is free software: You can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation, either version 3 of the License, or (at your
+// option) any later version.
+//
+// Runbox 7 is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Runbox 7. If not, see .
+// ---------- END RUNBOX LICENSE ----------
+
+import { of } from 'rxjs';
+
+import { DomainRegisterComponent } from './domainregister.component';
+
+describe('DomainRegisterComponent quota checks', () => {
+ function createComponent() {
+ const http = {
+ get: jasmine.createSpy('get').and.returnValues(
+ of({
+ result: {
+ product_list: [
+ {
+ tld: 'com',
+ period: '1',
+ price: '10.00',
+ supports_whois_privacy: 0,
+ privacy_price: '0.00'
+ }
+ ]
+ }
+ }),
+ of({
+ result: {
+ domain_quota_allowed: '20',
+ domain_quota_used: '7'
+ }
+ })
+ ),
+ post: jasmine.createSpy('post').and.returnValues(
+ of({
+ result: {
+ is_available: 0,
+ products: [],
+ privacy_products: []
+ }
+ }),
+ of({
+ result: {
+ agreement: {
+ generic: null,
+ specific: null
+ }
+ }
+ }),
+ of({
+ result: {
+ specific_docs: []
+ }
+ }),
+ of({
+ result: {
+ generic_docs: []
+ }
+ })
+ )
+ };
+ const snackBar = {
+ open: jasmine.createSpy('open')
+ };
+ const rmmapi = {
+ me: of({ is_trial: false })
+ };
+
+ const component = new DomainRegisterComponent(
+ http as any,
+ snackBar as any,
+ rmmapi as any
+ );
+
+ return { component, http, snackBar };
+ }
+
+ it('allows availability checks when string quota values are below the limit', () => {
+ const { component, http, snackBar } = createComponent();
+
+ component.domain_wanted = 'example.com';
+ component.domain_quota_used = '7' as any;
+ component.domain_quota_allowed = '20' as any;
+
+ component.check_avail();
+
+ expect(http.post).toHaveBeenCalledWith(
+ '/rest/v1/domain_registration/enom/check_avail',
+ { sld: 'example', tld: 'com' }
+ );
+ expect(snackBar.open).not.toHaveBeenCalledWith(
+ 'You have reached your allowed Email Domain quota. Please purchase more Email Hosting products.',
+ 'Dismiss',
+ jasmine.anything()
+ );
+ });
+});
diff --git a/src/app/domainregister/domainregister.component.ts b/src/app/domainregister/domainregister.component.ts
index 8e9f3d1c9..a5b8a790b 100644
--- a/src/app/domainregister/domainregister.component.ts
+++ b/src/app/domainregister/domainregister.component.ts
@@ -61,6 +61,20 @@ export interface ElementTld {
privacy_price: string;
}
+export function emailDomainQuotaCount(value: unknown): number {
+ const count = Number(value);
+ return Number.isFinite(count) ? count : 0;
+}
+
+export function isEmailDomainQuotaLimitReached(used: unknown, allowed: unknown): boolean {
+ const usedCount = emailDomainQuotaCount(used);
+ const allowedCount = emailDomainQuotaCount(allowed);
+
+ return usedCount > 0
+ && allowedCount > 0
+ && usedCount >= allowedCount;
+}
+
@Component({
// eslint-disable-next-line @angular-eslint/component-selector
selector: 'domain-register',
@@ -157,6 +171,10 @@ export class DomainRegisterComponent implements AfterViewInit {
return this.is_available ? 'primary' : 'button';
};
+ public is_domain_quota_limit_reached = function () {
+ return isEmailDomainQuotaLimitReached(this.domain_quota_used, this.domain_quota_allowed);
+ };
+
public calculate_total = function () {
// eslint-disable-next-line no-eval
this.total_price = eval(this.selected_product.price[0].price);
@@ -194,7 +212,7 @@ export class DomainRegisterComponent implements AfterViewInit {
public check_avail = function () {
if (this.is_btn_search_domain_disabled) { return; }
- if ( this.domain_quota_used && this.domain_quota_allowed && this.domain_quota_used >= this.domain_quota_allowed ) {
+ if ( this.is_domain_quota_limit_reached() ) {
return this.show_error('You have reached your allowed Email Domain quota. Please purchase more Email Hosting products.', 'Dismiss');
}
this.is_btn_search_domain_disabled = true;
@@ -820,9 +838,9 @@ export class DomainRegisterComponent implements AfterViewInit {
const req = this.http.get('/rest/v1/email_hosting/domains_quota');
req.pipe(timeout(180000))
.subscribe((result: any) => {
- this.domain_quota_allowed = result.result.domain_quota_allowed;
- this.domain_quota_used = result.result.domain_quota_used;
- if ( this.domain_quota_used >= this.domain_quota_allowed ) {
+ this.domain_quota_allowed = emailDomainQuotaCount(result.result.domain_quota_allowed);
+ this.domain_quota_used = emailDomainQuotaCount(result.result.domain_quota_used);
+ if ( this.is_domain_quota_limit_reached() ) {
this.show_error('You have reached your allowed Email Domain quota. Please purchase more Email Hosting products.', 'Dismiss');
}
},