diff --git a/Gemfile.lock b/Gemfile.lock index 0404d7f..5f3a970 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - strapi_ruby (0.1.4) + strapi_ruby (1.0.1) colorize (~> 1.1.0) faraday (~> 2.7) redcarpet (~> 3.6) diff --git a/README.md b/README.md index 85b88d5..5f7b8e2 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,18 @@ I think it's one of the actual coolest solution for integrating a CMS into Rails for example, so let's dive in! +## Important Notice: Strapi V5 and strapi_ruby + +Starting from version >=1.0.0, the StrapiRuby gem is only compatible with Strapi version 5 and above. This update includes significant changes to align with the new response format introduced in Strapi v5. Key changes include: + +- **Flattened Response Format**: The `attributes` object has been removed, and fields are now directly part of the `data` object. +- **ID Handling**: The `id` field has been replaced with `documentId` to uniquely identify resources. +- **Filter Adjustments**: Filters that previously used `id` should now use `documentId`. + +These changes ensure that the StrapiRuby gem takes full advantage of the improvements in Strapi v5, providing a more streamlined and efficient API interaction experience. Please ensure your Strapi server is updated to version 5 or later to use this version of the gem. + +Following will be the documentation for 1.xx release. + ## Table of contents - [Installation](#installation) @@ -43,15 +55,13 @@ I think it's one of the actual coolest solution for integrating a CMS into Rails ## Installation -Add this line to your application's Gemfile: +Add this line to your application's Gemfile - **make sure to take at least 1.0.1 version** ```ruby # Gemfile - gem "strapi_ruby" + gem 'strapi_ruby', '~> 1.0.1' ``` - - Then if you use Rails, run in your terminal to generate a config initializer. Otherwise copy paste and fill the config block. ```bash @@ -105,9 +115,9 @@ data = answer.data meta = answer.meta # Access a specific attribute -answer = StrapiRuby.get(resource: :articles, id: 2) +answer = StrapiRuby.get(resource: :articles, document_id: "clkgylmcc000008lcdd868feh") article = answer.data -title = article.attributes.title +title = article.title # If an error occur, it will be raised to be rescued and displayed in the answer. data = answer.data # => nil @@ -125,7 +135,7 @@ answer = StrapiRuby.get(resource: :restaurants) # Get a specific element -StrapiRuby.get(resource: :restaurants, id: 1) +StrapiRuby.get(resource: :restaurants, document_id: "clkgylmcc000008lcdd868feh") ``` #### .post @@ -143,7 +153,7 @@ StrapiRuby.post(resource: :articles, ```ruby # Update a specific item, return item updated StrapiRuby.put(resource: :articles, - id: 23, + document_id: "clkgylmcc000008lcdd868feh", data: {content: "'I've edited this article via a PUT request'"}) ``` @@ -151,7 +161,7 @@ StrapiRuby.put(resource: :articles, ```ruby # Delete an item, return item deleted -StrapiRuby.delete(resource: :articles, id: 12) +StrapiRuby.delete(resource: :articles, document_id: "clkgylmcc000008lcdd868feh") ``` @@ -176,7 +186,7 @@ end @@ -324,11 +334,11 @@ StrapiRuby.get(resource: :users, filters: { username: { "$eq" => "John" } }) # Using $in operator to match multiples values StrapiRuby.get(resource: :restaurants, filters: { - id: { - "$in" => ["3", "6", "8"], + documentId: { + "$in" => ["clkgylmcc000008lcdd868feh", "clkgylw7d000108lc4rw1bb6s"], }, }) -# => /restaurants?filters[id][$in][0]=3&filters[id][$in][1]=6&filters[id][$in][2]=8 +# => /restaurants?filters[documentId][$in][0]=clkgylmcc000008lcdd868feh&filters[documentId][$in][0]=clkgylw7d000108lc4rw1bb6s # -------------------------------- diff --git a/lib/strapi_ruby.rb b/lib/strapi_ruby.rb index 1543d51..efb28ac 100644 --- a/lib/strapi_ruby.rb +++ b/lib/strapi_ruby.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +require "ostruct" require_relative "strapi_ruby/version" require_relative "strapi_ruby/validations" diff --git a/lib/strapi_ruby/client.rb b/lib/strapi_ruby/client.rb index 25bafe6..fe6ad97 100644 --- a/lib/strapi_ruby/client.rb +++ b/lib/strapi_ruby/client.rb @@ -40,7 +40,8 @@ def set_connection(options, &block) "User-Agent" => "StrapiRuby/#{StrapiRuby::VERSION}" } Faraday.new(url: url) do |faraday| - faraday.request :url_encoded + # Use FlatParamsEncoder to prevent double encoding of special characters + faraday.options.params_encoder = Faraday::FlatParamsEncoder faraday.adapter Faraday.default_adapter block&.call(faraday) faraday.headers = default_headers.merge(faraday.headers) @@ -69,9 +70,9 @@ def build_data_payload(body) # rubocop:disable Metrics/AbcSize def handle_response(response) - body = convert_json_to_open_struct(response.body) + body = convert_json_to_open_struct(response.body) unless response.body.empty? case response.status - when 200 + when 200, 201 body when 400 raise BadRequestError.new(body.error.message, response.status) diff --git a/lib/strapi_ruby/endpoint/builder.rb b/lib/strapi_ruby/endpoint/builder.rb index 0cec14f..564f3f6 100644 --- a/lib/strapi_ruby/endpoint/builder.rb +++ b/lib/strapi_ruby/endpoint/builder.rb @@ -3,7 +3,7 @@ module Endpoint class Builder def initialize(options = {}) @resource = options[:resource] - @id = options[:id] + @document_id = options[:document_id] @query = Query.new(options).call @result = nil end @@ -20,7 +20,7 @@ def build_endpoint @result = if collection? "#{base_uri}/#{@resource}" else - "#{base_uri}/#{@resource}/#{@id}" + "#{base_uri}/#{@resource}/#{@document_id}" end end @@ -29,7 +29,7 @@ def append_query end def collection? - @id.nil? + @document_id.nil? end def base_uri diff --git a/lib/strapi_ruby/endpoint/strapi_parameters.rb b/lib/strapi_ruby/endpoint/strapi_parameters.rb index 45cb914..ce7cd5b 100644 --- a/lib/strapi_ruby/endpoint/strapi_parameters.rb +++ b/lib/strapi_ruby/endpoint/strapi_parameters.rb @@ -114,12 +114,11 @@ def traverse_hash(hash, parent_key = nil) traverse_hash({ index => item }, current_key) end else - # We can pass values as symbols but we need to convert them to string - # to be able to escape them value = value.to_s if value.is_a?(Symbol) + next if value.nil? # Skip nil values "#{current_key}=#{CGI.escape(value)}" end - end.join("&") + end.compact.join("&") end end end diff --git a/lib/strapi_ruby/formatter.rb b/lib/strapi_ruby/formatter.rb index dedd4a2..694aa49 100644 --- a/lib/strapi_ruby/formatter.rb +++ b/lib/strapi_ruby/formatter.rb @@ -20,9 +20,9 @@ def convert_to_datetime!(data) return unless StrapiRuby.config.convert_to_datetime if collection?(data) - data.each { |item| parse_into_datetime!(item.attributes) } + data.each { |item| parse_into_datetime!(item) } else - parse_into_datetime!(data.attributes) + parse_into_datetime!(data) end end @@ -62,9 +62,9 @@ def collection?(data) def convert_to_html!(data) if collection?(data) - data.each { |item| convert_attributes!(item.attributes) } + data.each { |item| convert_attributes!(item) } else - convert_attributes!(data.attributes) + convert_attributes!(data) end end diff --git a/lib/strapi_ruby/interface.rb b/lib/strapi_ruby/interface.rb index a020961..52f6a22 100644 --- a/lib/strapi_ruby/interface.rb +++ b/lib/strapi_ruby/interface.rb @@ -30,8 +30,10 @@ def request(http_verb, options = {}) validate_options(options) @endpoint = build_endpoint(options) answer = build_answer(http_verb, @endpoint, options) - data = format_data(answer.data, options) - meta = answer.meta + if answer + data = format_data(answer.data, options) unless answer.data.nil? + meta = answer.meta unless answer.meta.nil? + end return_success_open_struct(data, meta, options) rescue StrapiRuby::ClientError, StrapiRuby::ConfigurationError => e diff --git a/lib/strapi_ruby/markdown.rb b/lib/strapi_ruby/markdown.rb index 4aac905..5982c01 100644 --- a/lib/strapi_ruby/markdown.rb +++ b/lib/strapi_ruby/markdown.rb @@ -8,6 +8,8 @@ class Markdown include Singleton def to_html(markdown) + return "" if markdown.nil? + markdown_renderer.render(markdown) end diff --git a/lib/strapi_ruby/validations.rb b/lib/strapi_ruby/validations.rb index bbc5f4e..15dce5e 100644 --- a/lib/strapi_ruby/validations.rb +++ b/lib/strapi_ruby/validations.rb @@ -14,7 +14,7 @@ def validate_config(config) def validate_options(options) validate_config_presence validate_resource(options) - validate_id(options) + validate_document_id(options) validate_show_endpoint_params(options) validate_body(options) end @@ -47,8 +47,8 @@ def validate_resource(options) raise TypeError, "#{ErrorMessage.expected_string_symbol} Got #{options[:resource].class.name}" unless options[:resource].is_a?(String) || options[:resource].is_a?(Symbol) end - def validate_id(options) - raise TypeError, "#{ErrorMessage.expected_integer} Got #{options[:id].class.name}" if options.key?(:id) && !options[:id].is_a?(Integer) + def validate_document_id(options) + raise TypeError, "#{ErrorMessage.expected_string} Got #{options[:document_id].class.name}" if options.key?(:document_id) && !options[:document_id].is_a?(String) end def validate_show_endpoint_params(options) diff --git a/lib/strapi_ruby/version.rb b/lib/strapi_ruby/version.rb index 286a7b5..6e9e599 100644 --- a/lib/strapi_ruby/version.rb +++ b/lib/strapi_ruby/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module StrapiRuby - VERSION = "0.1.4" + VERSION = "1.0.1" end diff --git a/spec/client/client_spec.rb b/spec/client/client_spec.rb index eca5db8..9d21e90 100644 --- a/spec/client/client_spec.rb +++ b/spec/client/client_spec.rb @@ -4,20 +4,20 @@ let(:client) { StrapiRuby::Client.new(strapi_server_uri: "https://www.example.com") } before do - stub_request(:get, "https://www.example.com/articles/1").to_return(status: 200, body: '{"data": {"attributes":{"id": 1, "title": "Example"}}}') - stub_request(:post, "https://www.example.com/articles").to_return(status: 200, body: '{"data": {"attributes": {"title": "This is a new example"}}}') - stub_request(:put, "https://www.example.com/articles/1").to_return(status: 200, body: '{"data": {"attributes": {"title": "This is a modified example"}}}') - stub_request(:delete, "https://www.example.com/articles/1").to_return(status: 200, body: '{"data": {"attributes": {"title": "This is a deleted example"}}}') + stub_request(:get, "https://www.example.com/articles/clkgylw7d000108lc4rw1bb6s").to_return(status: 200, body: '{"data" :{"documentId": "clkgylw7d000108lc4rw1bb6s", "title": "Example"}}') + stub_request(:post, "https://www.example.com/articles").to_return(status: 200, body: '{"data": {"documentId": "clkgylw7d000108lc4rw1bb6s", "title": "This is a new example"}}') + stub_request(:put, "https://www.example.com/articles/clkgylw7d000108lc4rw1bb6s").to_return(status: 200, body: '{"data": {"documentId": "clkgylw7d000108lc4rw1bb6s", "title": "This is a modified example"}}') + stub_request(:delete, "https://www.example.com/articles/clkgylw7d000108lc4rw1bb6s").to_return(status: 200, body: '{"data": {"documentId": "clkgylw7d000108lc4rw1bb6s", "title": "This is a deleted example"}}') end describe "#get" do it "sends a GET request to the specified endpoint" do - faraday_response = client.connection.get("/articles/1") + faraday_response = client.connection.get("/articles/clkgylw7d000108lc4rw1bb6s") expect(faraday_response.status).to eq(200) end it "returns an OpenStruct object" do - response = client.get("/articles/1") + response = client.get("/articles/clkgylw7d000108lc4rw1bb6s") expect(response.class).to eq(OpenStruct) end @@ -41,7 +41,7 @@ expect(faraday_response.status).to eq(200) response = client.post("/articles", { title: "This is a new example" }) p - expect(response.data.attributes.title).to eq("This is a new example") + expect(response.data.title).to eq("This is a new example") end it "returns an OpenStruct object" do @@ -65,57 +65,57 @@ describe "#put" do it "sends a PUT request to the specified endpoint" do - faraday_response = client.connection.put("/articles/1", { title: "This is a modified example" }) + faraday_response = client.connection.put("/articles/clkgylw7d000108lc4rw1bb6s", { title: "This is a modified example" }) expect(faraday_response.status).to eq(200) - response = client.put("/articles/1", { title: "This is a modified example" }) - expect(response.data.attributes.title).to eq("This is a modified example") + response = client.put("/articles/clkgylw7d000108lc4rw1bb6s", { title: "This is a modified example" }) + expect(response.data.title).to eq("This is a modified example") end it "returns an OpenStruct object" do - response = client.put("/articles/1", { title: "This is a modified example" }) + response = client.put("/articles/clkgylw7d000108lc4rw1bb6s", { title: "This is a modified example" }) expect(response.class).to eq(OpenStruct) end it "handles connection errors gracefully" do allow_any_instance_of(Faraday::Connection).to receive(:put).and_raise(Faraday::ConnectionFailed.new("Connection failed")) - expect { client.put("/resource/1", {}) }.to raise_error(StrapiRuby::ConnectionError) + expect { client.put("/resource/clkgylw7d000108lc4rw1bb6s", {}) }.to raise_error(StrapiRuby::ConnectionError) end it "handles timeout errors gracefully" do allow_any_instance_of(Faraday::Connection).to receive(:put).and_raise(Faraday::TimeoutError.new("Timeout Error")) - expect { client.put("/resource/1", {}) }.to raise_error(StrapiRuby::ConnectionError) + expect { client.put("/resource/clkgylw7d000108lc4rw1bb6s", {}) }.to raise_error(StrapiRuby::ConnectionError) end it "handles other errors gracefully" do allow_any_instance_of(Faraday::Connection).to receive(:put).and_raise(StandardError.new("Something bad happened")) - expect { client.put("/resource/1", {}) }.to raise_error(StrapiRuby::ConnectionError) + expect { client.put("/resource/clkgylw7d000108lc4rw1bb6s", {}) }.to raise_error(StrapiRuby::ConnectionError) end end describe "#delete" do it "sends a DELETE request to the specified endpoint" do - faraday_response = client.connection.delete("/articles/1") + faraday_response = client.connection.delete("/articles/clkgylw7d000108lc4rw1bb6s") expect(faraday_response.status).to eq(200) - response = client.delete("/articles/1") - expect(response.data.attributes.title).to eq("This is a deleted example") + response = client.delete("/articles/clkgylw7d000108lc4rw1bb6s") + expect(response.data.title).to eq("This is a deleted example") end it "returns an OpenStruct object" do - response = client.put("/articles/1", { title: "This is a deleted example" }) + response = client.put("/articles/clkgylw7d000108lc4rw1bb6s", { title: "This is a deleted example" }) expect(response.class).to eq(OpenStruct) end it "handles connection errors gracefully" do allow_any_instance_of(Faraday::Connection).to receive(:delete).and_raise(Faraday::ConnectionFailed.new("Connection failed")) - expect { client.delete("/resource/1") }.to raise_error(StrapiRuby::ConnectionError) + expect { client.delete("/resource/clkgylw7d000108lc4rw1bb6s") }.to raise_error(StrapiRuby::ConnectionError) end it "handles timeout errors gracefully" do allow_any_instance_of(Faraday::Connection).to receive(:delete).and_raise(Faraday::TimeoutError.new("Timeout Error")) - expect { client.delete("/resource/1") }.to raise_error(StrapiRuby::ConnectionError) + expect { client.delete("/resource/clkgylw7d000108lc4rw1bb6s") }.to raise_error(StrapiRuby::ConnectionError) end it "handles other errors gracefully" do allow_any_instance_of(Faraday::Connection).to receive(:delete).and_raise(StandardError.new("Something bad happened")) - expect { client.delete("/resource/1") }.to raise_error(StrapiRuby::ConnectionError) + expect { client.delete("/resource/clkgylw7d000108lc4rw1bb6s") }.to raise_error(StrapiRuby::ConnectionError) end end @@ -146,15 +146,15 @@ describe "#handle_response" do context "when the response status is 200" do - let(:response) { double(status: 200, message: "OK", body: '{"data": {"id": 1, "name": "Example"}}') } + let(:response) { double(status: 200, message: "OK", body: '{"data": {"documentId": "clkgylw7d000108lc4rw1bb6s", "title": "Example"}}') } it "returns an OpenStruct object" do expect(client.send(:handle_response, response)).to be_a(OpenStruct) end it "parses the JSON data into the OpenStruct object" do - expect(client.send(:handle_response, response).data.id).to eq(1) - expect(client.send(:handle_response, response).data.name).to eq("Example") + expect(client.send(:handle_response, response).data.documentId).to eq("clkgylw7d000108lc4rw1bb6s") + expect(client.send(:handle_response, response).data.title).to eq("Example") end end diff --git a/spec/config/config_spec.rb b/spec/config/config_spec.rb index b57aaf6..ec3f194 100644 --- a/spec/config/config_spec.rb +++ b/spec/config/config_spec.rb @@ -17,7 +17,6 @@ config.strapi_server_uri = "https://example.com" config.strapi_token = "124" config.faraday = faraday_string - p config expect { config.call }.to raise_error(TypeError) end end diff --git a/spec/formatter/formatter_spec.rb b/spec/formatter/formatter_spec.rb index 705cec1..1a49994 100644 --- a/spec/formatter/formatter_spec.rb +++ b/spec/formatter/formatter_spec.rb @@ -3,53 +3,52 @@ RSpec.describe StrapiRuby::Formatter do before do html_value = "

