Skip to content

Commit fd6eb48

Browse files
authored
Feature/placeholder component
1 parent ad0de11 commit fd6eb48

File tree

5 files changed

+391
-18
lines changed

5 files changed

+391
-18
lines changed

src/cloudinary-image.component.spec.ts

Lines changed: 272 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { Component, DebugElement } from '@angular/core';
2-
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
import {ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing';
33
import { By } from '@angular/platform-browser';
44
import { Cloudinary } from './cloudinary.service';
55
import CloudinaryConfiguration from './cloudinary-configuration.class';
66
import { CloudinaryImage } from './cloudinary-image.component';
77
import { CloudinaryTransformationDirective } from './cloudinary-transformation.directive';
88
import {LazyLoadDirective } from './cloudinary-lazy-load.directive';
9+
import { CloudinaryPlaceHolder } from'./cloudinary-placeholder.component';
910

1011
describe('CloudinaryImage', () => {
1112

@@ -555,6 +556,69 @@ describe('CloudinaryImage', () => {
555556
des = fixture.debugElement.queryAll(By.directive(CloudinaryImage));
556557
});
557558

559+
it('should load eagerly', () => {
560+
const img = des[0].children[0].nativeElement as HTMLImageElement;
561+
expect(img.hasAttribute('src')).toBe(true);
562+
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('image/upload/bear'));
563+
});
564+
it('Should lazy load post scroll', async() => {
565+
const delay = 300;
566+
const wait = (ms) => new Promise(res => setTimeout(res, ms));
567+
const count = async () => document.querySelectorAll('.startWindow').length;
568+
const scrollDown = async () => {
569+
document.querySelector('.endWindow')
570+
.scrollIntoView({ behavior: 'smooth', block: 'end', inline: 'end' });
571+
}
572+
573+
let preCount = 0;
574+
let postCount = 0;
575+
do {
576+
preCount = await count();
577+
await scrollDown();
578+
await wait(delay);
579+
postCount = await count();
580+
} while (postCount > preCount);
581+
await wait(delay);
582+
583+
const img = des[3].children[0].nativeElement as HTMLImageElement;
584+
expect(img.hasAttribute('src')).toBe(true);
585+
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('image/upload/bear'));
586+
});
587+
});
588+
describe('lazy load image with default placeholder', async () => {
589+
@Component({
590+
template: `
591+
<div class="startWindow"><cl-image loading="lazy" width="300" public-id="bear"></cl-image></div>
592+
<div style="margin-top: 300px"><cl-image loading="lazy" width="300" public-id="bear"></cl-image></div>
593+
<div style="margin-top: 300px"><cl-image loading="lazy" width="300" public-id="bear">
594+
<cl-placeholder></cl-placeholder>
595+
</cl-image></div>
596+
<div style="margin-top: 300px"><cl-image loading="lazy" width="300" public-id="bear"></cl-image></div>
597+
<div style="margin-top: 300px"><cl-image loading="lazy" width="300" public-id="bear"></cl-image></div>
598+
<div style="margin-top: 300px"><cl-image loading="lazy" width="300" public-id="bear"></cl-image></div>
599+
<div style="margin-top: 300px"><cl-image loading="lazy" width="300" public-id="bear"></cl-image></div>
600+
<div class="endWindow" style="margin-top: 300px"><cl-image loading="lazy" width="300" public-id="bear"></cl-image></div>`
601+
})
602+
class TestComponent {}
603+
604+
let fixture: ComponentFixture<TestComponent>;
605+
let des: DebugElement[]; // the elements w/ the directive
606+
let placeholder: DebugElement[];
607+
let testLocalCloudinary: Cloudinary = new Cloudinary(require('cloudinary-core'),
608+
{ cloud_name: '@@fake_angular2_sdk@@', client_hints: true } as CloudinaryConfiguration);
609+
beforeEach(fakeAsync(() => {
610+
fixture = TestBed.configureTestingModule({
611+
declarations: [CloudinaryTransformationDirective, CloudinaryImage, TestComponent, LazyLoadDirective, CloudinaryPlaceHolder],
612+
providers: [{ provide: Cloudinary, useValue: testLocalCloudinary }]
613+
}).createComponent(TestComponent);
614+
615+
fixture.detectChanges(); // initial binding
616+
// all elements with an attached CloudinaryImage
617+
des = fixture.debugElement.queryAll(By.directive(CloudinaryImage));
618+
placeholder = fixture.debugElement.queryAll(By.directive(CloudinaryPlaceHolder));
619+
tick();
620+
fixture.detectChanges();
621+
}));
558622
it('should load eagerly', () => {
559623
const img = des[0].children[0].nativeElement as HTMLImageElement;
560624
expect(img.hasAttribute('src')).toBe(true);
@@ -579,9 +643,216 @@ describe('CloudinaryImage', () => {
579643
} while (postCount > preCount);
580644
await wait(delay);
581645

646+
const placeholderimg = placeholder[0].children[0].nativeElement as HTMLImageElement;
582647
const img = des[3].children[0].nativeElement as HTMLImageElement;
648+
expect(placeholderimg.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('image/upload/e_blur:2000,f_auto,q_1/bear'));
583649
expect(img.hasAttribute('src')).toBe(true);
584650
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('image/upload/bear'));
585651
});
586652
});
653+
describe('lazy load image with pixelate placeholder', async () => {
654+
@Component({
655+
template: `
656+
<div class="startWindow"><cl-image loading="lazy" width="300" public-id="bear"></cl-image></div>
657+
<div style="margin-top: 300px"><cl-image loading="lazy" width="300" public-id="bear"></cl-image></div>
658+
<div style="margin-top: 300px">
659+
<cl-image loading="lazy" width="300" public-id="bear">
660+
<cl-placeholder type="pixelate"></cl-placeholder>
661+
</cl-image>
662+
</div>
663+
<div style="margin-top: 300px"><cl-image loading="lazy" width="300" public-id="bear"></cl-image></div>
664+
<div class="endWindow" style="margin-top: 300px"><cl-image loading="lazy" width="300" public-id="bear"></cl-image></div>`
665+
})
666+
class TestComponent {}
667+
668+
let fixture: ComponentFixture<TestComponent>;
669+
let des: DebugElement[]; // the elements w/ the directive
670+
let testLocalCloudinary: Cloudinary = new Cloudinary(require('cloudinary-core'),
671+
{ cloud_name: '@@fake_angular2_sdk@@', client_hints: true } as CloudinaryConfiguration);
672+
beforeEach(() => {
673+
fixture = TestBed.configureTestingModule({
674+
declarations: [CloudinaryTransformationDirective, CloudinaryImage, TestComponent, LazyLoadDirective, CloudinaryPlaceHolder],
675+
providers: [{ provide: Cloudinary, useValue: testLocalCloudinary }]
676+
}).createComponent(TestComponent);
677+
678+
fixture.detectChanges(); // initial binding
679+
// all elements with an attached CloudinaryImage
680+
des = fixture.debugElement.queryAll(By.directive(CloudinaryPlaceHolder));
681+
});
682+
it('should load placeholder eagerly', fakeAsync(() => {
683+
tick();
684+
fixture.detectChanges();
685+
const img = des[0].children[0].nativeElement as HTMLImageElement;
686+
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('image/upload/e_pixelate,f_auto,q_1/bear'));
687+
}));
688+
});
689+
describe('placeholder default', () => {
690+
@Component({
691+
template: `<cl-image public-id="bear">
692+
<cl-placeholder></cl-placeholder>
693+
</cl-image>`
694+
})
695+
class TestComponent {}
696+
697+
let fixture: ComponentFixture<TestComponent>;
698+
let des: DebugElement[]; // the elements w/ the directive
699+
let testLocalCloudinary: Cloudinary = new Cloudinary(require('cloudinary-core'),
700+
{ cloud_name: '@@fake_angular2_sdk@@', client_hints: true } as CloudinaryConfiguration);
701+
beforeEach(() => {
702+
fixture = TestBed.configureTestingModule({
703+
declarations: [CloudinaryTransformationDirective, CloudinaryImage, TestComponent, CloudinaryPlaceHolder],
704+
providers: [{ provide: Cloudinary, useValue: testLocalCloudinary }]
705+
}).createComponent(TestComponent);
706+
707+
fixture.detectChanges(); // initial binding
708+
des = fixture.debugElement.queryAll(By.directive(CloudinaryPlaceHolder));
709+
});
710+
it('creates an img element with placeholder', fakeAsync(() => {
711+
tick();
712+
fixture.detectChanges();
713+
const img = des[0].children[0].nativeElement as HTMLImageElement;
714+
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('image/upload/e_blur:2000,f_auto,q_1/bear'));
715+
}));
716+
});
717+
describe('placeholder type blur', () => {
718+
@Component({
719+
template: `<cl-image public-id="bear" width="300" crop="fit">
720+
<cl-placeholder type="blur"></cl-placeholder>
721+
</cl-image>`
722+
})
723+
class TestComponent {}
724+
725+
let fixture: ComponentFixture<TestComponent>;
726+
let des: DebugElement[]; // the elements w/ the directive
727+
let testLocalCloudinary: Cloudinary = new Cloudinary(require('cloudinary-core'),
728+
{ cloud_name: '@@fake_angular2_sdk@@', client_hints: true } as CloudinaryConfiguration);
729+
beforeEach(() => {
730+
fixture = TestBed.configureTestingModule({
731+
declarations: [CloudinaryTransformationDirective, CloudinaryImage, TestComponent, CloudinaryPlaceHolder],
732+
providers: [{ provide: Cloudinary, useValue: testLocalCloudinary }]
733+
}).createComponent(TestComponent);
734+
735+
fixture.detectChanges(); // initial binding
736+
des = fixture.debugElement.queryAll(By.directive(CloudinaryPlaceHolder));
737+
});
738+
it('creates an img element with placeholder', fakeAsync(() => {
739+
tick();
740+
fixture.detectChanges();
741+
const img = des[0].children[0].nativeElement as HTMLImageElement;
742+
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('c_fit,w_30/e_blur:2000,f_auto,q_1/bear'));
743+
}));
744+
});
745+
describe('placeholder type pixelate', () => {
746+
@Component({
747+
template: `<cl-image public-id="bear" width="300" crop="fit">
748+
<cl-placeholder type="pixelate"></cl-placeholder>
749+
</cl-image>`
750+
})
751+
class TestComponent {}
752+
753+
let fixture: ComponentFixture<TestComponent>;
754+
let des: DebugElement[]; // the elements w/ the directive
755+
let testLocalCloudinary: Cloudinary = new Cloudinary(require('cloudinary-core'),
756+
{ cloud_name: '@@fake_angular2_sdk@@', client_hints: true } as CloudinaryConfiguration);
757+
beforeEach(() => {
758+
fixture = TestBed.configureTestingModule({
759+
declarations: [CloudinaryTransformationDirective, CloudinaryImage, TestComponent, CloudinaryPlaceHolder],
760+
providers: [{ provide: Cloudinary, useValue: testLocalCloudinary }]
761+
}).createComponent(TestComponent);
762+
763+
fixture.detectChanges(); // initial binding
764+
des = fixture.debugElement.queryAll(By.directive(CloudinaryPlaceHolder));
765+
});
766+
it('creates an img element with placeholder', fakeAsync(() => {
767+
tick();
768+
fixture.detectChanges();
769+
const img = des[0].children[0].nativeElement as HTMLImageElement;
770+
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('image/upload/c_fit,w_30/e_pixelate,f_auto,q_1/bear'));
771+
}));
772+
});
773+
describe('placeholder type solid', () => {
774+
@Component({
775+
template: `<cl-image public-id="bear" width="300" crop="fit">
776+
<cl-placeholder type="solid"></cl-placeholder>
777+
</cl-image>`
778+
})
779+
class TestComponent {}
780+
781+
let fixture: ComponentFixture<TestComponent>;
782+
let des: DebugElement[]; // the elements w/ the directive
783+
let testLocalCloudinary: Cloudinary = new Cloudinary(require('cloudinary-core'),
784+
{ cloud_name: '@@fake_angular2_sdk@@', client_hints: true } as CloudinaryConfiguration);
785+
beforeEach(() => {
786+
fixture = TestBed.configureTestingModule({
787+
declarations: [CloudinaryTransformationDirective, CloudinaryImage, TestComponent, CloudinaryPlaceHolder],
788+
providers: [{ provide: Cloudinary, useValue: testLocalCloudinary }]
789+
}).createComponent(TestComponent);
790+
791+
fixture.detectChanges(); // initial binding
792+
des = fixture.debugElement.queryAll(By.directive(CloudinaryPlaceHolder));
793+
});
794+
it('creates an img element with placeholder', fakeAsync(() => {
795+
tick();
796+
fixture.detectChanges();
797+
const img = des[0].children[0].nativeElement as HTMLImageElement;
798+
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('image/upload/c_fit,w_30/ar_1,b_auto,' +
799+
'c_pad,w_iw_div_2/c_crop,g_north_east,h_10,w_10/c_fill,h_ih,w_iw/f_auto,q_auto/bear'));
800+
}));
801+
});
802+
describe('placeholder type vectorize', () => {
803+
@Component({
804+
template: `<cl-image public-id="bear" width="300" crop="fit">
805+
<cl-placeholder type="vectorize"></cl-placeholder>
806+
</cl-image>`
807+
})
808+
class TestComponent {}
809+
810+
let fixture: ComponentFixture<TestComponent>;
811+
let des: DebugElement[]; // the elements w/ the directive
812+
let testLocalCloudinary: Cloudinary = new Cloudinary(require('cloudinary-core'),
813+
{ cloud_name: '@@fake_angular2_sdk@@', client_hints: true } as CloudinaryConfiguration);
814+
beforeEach(() => {
815+
fixture = TestBed.configureTestingModule({
816+
declarations: [CloudinaryTransformationDirective, CloudinaryImage, TestComponent, CloudinaryPlaceHolder],
817+
providers: [{ provide: Cloudinary, useValue: testLocalCloudinary }]
818+
}).createComponent(TestComponent);
819+
820+
fixture.detectChanges(); // initial binding
821+
des = fixture.debugElement.queryAll(By.directive(CloudinaryPlaceHolder));
822+
});
823+
it('creates an img element with placeholder', fakeAsync(() => {
824+
tick();
825+
fixture.detectChanges();
826+
const img = des[0].children[0].nativeElement as HTMLImageElement;
827+
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('image/upload/c_fit,w_30/e_vectorize,q_1/bear'));
828+
}));
829+
});
830+
describe('placeholder with cl-transformation', () => {
831+
@Component({
832+
template: `<cl-image public-id="bear" width="300" crop="fit">
833+
<cl-transformation effect="sepia"></cl-transformation>
834+
<cl-placeholder type="blur"></cl-placeholder>
835+
</cl-image>`
836+
})
837+
class TestComponent {}
838+
839+
let fixture: ComponentFixture<TestComponent>;
840+
let des: DebugElement[]; // the elements w/ the directive
841+
let testLocalCloudinary: Cloudinary = new Cloudinary(require('cloudinary-core'),
842+
{ cloud_name: '@@fake_angular2_sdk@@', client_hints: true } as CloudinaryConfiguration);
843+
beforeEach(() => {
844+
fixture = TestBed.configureTestingModule({
845+
declarations: [CloudinaryTransformationDirective, CloudinaryImage, TestComponent, CloudinaryPlaceHolder],
846+
providers: [{ provide: Cloudinary, useValue: testLocalCloudinary }]
847+
}).createComponent(TestComponent);
848+
fixture.detectChanges(); // initial binding
849+
des = fixture.debugElement.queryAll(By.directive(CloudinaryPlaceHolder));
850+
});
851+
it('creates an img element with placeholder and cl-transformations', fakeAsync(() => {
852+
tick();
853+
fixture.detectChanges();
854+
const img = des[0].children[0].nativeElement as HTMLImageElement;
855+
expect(img.attributes.getNamedItem('src').value).toEqual(jasmine.stringMatching('e_sepia/c_fit,w_30/e_blur:2000,f_auto,q_1/bear'));
856+
}));
857+
});
587858
});

0 commit comments

Comments
 (0)