diff --git a/src/app/pages/settings/chains/chain-form/chain-form.html b/src/app/pages/settings/chains/chain-form/chain-form.html
new file mode 100644
index 0000000..5b91906
--- /dev/null
+++ b/src/app/pages/settings/chains/chain-form/chain-form.html
@@ -0,0 +1,8 @@
+@let form = this.form();
+
\ No newline at end of file
diff --git a/src/app/pages/settings/chains/chain-form/chain-form.spec.ts b/src/app/pages/settings/chains/chain-form/chain-form.spec.ts
new file mode 100644
index 0000000..03a0eb0
--- /dev/null
+++ b/src/app/pages/settings/chains/chain-form/chain-form.spec.ts
@@ -0,0 +1,49 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { ChainForm } from './chain-form';
+import { provideTranslateService } from '@ngx-translate/core';
+import { Component } from '@angular/core';
+import { ImageUploader } from '../../../../components/image-uploader/image-uploader';
+import { By } from '@angular/platform-browser';
+
+@Component({
+ template: ``
+})
+class ImageUploaderMock extends ImageUploader {
+
+}
+
+describe('ChainForm', () => {
+ let component: ChainForm;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ TestBed.overrideComponent(ImageUploader, {
+ remove: { imports: [ImageUploader] },
+ add: { imports: [ImageUploaderMock] },
+ });
+
+ await TestBed.configureTestingModule({
+ imports: [ChainForm],
+ providers: [provideTranslateService()]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(ChainForm);
+ component = fixture.componentInstance;
+ await fixture.whenStable();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should populate form with emitted files', async () => {
+ const FILE_MOCK = new File([], 'mock');
+ const patchValueSpy = vi.spyOn(component.form().controls.image, 'patchValue');
+ const imageUploaderComp: ImageUploaderMock = fixture.debugElement.query(By.css('app-image-uploader')).componentInstance;
+ imageUploaderComp.file.emit(FILE_MOCK);
+ await fixture.whenStable();
+ expect(patchValueSpy).toHaveBeenCalledExactlyOnceWith(FILE_MOCK);
+ });
+});
diff --git a/src/app/pages/settings/chains/chain-form/chain-form.ts b/src/app/pages/settings/chains/chain-form/chain-form.ts
new file mode 100644
index 0000000..d369b74
--- /dev/null
+++ b/src/app/pages/settings/chains/chain-form/chain-form.ts
@@ -0,0 +1,28 @@
+import { Component, input } from '@angular/core';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
+import { ImageUploader } from '../../../../components/image-uploader/image-uploader';
+import { ReactiveFormsModule } from '@angular/forms';
+import { ChainFormGroup } from '../chain-formgroup';
+import { TranslatePipe } from '@ngx-translate/core';
+import { UpperfirstPipe } from "../../../../pipes/upperfirst-pipe";
+
+@Component({
+ selector: 'app-chain-form',
+ imports: [MatFormFieldModule, MatInputModule, ImageUploader, ReactiveFormsModule, TranslatePipe, UpperfirstPipe],
+ templateUrl: './chain-form.html',
+ styles: ``,
+})
+export class ChainForm {
+ form = input(new ChainFormGroup())
+
+ get file() {
+ return this.form().controls.image.value;
+ }
+
+ updateFileImage(file: File) {
+ const form = this.form();
+ form.controls.image.patchValue(file);
+ form.controls.image.markAsDirty();
+ }
+}