flico 1.0.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: adca32d7e5ee313f13e0ea06a104fe7f1f2fb0dee521b2997c96cd0901c67dcf
4
- data.tar.gz: adf98002d3585edf868ab0ddc0a655cf48b932aa3671a079217398956b0c5705
3
+ metadata.gz: 473a26ece9ff8cf869ea977bdc1a96a5b800848ce82f4ee0282dad74bda96bdc
4
+ data.tar.gz: b4e83f8d45ea19e79e4d5884603f3941af769e279d8267dff9379f662f3acbbf
5
5
  SHA512:
6
- metadata.gz: f7813fde11543901c15b0f212e81a6d36968f82be4974784f09b5a45365c13e6e83a50502ecd70b56a7a9a10acdcc071cfa00dfc330516ce14175cb3358ed704
7
- data.tar.gz: cf5e50c394033d3feee1f4bbb3d74ed40c07952b440b12e2e28fd16dc9d2340d12bf80526d30a2fddb2426034fc6dee57ca0947454c709ef2ba106ad77176fc8
6
+ metadata.gz: 55a33bfccc1180547b859c572ef4802f4bd6b6299298319e0b21519ae381b4f040b0620ffbde06e002c9d9216d6f00b559af148aa38b93d9968b10464351c918
7
+ data.tar.gz: c96edd9e612f9cb0dbc1711c0d0dedf5ade8be1b1e685316055cd4d48b3bbda9bbdc6c2b8aa8eea6073a9da88f10d8589b9f1c4bfad9db033d7d20664ec3ab7a
data/flico.gemspec CHANGED
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'flico'
8
- spec.version = '1.0.0'
8
+ spec.version = '2.0.0'
9
9
  spec.summary = 'A CLI tool to create collage from keywords using Flickr'
10
10
  spec.homepage = 'https://github.com/amandeepbhamra/flico'
11
11
  spec.license = 'MIT'
data/lib/flico/app.rb CHANGED
@@ -1,44 +1,51 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'flico/dictionary'
4
+ require 'flico/collager'
5
+ require 'flico/image_file'
6
+
3
7
  module Flico
4
8
  class ApplicationError < StandardError; end
5
- class KeywordMissing < StandardError; end
6
- class NoImage < StandardError; end
7
- class FetchingError < StandardError; end
8
9
 
9
10
  class App
10
- attr_reader :resources
11
+ KEYWORDS_COUNT = 10
12
+
13
+ attr_reader :keywords, :options
11
14
 
12
- def initialize(resources)
13
- @resources = resources
15
+ def initialize(keywords, options)
16
+ @keywords = add_missing_keywords(keywords)
17
+ @options = options
14
18
  end
15
19
 
16
- def create_collage
17
- image_urls = []
18
- loop do
19
- image_urls.push get_images
20
- break unless image_urls.count < 10
21
- end
22
- collage(image_urls)
20
+ def create
21
+ options[:file_name] = prepare_file_name(options)
22
+
23
+ Collager.new(prepare_images, options[:file_name]).save
24
+
25
+ puts "Flicollage saved at #{options[:file_name]}"
23
26
  end
24
27
 
25
- def collage(images)
26
- resources.save_collage.call(resources.collager.call(images))
28
+ def prepare_images
29
+ keywords.map { |keyword| ImageFile.new(keyword).fetch_from_flickr }
27
30
  end
28
31
 
29
- def get_images
30
- keyword = resources.dictionary.call
31
- image_url = resources.flickr_api.call(keyword)
32
- resources.fetch_image.call(image_url)
33
- rescue NoImage => e
34
- puts "Image not found for keyword '#{keyword}'. Message: #{e.message}. Retrying"
35
- unless (tries -= 1).positive?
36
- raise ApplicationError, "Failed getting image after retrying #{MAX_KEYWORD_RETRIES} times"
37
- end
38
-
39
- retry
40
- rescue FetchingError => e
41
- raise ApplicationError, e.message
32
+ private
33
+
34
+ def add_missing_keywords(words)
35
+ words_count = words.size
36
+ return words if words_count == KEYWORDS_COUNT
37
+
38
+ words += Dictionary.new.words(KEYWORDS_COUNT - words_count)
39
+ puts "KEYWORDS: #{words}"
40
+ words
41
+ end
42
+
43
+ def prepare_file_name(options)
44
+ return options[:file_name] unless options[:file_name].nil?
45
+
46
+ puts 'Enter file name for collage (press ENTER to use default)'
47
+ file_name = $stdin.gets.strip
48
+ file_name.empty? ? "flicollage-#{Time.now.strftime('%Y%m%d%H%M%S')}.png" : file_name
42
49
  end
