25 Commits

Author SHA1 Message Date
rajukottedi 1864d49d6c style: improve code readability and consistency in Jenkinsfile 2026-03-06 12:50:57 +05:30
rajukottedi 37d7df2794 style: format code for better readability and consistency 2026-03-06 12:39:31 +05:30
rajukottedi 15788dbaa6 fix: update test command to use ChromeHeadless browser 2026-03-06 12:11:47 +05:30
rajukottedi 3aec2d5290 fix: update test command to use ChromeHeadlessCI browser 2026-03-06 12:07:33 +05:30
rajukottedi ddf92e0548 fix: update ChromeHeadless command to include --no-sandbox option 2026-03-06 11:58:30 +05:30
rajukottedi 196ad13eea feat: update Angular dependencies and improve test configurations 2026-03-06 09:24:54 +05:30
rajukottedi 1eca714680 refactor: enhance Jenkinsfile structure and improve stage conditions for better clarity and maintainability 2026-03-06 08:03:03 +05:30
rajukottedi f33bf8cd01 fix: remove unnecessary backticks from Jenkinsfile 2026-03-06 07:33:38 +05:30
rajukottedi 85fe20d0f3 fix: remove unnecessary backticks from Jenkinsfile 2026-03-06 07:31:42 +05:30
rajukottedi 8de5d29a4d refactor: reorganize Jenkinsfile stages and improve environment variable handling 2026-03-06 07:16:33 +05:30
rajukottedi 17d2289974 fix: correct agent label for production environment in Jenkinsfile
bangararaju.kottedi.in/admin/admin-uat/pipeline/head This commit looks good
2026-02-16 20:35:22 +05:30
rajukottedi a0e56f6a89 refactor: streamline Jenkinsfile by using helper methods for environment variables and agent labels
bangararaju.kottedi.in/admin/admin-prod/pipeline/head This commit looks good
bangararaju.kottedi.in/admin/admin-uat/pipeline/head This commit looks good
2026-02-16 20:28:02 +05:30
rajukottedi 8885e288ed removed test file
bangararaju.kottedi.in/admin/admin-uat/pipeline/head This commit looks good
bangararaju.kottedi.in/admin/admin-prod/pipeline/head This commit looks good
2026-02-16 20:05:39 +05:30
rajukottedi a888636487 webhook test
bangararaju.kottedi.in/admin/admin-uat-new/pipeline/head This commit looks good
bangararaju.kottedi.in/admin/admin-prod/pipeline/head This commit looks good
2026-02-16 19:57:11 +05:30
rajukottedi dad46d788d webhook test
bangararaju.kottedi.in/admin/admin-uat-new/pipeline/head This commit looks good
2026-02-16 19:45:15 +05:30
rajukottedi 3619e33f44 webhook test
bangararaju.kottedi.in/admin/admin-uat-new/pipeline/head This commit looks good
2026-02-16 19:31:46 +05:30
rajukottedi cf8e3b880c fix: add sudo to systemctl reload command in deployment stage
bangararaju.kottedi.in/admin/admin-uat-new/pipeline/head This commit looks good
2026-02-16 19:13:30 +05:30
rajukottedi a6e48d6b2b fix: remove redundant ownership change command in deployment stage
bangararaju.kottedi.in/admin/admin-uat-new/pipeline/head There was a failure building this commit
2026-02-16 18:39:34 +05:30
rajukottedi 06a64fa018 fix: add npm install step before building Angular
bangararaju.kottedi.in/admin/admin-uat-new/pipeline/head There was a failure building this commit
2026-02-16 18:28:53 +05:30
rajukottedi 1bec713692 fix: ensure cleanup of deployment directory before building Angular
bangararaju.kottedi.in/admin/admin-uat-new/pipeline/head There was a failure building this commit
2026-02-16 18:11:14 +05:30
rajukottedi cea6d218f8 feat: add Jenkins pipeline for automated deployment
bangararaju.kottedi.in/admin/admin-uat-new/pipeline/head There was a failure building this commit
2026-02-16 17:40:09 +05:30
rajukottedi 3dbecd171f Merge pull request 'fix: enhance OTP sending logic and add success message display' (#7) from task/popup-for-dynamic-form into develop
Reviewed-on: #7
2026-02-16 10:03:02 +05:30
rajukottedi bdba683f00 fix: enhance OTP sending logic and add success message display 2026-02-16 10:02:26 +05:30
rajukottedi 15ad26c505 Merge pull request 'fix: update project categories check and adjust border style in project detail popup' (#6) from task/popup-for-dynamic-form into develop
Reviewed-on: #6
2026-02-16 09:26:17 +05:30
rajukottedi e529f101b7 fix: update project categories check and adjust border style in project detail popup 2026-02-16 09:24:45 +05:30
25 changed files with 383 additions and 80 deletions
Vendored
+161
View File
@@ -0,0 +1,161 @@
pipeline {
agent none
options {
buildDiscarder(logRotator(numToKeepStr: '10'))
disableConcurrentBuilds()
}
stages {
stage('Build & Test') {
agent { label getAgentLabel() }
environment {
CHROME_BIN = "${getChromeBin()}"
}
stages {
stage('Cleanup Workspace') {
steps { cleanWs() }
}
stage('Checkout') {
steps { checkout scm }
}
stage('Inject Environment File') {
when {
not {
anyOf {
branch pattern: "feature/.*", comparator: "REGEXP"
branch pattern: "bug/.*", comparator: "REGEXP"
}
}
}
steps {
configFileProvider([
configFile(
fileId: getEnvFileId(),
targetLocation: 'src/environments/environment.ts',
replaceTokens: true
)
]) {
echo "Injected environment for ${env.BRANCH_NAME}"
}
}
}
stage('Install Dependencies') {
steps { sh 'npm ci' }
}
stage('Run Tests') {
when {
anyOf {
branch pattern: "feature/.*", comparator: "REGEXP"
branch pattern: "bug/.*", comparator: "REGEXP"
branch 'develop'
branch 'prod'
changeRequest()
}
}
steps {
sh 'npm run test -- --watch=false --browsers=ChromeHeadless'
}
}
stage('Build Angular App') {
when {
anyOf {
branch 'develop'
branch 'prod'
changeRequest()
}
}
steps {
sh 'ng build --configuration production --base-href /admin/'
}
}
}
}
stage('Production Approval') {
when { branch 'prod' }
steps {
input message: 'Approve deployment to PRODUCTION?', ok: 'Deploy'
}
}
stage('Deploy & Verify') {
when {
anyOf {
branch 'develop'
branch 'prod'
}
}
agent { label getAgentLabel() }
stages {
stage('Deploy') {
steps {
sh """
rsync -av --delete dist/portfolio-admin/browser/ ${getDeployPath()}/
sudo /usr/bin/systemctl reload nginx
"""
}
}
stage('Health Check') {
steps {
sh """
sleep 3
curl -f ${getHealthUrl()}
"""
}
}
}
}
}
post {
success { echo "Deployment successful for ${env.BRANCH_NAME}" }
failure { echo "Deployment failed for ${env.BRANCH_NAME}" }
}
}
//
// -------- Helper Methods --------
//
def getAgentLabel() {
return env.BRANCH_NAME == 'prod' ? 'oracle-prod' : 'built-in'
}
def getEnvFileId() {
return env.BRANCH_NAME == 'prod' ? 'admin-prod-properties' : 'admin-uat-properties'
}
def getDeployPath() {
return env.BRANCH_NAME == 'prod'
? "/var/www/bangararaju.kottedi.in/admin"
: "/var/www/bangararaju.kottedi.in/admin"
}
def getHealthUrl() {
return env.BRANCH_NAME == 'prod'
? "https://bangararaju.kottedi.in/admin"
: "https://bangararaju-uat.kottedi.in/admin"
}
def getChromeBin() {
return env.BRANCH_NAME == 'prod'
? "/snap/bin/chromium"
: "/usr/bin/chromium"
}
+2
View File
@@ -79,6 +79,8 @@
"test": {
"builder": "@angular/build:karma",
"options": {
"main": "./src/test.ts",
"polyfills": [],
"tsConfig": "tsconfig.spec.json",
"inlineStyleLanguage": "scss",
"assets": [
+20
View File
@@ -28,6 +28,7 @@
"@angular/build": "^20.3.2",
"@angular/cli": "^20.3.2",
"@angular/compiler-cli": "^20.3.0",
"@angular/platform-browser-dynamic": "^20.3.4",
"@types/express": "^5.0.1",
"@types/jasmine": "~5.1.0",
"@types/node": "^20.17.19",
@@ -754,6 +755,25 @@
}
}
},
"node_modules/@angular/platform-browser-dynamic": {
"version": "20.3.4",
"resolved": "https://registry.npmjs.org/@angular/platform-browser-dynamic/-/platform-browser-dynamic-20.3.4.tgz",
"integrity": "sha512-eeScVJyZLDTNrnEDDBgF/WZpZrjEszFFkuEzNQ43sbPjc5M7Noue38Nd9QZ664ZQ3a4ZpUpritfHvc55a/fl9Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"tslib": "^2.3.0"
},
"engines": {
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
},
"peerDependencies": {
"@angular/common": "20.3.4",
"@angular/compiler": "20.3.4",
"@angular/core": "20.3.4",
"@angular/platform-browser": "20.3.4"
}
},
"node_modules/@angular/platform-server": {
"version": "20.3.4",
"resolved": "https://registry.npmjs.org/@angular/platform-server/-/platform-server-20.3.4.tgz",
+1
View File
@@ -44,6 +44,7 @@
"@angular/build": "^20.3.2",
"@angular/cli": "^20.3.2",
"@angular/compiler-cli": "^20.3.0",
"@angular/platform-browser-dynamic": "^20.3.4",
"@types/express": "^5.0.1",
"@types/jasmine": "~5.1.0",
"@types/node": "^20.17.19",
+3 -1
View File
@@ -1,4 +1,5 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { About } from './about';
@@ -8,7 +9,8 @@ describe('About', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [About]
imports: [About],
providers: [provideHttpClientTesting()]
})
.compileComponents();
+3 -1
View File
@@ -1,4 +1,5 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { Contact } from './contact';
@@ -8,7 +9,8 @@ describe('Contact', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [Contact]
imports: [Contact],
providers: [provideHttpClientTesting()]
})
.compileComponents();
@@ -88,7 +88,7 @@
</div>
}
@if (project.categories?.length) {
@if (project.categories.length) {
<div class="detail-section">
<h4>Categories</h4>
<div class="tag-list">
@@ -4,7 +4,7 @@
max-height: 80vh;
overflow-y: auto;
background: var(--eerie-black-2, #1e1e1e);
border: 1px solid var(--jet, #383838);
border: 1.2px solid hsla(45, 100%, 72%, 0.45);
border-radius: 14px;
}
+3 -1
View File
@@ -1,4 +1,5 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { Projects } from './projects';
@@ -8,7 +9,8 @@ describe('Projects', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [Projects]
imports: [Projects],
providers: [provideHttpClientTesting()]
})
.compileComponents();
+3 -1
View File
@@ -1,4 +1,5 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { Resume } from './resume';
@@ -8,7 +9,8 @@ describe('Resume', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [Resume]
imports: [Resume],
providers: [provideHttpClientTesting()]
})
.compileComponents();
+4 -1
View File
@@ -1,4 +1,5 @@
import { TestBed } from '@angular/core/testing';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { AdminService } from './admin.service';
@@ -6,7 +7,9 @@ describe('AdminService', () => {
let service: AdminService;
beforeEach(() => {
TestBed.configureTestingModule({});
TestBed.configureTestingModule({
providers: [provideHttpClientTesting()]
});
service = TestBed.inject(AdminService);
});
+1 -7
View File
@@ -15,11 +15,5 @@ describe('App', () => {
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it('should render title', () => {
const fixture = TestBed.createComponent(App);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, portfolio-admin');
});
// title rendering test removed — template doesn't render a static H1
});
+7 -3
View File
@@ -1,12 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { provideRouter } from '@angular/router';
import { AuthService } from './auth.service';
describe('AuthService', () => {
let service: AuthService;
beforeEach(() => {
TestBed.configureTestingModule({});
beforeEach(async () => {
await TestBed.configureTestingModule({
providers: [provideRouter([]), provideHttpClientTesting(), AuthService]
}).compileComponents();
service = TestBed.inject(AuthService);
});
+5 -1
View File
@@ -1,4 +1,6 @@
import { TestBed } from '@angular/core/testing';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { provideRouter } from '@angular/router';
import { AuthService} from './auth.service';
@@ -6,7 +8,9 @@ describe('AuthService', () => {
let service: AuthService;
beforeEach(() => {
TestBed.configureTestingModule({});
TestBed.configureTestingModule({
providers: [provideRouter([]), provideHttpClientTesting()]
});
service = TestBed.inject(AuthService);
});
+16 -12
View File
@@ -2,11 +2,11 @@
<div class="verify-card">
@if(!isOtpSent()){
<h2 class="title">🔐 Login</h2>
<h2 class="title">🔐 Login</h2>
}
@if(isOtpSent() && !isVerified()){
<h2 class="title">🔐 OTP Verification</h2>
<h2 class="title">🔐 OTP Verification</h2>
}
<!-- Step 1: Enter Email -->
@@ -21,19 +21,9 @@
<!-- Step 2: OTP Input -->
@if (isOtpSent() && !isVerified()) {
<div class="otp-section">
<p class="info-text">
OTP sent to <b>{{ emailForm.value.email }}</b>
</p>
<form [formGroup]="otpForm" (ngSubmit)="verifyOtp()">
<label for="otp">Enter 6-digit OTP</label>
<input id="otp" type="text" maxlength="6" formControlName="otp" placeholder="123456" />
@if (isError()) {
<div class="error-banner">
<i class="fa-solid fa-circle-exclamation"></i>
<span>{{ message() }}</span>
</div>
}
<button type="submit" [disabled]="otpForm.invalid">
Verify OTP
</button>
@@ -47,5 +37,19 @@
</button>
</div>
}
@if (isError()) {
<div class="error-banner">
<i class="fa-solid fa-circle-exclamation"></i>
<span>{{ message() }}</span>
</div>
}
@if (!isError() && isOtpSent() && !isVerified()) {
<div class="success-banner">
<i class="fa-solid fa-circle-check"></i>
<span>{{ message() }}</span>
</div>
}
</div>
</div>
+20
View File
@@ -171,3 +171,23 @@ button {
font-size: 14px;
margin-bottom: 10px;
}
/* Success banner for OTP sent */
.success-banner {
display: flex;
align-items: center;
gap: 8px;
background: rgba(120, 255, 140, 0.07);
border: 1px solid rgba(120, 255, 140, 0.25);
border-radius: 8px;
padding: 10px 14px;
margin: 10px 0 10px;
color: #78ff8c;
font-size: 13px;
i {
font-size: 15px;
flex-shrink: 0;
color: #78ff8c;
}
}
+4 -1
View File
@@ -1,4 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { provideRouter } from '@angular/router';
import { OtpComponent } from './otp.component';
@@ -8,7 +10,8 @@ describe('OtpComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [OtpComponent]
imports: [OtpComponent],
providers: [provideRouter([]), provideHttpClientTesting()]
})
.compileComponents();
+17 -5
View File
@@ -48,15 +48,27 @@ export class OtpComponent implements OnInit {
if (this.emailForm.invalid) return;
const email = this.emailForm.value.email;
this.authService.sendOtp(email).subscribe(() => {
this.isOtpSent.set(true);
this.message.set('OTP sent successfully!');
this.startTimer(30); // 30 seconds countdown
this.authService.sendOtp(email).subscribe({
next: () => {
this.isOtpSent.set(true);
this.isError.set(false);
this.message.set(`OTP sent to ${email}.`);
this.startTimer(30); // 30 seconds countdown
},
error: (err) => {
this.isError.set(true);
if (err.status === 404) {
this.message.set('Email not found. Please check and try again.');
} else {
this.message.set('Failed to send OTP. Please try again.');
}
}
});
}
}
resendOtp() {
if (this.countdown() > 0) return;
this.otpForm.reset();
this.sendOtp();
}
+16 -3
View File
@@ -1,16 +1,29 @@
import { TestBed } from '@angular/core/testing';
import { of } from 'rxjs';
import { HttpInterceptorFn } from '@angular/common/http';
import { AuthInterceptor } from './auth-interceptor';
import { AuthService } from '../auth/auth.service';
describe('AuthInterceptor', () => {
const mockAuthService: Partial<AuthService> = {
getApiKey: () => '',
currentToken: null as unknown as string | null,
refreshToken: () => of({ accessToken: 'new-token' }),
safeSetToken: () => { /* no-op for testing */ },
logout: () => { /* no-op for testing */ }
};
const interceptor: HttpInterceptorFn = (req, next) =>
TestBed.runInInjectionContext(() => AuthInterceptor(req, next));
beforeEach(() => TestBed.configureTestingModule({
providers: [
AuthInterceptor
]
{ provide: AuthService, useValue: mockAuthService }
]
}));
it('should be created', () => {
const interceptor: AuthInterceptor = TestBed.inject(AuthInterceptor);
expect(interceptor).toBeTruthy();
});
});
@@ -1,4 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { provideRouter } from '@angular/router';
import { AdminLayout } from './admin-layout';
@@ -8,7 +10,8 @@ describe('AdminLayout', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AdminLayout]
imports: [AdminLayout],
providers: [provideRouter([]), provideHttpClientTesting()]
})
.compileComponents();
+55 -29
View File
@@ -1,41 +1,65 @@
/* Dynamic form spacing and material tweaks to match popup theme */
.full-width { width: 100%; display: block; }
.full-width {
width: 100%;
display: block;
}
mat-form-field.full-width { margin-bottom: 12px; }
mat-form-field.full-width {
margin-bottom: 12px;
}
/* Reduce label size slightly to fit popup */
mat-form-field .mat-form-field-label { font-size: 0.95rem; color: var(--light-gray-70); }
mat-form-field .mat-form-field-label {
font-size: 0.95rem;
color: var(--light-gray-70);
}
/* Make input text contrast better */
.mat-input-element,
input.mat-mdc-input-element,
textarea.mat-mdc-input-element,
.mat-mdc-input-element {
color: var(--white-1) !important;
color: var(--white-1) !important;
}
/* Smaller helper/hint text */
.mat-hint { color: var(--light-gray-70); font-size: 0.85rem; }
.mat-hint {
color: var(--light-gray-70);
font-size: 0.85rem;
}
/* Error styling consistent with theme */
mat-error { color: #ff8a80; font-size: 0.9rem; }
mat-error {
color: #ff8a80;
font-size: 0.9rem;
}
/* Outline border always visible, highlight on focus */
::ng-deep .mdc-notched-outline__leading,
::ng-deep .mdc-notched-outline__notch,
::ng-deep .mdc-notched-outline__trailing {
border-color: var(--light-gray-70) !important;
border-color: var(--light-gray-70) !important;
}
::ng-deep .mat-mdc-form-field.mat-focused .mdc-notched-outline__leading,
::ng-deep .mat-mdc-form-field.mat-focused .mdc-notched-outline__notch,
::ng-deep .mat-mdc-form-field.mat-focused .mdc-notched-outline__trailing {
border-color: var(--orange-yellow-crayola) !important;
border-color: var(--orange-yellow-crayola) !important;
}
/* Make array item fields inline on larger screens */
.array-item-fields { display: flex; gap: 12px; align-items: baseline; flex-wrap: wrap; }
.array-item-fields mat-form-field { flex: 1 1 auto; margin-bottom: 0; min-width: 120px; }
.array-item-fields {
display: flex;
gap: 12px;
align-items: baseline;
flex-wrap: wrap;
}
.array-item-fields mat-form-field {
flex: 1 1 auto;
margin-bottom: 0;
min-width: 120px;
}
/* Stack array item fields vertically on small screens */
@media (max-width: 580px) {
@@ -52,37 +76,38 @@ mat-error { color: #ff8a80; font-size: 0.9rem; }
/* Hide subscript wrapper inside array items so fields align */
.array-item ::ng-deep .mat-mdc-form-field-subscript-wrapper {
display: none;
display: none;
}
/* Remove link at bottom-right of each array card */
.array-item-actions {
display: flex;
justify-content: center;
margin-top: 4px;
display: flex;
justify-content: center;
margin-top: 4px;
}
.remove-link {
background: none;
border: none;
color: rgba(255, 255, 255, 0.35);
font-size: 0.8rem;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 5px;
padding: 4px 8px;
border-radius: 4px;
transition: color 0.2s ease, background 0.2s ease;
background: none;
border: none;
color: rgba(255, 255, 255, 0.35);
font-size: 0.8rem;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 5px;
padding: 4px 8px;
border-radius: 4px;
transition: color 0.2s ease, background 0.2s ease;
&:hover {
color: hsl(0deg 75% 60%);
background: rgba(255, 70, 70, 0.1);
}
&:hover {
color: hsl(0deg 75% 60%);
background: rgba(255, 70, 70, 0.1);
}
}
/* Force material label/input colors to match dark popup theme (covers MDC + legacy classes) */
.themed-popup {
::ng-deep .mat-form-field-label,
::ng-deep .mat-mdc-floating-label,
::ng-deep .mat-form-field .mat-form-field-label {
@@ -107,6 +132,7 @@ mat-error { color: #ff8a80; font-size: 0.9rem; }
opacity: 1 !important;
}
}
.form-array {
margin-bottom: 20px;
padding: 10px 0;
@@ -1,19 +1,21 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DynamicForm } from './dynamic-form';
import { DynamicFormComponent } from './dynamic-form';
import { DynamicFormConfig } from './dynamic-form-config';
describe('DynamicForm', () => {
let component: DynamicForm;
let fixture: ComponentFixture<DynamicForm>;
let component: DynamicFormComponent;
let fixture: ComponentFixture<DynamicFormComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [DynamicForm]
imports: [DynamicFormComponent]
})
.compileComponents();
fixture = TestBed.createComponent(DynamicForm);
fixture = TestBed.createComponent(DynamicFormComponent);
component = fixture.componentInstance;
component.config = { fields: [] } as unknown as DynamicFormConfig;
fixture.detectChanges();
});
@@ -1,6 +1,8 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { DynamicPopupComponent } from './dynamic-popup';
import { DynamicFormConfig } from '../dynamic-form/dynamic-form-config';
describe('DynamicPopupComponent', () => {
let component: DynamicPopupComponent;
@@ -8,12 +10,15 @@ describe('DynamicPopupComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [DynamicPopupComponent]
imports: [DynamicPopupComponent],
providers: [provideHttpClientTesting()]
})
.compileComponents();
fixture = TestBed.createComponent(DynamicPopupComponent);
component = fixture.componentInstance;
component.config = { title: 'Test', submitLabel: 'Save', fields: [] } as DynamicFormConfig;
component.data = {};
fixture.detectChanges();
});
+4 -5
View File
@@ -507,9 +507,9 @@
.mat-mdc-text-field.mat-mdc-focused .mat-mdc-notched-outline .mat-mdc-notched-outline-path {
stroke: var(--orange-yellow-crayola) !important;
border-color: var(--orange-yellow-crayola) !important;
}
/* Additional overrides: set MDC theme variables and force a gold focus ring */
.themed-popup {
// .themed-popup {
/* Override MDC primary color used by many Material components */
--mdc-theme-primary: var(--orange-yellow-crayola);
--mdc-theme-on-primary: var(--smoky-black);
@@ -529,10 +529,9 @@
.mat-mdc-text-field.mat-mdc-focused .mat-mdc-notched-outline-path {
stroke: var(--orange-yellow-crayola) !important;
}
}
box-shadow: 0 6px 18px rgba(36,26,18,0.12) !important;
// }
// box-shadow: 0 6px 18px rgba(36,26,18,0.12) !important;
}
}
.contacts-list {
display: grid;
+19
View File
@@ -0,0 +1,19 @@
// Test bootstrap for Karma
import { provideZonelessChangeDetection } from '@angular/core';
import { getTestBed, TestBed } from '@angular/core/testing';
import { BrowserTestingModule, platformBrowserTesting } from '@angular/platform-browser/testing';
import { provideHttpClient } from '@angular/common/http';
import { provideHttpClientTesting } from '@angular/common/http/testing';
declare const beforeEach: (fn: () => void) => void;
getTestBed().initTestEnvironment(
BrowserTestingModule,
platformBrowserTesting()
);
beforeEach(() => {
TestBed.configureTestingModule({
providers: [provideZonelessChangeDetection(), provideHttpClient(), provideHttpClientTesting()]
});
});