diff --git a/packages/framework/src/Console/Commands/MakePublicationCommand.php b/packages/framework/src/Console/Commands/MakePublicationCommand.php index 11ed8b3c130..6c507cb52dc 100644 --- a/packages/framework/src/Console/Commands/MakePublicationCommand.php +++ b/packages/framework/src/Console/Commands/MakePublicationCommand.php @@ -4,6 +4,7 @@ namespace Hyde\Console\Commands; +use function array_merge; use Hyde\Console\Commands\Helpers\InputStreamHandler; use Hyde\Console\Concerns\ValidatingCommand; use Hyde\Framework\Actions\CreatesNewPublicationPage; @@ -12,8 +13,8 @@ use Hyde\Framework\Features\Publications\PublicationFieldTypes; use Hyde\Framework\Features\Publications\PublicationService; use Illuminate\Support\Collection; -use Illuminate\Support\Str; use function implode; +use function in_array; use InvalidArgumentException; use LaravelZero\Framework\Commands\Command; @@ -27,172 +28,166 @@ class MakePublicationCommand extends ValidatingCommand { /** @var string */ protected $signature = 'make:publication - {publicationType? : The name of the PublicationType to create a publication for} + {publicationType? : The name of the publication type to create a publication for} {--force : Should the generated file overwrite existing publications with the same filename?}'; /** @var string */ protected $description = 'Create a new publication item'; - protected PublicationType $pubType; + protected PublicationType $publicationType; public function safeHandle(): int { - $this->title('Creating a new Publication!'); + $this->title('Creating a new publication!'); - $this->pubType = $this->getPubTypeSelection($this->getPublicationTypes()); - $fieldData = $this->collectFieldData($this->pubType); + $this->publicationType = $this->getPublicationTypeSelection(); - $creator = new CreatesNewPublicationPage($this->pubType, $fieldData, $this->hasForceOption(), $this->output); + $fieldData = $this->collectFieldData(); + + $creator = new CreatesNewPublicationPage($this->publicationType, $fieldData, (bool) $this->option('force')); if ($creator->hasFileConflict()) { $this->error('Error: A publication already exists with the same canonical field value'); if ($this->confirm('Do you wish to overwrite the existing file?')) { $creator->force(); } else { - $this->output->writeln('Exiting without overwriting existing publication file!'); + $this->info('Exiting without overwriting existing publication file!'); return ValidatingCommand::USER_EXIT; } } - $creator->create(); - $this->info('Publication created successfully!'); + $this->info("Created file {$creator->getOutputPath()}"); return Command::SUCCESS; } - protected function captureFieldInput(PublicationField $field, PublicationType $pubType): string|array + protected function getPublicationTypeSelection(): PublicationType { - if ($field->type === PublicationFieldTypes::Text) { - return $this->captureTextFieldInput($field); - } - - if ($field->type === PublicationFieldTypes::Array) { - return $this->captureArrayFieldInput($field); - } - - if ($field->type === PublicationFieldTypes::Image) { - return $this->captureImageFieldInput($field, $pubType); - } - - if ($field->type === PublicationFieldTypes::Tag) { - return $this->captureTagFieldInput($field); - } - - $fieldRules = $this->generateFieldRules($field); - - return $this->askWithValidation($field->name, $field->name, $fieldRules->toArray()); - } + $publicationTypes = $this->getPublicationTypes(); - /** - * @param \Illuminate\Support\Collection $pubTypes - * @return \Hyde\Framework\Features\Publications\Models\PublicationType - */ - protected function getPubTypeSelection(Collection $pubTypes): PublicationType - { - $pubTypeSelection = $this->argument('publicationType') ?? $pubTypes->keys()->get( - (int) $this->choice('Which publication type would you like to create a publication item for?', - $pubTypes->keys()->toArray() + $publicationTypeSelection = $this->argument('publicationType') ?? $publicationTypes->keys()->get( + (int) $this->choice( + 'Which publication type would you like to create a publication item for?', + $publicationTypes->keys()->toArray() ) ); - if ($pubTypes->has($pubTypeSelection)) { - $this->line("Creating a new publication of type [$pubTypeSelection]"); + if ($publicationTypes->has($publicationTypeSelection)) { + $this->line("Creating a new publication of type [$publicationTypeSelection]"); - return $pubTypes->get($pubTypeSelection); + return $publicationTypes->get($publicationTypeSelection); } - throw new InvalidArgumentException("Unable to locate publication type [$pubTypeSelection]"); + throw new InvalidArgumentException("Unable to locate publication type [$publicationTypeSelection]"); } - /** - * @param \Hyde\Framework\Features\Publications\Models\PublicationType $pubType - * @return \Illuminate\Support\Collection - */ - protected function collectFieldData(PublicationType $pubType): Collection + /** @return \Illuminate\Support\Collection */ + protected function getPublicationTypes(): Collection { - $this->output->writeln("\nNow please enter the field data:"); + $publicationTypes = PublicationService::getPublicationTypes(); + if ($publicationTypes->isEmpty()) { + throw new InvalidArgumentException('Unable to locate any publication types. Did you create any?'); + } - return Collection::make($pubType->fields)->mapWithKeys(function ($field) use ($pubType) { - return [$field['name'] => $this->captureFieldInput(PublicationField::fromArray($field), $pubType)]; - }); + return $publicationTypes; } - /** - * @return \Illuminate\Support\Collection - * - * @throws \InvalidArgumentException - */ - protected function getPublicationTypes(): Collection + /** @return \Illuminate\Support\Collection */ + protected function collectFieldData(): Collection { - $pubTypes = PublicationService::getPublicationTypes(); - if ($pubTypes->isEmpty()) { - throw new InvalidArgumentException('Unable to locate any publication types. Did you create any?'); + $this->newLine(); + $this->info('Now please enter the field data:'); + $data = new Collection(); + + /** @var PublicationField $field */ + foreach ($this->publicationType->getFields() as $field) { + $this->newLine(); + $data->put($field->name, $this->captureFieldInput($field)); } - return $pubTypes; + return $data; } - protected function hasForceOption(): bool + protected function captureFieldInput(PublicationField $field): string|array|null { - return (bool) $this->option('force'); + return match ($field->type) { + PublicationFieldTypes::Text => $this->captureTextFieldInput($field), + PublicationFieldTypes::Array => $this->captureArrayFieldInput($field), + PublicationFieldTypes::Image => $this->captureImageFieldInput($field), + PublicationFieldTypes::Tag => $this->captureTagFieldInput($field), + default => $this->askWithValidation($field->name, $field->name, $field->type->rules()), + }; } protected function captureTextFieldInput(PublicationField $field): string { - $this->output->writeln($field->name.' (end with an empty line)'); + $this->line(InputStreamHandler::formatMessage($field->name)); return implode("\n", InputStreamHandler::call()); } protected function captureArrayFieldInput(PublicationField $field): array { - $this->output->writeln($field->name.' (end with an empty line)'); + $this->line(InputStreamHandler::formatMessage($field->name)); return InputStreamHandler::call(); } - protected function captureImageFieldInput(PublicationField $field, PublicationType $pubType): string + protected function captureImageFieldInput(PublicationField $field): string|null { - $this->output->writeln($field->name.' (end with an empty line)'); - do { - $offset = 0; - $mediaFiles = PublicationService::getMediaForPubType($pubType); - foreach ($mediaFiles as $index => $file) { - $offset = $index + 1; - $this->output->writeln(" $offset: $file"); - } - $selected = (int) $this->askWithValidation($field->name, $field->name, ['required', 'integer', "between:1,$offset"]); - } while ($selected == 0); - $file = $mediaFiles->{$selected - 1}; + $this->infoComment('Select file for image field', $field->name); - return '_media/'.Str::of($file)->after('media/')->toString(); + $mediaFiles = PublicationService::getMediaForPubType($this->publicationType); + if ($mediaFiles->isEmpty()) { + return $this->handleEmptyOptionsCollection('media file', "No media files found in directory _media/{$this->publicationType->getIdentifier()}/"); + } + + $filesArray = $mediaFiles->toArray(); + $selection = (int) $this->choice('Which file would you like to use?', $filesArray); + + return $filesArray[$selection]; } - protected function captureTagFieldInput(PublicationField $field) + protected function captureTagFieldInput(PublicationField $field): array|string|null { - $this->output->writeln($field->name.' (enter 0 to reload tag definitions)'); - do { - $offset = 0; - $tagsForGroup = PublicationService::getAllTags()->{$this->pubType->name}; - foreach ($tagsForGroup as $index => $value) { - $offset = $index + 1; - $this->output->writeln(" $offset: $value"); - } - $selected = (int) $this->askWithValidation($field->name, $field->name, ['required', 'integer', "between:0,$offset"]); - } while ($selected == 0); + $this->infoComment('Select a tag for field', $field->name, "from the {$this->publicationType->getIdentifier()} group"); + + $options = PublicationService::getValuesForTagName($this->publicationType->getIdentifier()); + if ($options->isEmpty()) { + return $this->handleEmptyOptionsCollection('tag', 'No tags for this publication type found in tags.json'); + } + + $this->tip('You can enter multiple tags separated by commas'); - return $tagsForGroup->{$selected - 1}; + $reloadMessage = '[Reload tags.json]'; + do { + $options = PublicationService::getValuesForTagName($this->publicationType->getIdentifier()); + $selection = $this->choice( + 'Which tag would you like to use?', + array_merge([$reloadMessage], $options->toArray()), + multiple: true + ); + } while (in_array($reloadMessage, (array) $selection)); + + return $selection; } - // Get rules for fields which are not of type array, text or image - protected function generateFieldRules(PublicationField $field): Collection + /** @return null */ + protected function handleEmptyOptionsCollection(string $type, string $message) { - $fieldRules = Collection::make($field->type->rules()); - if ($fieldRules->contains('between')) { - $fieldRules->forget($fieldRules->search('between')); + $this->newLine(); + $this->warn("Warning: $message"); + // TODO we might want to check if the field has a required rule which should jump straight to the exception + if ($this->confirm('Would you like to skip this field?', true)) { + return null; + } else { + throw new InvalidArgumentException("Unable to locate any {$type}s for this publication type"); } + } - return $fieldRules; + protected function tip(string $message): void + { + $this->line("Tip: $message"); } } diff --git a/packages/framework/src/Framework/Actions/CreatesNewPublicationPage.php b/packages/framework/src/Framework/Actions/CreatesNewPublicationPage.php index 727ccf95e73..c1611115420 100644 --- a/packages/framework/src/Framework/Actions/CreatesNewPublicationPage.php +++ b/packages/framework/src/Framework/Actions/CreatesNewPublicationPage.php @@ -7,14 +7,13 @@ use function array_merge; use Hyde\Framework\Actions\Concerns\CreateAction; use Hyde\Framework\Actions\Contracts\CreateActionContract; -use Hyde\Framework\Features\Publications\Models\PublicationField; use Hyde\Framework\Features\Publications\Models\PublicationType; use Hyde\Framework\Features\Publications\PublicationFieldTypes; -use Illuminate\Console\OutputStyle; use Illuminate\Support\Carbon; use Illuminate\Support\Collection; -use Illuminate\Support\Str; +use function rtrim; use RuntimeException; +use function substr; use Symfony\Component\Yaml\Yaml; use function trim; @@ -30,58 +29,48 @@ public function __construct( protected PublicationType $pubType, protected Collection $fieldData, protected bool $force = false, - protected ?OutputStyle $output = null, ) { - $canonicalFieldName = $this->pubType->canonicalField; - $canonicalFieldDefinition = $this->pubType->getCanonicalFieldDefinition(); - $canonicalValue = $this->getCanonicalValue($canonicalFieldDefinition, $canonicalFieldName); - $canonicalStr = Str::of($canonicalValue)->substr(0, 64); - - $fileName = $this->formatStringForStorage($canonicalStr->slug()->toString()); - $directory = $this->pubType->getDirectory(); - $this->outputPath = "$directory/$fileName.md"; + $this->outputPath = "{$this->pubType->getDirectory()}/{$this->getFilename()}.md"; } protected function handleCreate(): void { - $now = Carbon::now()->format('Y-m-d H:i:s'); - $output = <<createFrontMatter($now)} - --- - - ## Write something awesome. - - - MARKDOWN; - - $this->output?->writeln("Saving publication data to [$this->outputPath]"); + $output = "--- +{$this->createFrontMatter()} +--- + +## Write something awesome. + +"; $this->save($output); } - protected function getCanonicalValue(PublicationField $canonicalFieldDefinition, string $canonicalFieldName): string + protected function getFilename(): string + { + return $this->formatStringForStorage(substr($this->getCanonicalValue(), 0, 64)); + } + + protected function getCanonicalValue(): string { - if ($canonicalFieldName === '__createdAt') { + if ($this->pubType->canonicalField === '__createdAt') { return Carbon::now()->format('Y-m-d H:i:s'); } - // TODO: Is it reasonable to use arrays as canonical field values? - if ($canonicalFieldDefinition->type === PublicationFieldTypes::Array) { - $canonicalValue = ($this->fieldData->get($canonicalFieldName) ?? [])[0]; - } else { - $canonicalValue = $this->fieldData->get($canonicalFieldName); - } + return (string) $this->fieldData->get($this->pubType->canonicalField) + ?: throw new RuntimeException("Could not find field value for '{$this->pubType->canonicalField}' which is required for as it's the type's canonical field", 404); + } - return $canonicalValue ?? throw new RuntimeException("Could not find field value for '$canonicalFieldName' which is required for as it's the type's canonical field", 404); + protected function createFrontMatter(): string + { + return rtrim(Yaml::dump($this->getMergedData(), flags: YAML::DUMP_MULTI_LINE_LITERAL_BLOCK)); } - protected function createFrontMatter(string $now): string + protected function getMergedData(): array { - return rtrim(Yaml::dump($this->normalizeData(array_merge( - ['__createdAt' => $now], $this->fieldData->toArray())), - flags: YAML::DUMP_MULTI_LINE_LITERAL_BLOCK - )); + return array_merge(['__createdAt' => Carbon::now()], + $this->normalizeData($this->fieldData->toArray()) + ); } protected function normalizeData(array $array): array @@ -89,9 +78,7 @@ protected function normalizeData(array $array): array foreach ($array as $key => $value) { $type = $this->pubType->getFields()->get($key); - if ($key === '__createdAt') { - $array[$key] = Carbon::parse($value); - } elseif ($type?->type === PublicationFieldTypes::Text) { + if ($type->type === PublicationFieldTypes::Text) { // In order to properly store text fields as block literals, // we need to make sure they end with a newline. $array[$key] = trim($value)."\n"; diff --git a/packages/framework/tests/Feature/Commands/MakePublicationCommandTest.php b/packages/framework/tests/Feature/Commands/MakePublicationCommandTest.php index 5c6ad0edd97..2fb6357337b 100644 --- a/packages/framework/tests/Feature/Commands/MakePublicationCommandTest.php +++ b/packages/framework/tests/Feature/Commands/MakePublicationCommandTest.php @@ -7,12 +7,13 @@ use function array_merge; use function config; use function file_get_contents; +use function file_put_contents; use Hyde\Console\Commands\Helpers\InputStreamHandler; use Hyde\Facades\Filesystem; use Hyde\Hyde; use Hyde\Testing\TestCase; use Illuminate\Support\Carbon; -use Illuminate\Support\Facades\File; +use function json_encode; /** * @covers \Hyde\Console\Commands\MakePublicationCommand @@ -22,7 +23,6 @@ class MakePublicationCommandTest extends TestCase { protected function setUp(): void { - $this->markTestSkipped('Skipping test as it needs to be integrated in https://github.com/hydephp/develop/pull/774'); parent::setUp(); config(['app.throw_on_console_exception' => true]); @@ -41,15 +41,14 @@ public function test_command_creates_publication() $this->makeSchemaFile(); $this->artisan('make:publication') - ->expectsOutputToContain('Creating a new Publication!') - ->expectsChoice('Which publication type would you like to create a publication item for?', 0, ['test-publication']) - ->expectsOutput('Creating a new publication of type [test-publication]') - ->expectsQuestion('Title', 'Hello World') - ->expectsOutput('Saving publication data to [test-publication/hello-world.md]') - ->expectsOutput('Publication created successfully!') - ->assertExitCode(0); - - $this->assertTrue(File::exists(Hyde::path('test-publication/hello-world.md'))); + ->expectsOutputToContain('Creating a new publication!') + ->expectsChoice('Which publication type would you like to create a publication item for?', 0, ['test-publication']) + ->expectsOutput('Creating a new publication of type [test-publication]') + ->expectsQuestion('Title', 'Hello World') + ->expectsOutput('Created file test-publication/hello-world.md') + ->assertExitCode(0); + + $this->assertFileExists(Hyde::path('test-publication/hello-world.md')); $this->assertPublicationFileWasCreatedCorrectly(); } @@ -57,9 +56,9 @@ public function test_command_with_no_publication_types() { config(['app.throw_on_console_exception' => false]); $this->artisan('make:publication') - ->expectsOutputToContain('Creating a new Publication!') - ->expectsOutput('Error: Unable to locate any publication types. Did you create any?') - ->assertExitCode(1); + ->expectsOutputToContain('Creating a new publication!') + ->expectsOutput('Error: Unable to locate any publication types. Did you create any?') + ->assertExitCode(1); } public function test_command_with_existing_publication() @@ -68,14 +67,14 @@ public function test_command_with_existing_publication() file_put_contents(Hyde::path('test-publication/hello-world.md'), 'foo'); $this->artisan('make:publication') - ->expectsOutputToContain('Creating a new Publication!') - ->expectsChoice('Which publication type would you like to create a publication item for?', 0, ['test-publication']) - ->expectsQuestion('Title', 'Hello World') - ->expectsOutput('Error: A publication already exists with the same canonical field value') - ->expectsConfirmation('Do you wish to overwrite the existing file?') - ->expectsOutput('Exiting without overwriting existing publication file!') - ->doesntExpectOutput('Publication created successfully!') - ->assertExitCode(130); + ->expectsOutputToContain('Creating a new publication!') + ->expectsChoice('Which publication type would you like to create a publication item for?', 0, ['test-publication']) + ->expectsQuestion('Title', 'Hello World') + ->expectsOutput('Error: A publication already exists with the same canonical field value') + ->expectsConfirmation('Do you wish to overwrite the existing file?') + ->expectsOutput('Exiting without overwriting existing publication file!') + ->doesntExpectOutput('Publication created successfully!') + ->assertExitCode(130); $this->assertSame('foo', file_get_contents(Hyde::path('test-publication/hello-world.md'))); } @@ -86,12 +85,11 @@ public function test_command_with_existing_publication_and_overwrite() file_put_contents(Hyde::path('test-publication/hello-world.md'), 'foo'); $this->artisan('make:publication') - ->expectsOutputToContain('Creating a new Publication!') + ->expectsOutputToContain('Creating a new publication!') ->expectsChoice('Which publication type would you like to create a publication item for?', 0, ['test-publication']) ->expectsQuestion('Title', 'Hello World') ->expectsOutput('Error: A publication already exists with the same canonical field value') ->expectsConfirmation('Do you wish to overwrite the existing file?', 'yes') - ->expectsOutput('Publication created successfully!') ->assertExitCode(0); $this->assertNotEquals('foo', file_get_contents(Hyde::path('test-publication/hello-world.md'))); @@ -103,10 +101,9 @@ public function test_can_overwrite_existing_publication_by_passing_force_flag() file_put_contents(Hyde::path('test-publication/hello-world.md'), 'foo'); $this->artisan('make:publication', ['--force' => true]) - ->expectsOutputToContain('Creating a new Publication!') + ->expectsOutputToContain('Creating a new publication!') ->expectsChoice('Which publication type would you like to create a publication item for?', 0, ['test-publication']) ->expectsQuestion('Title', 'Hello World') - ->expectsOutput('Publication created successfully!') ->assertExitCode(0); $this->assertNotEquals('foo', file_get_contents(Hyde::path('test-publication/hello-world.md'))); @@ -117,13 +114,12 @@ public function test_command_with_publication_type_passed_as_argument() $this->makeSchemaFile(); $this->artisan('make:publication test-publication') - ->expectsOutput('Creating a new publication of type [test-publication]') - ->expectsQuestion('Title', 'Hello World') - ->expectsOutput('Saving publication data to [test-publication/hello-world.md]') - ->expectsOutput('Publication created successfully!') - ->assertExitCode(0); + ->expectsOutput('Creating a new publication of type [test-publication]') + ->expectsQuestion('Title', 'Hello World') + ->expectsOutput('Created file test-publication/hello-world.md') + ->assertExitCode(0); - $this->assertTrue(File::exists(Hyde::path('test-publication/hello-world.md'))); + $this->assertFileExists(Hyde::path('test-publication/hello-world.md')); $this->assertPublicationFileWasCreatedCorrectly(); } @@ -133,8 +129,8 @@ public function test_command_with_invalid_publication_type_passed_as_argument() $this->makeSchemaFile(); $this->artisan('make:publication foo') - ->expectsOutput('Error: Unable to locate publication type [foo]') - ->assertExitCode(1); + ->expectsOutput('Error: Unable to locate publication type [foo]') + ->assertExitCode(1); } public function test_command_with_schema_using_canonical_meta_field() @@ -148,22 +144,24 @@ public function test_command_with_schema_using_canonical_meta_field() $this->artisan('make:publication test-publication') ->assertExitCode(0); - $this->assertTrue(File::exists(Hyde::path('test-publication/2022-01-01-000000.md'))); - $this->assertEquals('--- -__createdAt: 2022-01-01 00:00:00 ---- - -## Write something awesome. - -', file_get_contents(Hyde::path('test-publication/2022-01-01-000000.md'))); + $this->assertFileExists(Hyde::path('test-publication/2022-01-01-000000.md')); + $this->assertEquals( + <<<'MARKDOWN' + --- + __createdAt: 2022-01-01T00:00:00+00:00 + --- + + ## Write something awesome. + + + MARKDOWN, file_get_contents(Hyde::path('test-publication/2022-01-01-000000.md'))); } - // text public function test_command_with_text_input() { InputStreamHandler::mockInput("Hello\nWorld"); $this->makeSchemaFile([ - 'canonicalField' => 'description', + 'canonicalField' => '__createdAt', 'fields' => [[ 'type' => 'text', 'name' => 'description', @@ -173,25 +171,18 @@ public function test_command_with_text_input() $this->artisan('make:publication test-publication') ->assertExitCode(0); - $this->assertTrue(File::exists(Hyde::path('test-publication/hello-world.md'))); - $this->assertEquals('--- -__createdAt: 2022-01-01 00:00:00 -description: | - Hello - World ---- - -## Write something awesome. - -', file_get_contents(Hyde::path('test-publication/hello-world.md'))); + $this->assertDatedPublicationExists(); + $this->assertCreatedPublicationMatterEquals('description: | + Hello + World' + ); } - // array public function test_command_with_array_input() { InputStreamHandler::mockInput("First Tag\nSecond Tag\nThird Tag"); $this->makeSchemaFile([ - 'canonicalField' => 'tags', + 'canonicalField' => '__createdAt', 'fields' => [[ 'type' => 'array', 'name' => 'tags', @@ -202,18 +193,164 @@ public function test_command_with_array_input() $this->artisan('make:publication test-publication') ->assertExitCode(0); - $this->assertTrue(File::exists(Hyde::path('test-publication/first-tag.md'))); - $this->assertEquals('--- -__createdAt: 2022-01-01 00:00:00 -tags: - - "First Tag" - - "Second Tag" - - "Third Tag" ---- + $this->assertDatedPublicationExists(); + $this->assertCreatedPublicationMatterEquals( + "tags: + - 'First Tag' + - 'Second Tag' + - 'Third Tag'", + ); + } + + public function test_command_with_image_input() + { + $this->directory('_media/test-publication'); + $this->file('_media/test-publication/image.jpg'); + $this->makeSchemaFile([ + 'canonicalField' => '__createdAt', + 'fields' => [[ + 'type' => 'image', + 'name' => 'image', + ], + ], + ]); + + $this->artisan('make:publication test-publication') + ->expectsQuestion('Which file would you like to use?', '_media/test-publication/image.jpg') + ->assertExitCode(0); + + $this->assertDatedPublicationExists(); + $this->assertCreatedPublicationMatterEquals('image: _media/test-publication/image.jpg'); + } + + public function test_command_with_tag_input() + { + $this->file('tags.json', json_encode([ + 'test-publication' => ['foo', 'bar', 'baz'], + ])); + $this->makeSchemaFile([ + 'canonicalField' => '__createdAt', + 'fields' => [[ + 'type' => 'tag', + 'name' => 'tag', + ], + ], + ]); + + $this->artisan('make:publication test-publication') + ->expectsQuestion('Which tag would you like to use?', 'foo') + ->assertExitCode(0); + + $this->assertDatedPublicationExists(); + $this->assertCreatedPublicationMatterEquals('tag: foo'); + } + + public function test_command_with_multiple_tag_inputs() + { + $this->file('tags.json', json_encode([ + 'test-publication' => ['foo', 'bar', 'baz'], + ])); + $this->makeSchemaFile([ + 'canonicalField' => '__createdAt', + 'fields' => [[ + 'type' => 'tag', + 'name' => 'tags', + ], + ], + ]); + + $this->artisan('make:publication test-publication') + ->expectsQuestion('Which tag would you like to use?', ['foo', 'bar']) + ->assertExitCode(0); + + $this->assertDatedPublicationExists(); + $this->assertCreatedPublicationMatterEquals('tags: + - foo + - bar'); + } + + public function test_image_input_with_no_images() + { + config(['app.throw_on_console_exception' => false]); + $this->makeSchemaFile([ + 'canonicalField' => '__createdAt', + 'fields' => [[ + 'type' => 'image', + 'name' => 'image', + ], + ], + ]); + + $this->artisan('make:publication test-publication') + ->expectsOutput('Warning: No media files found in directory _media/test-publication/') + ->expectsConfirmation('Would you like to skip this field?') + ->expectsOutput('Error: Unable to locate any media files for this publication type') + ->assertExitCode(1); + + $this->assertFileDoesNotExist(Hyde::path('test-publication/2022-01-01-000000.md')); + } + + public function test_image_input_with_no_images_but_skips() + { + $this->makeSchemaFile([ + 'canonicalField' => '__createdAt', + 'fields' => [[ + 'type' => 'image', + 'name' => 'image', + ], + ], + ]); + + $this->artisan('make:publication test-publication') + ->expectsOutput('Warning: No media files found in directory _media/test-publication/') + ->expectsConfirmation('Would you like to skip this field?', 'yes') + ->doesntExpectOutput('Error: Unable to locate any media files for this publication type') + ->assertExitCode(0); + + $this->assertDatedPublicationExists(); + $this->assertCreatedPublicationMatterEquals('image: null'); + } -## Write something awesome. + public function test_tag_input_with_no_tags() + { + config(['app.throw_on_console_exception' => false]); + $this->makeSchemaFile([ + 'canonicalField' => '__createdAt', + 'fields' => [[ + 'type' => 'tag', + 'name' => 'tag', + ], + ], + ]); -', file_get_contents(Hyde::path('test-publication/first-tag.md'))); + $this->artisan('make:publication test-publication') + ->expectsOutput('Warning: No tags for this publication type found in tags.json') + ->expectsConfirmation('Would you like to skip this field?') + ->expectsOutput('Error: Unable to locate any tags for this publication type') + ->assertExitCode(1); + + $this->assertFileDoesNotExist(Hyde::path('test-publication/2022-01-01-000000.md')); + } + + public function test_tag_input_with_no_tags_but_skips() + { + $this->makeSchemaFile([ + 'canonicalField' => '__createdAt', + 'fields' => [[ + 'type' => 'tag', + 'name' => 'tag', + ], + ], + ]); + + $this->artisan('make:publication test-publication') + ->expectsOutput('Warning: No tags for this publication type found in tags.json') + ->expectsConfirmation('Would you like to skip this field?', 'yes') + ->doesntExpectOutput('Error: Unable to locate any tags for this publication type') + ->assertExitCode(0); + + $this->assertDatedPublicationExists(); + $this->assertCreatedPublicationMatterEquals('tag: null'); } protected function makeSchemaFile(array $merge = []): void @@ -246,8 +383,8 @@ protected function assertPublicationFileWasCreatedCorrectly(): void $this->assertEquals( <<<'MARKDOWN' --- - __createdAt: 2022-01-01 00:00:00 - title: Hello World + __createdAt: 2022-01-01T00:00:00+00:00 + title: 'Hello World' --- ## Write something awesome. @@ -256,4 +393,34 @@ protected function assertPublicationFileWasCreatedCorrectly(): void MARKDOWN, file_get_contents(Hyde::path('test-publication/hello-world.md')) ); } + + protected function assertDatedPublicationExists(): void + { + $this->assertFileExists(Hyde::path('test-publication/2022-01-01-000000.md')); + } + + protected function assertCreatedPublicationEquals(string $expected): void + { + $this->assertEquals($expected, $this->getDatedPublicationContents()); + } + + protected function assertCreatedPublicationMatterEquals(string $expected): void + { + $this->assertEquals( + <<getDatedPublicationContents()); + } + + protected function getDatedPublicationContents(): string + { + return file_get_contents(Hyde::path('test-publication/2022-01-01-000000.md')); + } }