日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Angular 应用级别的依赖 Fake

發(fā)布時間:2023/12/19 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Angular 应用级别的依赖 Fake 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原文:Faking dependencies in Angular applications

使用 Angular 依賴注入系統(tǒng)的強大功能,我們可以偽造特定的用例。 這對于自動化測試很有用,但在本文中,我們將研究一種將其用于手動測試的方法。

為了讓我們的生活更輕松,我們將創(chuàng)建一個瀏覽器偽造組件,由于自定義結(jié)構(gòu)指令,該組件僅在開發(fā)模式下啟用。 為了好玩,我們將添加文本管道以在我們的組件模板中使用常見的字符串操作。

Simulating a browser environment

Dynamically replacing a dependency using a class-based service

用戶代理令牌工廠只對每個模塊注入器評估一次,如果它沒有被祖先組件或指令提供的元素注入器替換,我們必須使用另一種技術(shù)來偽造依賴項。 我們將使用基于類的服務(wù)依賴替換依賴注入令牌依賴。

// internet-explorer-11-banner.component.ts import { Component } from '@angular/core';import { InternetExplorerService } from './internet-explorer.service';@Component({selector: 'internet-explorer-11-banner',templateUrl: './internet-explorer-11-banner.component.html', }) export class InternetExplorer11BannerComponent {private isDismissed = false;get isBannerVisible() {return this.internetExplorer.isInternetExplorer11State && !this.isDismissed;}constructor(private internetExplorer: InternetExplorerService,) {}onDismiss() {this.isDismissed = true;} } // internet-explorer-service.ts import { Inject, Injectable } from '@angular/core';import { userAgentToken } from './user-agent.token';@Injectable({providedIn: 'root', }) export class InternetExplorerService {get isInternetExplorer11State(): boolean {return this.isInternetExplorer11(this.userAgent);}constructor(@Inject(userAgentToken) private userAgent: string,) {}isInternetExplorer11(userAgent: string): boolean {return /Trident\/7\.0.+rv:11\.0/.test(userAgent);} }

首先,我們從依賴注入令牌中提取 Internet Explorer 11 檢測到我們新創(chuàng)建的 InternetExplorerService 類。 Internet Explorer 11 檢測令牌現(xiàn)在在根據(jù)用戶代理評估其值時委托給服務(wù)。

如前所述,我們不會使用元素注入器在模板中以聲明方式動態(tài)替換用戶代理令牌。 相反,我們將強制更改狀態(tài)。

Creating an observable state

下面展示的辦法不使用 userAgent token 的 injection token,而是使用 Observable. 這個 Observable 對象從另一個 Browser service 里獲得。

// internet-explorer.service.ts import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators';import { BrowserService } from './browser.service';@Injectable({providedIn: 'root', }) export class InternetExplorerService {isInternetExplorer11$: Observable<boolean> =this.browser.userAgent$.pipe(map(userAgent => this.isInternetExplorer11(userAgent)),);constructor(private browser: BrowserService,) {}isInternetExplorer11(userAgent: string): boolean {return /Trident\/7\.0.+rv:11\.0/.test(userAgent);} }

browser service 實現(xiàn)里,還是會使用 user agent injection token:

// browser.service.tsimport { Inject, Injectable, OnDestroy } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; import { distinctUntilChanged } from 'rxjs/operators';import { FakeUserAgent } from './fake-user-agent'; import { userAgentToken } from './user-agent.token';@Injectable({providedIn: 'root', }) export class BrowserService implements OnDestroy {// 這體現(xiàn)了 Observable 和 BehaviorSubject 的區(qū)別:后者實例化時,需要一個初始值:private userAgent = new BehaviorSubject(this.realUserAgent);userAgent$ = this.userAgent.pipe(distinctUntilChanged(),);constructor(@Inject(userAgentToken) private realUserAgent: string,) {}ngOnDestroy() {this.userAgent.complete();}fakeUserAgent(value: FakeUserAgent) {this.userAgent.next(FakeUserAgent[value]);}stopFakingUserAgent() {this.userAgent.next(this.realUserAgent);} }