43
50
  end
44
51
  end
@@ -1,44 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'flico/grid'
4
3
  require 'mini_magick'
5
4
 
6
5
  module Flico
7
6
  class Collager
8
- attr_reader :grid
7
+ attr_reader :images_url, :file_name
9
8
 
10
- def initialize(grid = Grid.new)
11
- @grid = grid
9
+ def initialize(images_url, file_name)
10
+ @images_url = images_url
11
+ @file_name = file_name
12
12
  end
13
13
 
14
- def call(image_urls)
15
- image_urls.map { |p| MiniMagick::Image.open p.path }
16
- temp_file = Tempfile.new ['collage_maker', '.png']
17
- MiniMagick::Tool::Convert.new do |i|
18
- i.size "#{grid.canv_width}x#{grid.canv_height}"
19
- i.xc 'white'
20
- i << temp_file.path
21
- end
22
-
23
- image_urls.map.with_index do |path, idx|
24
- image = MiniMagick::Image.open path.path
25
- image.crop(grid.crop_rectangle(idx, image.width, image.height).to_mm)
26
- image.resize(grid.resize_rectangle(idx, image.width, image.height).to_mm)
27
- print_to_canvas(image, grid.cell_rectangle(idx), temp_file)
28
- end
29
- temp_file
30
- end
31
-
32
- private
33
-
34
- def print_to_canvas(image, rectangle, temp_file)
35
- canvas = MiniMagick::Image.new temp_file.path
36
- result = canvas.composite(image) do |c|
37
- c.compose 'Over'
38
- c.geometry rectangle.to_mm
39
- end
40
- result.write temp_file.path
41
- temp_file.rewind
14
+ def save
15
+ montage = MiniMagick::Tool::Montage.new
16
+ montage.density '600'
17
+ montage.tile '5X2'
18
+ montage.geometry '+10+20'
19
+ montage.border '5'
20
+ images_url.each { |image_url| montage << image_url }
21
+ montage << file_name
22
+ montage.call
42
23
  end
43
24
  end
44
25
  end
@@ -2,23 +2,34 @@
2
2
 
3
3
  module Flico
4
4
  class Dictionary
5
- def initialize(dictionary_path)
6
- @dictionary_path = dictionary_path
5
+ PATH = '/usr/share/dict/words'
6
+ ALPHABETS_LOWER_LIMIT = 3
7
+ ALPHABETS_UPPER_LIMIT = 10
8
+
9
+ def initialize
10
+ @dictionary_path = validate(PATH)
7
11
  @words = []
8
12
  end
9
13
 
10
- def call
11
- @words.shift || dictionary_word
14
+ def words(count)
15
+ @words += pick_words(count)
12
16
  end
13
17
 
14
- def append(keywords)
15
- @words += keywords
18
+ private
19
+
20
+ def pick_words(count)
21
+ File.readlines(PATH).select do |word|
22
+ word.size > ALPHABETS_LOWER_LIMIT && word.size < ALPHABETS_UPPER_LIMIT
23
+ end.sample(count).map(&:strip)
16
24
  end
17
25
 
18
- private
26
+ def validate(path)
27
+ unless File.exist?(path)
28
+ warn "Exiting due to missing dictionary at path: #{path}"
29
+ exit 1
30
+ end
19
31
 
20
- def dictionary_word
21
- File.readlines("/usr/share/dict/words").select { |word| word.size > 3 && word.size < 10 }.sample.strip
32
+ path
22
33
  end
23
34
  end
24
35
  end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'flickraw'
