Back to Repositories

Testing Reactive Map Operations in sveltejs/svelte

This test suite validates the SvelteMap implementation, focusing on reactive map operations and their integration with Svelte’s effect system. The tests verify key Map functionality while ensuring proper reactivity handling and state management.

Test Coverage Overview

The test suite provides comprehensive coverage of SvelteMap operations including values(), get(), has(), forEach(), and delete() methods.

Key functionality tested:
  • Map value mutations and reactivity tracking
  • Effect system integration with map operations
  • Handling of undefined values
  • Map instance type verification
Edge cases include undefined value handling and reactivity behavior when values are not present in the map.

Implementation Analysis

The testing approach uses Vitest for assertions and combines Svelte’s effect_root and render_effect utilities to validate reactive behavior. The tests follow a pattern of setting up initial map state, executing operations within effect contexts, and verifying both the map state and reactive updates through log arrays.

Framework-specific features utilized include:
  • flushSync for synchronous updates
  • effect_root for managing reactive contexts
  • render_effect for tracking reactive dependencies

Technical Details

Testing tools and setup:
  • Vitest for test runner and assertions
  • TypeScript for type safety
  • SvelteMap custom implementation
  • Internal reactivity utilities from Svelte
Configuration includes effect cleanup handling and synchronous update management through flushSync.

Best Practices Demonstrated

The test suite exemplifies high-quality testing practices through comprehensive state verification and proper cleanup of reactive effects. Notable practices include:
  • Isolated test cases for specific functionality
  • Thorough edge case coverage
  • Proper effect cleanup to prevent memory leaks
  • Clear test organization and naming
  • Consistent assertion patterns

sveltejs/svelte

packages/svelte/src/reactivity/map.test.ts

            
import { render_effect, effect_root } from '../internal/client/reactivity/effects.js';
import { flushSync } from '../index-client.js';
import { SvelteMap } from './map.js';
import { assert, test } from 'vitest';

test('map.values()', () => {
	const map = new SvelteMap([
		[1, 1],
		[2, 2],
		[3, 3],
		[4, 4],
		[5, 5]
	]);

	const log: any = [];

	const cleanup = effect_root(() => {
		render_effect(() => {
			log.push(map.size);
		});

		render_effect(() => {
			log.push(map.has(3));
		});

		render_effect(() => {
			log.push(Array.from(map.values()));
		});
	});

	flushSync(() => {
		map.delete(3);
	});

	flushSync(() => {
		map.clear();
	});

	flushSync(() => {
		map.set(3, 3);
	});

	flushSync(() => {
		map.set(3, 4);
	});

	assert.deepEqual(log, [
		5,
		true,
		[1, 2, 3, 4, 5],
		4,
		false,
		[1, 2, 4, 5],
		0,
		false,
		[],
		1,
		true,
		[3],
		true,
		[4]
	]);

	cleanup();
});

test('map.get(...)', () => {
	const map = new SvelteMap([
		[1, 1],
		[2, 2],
		[3, 3]
	]);

	const log: any = [];

	const cleanup = effect_root(() => {
		render_effect(() => {
			log.push('get 1', map.get(1));
		});

		render_effect(() => {
			log.push('get 2', map.get(2));
		});

		render_effect(() => {
			log.push('get 3', map.get(3));
		});
	});

	flushSync(() => {
		map.delete(2);
	});

	flushSync(() => {
		map.set(2, 2);
	});

	assert.deepEqual(log, ['get 1', 1, 'get 2', 2, 'get 3', 3, 'get 2', undefined, 'get 2', 2]);

	cleanup();
});

test('map.has(...)', () => {
	const map = new SvelteMap([
		[1, 1],
		[2, 2],
		[3, 3]
	]);

	const log: any = [];

	const cleanup = effect_root(() => {
		render_effect(() => {
			log.push('has 1', map.has(1));
		});

		render_effect(() => {
			log.push('has 2', map.has(2));
		});

		render_effect(() => {
			log.push('has 3', map.has(3));
		});
	});

	flushSync(() => {
		map.delete(2);
	});

	flushSync(() => {
		map.set(2, 2);
	});

	assert.deepEqual(log, [
		'has 1',
		true,
		'has 2',
		true,
		'has 3',
		true,
		'has 2',
		false,
		'has 2',
		true
	]);

	cleanup();
});

test('map.forEach(...)', () => {
	const map = new SvelteMap([
		[1, 1],
		[2, 2],
		[3, 3]
	]);

	const log: any = [];
	const this_arg = {};

	map.forEach(function (this: unknown, ...args) {
		log.push([...args, this]);
	}, this_arg);

	assert.deepEqual(log, [
		[1, 1, map, this_arg],
		[2, 2, map, this_arg],
		[3, 3, map, this_arg]
	]);
});

test('map.delete(...)', () => {
	const map = new SvelteMap([
		[1, 1],
		[2, 2],
		[3, 3]
	]);

	assert.equal(map.delete(3), true);
	assert.equal(map.delete(3), false);

	assert.deepEqual(Array.from(map.values()), [1, 2]);
});

test('map handling of undefined values', () => {
	const map = new SvelteMap();

	const log: any = [];

	const cleanup = effect_root(() => {
		map.set(1, undefined);

		render_effect(() => {
			log.push(map.get(1));
		});

		flushSync(() => {
			map.delete(1);
		});

		flushSync(() => {
			map.set(1, 1);
		});
	});

	assert.deepEqual(log, [undefined, undefined, 1]);

	cleanup();
});

test('not invoking reactivity when value is not in the map after changes', () => {
	const map = new SvelteMap([[1, 1]]);

	const log: any = [];

	const cleanup = effect_root(() => {
		render_effect(() => {
			log.push(map.get(1));
		});

		render_effect(() => {
			log.push(map.get(2));
		});

		flushSync(() => {
			map.delete(1);
		});

		flushSync(() => {
			map.set(1, 1);
		});
	});

	assert.deepEqual(log, [1, undefined, undefined, undefined, 1, undefined]);

	cleanup();
});

test('Map.instanceOf', () => {
	assert.equal(new SvelteMap() instanceof Map, true);
});