我們將當(dāng)前用戶代理狀態(tài)存儲在 BehaviorSubject 中,它暴露在 BrowserService 的可觀察 userAgent$ 屬性中。 當(dāng)整個應(yīng)用程序需要用戶代理時,它應(yīng)該依賴于這個 observable。

最初,behavior subject 的初始值來自用戶代理令牌的真實用戶代理字符串。 該值也被存儲以備后用,因為我們允許通過兩個命令更改瀏覽器狀態(tài)。

我們公開了 fakeUserAgent 方法,該方法將用戶代理狀態(tài)設(shè)置為假用戶代理字符串。 此外,我們允許依賴者調(diào)用 stopFakingUserAgent 方法,該方法將用戶代理狀態(tài)重置為真實的用戶代理字符串。

Internet Explorer Service 現(xiàn)在公開一個名為 isInternetExplorer11$ 的可觀察屬性,只要瀏覽器服務(wù)的可觀察用戶代理屬性發(fā)出值,就會評估該屬性。

The Internet Explorer service now exposes an observable property called isInternetExplorer11$ which is evaluated whenever the observable user agent property of the browser service emits a value.

我們現(xiàn)在需要的只是讓棄用橫幅組件依賴于可觀察的 Internet Explorer 11 檢測屬性,而不是我們替換的常規(guī)屬性。

<!-- internet-explorer-11-banner.component.html --> <aside *ngIf="isBannerVisible$ | async">Sorry, we will not continue to support Internet Explorer 11.<br />Please upgrade to Microsoft Edge.<br /><button (click)="onDismiss()">Dismiss</button> </aside>

現(xiàn)在 banner 是否 visible,是由兩個 boolean 值控制了,所以使用 combineLatest.

// internet-explorer-11-banner.component.ts import { Component } from '@angular/core'; import { BehaviorSubject, combineLatest } from 'rxjs'; import { map } from 'rxjs/operators';import { InternetExplorerService } from './internet-explorer.service';@Component({host: { style: 'display: block;' },selector: 'internet-explorer-11-banner',templateUrl: './internet-explorer-11-banner.component.html', }) export class InternetExplorer11BannerComponent {private isDismissed = new BehaviorSubject(false);isBannerVisible$ = combineLatest(this.internetExplorer.isInternetExplorer11$,this.isDismissed,).pipe(map(([isInternetExplorer11, isDismissed]) =>isInternetExplorer11 && !isDismissed),);constructor(private internetExplorer: InternetExplorerService,) {}onDismiss(): void {this.isDismissed.next(true);} }

在棄用橫幅組件中,我們將 Boolean isDismissed 屬性替換為 BehaviorSubject ,該屬性最初被清除(設(shè)置為 false)。 我們現(xiàn)在有一個可觀察的 isBannerVisible$ 屬性,它是來自 isDismissed 和 InternetExplorerService#isInternetExplorer11$ 的可觀察狀態(tài)的組合。 UI 行為邏輯與之前類似,不同之處在于它現(xiàn)在表示為 observable 管道的一部分。

現(xiàn)在,onDismiss 事件處理程序不再為屬性分配布爾值,而是通過 isDismissed 行為主體發(fā)出布爾值。

此時,應(yīng)用程序的行為與我們引入 Internet Explorer 服務(wù)和瀏覽器服務(wù)之前的行為完全相同。 我們有瀏覽器狀態(tài)更改命令,但我們需要某種機制來觸發(fā)它們。

為此,我們將開發(fā)一個瀏覽器偽造器組件,使我們能夠為應(yīng)用程序的其余部分偽造瀏覽器環(huán)境。