4
+
5
+ module Flico
6
+ module Flickr
7
+ class BaseApi
8
+ attr_reader :key, :secret, :api
9
+
10
+ def initialize
11
+ @key = ENV['FLICKR_KEY']
12
+ @secret = ENV['FLICKR_SECRET']
13
+ @api = flickraw_api
14
+ end
15
+
16
+ def get_photo(keyword)
17
+ valid_keyword?(keyword)
18
+
19
+ puts "Searching images for keyword: #{keyword}"
20
+
21
+ results = search_api(keyword)
22
+
23
+ results.count.zero? ? (warn "No Image for keyword: #{keyword}") : photo_url(results.first.id)
24
+ end
25
+
26
+ private
27
+
28
+ def flickraw_api
29
+ valid_secrets?
30
+
31
+ FlickRaw.api_key = key
32
+ FlickRaw.shared_secret = secret
33
+ FlickRaw::Flickr.new
34
+ end
35
+
36
+ def valid_secrets?
37
+ if key.nil? || secret.nil?
38
+ warn 'Exiting due to missing required environment variables: FLICKR_KEY or FLICKR_SECRET'
39
+ exit 1
40
+ end
41
+
42
+ true
43
+ end
44
+
45
+ def search_api(keyword)
46
+ api.photos.search({ text: keyword, per_page: 10, sort: 'interestingness-desc' })
47
+ end
48
+
49
+ def info_api(image)
50
+ api.photos.getInfo(photo_id: image)
51
+ end
52
+
53
+ def size_api(id)
54
+ api.photos.getSizes(photo_id: id)
55
+ end
56
+
57
+ def photo_url(id)
58
+ size_api(id).find { |v| v['label'] == 'Square' }['source']
59
+ end
60
+
61
+ def valid_keyword?(keyword)
62
+ warn "Missing Keywords (can't be nil)" if keyword.nil?
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'flico/flickr/base_api'
4
+
5
+ module Flico
6
+ class NoImage < StandardError; end
7
+ class FetchingError < StandardError; end
8
+
9
+ class ImageFile
10
+ attr_accessor :keyword
11
+
12
+ def initialize(keyword)
13
+ @keyword = keyword
14
+ end
15
+
16
+ def fetch_from_flickr
17
+ Flickr::BaseApi.new.get_photo(keyword)
18
+ rescue NoImage => e
19
+ puts "Image not found for keyword '#{keyword}'. Message: #{e.message}. Retrying"
20
+ unless (tries -= 1).positive?
21
+ raise ApplicationError, "Failed getting image after retrying #{MAX_KEYWORD_RETRIES} times"
22
+ end
23
+
24
+ retry
25
+ rescue FetchingError => e
26
+ raise ApplicationError, e.message
27
+ end
28
+ end
29
+ end
data/lib/flico.rb CHANGED
@@ -1,13 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'flickraw'
4
3
  require 'ostruct'
5
4
  require 'optparse'
6
5
  require 'flico/app'
7
- require 'flico/flickr_command'
8
- require 'flico/dictionary'
9
- require 'flico/saver'
10
- require 'flico/collager'
11
6
 
12
7
  module Flico
13
8
  class CommandLineInterface
@@ -24,54 +19,7 @@ module Flico
24
19
 
25
20
  def self.start(args)
26
21
  keywords, options = parse_args(args)