Mocked content

\n" - allow(attributes).to receive(:content).and_return(html_value) - allow(attributes).to receive(:content=).with(html_value) + allow(data).to receive(:content).and_return(html_value) + allow(data).to receive(:content=).with(html_value) end describe "#convert_to_html!" do let(:convert_to_html_keys) { [:content] } - let(:attributes) { double("attributes", content: "Mocked content", title: "# Mocked title") } - let(:data) { double("data", attributes: attributes) } + let(:data) { OpenStruct.new(content: "Mocked content", title: "# Mocked title") } let(:data_collection) { [data, data] } let(:empty_data) { OpenStruct.new } let(:formatter) { StrapiRuby::Formatter.new({ convert_to_html: convert_to_html_keys }) } + context "when data is a single item" do context "and when the key matches" do it "should convert data to HTML" do converted_content = "

Mocked content

\n" - converted_data = data - formatter.send(:convert_to_html!, converted_data) - expect(converted_data.attributes.content).to eq(converted_content) + formatter.send(:convert_to_html!, data) + expect(data.content).to eq(converted_content) end end + context "and when the key does not match" do - it "should not convert data to HTML if data.attributes.key is the same" do + it "should not convert data to HTML if data.key is the same" do converted_title = "

Mocked title

\n" - converted_data = data - formatter.send(:convert_to_html!, converted_data) - expect(converted_data.attributes.title).not_to eq(converted_title) + formatter.send(:convert_to_html!, data) + expect(data.title).not_to eq(converted_title) end end end + context "when data is a collection" do context "and when the key matches" do it "should convert each data to HTML" do converted_content = "