<!-- browser-faker.component.html --> <label>Fake a browser<select [formControl]="selectedBrowser"><option value="">My browser</option><option *ngFor="let browser of browsers"[value]="browser">{{browser | replace:wordStartPattern:' $&' | trim}}</option></select> </label> // browser-faker.component.ts import { Component, OnDestroy, OnInit } from '@angular/core'; import { FormControl } from '@angular/forms'; import { Observable, Subject } from 'rxjs'; import { filter, takeUntil } from 'rxjs/operators';import { BrowserService } from './browser.service'; import { FakeUserAgent } from './fake-user-agent';@Component({host: { style: 'display: block;' },selector: 'browser-faker',templateUrl: './browser-faker.component.html', }) export class BrowserFakerComponent implements OnDestroy, OnInit {private defaultOptionValue = '';private destroy = new Subject<void>();private fakeBrowserSelection$: Observable<FakeUserAgent>;private realBrowserSelection$: Observable<void>;browsers = Object.keys(FakeUserAgent);selectedBrowser = new FormControl(this.defaultOptionValue);wordStartPattern = /[A-Z]|\d+/g;constructor(private browser: BrowserService,) {this.realBrowserSelection$ = this.selectedBrowser.valueChanges.pipe(filter(value => value === this.defaultOptionValue),takeUntil(this.destroy),);this.fakeBrowserSelection$ = this.selectedBrowser.valueChanges.pipe(filter(value => value !== this.defaultOptionValue),takeUntil(this.destroy),);}ngOnInit(): void {this.bindEvents();}ngOnDestroy() {this.unbindEvents();}private bindEvents(): void { // 一旦這個 Observable 有事件發(fā)生,說明用戶選擇了 fake browserthis.fakeBrowserSelection$.subscribe(userAgent =>this.browser.fakeUserAgent(userAgent));this.realBrowserSelection$.subscribe(() =>this.browser.stopFakingUserAgent());}private unbindEvents(): void {this.destroy.next();this.destroy.complete();} }

browser faker 組件注入瀏覽器服務(wù)。 它有一個綁定到本機 select 控件的表單控件。 選擇瀏覽器后,我們開始通過瀏覽器服務(wù)偽造其用戶代理。 選擇默認(rèn)瀏覽器選項后,我們會停止偽造用戶代理。

現(xiàn)在我們有一個瀏覽器偽造組件,但我們只希望在開發(fā)過程中啟用它。 讓我們創(chuàng)建一個僅在開發(fā)模式下有條件地呈現(xiàn)的結(jié)構(gòu)指令。

創(chuàng)建一個 injection token:

// is-development-mode.token.ts import { InjectionToken, isDevMode } from '@angular/core';export const isDevelopmentModeToken: InjectionToken<boolean> =new InjectionToken('Development mode flag', {factory: (): boolean => isDevMode(),providedIn: 'root',}); // development-only.directive.ts import {Directive,Inject,OnDestroy,OnInit,TemplateRef,ViewContainerRef, } from '@angular/core';import { isDevelopmentModeToken } from './is-development-mode.token';@Directive({exportAs: 'developmentOnly',selector: '[developmentOnly]', }) export class DevelopmentOnlyDirective implements OnDestroy, OnInit {private get isEnabled(): boolean {return this.isDevelopmentMode;}constructor(private container: ViewContainerRef,private template: TemplateRef<any>,@Inject(isDevelopmentModeToken) private isDevelopmentMode: boolean,) {}ngOnInit(): void {if (this.isEnabled) {this.createAndAttachView();}}ngOnDestroy(): void {this.destroyView();}private createAndAttachView(): void {this.container.createEmbeddedView(this.template);}private destroyView(): void {this.container.clear();} }

如果應(yīng)用程序在開發(fā)模式下運行,則此結(jié)構(gòu)指令僅呈現(xiàn)它所附加的組件或元素,正如其測試套件所驗證的那樣。

現(xiàn)在,剩下的就是將棄用橫幅和瀏覽器偽裝器添加到我們的應(yīng)用程序中。

<!-- app.component.html --> <browser-faker *developmentOnly></browser-faker> <internet-explorer-11-banner></internet-explorer-11-banner>URL: <code><browser-url></browser-url></code>