27
- puts "Given Keywords: #{keywords.join(' ')} with Options: #{options}"
28
- resources = validate_resources(keywords, options)
29
- App.new(resources).create_collage
30
- end
31
-
32
- def self.validate_resources(keywords, options = {})
33
- dictionary = validate_dictionary
34
- dictionary.append(keywords)
35
- col = SaveCollage.new
36
- col.output_file_name = options[:file_name]
37
-
38
- Resource.new(flickr_api: validate_flickr_api, dictionary:, fetch_image: FetchImage.new,
39
- collager: Collager.new, save_collage: col)
40
- end
41
-
42
- def self.validate_flickr_api
43
- key = ENV['FLICKR_KEY']
44
- secret = ENV['FLICKR_SECRET']
45
- if key.nil? && secret.nil?
46
- warn 'Performing AutoExit due to missing required environment variables: FLICKR_KEY and FLICKR_SECRET'
47
- exit 1
48
- else
49
- FlickRaw.api_key = key
50
- FlickRaw.shared_secret = secret
51
- FlickrCommand.setup(FlickRaw::Flickr.new)
52
- end
53
- end
54
-
55
- def self.validate_dictionary
56
- dictionary_path = '/usr/share/dict/words'
57
- if File.exist?(dictionary_path)
58
- Dictionary.new(dictionary_path)
59
- else
60
- warn "Performing AutoExit due to missing required dictionary at path: #{dictionary_path}"
61
- exit 1
62
- end
63
- end
64
- end
65
-
66
- class Resource
67
- attr_reader :flickr_api, :dictionary, :fetch_image, :collager, :save_collage
68
-
69
- def initialize(params = {})
70
- @flickr_api = params.fetch(:flickr_api)
71
- @dictionary = params.fetch(:dictionary)
72
- @fetch_image = params.fetch(:fetch_image)
73
- @collager = params.fetch(:collager)
74
- @save_collage = params.fetch(:save_collage)
22
+ App.new(keywords, options).create
75
23
  end
76
24
  end
77
25
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'flico/flickr/base_api'
5
+
6
+ describe Flico::Flickr::BaseApi do
7
+ let(:photo_url) do
8
+ {
9
+ 'label' => 'Square',
10
+ 'width' => 75,
11
+ 'height' => 75,
12
+ 'source' => 'https://farm3.staticflickr.com/2805/33472607802_42e011bcf5_s.jpg',
13
+ 'url' => 'https://farm3.staticflickr.com/2805/33472607802_42e011bcf5/sizes/sq/',
14
+ 'media' => 'photo'
15
+ }
16
+ end
17
+
18
+ let(:subject) { described_class.new }
19
+
20
+ context 'search success' do
21
+ before do
22
+ ENV['FLICKR_KEY'] = 'FOO'
23
+ ENV['FLICKR_SECRET'] = 'BAR'
24
+ end
25
+
26
+ it 'should return image url for search keyword' do
27
+ allow_any_instance_of(Flico::Flickr::BaseApi).to receive(:flickraw_api).and_return(double('flickraw_api'))
28
+ allow_any_instance_of(Flico::Flickr::BaseApi).to receive(:get_photo).and_return(photo_url)
29
+
30
+ expect(subject.get_photo('Volkswagen Golf in Luxembourg')['source']).to eq('https://farm3.staticflickr.com/2805/33472607802_42e011bcf5_s.jpg')
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'flico/dictionary'
5
+
6
+ describe Flico::Dictionary do
7
+ let(:subject) { described_class.new }
8
+
9
+ context '#words' do
10
+ let(:count) { 3 }
11
+ let(:words) { subject.words(count) }
12
+
13
+ it 'should not be empty' do
14
+ expect(words).to_not be_empty
15
+ end
16
+
17
+ it 'should return 3 random words' do
18
+ expect(words.count).to eq count
19
+ end
20
+ end
21
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flico
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Amandeep Singh Bhamra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-28 00:00:00.000000000 Z
11
+ date: 2023-07-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: flickraw
@@ -114,13 +114,12 @@ files:
114
114
  - flico.gemspec
115
115
  - lib/flico.rb
116
116
  - lib/flico/app.rb
117
- - lib/flico/cell.rb
118
117
  - lib/flico/collager.rb
119
118
  - lib/flico/dictionary.rb
120
- - lib/flico/flickr_command.rb
121
- - lib/flico/grid.rb
122
- - lib/flico/saver.rb
123
- - spec/flickr_command_spec.rb
119
+ - lib/flico/flickr/base_api.rb
120
+ - lib/flico/image_file.rb
121
+ - spec/base_api_spec.rb
122
+ - spec/dictionary_spec.rb
124
123
  - spec/spec_helper.rb
125
124
  homepage: https://github.com/amandeepbhamra/flico
126
125
  licenses:
