You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular 5:测试兼容Chrome与Firefox的存储服务(含原生方法与.then)

Testing Your Cross-Browser Storage Quota Service (Chrome + Firefox)

Awesome that you’ve expanded your storage quota service to support Firefox! Testing cross-browser services can feel a bit tedious, but let’s break down a structured approach to validate everything works as expected for both browsers.

First: Test Setup

Before diving in, make sure you’ve got the right tools ready:

  • Angular’s testing utilities: @angular/core/testing
  • RxJS testing helpers (like firstValueFrom for async Observable handling)
  • Mocking support for the bowser library (we’ll use Jest here, but you can adapt for Karma/Jasmine too)

Core Unit Testing Scenarios

1. Mock Browser Detection (via Bowser)

Your service uses bowser to identify the browser, so we need to mock this library to test both Chrome and Firefox logic branches independently.

import { TestBed } from '@angular/core/testing';
import { StorageService } from './storage.service';
import * as bowser from 'bowser';
import { firstValueFrom } from 'rxjs';

// Mock the entire bowser library
jest.mock('bowser', () => ({
  getParser: jest.fn(() => ({
    getBrowserName: jest.fn(),
  })),
}));

describe('StorageService', () => {
  let service: StorageService;
  let mockBowserParser: jest.Mocked<ReturnType<typeof bowser.getParser>>;

  beforeEach(() => {
    TestBed.configureTestingModule({});
    service = TestBed.inject(StorageService);
    
    // Grab our mock parser instance to control browser detection
    mockBowserParser = (bowser.getParser as jest.Mock).mockReturnValue({
      getBrowserName: jest.fn(),
    })();
  });

  it('should fetch quota correctly for Chrome', async () => {
    // Tell bowser we're in Chrome
    mockBowserParser.getBrowserName.mockReturnValue('Chrome');
    
    // Fetch the quota and wait for the Observable to resolve
    const quotaResult = await firstValueFrom(service.getStorageQuota());
    
    expect(quotaResult).toBeDefined();
    // Add assertions specific to Chrome's expected quota structure here
  });

  it('should fetch quota correctly for Firefox', async () => {
    // Switch to Firefox mode
    mockBowserParser.getBrowserName.mockReturnValue('Firefox');
    
    const quotaResult = await firstValueFrom(service.getStorageQuota());
    
    expect(quotaResult).toBeDefined();
    // Add assertions specific to Firefox's expected quota structure here
  });
});

2. Mock Browser Storage API Behavior

Chrome and Firefox might handle storage quota APIs slightly differently (even if they share the same method names). Let’s mock the navigator.storage API to simulate both browser’s response formats.

describe('StorageService', () => {
  // ... previous setup code ...

  beforeEach(() => {
    // Mock the browser's storage API
    Object.defineProperty(window.navigator, 'storage', {
      value: {
        estimate: jest.fn().mockResolvedValue({
          quota: 1073741824, // 1GB
          usage: 524288000   // 500MB
        }),
      },
      writable: true,
    });

    // ... remaining setup ...
  });

  it('should map Firefox-specific API responses correctly', async () => {
    mockBowserParser.getBrowserName.mockReturnValue('Firefox');
    
    // Simulate Firefox's hypothetical response structure (adjust if your service handles this)
    (window.navigator.storage.estimate as jest.Mock).mockResolvedValue({
      totalQuota: 1073741824,
      usedSpace: 524288000
    });
    
    const quotaResult = await firstValueFrom(service.getStorageQuota());
    
    // Verify your service maps Firefox's fields to your standard response shape
    expect(quotaResult.quota).toBe(1073741824);
    expect(quotaResult.usage).toBe(524288000);
  });
});

3. Test Error Handling

Don’t forget to validate edge cases, like when the browser doesn’t support the storage quota API at all:

it('should emit an error if storage API is unsupported', async () => {
  // Remove the mock storage API to simulate an unsupported browser
  delete window.navigator.storage;
  
  await expect(firstValueFrom(service.getStorageQuota())).rejects.toThrow(
    'Storage quota API not supported' // Match your service's error message
  );
});

Optional: End-to-End (E2E) Testing

For real-world validation, use tools like Cypress or Playwright to test your service in actual Chrome and Firefox browsers:

Example with Cypress

describe('Storage Quota Service', () => {
  it('returns valid quota in Chrome', () => {
    cy.visit('/');
    cy.window().then(win => {
      // Grab the service from Angular's injector
      const storageService = win.ng.getComponent(win.document.body).injector.get(StorageService);
      storageService.getStorageQuota().subscribe(quota => {
        expect(quota).to.have.property('quota');
        expect(quota).to.have.property('usage');
      });
    });
  });

  it('returns valid quota in Firefox', () => {
    // Run this test in Firefox (configure Cypress to target multiple browsers)
    cy.visit('/');
    cy.window().then(win => {
      const storageService = win.ng.getComponent(win.document.body).injector.get(StorageService);
      storageService.getStorageQuota().subscribe(quota => {
        expect(quota).to.have.property('quota');
        expect(quota).to.have.property('usage');
      });
    });
  });
});

Key Tips

  • Cover all code branches: Make sure every line of your browser-specific logic is tested with mocks.
  • Use async/await for Observables: firstValueFrom (RxJS 7+) makes handling async Observable tests cleaner than done callbacks.
  • Validate response consistency: Ensure your service returns the same shape of data regardless of the browser, so downstream components don’t break.

内容的提问来源于stack exchange,提问作者Robbert Raats

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:06:22