← Back to Work

_VOIS / Vodafone UK

Senior Frontend Engineer at _VOIS (Vodafone subsidiary). Shipped CRO features on a high-traffic telecoms platform serving millions of users, and led an Enzyme → React Testing Library migration raising coverage from 70% to 85%.

Role
Senior Frontend Engineer (Mid-senior → Senior)
Published
April 2025
Coverage before
70%
Coverage after
85%
Users
Millions
Next.jsReactTypeScriptContentful CMSReact Testing LibraryPlaywright

NDA note: Internal system names, specific product metrics, and Vodafone-proprietary tooling are not disclosed. The descriptions below cover engineering approach and outcomes at the level cleared for public discussion.

Context

_VOIS is a Vodafone subsidiary. The platform served millions of users across a UK telecoms marketing and product site — high-traffic, performance-sensitive, with a content team publishing changes via Contentful CMS.

Two distinct workstreams during my 18-month tenure:

  1. CRO feature delivery — building data-driven UI features against an internal A/B testing framework, shipping product comparison and decision-flow improvements
  2. Test infrastructure migration — leading the Enzyme → React Testing Library migration, raising coverage from 70% to 85%

Workstream 1 — Product comparison feature (CRO)

Problem

Purchase decision flows had identifiable drop-off in funnel analytics. The hypothesis, shared by product and analytics teams, was that users couldn't compare tariffs side-by-side without leaving the page. A new comparison component would reduce that friction.

Architecture

Implementation

The comparison component needed to:

The Contentful integration used a reference field on the existing page type — editors could tag up to 4 tariff entries for comparison without any new content modelling. The component reads the reference list and renders accordingly.

Outcome

The feature shipped, was A/B tested against the existing decision flow, and contributed to CRO uplift for the purchase funnel. Specific conversion percentages are commercially sensitive and not disclosed here.


Workstream 2 — Enzyme → RTL migration

Problem

The test suite had ~70% coverage but was brittle. Tests were written against component internals — checking whether specific internal methods were called, asserting on implementation details like state variable names. When the team refactored a component's internals (without changing any observable behaviour), multiple tests broke, creating false alarm noise.

The result: engineers were spending time fixing tests that didn't actually catch regressions, and coverage was a vanity metric rather than a signal of confidence.

Architecture — migration strategy

Implementation

The core principle shift: RTL tests ask "does this component behave correctly from the user's perspective?" not "does this component do what I think it does internally?".

// Before (Enzyme) — tests implementation detail
it('should set loading state', () => {
  const wrapper = shallow(<TariffCard id="t1" />)
  expect(wrapper.state('isLoading')).toBe(true)
})
 
// After (RTL) — tests observable behaviour
it('shows a loading skeleton while fetching', async () => {
  render(<TariffCard id="t1" />)
  expect(screen.getByRole('status', { name: /loading/i })).toBeInTheDocument()
  await waitForElementToBeRemoved(() => screen.queryByRole('status'))
  expect(screen.getByText(/monthly/i)).toBeInTheDocument()
})

Handling the connected components: the trickiest migrations were components deeply integrated with Redux or React Query. The pattern we settled on: test at the feature level with a rendered Provider tree, not by mocking the store internals. This made the tests slower but dramatically more reliable — a fake Redux state that mirrors the real API contract.

Mentor role: I led the migration rather than doing it solo. Pair programming sessions with junior engineers on the team were part of the approach — each engineer migrated one component category with guidance. This spread RTL fluency across the team rather than creating a single point of knowledge.

Outcome

This migration was also what I'd now recommend for any team still on Enzyme. The testing pyramid doesn't change, but the confidence per test improves significantly when tests describe observable behaviour.

← All case studies