data/lib/flico/cell.rb DELETED
@@ -1,32 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Flico
4
- class Cell
5
- attr_reader :x, :y, :width, :height
6
-
7
- def initialize(x = 0, y = 0, width, height)
8
- @x = x
9
- @y = y
10
- @width = width
11
- @height = height
12
- end
13
-
14
- def aspect_ratio
15
- width.to_f / height
16
- end
17
-
18
- def to_mm
19
- "#{width}x#{height}+#{x}+#{y}"
20
- end
21
-
22
- def ==(other)
23
- other.class == self.class && other.state == state
24
- end
25
-
26
- protected
27
-
28
- def state
29
- [@x, @y, @width, @height]
30
- end
31
- end
32
- end
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Flico
4
- class FlickrCommand
5
- def initialize(search_command:, sizes_command:)
6
- @search_command = search_command
7
- @sizes_command = sizes_command
8
- end
9
-
10
- def self.setup(flickraw)
11
- new(search_command: SearchCommand.new(flickraw), sizes_command: SizesCommand.new(flickraw))
12
- end
13
-
14
- def call(keyword)
15
- if keyword.nil?
16
- warn "Missing Keywords (can't be nil)"
17
- else
18
- puts "Searching images for keyword: #{keyword}"
19
- results = @search_command.call(keyword)
20
- if results.count.zero?
21
- warn "No Image for keyword: #{keyword}"
22
- else
23
- get_image_url(results.first['id'])
24
- end
25
- end
26
- end
27
-
28
- private
29
-
30
- def get_image_url(photo_id)
31
- sizes = @sizes_command.call(photo_id)
32
- sizes[sizes.count / 2]['source']
33
- end
34
- end
35
-
36
- class FlickrBase
37
- attr_reader :api
38
-
39
- def initialize(flickraw)
40
- @api = flickraw
41
- end
42
- end
43
-
44
- class SearchCommand < FlickrBase
45
- def call(keyword)
46
- api.photos.search({ text: keyword, per_page: 10, sort: 'interestingness-desc' })
47
- end
48
- end
49
-
50
- class SizesCommand < FlickrBase
51
- def call(photo_id)
52
- api.photos.getSizes(photo_id:)
53
- end
54
- end
55
- end
data/lib/flico/grid.rb DELETED
@@ -1,83 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'flico/cell'
4
-
5
- module Flico
6
- class Grid
7
- GRID = [[0, 1, 1, 2], [3, 4, 5, 6], [7, 8, 8, 9]].freeze
8
- CANV_WIDTH = 1750
9
- CANV_HEIGHT = 1250
10
-
11
- def canv_width
12
- CANV_WIDTH
13
- end
14
-
15
- def canv_height
16
- CANV_HEIGHT
17
- end
18
-
19
- def columns
20
- GRID.max_by(&:size).size
21
- end
22
-
23
- def column_cells
24
- GRID.transpose
25
- end
26
-
27
- def rows
28
- GRID.size
29
- end
30
-
31
- def row_cells
32
- GRID
33
- end
34
-
35
- def cell_width(name)
36
- cell_size(CANV_WIDTH, columns, size_multiplier(row_cells, name))
37
- end
38
-
39
- def cell_height(name)
40
- cell_size(CANV_HEIGHT, rows, size_multiplier(column_cells, name))
41
- end
42
-
43
- def crop_rectangle(cell_name, image_width, image_height)
44
- x = 0
45
- y = 0
46
- image = Cell.new(image_width, image_height)
47
- cell = cell_rectangle(cell_name)
48
-
49
- if image.aspect_ratio >= cell.aspect_ratio
50
- final_width = image_width - (image.width - (image.height * cell.aspect_ratio))
51
- final_height = image.height
52
- else
53
- final_width = image.width
54
- final_height = image.height - (image.height - (image.width / cell.aspect_ratio))
55
- end
56
-
57
- Cell.new(x, y, final_width, final_height)
58
- end
59
-
60
- def resize_rectangle(cell_name, image_width, image_height)
61
- Cell.new(image_width, image_height)
62
- cell_rectangle(cell_name)
63
- end
64
-
65
- def cell_rectangle(name)
66
- column = column_cells.find_index do |row|
67
- row.include? name
68
- end
69
- row = row_cells.find_index { |row| row.include? name }
70
- Cell.new(column * (CANV_WIDTH / columns), row * (CANV_HEIGHT / rows), cell_width(name), cell_height(name))
71
- end
72
-
73
- private
74
-
75
- def size_multiplier(table, name)
76
- table.map { |row| row.count(name) }.max
77
- end
78
-
79
- def cell_size(total, divisions, multiplier)
80
- multiplier.zero? ? 0 : ((total / divisions) * multiplier)
81
- end
82
- end
83
- end
data/lib/flico/saver.rb DELETED
@@ -1,39 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'open-uri'
4
- require 'tempfile'
5
- require 'fileutils'
6
- require 'date'
7
-
8
- module Flico
9
- class FetchingError < StandardError; end
10
-
11
- class FetchImage
12
- def call(url)
13
- tempfile = Tempfile.new 'temp_image'
14
- IO.copy_stream(URI.open(url, read_timeout: 5), tempfile)
15
- tempfile.rewind
16
- tempfile
17
- rescue OpenURI::HTTPError => e
18
- raise FetchingError, "Couldn't download from: #{url} due to #{e.message}"
19
- end
20
- end
21
-
22
- class SaveCollage
23
- attr_accessor :output_file_name
24
-
25
- def call(file_path)
26
- file_name = output_file_name || validate_file_name
27
- FileUtils.mv file_path, file_name
28
- puts "Flicollage saved at #{file_name}"
29
- end
30
-
31
- private
32
-
33
- def validate_file_name
34
- puts "Enter file name for collage (press ENTER to use '#{default}')"
35
- file_name = $stdin.gets.strip
36
- file_name.empty? ? "flicollage-#{Time.now.strftime('%Y%m%d%H%M%S')}.png" : file_name
37
- end
38
- end
39
- end
@@ -1,60 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'spec_helper'
4
- require 'flico/flickr_command'
5
-
6
- describe Flico::FlickrCommand do
7
- let(:search_results) do
8
- [
9
- {
10
- 'id' => '33472607802',
11
- 'owner' => '78759190@N05',
12
- 'secret' => '42e011bcf5',
13
- 'server' => '2805',
14
- 'farm' => 3,
15
- 'title' => 'Volkswagen Golf in Luxembourg',
16
- 'ispublic' => 1,
17
- 'isfriend' => 0,
18
- 'isfamily' => 0
19
- }
20
- ]
21
- end
22
- let(:sizes_results) do
23
- [
24
- {
25
- 'label' => 'Square',
26
- 'width' => 75,
27
- 'height' => 75,
28
- 'source' => 'https://farm3.staticflickr.com/2805/33472607802_42e011bcf5_s.jpg',
29
- 'url' => 'https://farm3.staticflickr.com/2805/33472607802_42e011bcf5/sizes/sq/',
30
- 'media' => 'photo'
31
- },
32
- {
33
- 'label' => 'Large Square',
34
- 'width' => '150',
35
- 'height' => '150',
36
- 'source' => 'https://farm3.staticflickr.com/2805/33472607802_42e011bcf5_q.jpg',
37
- 'url' => 'https://farm3.staticflickr.com/2805/33472607802_42e011bcf5/sizes/q/',
38
- 'media' => 'photo'
39
- },
40
-
41
- {
42
- 'label' => 'Thumbnail',
43
- 'width' => '100',
44
- 'height' => '66',
45
- 'source' => 'https://farm3.staticflickr.com/2805/33472607802_42e011bcf5_t.jpg',
46
- 'url' => 'https://farm3.staticflickr.com/2805/33472607802_42e011bcf5/sizes/t/',
47
- 'media' => 'photo'
48
- }
49
- ]
50
- end
51
- let(:subject) { described_class.new(search_command:, sizes_command:) }
52
- let(:search_command) { double('search', call: search_results) }
53
- let(:sizes_command) { double('sizes', call: sizes_results) }
54
-
55
- context 'search success' do
56
- it 'should return image url for search keyword' do
57
- expect(subject.call('Volkswagen Golf in Luxembourg')).to eq('https://farm3.staticflickr.com/2805/33472607802_42e011bcf5_q.jpg')
58
- end
59
- end
60
- end