Mocked content

\n" - converted_data_collection = data_collection - formatter.send(:convert_to_html!, converted_data_collection) - converted_data_collection.each do |converted_data| - expect(converted_data.attributes.content).to eq(converted_content) + formatter.send(:convert_to_html!, data_collection) + data_collection.each do |converted_data| + expect(converted_data.content).to eq(converted_content) end end end + context "and when the key does not match" do it "should not convert each data to HTML" do converted_title = "

Mocked title

\n" - converted_data_collection = data_collection - formatter.send(:convert_to_html!, converted_data_collection) - converted_data_collection.each do |converted_data| - expect(converted_data.attributes.title).not_to eq(converted_title) + formatter.send(:convert_to_html!, data_collection) + data_collection.each do |converted_data| + expect(converted_data.title).not_to eq(converted_title) end end end @@ -58,23 +57,22 @@ describe "#convert_to_datetime!" do let(:formatter) { StrapiRuby::Formatter.new } - let(:attributes) { OpenStruct.new(createdAt: "2023-10-04T12:34:56.000Z", updatedAt: "2023-10-04T13:45:30.000Z", publishedAt: "2023-10-04T14:56:12.000Z") } - let(:data) { double("data", attributes: attributes) } + let(:data) { OpenStruct.new(createdAt: "2023-10-04T12:34:56.000Z", updatedAt: "2023-10-04T13:45:30.000Z", publishedAt: "2023-10-04T14:56:12.000Z") } context "when data contain ISO date strings" do it "parses createdAt attribute into DateTime" do formatter.send(:convert_to_datetime!, data) - expect(data.attributes.createdAt).to be_a(DateTime) + expect(data.createdAt).to be_a(DateTime) end it "parses updatedAt attribute into DateTime" do formatter.send(:convert_to_datetime!, data) - expect(data.attributes.updatedAt).to be_a(DateTime) + expect(data.updatedAt).to be_a(DateTime) end it "parses publishedAt attribute into DateTime" do formatter.send(:convert_to_datetime!, data) - expect(data.attributes.publishedAt).to be_a(DateTime) + expect(data.publishedAt).to be_a(DateTime) end end end diff --git a/spec/integration.rb b/spec/integration.rb index d0d28cb..d6a5fef 100644 --- a/spec/integration.rb +++ b/spec/integration.rb @@ -24,103 +24,186 @@ def configure_strapi end end - # Test fetching all articles def test_get_all_articles test_get = StrapiRuby.get(resource: "articles") - test_get.data + test_get end # Test fetching one article def test_get_one_article - test_get = StrapiRuby.get(resource: "articles", id: 1) - test_get.data + test_get = StrapiRuby.get(resource: "articles", documentId: "1") + test_get end # Test pagination def test_pagination + # Create 4 articles + first_article = StrapiRuby.post(resource: "articles", data: { title: "This is my first article", content: "This is some dummy content" }) + second_article = StrapiRuby.post(resource: "articles", data: { title: "This is my second article", content: "This is some dummy content" }) + third_article = StrapiRuby.post(resource: "articles", data: { title: "This is my third article", content: "This is some dummy content" }) + fourth_article = StrapiRuby.post(resource: "articles", data: { title: "This is my fourth article", content: "This is some dummy content" }) test_get = StrapiRuby.get(resource: "articles", page: 1, page_size: 2) - test_get.data.count + p "test_pagination: #{test_get.data.count == 2}" + # Delete the articles + StrapiRuby.delete(resource: "articles", document_id: first_article.data.documentId) + StrapiRuby.delete(resource: "articles", document_id: second_article.data.documentId) + StrapiRuby.delete(resource: "articles", document_id: third_article.data.documentId) + StrapiRuby.delete(resource: "articles", document_id: fourth_article.data.documentId) end # Test sorting def test_sorting test_get = StrapiRuby.get(resource: "articles", sort: ["createdAt:desc", "title:asc"]) test_get.data.map do |item| - item.attributes.createdAt + item.createdAt end + # data should be sorted by createdAt descending and title ascending + # the first item should have the highest createdAt and the lowest title + first_item = test_get.data.first + last_item = test_get.data.last + p "test_sorting: #{first_item.createdAt > last_item.createdAt}" + p "test_sorting: #{first_item.title < last_item.title}" end # Test filtering def test_filtering - test_get = StrapiRuby.get(resource: "articles", fields: :title, filters: { id: { "$in" => ["1", "3"] } }) + # Make sure we have at least 3 articles: this test is dependent on the test_post_article test and test_delete_article test + first_article = StrapiRuby.post(resource: "articles", data: { title: "This is my fourth article", content: "This is some dummy content" }) + second_article = StrapiRuby.post(resource: "articles", data: { title: "This is my fifth article", content: "This is some dummy content" }) + third_article = StrapiRuby.post(resource: "articles", data: { title: "This is my sixth article", content: "This is some dummy content" }) + + test_get = StrapiRuby.get(resource: "articles", fields: :title, filters: { documentId: { "$in" => [first_article.data.documentId, third_article.data.documentId] } }) test_get.data + p "test_filtering: #{test_get.data.count == 2}" + # delete the articles + StrapiRuby.delete(resource: "articles", document_id: first_article.data.documentId) + StrapiRuby.delete(resource: "articles", document_id: third_article.data.documentId) + StrapiRuby.delete(resource: "articles", document_id: second_article.data.documentId) end # Test complex filtering def test_complex_filtering - test_get= StrapiRuby.get(resource: :books, - filters: { - "$or" => [ - { - date: { - "$eq" => "2020-01-01", - }, - }, - { - date: { - "$eq" => "2020-01-02", - }, - }, - ], - author: { - name: { - "$eq" => "Kai doe", - }, - }, - }) - test_get.endpoint + # Create an article with the following data: + first_article = StrapiRuby.post(resource: "articles", data: { title: "Babar", content: "Aventure au pays des éléphants" }) + second_article = StrapiRuby.post(resource: "articles", data: { title: "Tintin", content: "Objectif lune" }) + third_article = StrapiRuby.post(resource: "articles", data: { title: "Astérix", content: "La table des dieux" }) + fourth_article = StrapiRuby.post(resource: "articles", data: { title: "Batman", content: "Gotham ne deviendra pas une victime" }) + + # Adjust the filters to match the fields in your articles + test_get = StrapiRuby.get(resource: :articles, + filters: { + "$or" => [ + { + title: { + "$eq" => "Babar", + }, + }, + { + title: { + "$eq" => "Tintin", # Tintin + }, + }, + { + content: { + "$eq" => "Gotham ne deviendra pas une victime", # Aventure au pays des éléphants + }, + }, + ], + }) + + p "test_complex_filtering: #{test_get.data.count == 3}" + + test_get_2 = StrapiRuby.get(resource: :articles, + filters: { + "$or" => [ + { title: { "$eq" => "Batman" } }, + { title: { "$eq" => "Tintin" } }, + ], + content: { + "$eq" => "Gotham ne deviendra pas une victime", + }, + }) + + p "test_complex_filtering_2: #{test_get_2.data.count == 1}" + + # Delete the articles + StrapiRuby.delete(resource: "articles", document_id: first_article.data.documentId) + StrapiRuby.delete(resource: "articles", document_id: second_article.data.documentId) + StrapiRuby.delete(resource: "articles", document_id: third_article.data.documentId) + StrapiRuby.delete(resource: "articles", document_id: fourth_article.data.documentId) end # Test raw query def test_raw_query - test_get = StrapiRuby.get(resource: "articles", raw: "?fields=title&sort=createdAt:asc") - test_get.data.map do |item| - item.attributes.title - end + first_article = StrapiRuby.post(resource: "articles", data: { title: "This is my first article", content: "This is some dummy content" }) + second_article = StrapiRuby.post(resource: "articles", data: { title: "This is my second article", content: "This is some dummy content" }) + third_article = StrapiRuby.post(resource: "articles", data: { title: "This is my third article", content: "This is some dummy content" }) + test_get = StrapiRuby.get(resource: "articles", raw: "?fields=title&sort=createdAt:desc") + p "test_raw_query: #{test_get.data.count == 3}" + p "test_raw_query: #{test_get.data.first.title == "This is my third article"}" + p "test_raw_query: #{test_get.data.last.title == "This is my first article"}" + + StrapiRuby.delete(resource: "articles", document_id: first_article.data.documentId) + StrapiRuby.delete(resource: "articles", document_id: second_article.data.documentId) + StrapiRuby.delete(resource: "articles", document_id: third_article.data.documentId) end # Test offset pagination def test_offset_pagination - test_get = StrapiRuby.get(resource: "articles", start: 0, limit: 1) + # Create 4 articles + first_article = StrapiRuby.post(resource: "articles", data: { title: "This is my first article", content: "This is some dummy content" }) + second_article = StrapiRuby.post(resource: "articles", data: { title: "This is my second article", content: "This is some dummy content" }) + third_article = StrapiRuby.post(resource: "articles", data: { title: "This is my third article", content: "This is some dummy content" }) + fourth_article = StrapiRuby.post(resource: "articles", data: { title: "This is my fourth article", content: "This is some dummy content" }) + test_get = StrapiRuby.get(resource: "articles", start: 2, limit: 1) test_get.data + p "test_offset_pagination: #{test_get.data.count == 1}" + # delete the articles + StrapiRuby.delete(resource: "articles", document_id: first_article.data.documentId) + StrapiRuby.delete(resource: "articles", document_id: second_article.data.documentId) + StrapiRuby.delete(resource: "articles", document_id: third_article.data.documentId) + StrapiRuby.delete(resource: "articles", document_id: fourth_article.data.documentId) end -# Test locale +# Test locale: this won't work if you don't create the local on strapi in settings then enable it in on your collection type advanced settings def test_locale - test_get = StrapiRuby.get(resource: "articles", locale: :en) + first_article = StrapiRuby.post(resource: "articles", data: { title: "This is my japanese article", content: "some japanese content", locale: "ja" }) + second_article = StrapiRuby.post(resource: "articles", data: { title: "This is my italian article", content: "some italian content", locale: "it" }) + test_get = StrapiRuby.get(resource: "articles", locale: "ja") + test_get.data + p "test_locale: #{test_get.data.count == 1}" + test_get = StrapiRuby.get(resource: "articles", locale: "it") test_get.data + p "test_locale: #{test_get.data.count == 1}" + # delete the articles + StrapiRuby.delete(resource: "articles", document_id: first_article.data.documentId) + StrapiRuby.delete(resource: "articles", document_id: second_article.data.documentId) end # Test selecting fields def test_selecting_fields + first_article = StrapiRuby.post(resource: "articles", data: { title: "This is my first article", content: "This is some dummy content" }) test_get = StrapiRuby.get(resource: :articles, fields: [:title]) - test_get.data + # Should not contain content field + p "test_selecting_fields: #{test_get.data.first.content.nil?}" + p "test_selecting_fields: #{!test_get.data.first.title.nil? && !test_get.data.first.title.empty?}" + # Delete the article + StrapiRuby.delete(resource: "articles", document_id: first_article.data.documentId) end -# Test populate +# Test populate: add featuredMedia field to the article and see if its populated def test_populate + first_article = StrapiRuby.post(resource: "articles", data: { title: "This is my first article", content: "This is some dummy content" }) test_get = StrapiRuby.get(resource: :articles, populate: :*) - test_get.data.first.attributes.featuredMedia + test_get.data.first.featuredMedia + # Delete the article + StrapiRuby.delete(resource: "articles", document_id: first_article.data.documentId) end -# Test a 404 endpoint +# Test a 404 endpoint: this will fail poorly def test_404_endpoint answer = StrapiRuby.get(resource: "thisDoesNotExist") - { error: answer.error, - data: answer.data, - meta: answer.meta } - # p test_get.data.count end # Test post article @@ -130,22 +213,23 @@ def test_post_article # Test put article def test_put_article - id = StrapiRuby.get(resource: "articles", sort: "createdAt:asc").data.last.id - StrapiRuby.put(resource: "articles", id: id, data: { title: "Title has been changed by PUT request" }) + document_id = StrapiRuby.get(resource: "articles", sort: "createdAt:asc").data.last.documentId + StrapiRuby.put(resource: "articles", document_id: document_id, data: { title: "Title has been changed by PUT request" }) end # Test delete article def test_delete_article - id = StrapiRuby.get(resource: "articles", sort: "createdAt:asc").data.last.id - StrapiRuby.delete(resource: "articles", id: id) + document_id = StrapiRuby.get(resource: "articles", sort: "createdAt:asc").data.last.documentId + StrapiRuby.delete(resource: "articles", document_id: document_id) end def test_show_endpoint - StrapiRuby.get(resource: "articles", show_endpoint: true).endpoint + endpoint = StrapiRuby.get(resource: "articles", filters: { documentId: { "$in" => ["someId", "someOtherId"] } }, show_endpoint: true).endpoint + p "test_show_endpoint: #{endpoint.include?("http://localhost:1337/api/articles?filters[documentId][$in][0]=someId&filters[documentId][$in][1]=someOtherId")}" end def test_escape_empty_answer - answer = StrapiRuby.get(resource: "articles", id: 233) + answer = StrapiRuby.get(resource: "articles", document_id: "thisDoesNotExist") StrapiRuby.escape_empty_answer(answer) do puts "if you see this, it means the test is not passing" @@ -155,45 +239,29 @@ def test_escape_empty_answer answer end -def test_trigger_error_using_collection_parameters_on_single_endpoint - begin - StrapiRuby.get(resource: "articles", id: 1, page: 1) - rescue ArgumentError => e - puts e.message - puts "if you see this, it means the test is passing" - end - begin - StrapiRuby.get(resource: "articles", id: 1, filters: { id: { "$in" => ["1", "3"] } }) - rescue ArgumentError => e - puts e.message - puts "if you see this, it means the test is passing" - end -end - # Main execution configure_strapi puts "\n\n" # Uncomment and run the desired test functions here tests = [ - # :test_get_all_articles, - # :test_get_one_article, - # :test_post_article, - # :test_put_article, - # :test_delete_article, - # :test_sorting, - # :test_filtering, - # :test_complex_filtering, - # :test_pagination, - # :test_offset_pagination, - # :test_locale, - # :test_selecting_fields, - # :test_populate, - # :test_raw_query, - # :test_404_endpoint, - # :test_show_endpoint, - # :test_escape_empty_answer, - # :test_trigger_error_using_collection_parameters_on_single_endpoint, + :test_post_article, + :test_get_all_articles, + :test_get_one_article, + :test_put_article, + :test_delete_article, + :test_sorting, + :test_filtering, + :test_complex_filtering, + :test_pagination, + :test_offset_pagination, + :test_locale, + :test_selecting_fields, + :test_populate, + :test_raw_query, + :test_404_endpoint, + :test_show_endpoint, + :test_escape_empty_answer, ] tests.each do |test|