Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.2.8 2025-11-01

**Bugfix**
1. Fixed a bug where calling `.contents` on a truly empty folder would cause `SystemStackError`.

## 0.2.7 2025-08-01

**Changes**
Expand Down
6 changes: 3 additions & 3 deletions lib/pcloud/folder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ def parent_folder
# Some APIs return `nil` or `[]` for contents when a folder does actually
# have contents. This method allows us to re-try one time if we try to get
# the contents and find that they're missing.
def contents
return @contents if @contents_are_confirmed
@contents = Folder.find(id).contents
def contents(is_retry: false)
return @contents if @contents_are_confirmed || is_retry
@contents = Folder.find(id).contents(is_retry: true)
@contents_are_confirmed = true
@contents
end
Expand Down
2 changes: 1 addition & 1 deletion lib/pcloud/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module Pcloud
VERSION = "0.2.7"
VERSION = "0.2.8"
end
100 changes: 73 additions & 27 deletions spec/pcloud/folder_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,32 @@
)
end

let(:phrynes_empty_contents_folder) do
Pcloud::Folder.new(
id: 666,
path: "/phrynes_empty_contents_folder",
name: "phrynes_empty_contents_folder",
parent_folder_id: 0,
contents: [],
is_deleted: false,
created_at: "Sat, 1 Nov 2025 16:22:06 +0000",
modified_at: "Sat, 1 Nov 2025 16:22:06 +0000"
)
end

let(:phrynes_nil_contents_folder) do
Pcloud::Folder.new(
id: 666,
path: "/phrynes_nil_contents_folder",
name: "phrynes_nil_contents_folder",
parent_folder_id: 0,
contents: [],
is_deleted: false,
created_at: "Sat, 1 Nov 2025 16:22:06 +0000",
modified_at: "Sat, 1 Nov 2025 16:22:06 +0000"
)
end

describe "#initialize" do
it "raises an error if a required attribute is missing from params" do
expect {
Expand Down Expand Up @@ -325,44 +351,64 @@
end

describe "#contents" do
let(:jacks_folder_no_confirmed_contents) { jacks_folder.dup }

before do
allow(Pcloud::Folder).to receive(:find).and_return(jacks_folder)
end

# Some APIs (mainly recursive operations according to pCloud) return either a
# nil or an empty array of contents. In these cases, the @contents_are_confirmed
# flag is set to `false` in order to allow one retry to fetch the actual
# contents if the `contents` method is called on a folder object that does not
# have any contents set yet.
context "when no contents are present" do
before do
jacks_folder_no_confirmed_contents.instance_variable_set(:@contents, nil)
jacks_folder_no_confirmed_contents.instance_variable_set(:@contents_are_confirmed, false)
context "missing contents" do
context "when contents is nil" do
before do
allow(Pcloud::Folder).to receive(:find).and_return(phrynes_nil_contents_folder)
end

it "makes a find request for the folder contents" do
expect(Pcloud::Folder)
.to receive(:find)
.with(666)
phrynes_nil_contents_folder.contents
end

it "returns empty contents" do
contents = phrynes_nil_contents_folder.contents
expect(contents.size).to eq(0)
end

it "caches the response" do
expect(Pcloud::Folder).to receive(:find).once
5.times { phrynes_nil_contents_folder.contents }
end
end

it "makes a find request for the folder contents" do
expect(Pcloud::Folder)
.to receive(:find)
.with(9000)
jacks_folder_no_confirmed_contents.contents
end

it "returns the folder contents" do
contents = jacks_folder_no_confirmed_contents.contents
expect(contents.size).to eq(2)
expect(contents.first).to be_a(Pcloud::File)
expect(contents.last).to be_a(Pcloud::Folder)
end

it "caches the response" do
expect(Pcloud::Folder).to receive(:find).once
5.times { jacks_folder_no_confirmed_contents.contents }
context "when contents is empty" do
before do
allow(Pcloud::Folder).to receive(:find).and_return(phrynes_empty_contents_folder)
end

it "makes a find request for the folder contents" do
expect(Pcloud::Folder)
.to receive(:find)
.with(666)
phrynes_empty_contents_folder.contents
end

it "returns empty contents" do
contents = phrynes_empty_contents_folder.contents
expect(contents.size).to eq(0)
end

it "caches the response" do
expect(Pcloud::Folder).to receive(:find).once
5.times { phrynes_empty_contents_folder.contents }
end
end
end

context "when contents are already present" do
before do
allow(Pcloud::Folder).to receive(:find).and_return(jacks_folder)
end

it "returns the folder contents" do
contents = jacks_folder.contents
expect(contents.size).to eq(2)
Expand Down