|
59 | 59 | require "spec_helper" |
60 | 60 |
|
61 | 61 | RSpec.describe OpenProject::Files do |
62 | | - describe "build_uploaded_file" do |
| 62 | + describe ".build_uploaded_file" do |
63 | 63 | let(:original_filename) { "test.png" } |
64 | 64 | let(:content_type) { "image/png" } |
65 | 65 | let(:file) do |
66 | | - OpenProject::Files.create_temp_file(name: original_filename) |
| 66 | + Tempfile.new(File.basename(original_filename)) |
67 | 67 | end |
68 | 68 |
|
69 | | - subject { OpenProject::Files.build_uploaded_file(file, content_type) } |
| 69 | + subject { described_class.build_uploaded_file(file, content_type, file_name: original_filename) } |
70 | 70 |
|
71 | 71 | it "has the original file name" do |
72 | 72 | expect(subject.original_filename).to eql(original_filename) |
|
79 | 79 | context "with custom file name" do |
80 | 80 | let(:file_name) { "my-custom-filename.png" } |
81 | 81 |
|
82 | | - subject { OpenProject::Files.build_uploaded_file(file, content_type, file_name:) } |
| 82 | + subject { described_class.build_uploaded_file(file, content_type, file_name:) } |
83 | 83 |
|
84 | 84 | it "has the custom file name" do |
85 | 85 | expect(subject.original_filename).to eql(file_name) |
86 | 86 | end |
87 | 87 | end |
88 | 88 | end |
89 | 89 |
|
90 | | - describe "create_uploaded_file" do |
91 | | - context "without parameters" do |
92 | | - let(:file) { OpenProject::Files.create_uploaded_file } |
93 | | - |
94 | | - it 'creates a file with the default name "test.txt"' do |
95 | | - expect(file.original_filename).to eq "test.txt" |
96 | | - end |
97 | | - |
98 | | - it "creates distinct files even with identical names" do |
99 | | - file_2 = OpenProject::Files.create_uploaded_file |
100 | | - |
101 | | - expect(file.original_filename).to eq file_2.original_filename |
102 | | - expect(file.path).not_to eq file_2.path |
103 | | - end |
104 | | - |
105 | | - it 'writes some default content "test content"' do |
106 | | - expect(file.read).to eq "test content" |
107 | | - end |
108 | | - |
109 | | - it 'set default content type "text/plain"' do |
110 | | - expect(file.content_type).to eq "text/plain" |
111 | | - end |
112 | | - end |
113 | | - |
| 90 | + describe ".create_uploaded_file" do |
114 | 91 | context "with a custom name, content and content type" do |
115 | 92 | let(:name) { "foo.jpg" } |
116 | 93 | let(:content) { "not-really-a-jpg" } |
117 | 94 | let(:content_type) { "image/jpeg" } |
118 | 95 |
|
119 | 96 | let(:file) do |
120 | | - OpenProject::Files.create_uploaded_file name:, |
121 | | - content:, |
122 | | - content_type: |
| 97 | + described_class.create_uploaded_file name:, |
| 98 | + content:, |
| 99 | + content_type: |
123 | 100 | end |
124 | 101 |
|
125 | 102 | it 'creates a file called "foo.jpg"' do |
|
138 | 115 | context "with binary content" do |
139 | 116 | let(:content) { "\xD1\x9B\x86".b } |
140 | 117 | let(:binary) { false } |
141 | | - let(:file) { OpenProject::Files.create_uploaded_file content:, binary: } |
| 118 | + let(:file) do |
| 119 | + described_class.create_uploaded_file( |
| 120 | + name: "binary_file", |
| 121 | + content_type: "application/octet-stream", |
| 122 | + content: content, |
| 123 | + binary: binary |
| 124 | + ) |
| 125 | + end |
142 | 126 |
|
143 | 127 | it "fails when the content is not marked as binary" do |
144 | 128 | expect { file }.to raise_error(Encoding::UndefinedConversionError) |
|
152 | 136 | end |
153 | 137 | end |
154 | 138 | end |
| 139 | + |
| 140 | + context "when a relative filename is provided" do |
| 141 | + let(:name) { "../../hello/../../../foo.txt" } |
| 142 | + let(:file) do |
| 143 | + described_class.create_uploaded_file name:, |
| 144 | + content: "content", |
| 145 | + content_type: "text/plain" |
| 146 | + end |
| 147 | + |
| 148 | + it "sanitizes the file name" do |
| 149 | + expect(file.original_filename).to eq "foo.txt" |
| 150 | + end |
| 151 | + end |
| 152 | + end |
| 153 | + |
| 154 | + describe ".create_temp_file" do |
| 155 | + let(:name) { "tempfile.txt" } |
| 156 | + let(:content) { "temporary content" } |
| 157 | + let(:binary) { false } |
| 158 | + |
| 159 | + subject do |
| 160 | + described_class.create_temp_file(name:, content:, binary:, &:read) |
| 161 | + end |
| 162 | + |
| 163 | + it "yields a file with the given content" do |
| 164 | + expect(subject).to eq content |
| 165 | + end |
| 166 | + |
| 167 | + context "with binary content" do |
| 168 | + let(:content) { "\xD1\x9B\x86".b } |
| 169 | + let(:binary) { true } |
| 170 | + |
| 171 | + it "yields the binary content" do |
| 172 | + expect(subject).to eq content |
| 173 | + end |
| 174 | + end |
| 175 | + |
| 176 | + context "when a relative filename is provided" do |
| 177 | + let(:name) { "../../tempfile.txt" } |
| 178 | + |
| 179 | + it "sanitizes the file name" do |
| 180 | + described_class.create_temp_file(name:, content:, binary:) do |f| |
| 181 | + expect(f.path).to eq(File.expand_path(f.path)) |
| 182 | + end |
| 183 | + end |
| 184 | + end |
155 | 185 | end |
156 | 186 | end |
0 commit comments