From e2d385d19fe6a95e7eb15f4a4c2183481ad666a0 Mon Sep 17 00:00:00 2001 From: Koji Onishi Date: Tue, 1 Oct 2024 16:22:17 +0900 Subject: [PATCH] test against YAML desirialization permission options --- spec/lib/dumped_railers/configuration_spec.rb | 15 + spec/lib/dumped_railers/dump_spec.rb | 166 ++-- .../fixture_builder/record_spec.rb | 15 +- spec/lib/dumped_railers/import_spec.rb | 870 ++++++++++-------- spec/lib/dumped_railers_spec.rb | 158 +++- 5 files changed, 734 insertions(+), 490 deletions(-) diff --git a/spec/lib/dumped_railers/configuration_spec.rb b/spec/lib/dumped_railers/configuration_spec.rb index 56c8f07..e498985 100644 --- a/spec/lib/dumped_railers/configuration_spec.rb +++ b/spec/lib/dumped_railers/configuration_spec.rb @@ -101,6 +101,7 @@ config.ignorable_columns = [:uuid] config.preprocessors = [:foo, :bar] config.authorized_models = [:model1, :model2] + config.yaml_column_permitted_classes = [Date] config.a_random_option = 'something' end end @@ -110,6 +111,7 @@ ignorable_columns: [:uuid], preprocessors: [:foo, :bar], authorized_models: [:model1, :model2], + yaml_column_permitted_classes: [Date], a_random_option: 'something', ) } @@ -118,6 +120,7 @@ subject { klass.options[:ignorable_columns] << :published_at klass.options[:preprocessors] << :baz + klass.options[:yaml_column_permitted_classes] << Time } it 'does updates original configurations' do @@ -126,6 +129,7 @@ ignorable_columns: [:uuid, :published_at], preprocessors: [:foo, :bar, :baz], authorized_models: [:model1, :model2], + yaml_column_permitted_classes: [Date, Time], a_random_option: 'something', } ) @@ -141,10 +145,17 @@ config.ignorable_columns = [:uuid] config.preprocessors = [:foo, :bar] config.authorized_models = [:model1, :model2] + config.yaml_column_permitted_classes = [Date, Time] config.a_random_option = :something end end + it 'has preset options' do + expect { subject }.to change { klass.options.keys }.to contain_exactly( + *%i[ignorable_columns preprocessors authorized_models yaml_column_permitted_classes] + ) + end + it 'resets ignorable_columns' do expect { subject }.to change { klass.ignorable_columns }.to %w[id created_at updated_at] end @@ -157,6 +168,10 @@ expect { subject }.to change { klass.authorized_models }.to :any end + it 'resets yaml_column_permitted_classes' do + expect { subject }.to change { klass.yaml_column_permitted_classes }.to match_array(ActiveRecord.yaml_column_permitted_classes + [Date Time DateTime]) + end + it 'resets other options' do expect { subject }.to change { klass.instance_variable_get(:@_config).a_random_option }.to nil end diff --git a/spec/lib/dumped_railers/dump_spec.rb b/spec/lib/dumped_railers/dump_spec.rb index 5332c76..ef11670 100644 --- a/spec/lib/dumped_railers/dump_spec.rb +++ b/spec/lib/dumped_railers/dump_spec.rb @@ -7,9 +7,9 @@ let!(:author1) { Author.create!(name: 'William Shakespeare') } let!(:author2) { Author.create!(name: 'Shikibu Murasaki') } - let!(:article1) { Article.create!(title: 'Romeo and Juliet', writer: author1) } - let!(:article2) { Article.create!(title: 'King Lear', writer: author1) } - let!(:article3) { Article.create!(title: 'Genji Monogatari', writer: author2) } + let!(:article1) { Article.create!(title: 'Romeo and Juliet', writer: author1, published_date: '2020-10-10', published_time: '12:00:00', first_drafted_at: '2020-10-01 12:00:00') } + let!(:article2) { Article.create!(title: 'King Lear', writer: author1, published_date: '2021-10-10', published_time: '12:00:00', first_drafted_at: '2021-10-01 12:00:00') } + let!(:article3) { Article.create!(title: 'Genji Monogatari', writer: author2, published_date: '2022-10-10', published_time: '12:00:00', first_drafted_at: '2022-10-01 12:00:00') } let(:models) { [Author, Article] } context 'without any preprocessors' do @@ -19,42 +19,69 @@ is_expected.to match( 'authors' => { - '_fixture' => - { - 'model_class' => 'Author', - 'fixture_generated_by' => 'DumpedRailers', - }, - "__author_#{author1.id}" => { - 'id' => author1.id, + '_fixture' => + { + 'model_class' => 'Author', + 'fixture_generated_by' => 'DumpedRailers', + }, + "__author_#{author1.id}" => { + 'id' => author1.id, 'name' => author1.name - }, - "__author_#{author2.id}" => { - 'id' => author2.id, + }, + "__author_#{author2.id}" => { + 'id' => author2.id, 'name' => author2.name - }, - }, + }, + }, 'articles' => { - '_fixture' => - { - 'model_class' => 'Article', - 'fixture_generated_by' => 'DumpedRailers', - }, - "__article_#{article1.id}" => { - 'id' => article1.id, - 'title' => article1.title, + '_fixture' => + { + 'model_class' => 'Article', + 'fixture_generated_by' => 'DumpedRailers', + }, + "__article_#{article1.id}" => { + 'id' => article1.id, + 'title' => article1.title, 'writer' => "__author_#{author1.id}", - }, - "__article_#{article2.id}" => { - 'id' => article2.id, - 'title' => article2.title, + 'published_date' => have_attributes( + to_formatted_s: '2020-10-10' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => have_attributes( + to_formatted_s: a_string_including('2020-10-01 12:00:00') + ), + }, + "__article_#{article2.id}" => { + 'id' => article2.id, + 'title' => article2.title, 'writer' => "__author_#{author1.id}", - }, - "__article_#{article3.id}" => { - 'id' => article3.id, - 'title' => article3.title, + 'published_date' => have_attributes( + to_formatted_s: '2021-10-10' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => have_attributes( + to_formatted_s: a_string_including('2021-10-01 12:00:00') + ), + }, + "__article_#{article3.id}" => { + 'id' => article3.id, + 'title' => article3.title, 'writer' => "__author_#{author2.id}", - }, + 'published_date' => have_attributes( + to_formatted_s: '2022-10-10' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => have_attributes( + to_formatted_s: a_string_including('2022-10-01 12:00:00') + ), + }, } ) } @@ -78,37 +105,64 @@ is_expected.to match( 'authors' => { - '_fixture' => - { - 'model_class' => 'Author', - 'fixture_generated_by' => 'DumpedRailers', - }, - "__author_#{author1.id}" => { + '_fixture' => + { + 'model_class' => 'Author', + 'fixture_generated_by' => 'DumpedRailers', + }, + "__author_#{author1.id}" => { 'name' => author1.name.upcase - }, - "__author_#{author2.id}" => { + }, + "__author_#{author2.id}" => { 'name' => author2.name.upcase - }, - }, + }, + }, 'articles' => { - '_fixture' => - { - 'model_class' => 'Article', - 'fixture_generated_by' => 'DumpedRailers', - }, - "__article_#{article1.id}" => { - 'title' => article1.title, + '_fixture' => + { + 'model_class' => 'Article', + 'fixture_generated_by' => 'DumpedRailers', + }, + "__article_#{article1.id}" => { + 'title' => article1.title, 'writer' => "__author_#{author1.id}", - }, - "__article_#{article2.id}" => { - 'title' => article2.title, + 'published_date' => have_attributes( + to_formatted_s: '2020-10-10' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => have_attributes( + to_formatted_s: a_string_including('2020-10-01 12:00:00') + ), + }, + "__article_#{article2.id}" => { + 'title' => article2.title, 'writer' => "__author_#{author1.id}", - }, - "__article_#{article3.id}" => { - 'title' => article3.title, + 'published_date' => have_attributes( + to_formatted_s: '2021-10-10' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => have_attributes( + to_formatted_s: a_string_including('2021-10-01 12:00:00') + ), + }, + "__article_#{article3.id}" => { + 'title' => article3.title, 'writer' => "__author_#{author2.id}", - }, + 'published_date' => have_attributes( + to_formatted_s: '2022-10-10' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => have_attributes( + to_formatted_s: a_string_including('2022-10-01 12:00:00') + ), + }, } ) } diff --git a/spec/lib/dumped_railers/fixture_builder/record_spec.rb b/spec/lib/dumped_railers/fixture_builder/record_spec.rb index 9ebf828..e4a04ad 100644 --- a/spec/lib/dumped_railers/fixture_builder/record_spec.rb +++ b/spec/lib/dumped_railers/fixture_builder/record_spec.rb @@ -40,14 +40,21 @@ context 'when the record has a direct reference (using primary_key)' do let(:author) { Author.create!(name: 'Edgar Allan Poe') } - let(:record) { Article.create!(title: 'The Murders in the Rue Morgue', writer: author) } + let(:record) { Article.create!(title: 'The Murders in the Rue Morgue', writer: author, published_date: '2020-01-01', published_time: '12:00:00') } let(:model) { Article } it { is_expected.to match( - 'id' => record.id, - 'title' => 'The Murders in the Rue Morgue', - 'writer' => "__author_#{author.id}" + 'id' => record.id, + 'title' => 'The Murders in the Rue Morgue', + 'writer' => "__author_#{author.id}", + 'published_date' => have_attributes( + to_formatted_s: '2020-01-01' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => nil, ) } end diff --git a/spec/lib/dumped_railers/import_spec.rb b/spec/lib/dumped_railers/import_spec.rb index 95f14b2..06c53e6 100644 --- a/spec/lib/dumped_railers/import_spec.rb +++ b/spec/lib/dumped_railers/import_spec.rb @@ -6,278 +6,451 @@ described_class.new( *paths, authorized_models: authorized_models, + yaml_column_permitted_classes: yaml_column_permitted_classes, ) } subject { import_handler.import_all! } - context 'with full authorization' do + + context 'without permissions to relevant classes (Date, Time)' do let(:authorized_models) { :any } + let(:paths) { ['spec/fixtures/authors.yml', 'spec/fixtures/articles.yml'] } + context 'without any permissions' do + let(:yaml_column_permitted_classes) { [] } - context 'with fixture file paths' do - context 'with files that satisfies dependencies' do - let(:paths) { ['spec/fixtures/authors.yml', 'spec/fixtures/articles.yml'] } + it 'raises Psych::DisallowedClass' do + expect { subject }.to raise_error Psych::DisallowedClass + end + end - it 'generates corresponding records' do - expect { subject }.to change { Author.count }.by(5).and change { Article.count }.by(8) - end + context 'without partical permissions' do + let(:yaml_column_permitted_classes) { [Date] } - it 'generates author records' do - subject + it 'raises Psych::DisallowedClass' do + expect { subject }.to raise_error Psych::DisallowedClass + end + end + end - expect(Author.all).to contain_exactly( - have_attributes( - name: 'Osamu Tezuka' - ), - have_attributes( - name: 'J. K. Rowling' - ), - have_attributes( - name: 'Hayao Miyazaki' - ), - have_attributes( - name: 'Walt Disney' - ), - have_attributes( - name: 'John Ronald Reuel Tolkien' - ), - ) - end + context 'with permissions to relevant classes (Date, Time)' do + let(:yaml_column_permitted_classes) { [Date, Time] } - it 'generates article records with proper associations' do - subject + context 'with full authorization' do + let(:authorized_models) { :any } - expect(Article.all).to contain_exactly( - have_attributes( - title: 'Harry Potter', - writer: have_attributes( - name: 'J. K. Rowling' + context 'with fixture file paths' do + context 'with files that satisfies dependencies' do + let(:paths) { ['spec/fixtures/authors.yml', 'spec/fixtures/articles.yml'] } + + it 'generates corresponding records' do + expect { subject }.to change { Author.count }.by(5).and change { Article.count }.by(8) + end + + it 'generates author records' do + subject + + expect(Author.all).to contain_exactly( + have_attributes( + name: 'Osamu Tezuka' ), - ), - have_attributes( - title: 'Princess Mononoke', - writer: have_attributes( - name: 'Hayao Miyazaki' + have_attributes( + name: 'J. K. Rowling' ), - ), - have_attributes( - title: 'Sprited Away', - writer: have_attributes( + have_attributes( name: 'Hayao Miyazaki' ), - ), - have_attributes( - title: 'Alice in Wonderland', - writer: have_attributes( + have_attributes( name: 'Walt Disney' ), - ), - have_attributes( - title: 'Peter Pan', - writer: have_attributes( - name: 'Walt Disney' - ), - ), - have_attributes( - title: 'The Lord of the Rings', - writer: have_attributes( + have_attributes( name: 'John Ronald Reuel Tolkien' ), - ), - have_attributes( - title: 'Phoenix', - writer: have_attributes( - name: 'Osamu Tezuka' - ), - ), - have_attributes( - title: 'Black Jack', - writer: have_attributes( - name: 'Osamu Tezuka' - ), - ), - ) - end - end + ) + end - context 'with files that lack dependent records' do - let(:paths) { - [ - 'spec/fixtures/content_holders.yml', - 'spec/fixtures/text_contents.yml', - 'spec/fixtures/picture_contents.yml', - 'spec/fixtures/video_contents.yml', - ] - } + it 'generates article records with proper associations' do + subject - it 'raises RuntimeError' do - expect { subject }.to raise_error RuntimeError + expect(Article.all).to contain_exactly( + have_attributes( + title: 'Phoenix', + writer: have_attributes( + name: 'Osamu Tezuka' + ), + published_date: have_attributes( + to_formatted_s: '2024-04-01', + ), + published_time: have_attributes( + to_formatted_s: include('10:30:00'), + ), + first_drafted_at: have_attributes( + to_formatted_s: '2024-02-01 12:12:12 UTC', + ), + ), + have_attributes( + title: 'Harry Potter', + writer: have_attributes( + name: 'J. K. Rowling' + ), + published_date: have_attributes( + to_formatted_s: '2024-03-01', + ), + published_time: have_attributes( + to_formatted_s: include('10:00:00'), + ), + first_drafted_at: have_attributes( + to_formatted_s: '2024-02-01 01:10:10 UTC', + ), + ), + have_attributes( + title: 'Princess Mononoke', + writer: have_attributes( + name: 'Hayao Miyazaki' + ), + published_date: have_attributes( + to_formatted_s: '2024-05-01', + ), + published_time: have_attributes( + to_formatted_s: include('09:00:00'), + ), + first_drafted_at: have_attributes( + to_formatted_s: '2024-02-01 13:08:08 UTC', + ), + ), + have_attributes( + title: 'Sprited Away', + writer: have_attributes( + name: 'Hayao Miyazaki' + ), + ), + have_attributes( + title: 'Alice in Wonderland', + writer: have_attributes( + name: 'Walt Disney' + ), + ), + have_attributes( + title: 'Peter Pan', + writer: have_attributes( + name: 'Walt Disney' + ), + ), + have_attributes( + title: 'The Lord of the Rings', + writer: have_attributes( + name: 'John Ronald Reuel Tolkien' + ), + ), + have_attributes( + title: 'Black Jack', + writer: have_attributes( + name: 'Osamu Tezuka' + ), + ), + ) + end end - end - context 'with a directory' do - let(:paths) { ['spec/fixtures/'] } + context 'with files that lack dependent records' do + let(:paths) { + [ + 'spec/fixtures/content_holders.yml', + 'spec/fixtures/text_contents.yml', + 'spec/fixtures/picture_contents.yml', + 'spec/fixtures/video_contents.yml', + ] + } - it 'generates corresponding records' do - expect { subject }.to change { Author.count }.by(5) - .and change { Article.count }.by(8) - .and change { ContentHolder.count }.by(15) - .and change { TextContent.count }.by(9) - .and change { PictureContent.count }.by(3) - .and change { VideoContent.count }.by(3) + it 'raises RuntimeError' do + expect { subject }.to raise_error RuntimeError + end end - it 'generates author records' do - subject + context 'with a directory' do + let(:paths) { ['spec/fixtures/'] } - expect(Author.all).to contain_exactly( - have_attributes( - name: 'Osamu Tezuka' - ), - have_attributes( - name: 'J. K. Rowling' - ), - have_attributes( - name: 'Hayao Miyazaki' - ), - have_attributes( - name: 'Walt Disney' - ), - have_attributes( - name: 'John Ronald Reuel Tolkien' - ), - ) - end + it 'generates corresponding records' do + expect { subject }.to change { Author.count }.by(5) + .and change { Article.count }.by(8) + .and change { ContentHolder.count }.by(15) + .and change { TextContent.count }.by(9) + .and change { PictureContent.count }.by(3) + .and change { VideoContent.count }.by(3) + end - it 'generates article records with proper associations' do - subject + it 'generates author records' do + subject - expect(Article.all).to contain_exactly( - have_attributes( - title: 'Harry Potter', - writer: have_attributes( + expect(Author.all).to contain_exactly( + have_attributes( + name: 'Osamu Tezuka' + ), + have_attributes( name: 'J. K. Rowling' ), - ), - have_attributes( - title: 'Princess Mononoke', - writer: have_attributes( + have_attributes( name: 'Hayao Miyazaki' ), - ), - have_attributes( - title: 'Sprited Away', - writer: have_attributes( - name: 'Hayao Miyazaki' - ), - ), - have_attributes( - title: 'Alice in Wonderland', - writer: have_attributes( - name: 'Walt Disney' - ), - ), - have_attributes( - title: 'Peter Pan', - writer: have_attributes( + have_attributes( name: 'Walt Disney' ), - ), - have_attributes( - title: 'The Lord of the Rings', - writer: have_attributes( + have_attributes( name: 'John Ronald Reuel Tolkien' ), - ), - have_attributes( - title: 'Phoenix', - writer: have_attributes( - name: 'Osamu Tezuka' - ), - ), - have_attributes( - title: 'Black Jack', - writer: have_attributes( - name: 'Osamu Tezuka' - ), - ), - ) - end + ) + end - it 'generates content holders' do - subject + it 'generates article records with proper associations' do + subject - expect(ContentHolder.all).to contain_exactly( - have_attributes( - article: have_attributes( + expect(Article.all).to contain_exactly( + have_attributes( + title: 'Harry Potter', + writer: have_attributes( + name: 'J. K. Rowling' + ), + ), + have_attributes( + title: 'Princess Mononoke', + writer: have_attributes( + name: 'Hayao Miyazaki' + ), + ), + have_attributes( + title: 'Sprited Away', + writer: have_attributes( + name: 'Hayao Miyazaki' + ), + ), + have_attributes( + title: 'Alice in Wonderland', + writer: have_attributes( + name: 'Walt Disney' + ), + ), + have_attributes( + title: 'Peter Pan', + writer: have_attributes( + name: 'Walt Disney' + ), + ), + have_attributes( title: 'The Lord of the Rings', + writer: have_attributes( + name: 'John Ronald Reuel Tolkien' + ), ), - content: have_attributes( - body: "Where there's life there's hope, and need of vittles." + have_attributes( + title: 'Phoenix', + writer: have_attributes( + name: 'Osamu Tezuka' + ), ), - ), - have_attributes( - article: have_attributes( + have_attributes( title: 'Black Jack', + writer: have_attributes( + name: 'Osamu Tezuka' + ), ), - content: have_attributes( - body: "I don't know his real name, but they call him Black Jack." + ) + end + + it 'generates content holders' do + subject + + expect(ContentHolder.all).to contain_exactly( + have_attributes( + article: have_attributes( + title: 'The Lord of the Rings', + ), + content: have_attributes( + body: "Where there's life there's hope, and need of vittles." + ), + ), + have_attributes( + article: have_attributes( + title: 'Black Jack', + ), + content: have_attributes( + body: "I don't know his real name, but they call him Black Jack." + ), + ), + have_attributes( + article: have_attributes( + title: 'Alice in Wonderland', + ), + content: have_attributes( + body: 'This is an unbirthday party!' + ), + ), + have_attributes( + article: have_attributes( + title: 'Princess Mononoke', + ), + content: have_attributes( + body: 'To see with eyes unclouded by hate.' + ), + ), + have_attributes( + article: have_attributes( + title: 'Princess Mononoke', + ), + content: have_attributes( + body: 'You see everyone wants everything, that’s the way the world is.' + ), + ), + have_attributes( + article: have_attributes( + title: 'Phoenix', + ), + content: have_attributes( + body: "Life? Death? It's all meaningless!" + ), + ), + have_attributes( + article: have_attributes( + title: 'Harry Potter', + ), + content: have_attributes( + body: 'Of course it is happening inside your head, Harry, but why on earth should that mean that it is not real?' + ), + ), + have_attributes( + article: have_attributes( + title: 'Alice in Wonderland', + ), + content: have_attributes( + body: 'But how can one possibly pay attention to a book with no pictures in it?' + ), + ), + have_attributes( + content: have_attributes( + body: 'Our greatest natural resource is the minds of our children.' + ), + ), + have_attributes( + content: have_attributes( + file: { + 'url' => 'https://example.com/storage/the_hobbit/98x45672a.jpg', + 'metadata' => { + 'size' => 193450, + 'filename' => 'hobit.jpg', + } + } + ), + ), + have_attributes( + article: have_attributes( + title: 'Princess Mononoke', + ), + content: have_attributes( + file: { + 'url' => 'https://example.com/storage/princess_mononoke/98q3r28289s.png', + 'metadata' => { + 'size' => 1230890, + 'filename' => 'haku.png', + } + } + ), + ), + have_attributes( + article: have_attributes( + title: 'Phoenix', + ), + content: have_attributes( + file: { + 'url' => 'https://example.com/storage/phoenix/98m298sm912.jpg', + 'metadata' => { + 'size' => 823890, + 'filename' => 'phoenix.jpg', + } + } + ), + ), + have_attributes( + article: have_attributes( + title: 'Peter Pan', + ), + content: have_attributes( + file: { + 'url' => 'https://example.com/storage/peter_pan/9382sjdf8.mp4', + 'metadata' => { + 'size' => 9178348, + 'filename' => 'peter_and_wendy.mp4', + } + } + ), + ), + have_attributes( + article: have_attributes( + title: 'Harry Potter', + ), + content: have_attributes( + file: { + 'url' => 'https://example.com/storage/harry_potter/e9128347l.mp4', + 'metadata' => { + 'size' => 41735021, + 'filename' => 'hogwarts.mp4', + } + } + ), + ), + have_attributes( + article: have_attributes( + title: 'Sprited Away', + ), + content: have_attributes( + file: { + 'url' => 'https://example.com/storage/spritted_away/i012387413a.mp4', + 'metadata' => { + 'size' => 9747403, + 'filename' => 'yubaba.mp4', + } + } + ), ), - ), - have_attributes( - article: have_attributes( - title: 'Alice in Wonderland', + ) + end + + it 'generates text contents' do + subject + + expect(TextContent.all).to contain_exactly( + have_attributes( + body: "Where there's life there's hope, and need of vittles." ), - content: have_attributes( - body: 'This is an unbirthday party!' + have_attributes( + body: "I don't know his real name, but they call him Black Jack." ), - ), - have_attributes( - article: have_attributes( - title: 'Princess Mononoke', + have_attributes( + body: 'This is an unbirthday party!' ), - content: have_attributes( + have_attributes( body: 'To see with eyes unclouded by hate.' ), - ), - have_attributes( - article: have_attributes( - title: 'Princess Mononoke', - ), - content: have_attributes( + have_attributes( body: 'You see everyone wants everything, that’s the way the world is.' ), - ), - have_attributes( - article: have_attributes( - title: 'Phoenix', - ), - content: have_attributes( + have_attributes( body: "Life? Death? It's all meaningless!" ), - ), - have_attributes( - article: have_attributes( - title: 'Harry Potter', - ), - content: have_attributes( + have_attributes( body: 'Of course it is happening inside your head, Harry, but why on earth should that mean that it is not real?' ), - ), - have_attributes( - article: have_attributes( - title: 'Alice in Wonderland', - ), - content: have_attributes( + have_attributes( body: 'But how can one possibly pay attention to a book with no pictures in it?' ), - ), - have_attributes( - content: have_attributes( + have_attributes( body: 'Our greatest natural resource is the minds of our children.' ), - ), - have_attributes( - content: have_attributes( + ) + end + + it 'generates picture contents' do + subject + + expect(PictureContent.all).to contain_exactly( + have_attributes( file: { 'url' => 'https://example.com/storage/the_hobbit/98x45672a.jpg', 'metadata' => { @@ -286,12 +459,7 @@ } } ), - ), - have_attributes( - article: have_attributes( - title: 'Princess Mononoke', - ), - content: have_attributes( + have_attributes( file: { 'url' => 'https://example.com/storage/princess_mononoke/98q3r28289s.png', 'metadata' => { @@ -300,12 +468,7 @@ } } ), - ), - have_attributes( - article: have_attributes( - title: 'Phoenix', - ), - content: have_attributes( + have_attributes( file: { 'url' => 'https://example.com/storage/phoenix/98m298sm912.jpg', 'metadata' => { @@ -314,12 +477,14 @@ } } ), - ), - have_attributes( - article: have_attributes( - title: 'Peter Pan', - ), - content: have_attributes( + ) + end + + it 'generates video contents' do + subject + + expect(VideoContent.all).to contain_exactly( + have_attributes( file: { 'url' => 'https://example.com/storage/peter_pan/9382sjdf8.mp4', 'metadata' => { @@ -328,12 +493,7 @@ } } ), - ), - have_attributes( - article: have_attributes( - title: 'Harry Potter', - ), - content: have_attributes( + have_attributes( file: { 'url' => 'https://example.com/storage/harry_potter/e9128347l.mp4', 'metadata' => { @@ -342,12 +502,7 @@ } } ), - ), - have_attributes( - article: have_attributes( - title: 'Sprited Away', - ), - content: have_attributes( + have_attributes( file: { 'url' => 'https://example.com/storage/spritted_away/i012387413a.mp4', 'metadata' => { @@ -356,195 +511,93 @@ } } ), - ), - ) + ) + end end + end - it 'generates text contents' do - subject + context 'with in-memory fixtures' do + let(:fixtures) { + { + 'authors' => { + '_fixture' => + { + 'model_class' => 'Author', + 'fixture_generated_by' => 'DumpedRailers', + }, + '__author_1' => { + 'name' => 'William Shakespeare', + }, + '__author_2' => { + 'name' => 'Shikibu Murasaki', + }, + }, + 'articles' => { + '_fixture' => + { + 'model_class' => 'Article', + 'fixture_generated_by' => 'DumpedRailers', + }, + '__article_1' => { + 'title' => 'Romeo and Juliet', + 'writer' => '__author_1' + }, + '__article_2' => { + 'title' => 'King Lear', + 'writer' => '__author_1' + }, + '__article_3' => { + 'title' => 'Genji Monogatari', + 'writer' => '__author_2' + }, + } + } + } + let(:paths) { [fixtures] } - expect(TextContent.all).to contain_exactly( - have_attributes( - body: "Where there's life there's hope, and need of vittles." - ), - have_attributes( - body: "I don't know his real name, but they call him Black Jack." - ), - have_attributes( - body: 'This is an unbirthday party!' - ), - have_attributes( - body: 'To see with eyes unclouded by hate.' - ), - have_attributes( - body: 'You see everyone wants everything, that’s the way the world is.' - ), - have_attributes( - body: "Life? Death? It's all meaningless!" - ), - have_attributes( - body: 'Of course it is happening inside your head, Harry, but why on earth should that mean that it is not real?' - ), - have_attributes( - body: 'But how can one possibly pay attention to a book with no pictures in it?' - ), - have_attributes( - body: 'Our greatest natural resource is the minds of our children.' - ), - ) + it 'generates corresponding records' do + expect { subject }.to change { Author.count }.by(2).and change { Article.count }.by(3) end - it 'generates picture contents' do + it 'generates author records' do subject - expect(PictureContent.all).to contain_exactly( - have_attributes( - file: { - 'url' => 'https://example.com/storage/the_hobbit/98x45672a.jpg', - 'metadata' => { - 'size' => 193450, - 'filename' => 'hobit.jpg', - } - } - ), + expect(Author.all).to contain_exactly( have_attributes( - file: { - 'url' => 'https://example.com/storage/princess_mononoke/98q3r28289s.png', - 'metadata' => { - 'size' => 1230890, - 'filename' => 'haku.png', - } - } + name: 'William Shakespeare' ), have_attributes( - file: { - 'url' => 'https://example.com/storage/phoenix/98m298sm912.jpg', - 'metadata' => { - 'size' => 823890, - 'filename' => 'phoenix.jpg', - } - } + name: 'Shikibu Murasaki' ), ) end - it 'generates video contents' do + it 'generates article records with proper associations' do subject - expect(VideoContent.all).to contain_exactly( + expect(Article.all).to contain_exactly( have_attributes( - file: { - 'url' => 'https://example.com/storage/peter_pan/9382sjdf8.mp4', - 'metadata' => { - 'size' => 9178348, - 'filename' => 'peter_and_wendy.mp4', - } - } + title: 'Romeo and Juliet', + writer: have_attributes( + name: 'William Shakespeare' + ), ), have_attributes( - file: { - 'url' => 'https://example.com/storage/harry_potter/e9128347l.mp4', - 'metadata' => { - 'size' => 41735021, - 'filename' => 'hogwarts.mp4', - } - } + title: 'King Lear', + writer: have_attributes( + name: 'William Shakespeare' + ), ), have_attributes( - file: { - 'url' => 'https://example.com/storage/spritted_away/i012387413a.mp4', - 'metadata' => { - 'size' => 9747403, - 'filename' => 'yubaba.mp4', - } - } + title: 'Genji Monogatari', + writer: have_attributes( + name: 'Shikibu Murasaki' + ), ), ) end end end - - context 'with in-memory fixtures' do - let(:fixtures) { - { - 'authors' => { - '_fixture' => - { - 'model_class' => 'Author', - 'fixture_generated_by' => 'DumpedRailers', - }, - '__author_1' => { - 'name' => 'William Shakespeare', - }, - '__author_2' => { - 'name' => 'Shikibu Murasaki', - }, - }, - 'articles' => { - '_fixture' => - { - 'model_class' => 'Article', - 'fixture_generated_by' => 'DumpedRailers', - }, - '__article_1' => { - 'title' => 'Romeo and Juliet', - 'writer' => '__author_1' - }, - '__article_2' => { - 'title' => 'King Lear', - 'writer' => '__author_1' - }, - '__article_3' => { - 'title' => 'Genji Monogatari', - 'writer' => '__author_2' - }, - } - } - } - let(:paths) { [fixtures] } - - it 'generates corresponding records' do - expect { subject }.to change { Author.count }.by(2).and change { Article.count }.by(3) - end - - it 'generates author records' do - subject - - expect(Author.all).to contain_exactly( - have_attributes( - name: 'William Shakespeare' - ), - have_attributes( - name: 'Shikibu Murasaki' - ), - ) - end - - it 'generates article records with proper associations' do - subject - - expect(Article.all).to contain_exactly( - have_attributes( - title: 'Romeo and Juliet', - writer: have_attributes( - name: 'William Shakespeare' - ), - ), - have_attributes( - title: 'King Lear', - writer: have_attributes( - name: 'William Shakespeare' - ), - ), - have_attributes( - title: 'Genji Monogatari', - writer: have_attributes( - name: 'Shikibu Murasaki' - ), - ), - ) - end - end end describe 'callbacks' do @@ -553,11 +606,13 @@ *paths, authorized_models: :any, before_save: before_callbacks, - after_save: after_callbacks, + after_save: after_callbacks, + yaml_column_permitted_classes: yaml_column_permitted_classes, ) } let(:paths) { ['spec/fixtures/authors.yml', 'spec/fixtures/articles.yml'] } + let(:yaml_column_permitted_classes) { [Date, Time] } let(:before_callbacks) { [] } let(:after_callbacks) { [] } @@ -783,6 +838,7 @@ context 'when authorization granted for all the imported models' do let(:authorized_models) { [Author, Article] } let(:paths) { ['spec/fixtures/authors.yml', 'spec/fixtures/articles.yml'] } + let(:yaml_column_permitted_classes) { [Date, Time] } it 'does not raise RuntimeError' do expect { subject }.not_to raise_error @@ -796,6 +852,7 @@ context 'when authorization missing for part of the imported models' do let(:authorized_models) { [Author] } let(:paths) { ['spec/fixtures/authors.yml', 'spec/fixtures/articles.yml'] } + let(:yaml_column_permitted_classes) { [Date, Time] } it 'raises RuntimeError' do expect { subject }.to raise_error RuntimeError @@ -813,6 +870,7 @@ context 'with no authorization' do let(:authorized_models) { [] } let(:paths) { ['spec/fixtures/authors.yml', 'spec/fixtures/articles.yml'] } + let(:yaml_column_permitted_classes) { [Date, Time] } it 'raises RuntimeError' do expect { subject }.to raise_error RuntimeError diff --git a/spec/lib/dumped_railers_spec.rb b/spec/lib/dumped_railers_spec.rb index 4208689..fd18705 100644 --- a/spec/lib/dumped_railers_spec.rb +++ b/spec/lib/dumped_railers_spec.rb @@ -5,9 +5,9 @@ let!(:author1) { Author.create!(name: 'William Shakespeare') } let!(:author2) { Author.create!(name: 'Shikibu Murasaki') } - let!(:article1) { Article.create!(title: 'Romeo and Juliet', writer: author1) } - let!(:article2) { Article.create!(title: 'King Lear', writer: author1) } - let!(:article3) { Article.create!(title: 'Genji Monogatari', writer: author2) } + let!(:article1) { Article.create!(title: 'Romeo and Juliet', writer: author1, published_date: '2020-10-10', published_time: '12:00:00', first_drafted_at: '2020-10-01 12:00:00') } + let!(:article2) { Article.create!(title: 'King Lear', writer: author1, published_date: '2021-10-10', published_time: '12:00:00', first_drafted_at: '2021-10-01 12:00:00') } + let!(:article3) { Article.create!(title: 'Genji Monogatari', writer: author2, published_date: '2022-10-10', published_time: '12:00:00', first_drafted_at: '2022-10-01 12:00:00') } let(:models) { [Author, Article] } describe 'returned values' do @@ -15,36 +15,65 @@ it 'returns fixture data composed of record attributes by its model' do expect(subject).to match( - 'authors' => { + 'authors' => + { + '_fixture' => + { + 'model_class' => 'Author', + 'fixture_generated_by' => 'DumpedRailers', + }, + "__author_#{author1.id}" => { + 'name' => author1.name + }, + "__author_#{author2.id}" => { + 'name' => author2.name + }, + }, + 'articles' => + { '_fixture' => { - 'model_class' => 'Author', - 'fixture_generated_by' => 'DumpedRailers', - }, - "__author_#{author1.id}" => { - 'name' => author1.name - }, - "__author_#{author2.id}" => { - 'name' => author2.name - }, - }, - 'articles' => { - '_fixture' => - { - 'model_class' => 'Article', + 'model_class' => 'Article', 'fixture_generated_by' => 'DumpedRailers', }, "__article_#{article1.id}" => { - 'title' => article1.title, + 'title' => article1.title, 'writer' => "__author_#{author1.id}", + 'published_date' => have_attributes( + to_formatted_s: '2020-10-10' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => have_attributes( + to_formatted_s: a_string_including('2020-10-01 12:00:00') + ), }, "__article_#{article2.id}" => { - 'title' => article2.title, + 'title' => article2.title, 'writer' => "__author_#{author1.id}", + 'published_date' => have_attributes( + to_formatted_s: '2021-10-10' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => have_attributes( + to_formatted_s: a_string_including('2021-10-01 12:00:00') + ), }, "__article_#{article3.id}" => { - 'title' => article3.title, + 'title' => article3.title, 'writer' => "__author_#{author2.id}", + 'published_date' => have_attributes( + to_formatted_s: '2022-10-10' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => have_attributes( + to_formatted_s: a_string_including('2022-10-01 12:00:00') + ), }, } ) @@ -92,7 +121,7 @@ expect(File.exist?(fixture_file)) end - let(:fixture) { YAML.load_file(fixture_file) } + let(:fixture) { YAML.load_file(fixture_file, permitted_classes: described_class.yaml_column_permitted_classes) } it 'has the same attributes that the original records have' do expect(fixture).to match( @@ -105,14 +134,41 @@ "__article_#{article1.id}" => { 'title' => article1.title, 'writer' => "__author_#{author1.id}", + 'published_date' => have_attributes( + to_formatted_s: '2020-10-10' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => have_attributes( + to_formatted_s: a_string_including('2020-10-01 12:00:00') + ), }, "__article_#{article2.id}" => { 'title' => article2.title, 'writer' => "__author_#{author1.id}", + 'published_date' => have_attributes( + to_formatted_s: '2021-10-10' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => have_attributes( + to_formatted_s: a_string_including('2021-10-01 12:00:00') + ), }, "__article_#{article3.id}" => { 'title' => article3.title, 'writer' => "__author_#{author2.id}", + 'published_date' => have_attributes( + to_formatted_s: '2022-10-10' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => have_attributes( + to_formatted_s: a_string_including('2022-10-01 12:00:00') + ), }, } ) @@ -167,7 +223,7 @@ expect(File.exist?(fixture_file)) end - let(:fixture) { YAML.load_file(fixture_file) } + let(:fixture) { YAML.load_file(fixture_file, permitted_classes: described_class.yaml_column_permitted_classes) } it 'has upcased attributes' do expect(fixture).to match( @@ -181,16 +237,43 @@ 'id' => article1.id, 'title' => article1.title, 'writer' => "__author_#{author1.id}", + 'published_date' => have_attributes( + to_formatted_s: '2020-10-10' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => have_attributes( + to_formatted_s: a_string_including('2020-10-01 12:00:00') + ), }, "__article_#{article2.id}" => { 'id' => article2.id, 'title' => article2.title, 'writer' => "__author_#{author1.id}", + 'published_date' => have_attributes( + to_formatted_s: '2021-10-10' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => have_attributes( + to_formatted_s: a_string_including('2021-10-01 12:00:00') + ), }, "__article_#{article3.id}" => { 'id' => article3.id, 'title' => article3.title, 'writer' => "__author_#{author2.id}", + 'published_date' => have_attributes( + to_formatted_s: '2022-10-10' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => have_attributes( + to_formatted_s: a_string_including('2022-10-01 12:00:00') + ), }, } ) @@ -253,7 +336,7 @@ expect(File.exist?(fixture_file)) end - let(:fixture) { YAML.load_file(fixture_file) } + let(:fixture) { YAML.load_file(fixture_file, permitted_classes: described_class.yaml_column_permitted_classes) } it 'has upcased attributes' do expect(fixture).to match( @@ -266,14 +349,41 @@ "__article_#{article1.id}" => { 'title' => article1.title.upcase, 'writer' => "__author_#{author1.id}", + 'published_date' => have_attributes( + to_formatted_s: '2020-10-10' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => have_attributes( + to_formatted_s: a_string_including('2020-10-01 12:00:00') + ), }, "__article_#{article2.id}" => { 'title' => article2.title.upcase, 'writer' => "__author_#{author1.id}", + 'published_date' => have_attributes( + to_formatted_s: '2021-10-10' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => have_attributes( + to_formatted_s: a_string_including('2021-10-01 12:00:00') + ), }, "__article_#{article3.id}" => { 'title' => article3.title.upcase, 'writer' => "__author_#{author2.id}", + 'published_date' => have_attributes( + to_formatted_s: '2022-10-10' + ), + 'published_time' => have_attributes( + to_formatted_s: a_string_including('12:00:00') + ), + 'first_drafted_at' => have_attributes( + to_formatted_s: a_string_including('2022-10-01 12:00:00') + ), }, } )