最后的效果:選擇 IE 11 時,出現(xiàn) deprecation 提示:

選擇其他瀏覽器時,該提示消失:

Summary

為了能夠模擬用戶環(huán)境,我們創(chuàng)建了一個在開發(fā)模式下有條件地呈現(xiàn)的瀏覽器偽造組件。 我們將瀏覽器狀態(tài)封裝在一個基于類的服務(wù)中,并讓應(yīng)用程序依賴它。 這與瀏覽器偽造者使用的服務(wù)相同。

瀏覽器偽造器是在 Angular 應(yīng)用程序中偽造依賴項的一個簡單示例。 我們討論了動態(tài)配置 Angular 依賴注入機制的其他技術(shù)。

本文提到的測試程序地址:https://stackblitz.com/edit/testing-and-faking-angular-dependencies-app?file=src%2Fapp%2Fbrowser%2Fbrowser-faker.component.html

更多Jerry的原創(chuàng)文章,盡在:“汪子熙”:

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的Angular 应用级别的依赖 Fake的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 中国黄色一级大片 | 亚洲国产中文字幕在线观看 | 日韩高清av在线 | 久草福利资源 | 射射综合网 | 伊人开心网 | 国产a黄| 91传媒理伦片在线观看 | 香港av在线 | 青青操网站| 极品淫少妇 | 欧美一区二区视频免费观看 | 国产熟妇乱xxxxx大屁股网 | 成人va视频 | wwwwyoujizzcom| 精品一区二区三区精华液 | 久草一区二区 | 91一级片| 黄色一级大片在线观看 | 国产又粗又猛又爽又黄的视频小说 | 国产鲁鲁视频在线观看免费 | 久久国产亚洲 | 国产精品久免费的黄网站 | www.猫咪av.com | 亚洲女优在线观看 | 你懂的在线网站 | 成年人在线免费观看视频网站 | 黄av网站| 精品一区二区成人免费视频 | 免费观看一级一片 | 日本黄色片网址 | 国语对白对话在线观看 | 亚洲砖区免费 | 日韩第一页在线观看 | 狠狠干快播 | 日韩三级在线播放 | 青青草免费在线视频 | av一卡二卡| 五月天视频网 | 日本xxxx高潮少妇 | 久久亚洲av无码西西人体 | 国产精品va在线 | 97超级碰碰 | 91亚色在线观看 | 男人天堂社区 | 亚洲狠狠干 | 国产不卡在线视频 | 欧美一区二区三区黄色 | 久久久久成人片免费观看蜜芽 | 亚洲av毛片成人精品 | 五月天av网站| 大奶毛片 | 欧美成在线 | 少妇欧美激情一区二区三区 | 国产传媒视频在线 | 婷婷丁香综合 | 欧美日韩电影一区二区 | 亚洲熟女综合一区二区三区 | 国产无毛av | 九九人人 | 天堂va蜜桃一区二区三区 | 一道本在线观看视频 | 一区二区小说 | 久久综合狠狠 | av网址免费观看 | 大地资源影视在线播放观看高清视频 | 久久精品性 | 婷婷玖玖 | 免费看成人av | 精品动漫一区二区 | 色婷婷综合久久久中文字幕 | 黄色a毛片| 免费av的网站 | 伊人久久超碰 | 亚洲精品香蕉 | 美日韩三级| 成人午夜免费视频 | 亚洲一区电影 | 欧美日韩一区二区三区在线播放 | 97国产精品视频 | 国产精品wwww | 97在线免费视频观看 | 一区二区三区三区在线 | 欧洲午夜视频 | 日韩福利电影在线 | 中文字幕第十二页 | 欧美久久久久 | 欧美一区二区激情 | 天天干天天爽天天操 | 一区二区高清在线 | 超级碰在线视频 | 亚洲国产一区视频 | 久久久久久免费 | 亚洲日本护士毛茸茸 | 丝袜性爱视频 | 女人毛片视频 | 日韩av在线免费观看 | 国内精品在线观看视频 | 国产日本在线播放 |