diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3330a8a..5294f39 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -13,11 +13,13 @@ For a full diff see [`f4208b3...main`][f4208b3...main].
- Added `ValueGenerator` ([#1]), by [@localheinz]
- Added `OptionalValueGenerator` ([#2]), by [@localheinz]
- Added `ConcatenatingValueGenerator` ([#3]), by [@localheinz]
+- Added `SequentialValueGenerator` ([#4]), by [@localheinz]
[f4208b3...main]: https://github.com/ergebnis/data-generator/compare/f4208b3...main
[#1]: https://github.com/ergebnis/data-generator/pull/1
[#2]: https://github.com/ergebnis/data-generator/pull/2
[#3]: https://github.com/ergebnis/data-generator/pull/3
+[#4]: https://github.com/ergebnis/data-generator/pull/4
[@localheinz]: https://github.com/localheinz
diff --git a/README.md b/README.md
index e1cf832..31c159e 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,7 @@ This project comes with the following data generators:
- [`Ergebnis\DataGenerator\ConcatenatingValueGenerator`](#ConcatenatingValuegenerator)
- [`Ergebnis\DataGenerator\OptionalValueGenerator`](#optionalvaluegenerator)
+- [`Ergebnis\DataGenerator\SequentialValueGenerator`](#sequentialvaluegenerator)
- [`Ergebnis\DataGenerator\ValueGenerator`](#valuegenerator)
### `ConcatenatingValueGenerator`
@@ -93,6 +94,40 @@ foreach ($generator->generate() as $value) {
// baz
```
+### `SequentialValueGenerator`
+
+Use the `SequentialValueGenerator` to generate one or more values from one or more `StringGenerator`s:
+
+```php
+generate() as $value) {
+ echo $value . PHP_EOL
+}
+
+// foo
+// bar
+// baz
+// qux
+// quux
+```
+
### `ValueGenerator`
Use the `ValueGenerator` to generate one or more values from a list of `string` values:
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index e48efa3..ae3747f 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -10,6 +10,11 @@
$values
+
+
+ $values
+
+
$values
diff --git a/src/SequentialValueGenerator.php b/src/SequentialValueGenerator.php
new file mode 100644
index 0000000..4edddf8
--- /dev/null
+++ b/src/SequentialValueGenerator.php
@@ -0,0 +1,43 @@
+
+ */
+ private readonly array $generators;
+
+ /**
+ * @throws Exception\InvalidGeneratorsException
+ */
+ public function __construct(StringGenerator ...$generators)
+ {
+ if ([] === $generators) {
+ throw Exception\InvalidGeneratorsException::empty();
+ }
+
+ $this->generators = $generators;
+ }
+
+ public function generate(): \Generator
+ {
+ foreach ($this->generators as $generator) {
+ foreach ($generator->generate() as $value) {
+ yield $value;
+ }
+ }
+ }
+}
diff --git a/test/Unit/SequentialValueGeneratorTest.php b/test/Unit/SequentialValueGeneratorTest.php
new file mode 100644
index 0000000..bfb8373
--- /dev/null
+++ b/test/Unit/SequentialValueGeneratorTest.php
@@ -0,0 +1,71 @@
+expectException(Exception\InvalidGeneratorsException::class);
+
+ new SequentialValueGenerator();
+ }
+
+ public function testGenerateReturnsGeneratorThatYieldsValuesFromOneGenerator(): void
+ {
+ $values = self::faker()->words();
+
+ $generator = new SequentialValueGenerator(new ValueGenerator(...$values));
+
+ $generated = \iterator_to_array($generator->generate());
+
+ self::assertSame($values, $generated);
+ }
+
+ public function testGenerateReturnsGeneratorThatYieldsValuesFromTwoGenerators(): void
+ {
+ $generator = new SequentialValueGenerator(
+ new ValueGenerator(
+ 'foo',
+ 'bar',
+ 'baz',
+ ),
+ new ValueGenerator(
+ 'qux',
+ 'quux',
+ ),
+ );
+
+ $generated = \iterator_to_array($generator->generate());
+
+ $expected = [
+ 'foo',
+ 'bar',
+ 'baz',
+ 'qux',
+ 'quux',
+ ];
+
+ self::assertSame($expected, $generated);
+ }
+}