Skip to content

Commit 61535f1

Browse files
committed
Refactor FileUpload component and add unit tests for file upload functionality
1 parent 1551d46 commit 61535f1

File tree

5 files changed

+184
-56
lines changed

5 files changed

+184
-56
lines changed

models/CBWIREController.cfc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ component singleton {
139139
local.files = directoryList( path=local.storagePath, recurse=true, type="file", listInfo="query" );
140140
local.files.each( function( _file ) {
141141
if( dateDiff( "d", _file.DateLastModified, now() ) > 1 ){
142-
fileDelete( _file );
142+
fileDelete( _file.directory & "/" & _file.name );
143143
}
144144
} );
145145
// Verify the signed URL, throw 403 if invalid

models/FileUpload.cfc

Lines changed: 48 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,131 +1,124 @@
1-
/**
1+
/**
22
* This is the file entity that is used to represent a file that has been uploaded
33
* to the server. It is used to store the file in a temporary location and to
44
* provide access to the file's metadata.
55
*/
66
component {
77

8-
98
// Inject module settings
109
property name="moduleSettings" inject="coldbox:modulesettings:cbwire";
1110

1211
/**
1312
* Constructor
1413
*/
1514
function load( wire, dataPropertyName, uuid ){
16-
// Our CBWIRe Component
1715
variables.wire = arguments.wire;
18-
// The data property name the file upload is for
19-
variables.dataPropertyName = arguments.dataPropertyName; // getParams()[ 1 ]
20-
// The UUID of the file upload we provided after the upload was complete
21-
variables.uuid = arguments.uuid; // getParams()[ 2 ][ 1 ]
22-
// The temp directory
23-
local.tempDirectory = getCanonicalPath( variables.moduleSettings.moduleRootPath & "models/tmp" );
24-
// The file upload metadata JSON file path
25-
variables.metaPath = getCanonicalPath( local.tempDirectory & "/#variables.uuid#.json" );
26-
// Load the metadata, throw and exception if fails
27-
if ( fileExists( variables.metaPath ) ) {
28-
local.metaJSON = fileRead( variables.metaPath );
29-
variables.meta = deserializeJSON( local.metaJSON );
16+
variables.dataPropertyName = arguments.dataPropertyName;
17+
variables.uuid = arguments.uuid;
18+
19+
var metaPath = getMetaPath();
20+
21+
if ( fileExists( metaPath ) ) {
22+
var metaJSON = fileRead( metaPath );
23+
variables.meta = deserializeJSON( metaJSON );
3024
} else {
3125
throw( type="CBWIREException", message="File upload metadata not found." );
3226
}
33-
// The file upload temporary storage path
27+
3428
variables.temporaryStoragePath = getCanonicalPath( variables.meta.serverDirectory & "/#variables.meta.serverFile#" );
35-
// Return fileupload
3629
return this;
3730
}
3831

3932
/**
4033
* Returns the base64 representation of the file
41-
*
42-
* @return string
4334
*/
4435
function getBase64(){
4536
return toBase64( get() );
4637
}
4738

48-
/**
39+
/**
4940
* Returns the base64 src of the file
50-
*
51-
* @return string
5241
*/
5342
function getBase64Src(){
5443
return "data:#getMimeType()#;base64, #getBase64()#";
5544
}
5645

57-
/**
58-
* Returns the binary for the uploaded file.
59-
*
60-
* @return binary
46+
/**
47+
* Returns the binary for the uploaded file
6148
*/
6249
function get(){
6350
return fileReadBinary( variables.temporaryStoragePath );
6451
}
6552

6653
/**
67-
* Returns the file's size.
68-
*
69-
* @return numeric
54+
* Returns the file's size
7055
*/
7156
function getSize(){
7257
return variables.meta.fileSize;
7358
}
7459

75-
/**
76-
* Returns the file's MIME type.
77-
*
78-
* @return string
60+
/**
61+
* Returns the file's MIME type
7962
*/
8063
function getMIMEType(){
8164
return variables.meta.contentType & "/" & variables.meta.contentSubType;
8265
}
8366

84-
/**
85-
* Returns true if the uploaded file is an image.
86-
*
87-
* @return boolean
67+
/**
68+
* Returns true if the uploaded file is an image
8869
*/
8970
function isImage(){
9071
return variables.meta.contentType == "image";
9172
}
9273

93-
/**
94-
* Returns the file's preview URL.
95-
*
96-
* @return string
74+
/**
75+
* Returns the file's preview URL
9776
*/
9877
function getPreviewURL(){
9978
return "/cbwire/preview-file/#variables.uuid#";
10079
}
10180

10281
/**
10382
* Returns the temporary file path
104-
*
105-
* @return string
10683
*/
10784
function getTemporaryStoragePath(){
108-
return variables.temporaryStoragePath;
85+
return variables.temporaryStoragePath;
10986
}
11087

111-
/**
112-
* Deletes the file in temporary storage and the metadata file.
113-
*
114-
* @return void
88+
/**
89+
* Deletes the file in temporary storage and the metadata file
11590
*/
11691
function destroy(){
11792
fileDelete( variables.temporaryStoragePath );
118-
fileDelete( variables.metaPath );
93+
fileDelete( getMetaPath() );
11994
variables.wire.reset( variables.dataPropertyName );
12095
}
12196

122-
123-
/*
97+
/**
12498
* Serialize the file upload
125-
*
126-
* @return string
12799
*/
128-
function serializeIt() {
100+
function serializeIt(){
129101
return "fileupload:" & variables.uuid;
130102
}
131-
}
103+
104+
/**
105+
* Return the meta data for the upload
106+
*/
107+
function getMeta(){
108+
return variables.meta;
109+
}
110+
111+
/**
112+
* Returns the path to the temp directory (mockable in tests)
113+
*/
114+
function getTempDirectory(){
115+
return getCanonicalPath( variables.moduleSettings.moduleRootPath & "models/tmp" );
116+
}
117+
118+
/**
119+
* Returns the full path to the metadata file (mockable in tests)
120+
*/
121+
function getMetaPath(){
122+
return getCanonicalPath( getTempDirectory() & "/#variables.uuid#.json" );
123+
}
124+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"uuid":"test","fileSize":1234,"contentType":"text","contentSubType":"plain","serverDirectory":"/Users/grantcopley/Code/ortus/cbwire/cbwire/test-harness/tests/resources","serverFile":"logo.png"}
21.1 KB
Loading
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
component extends="coldbox.system.testing.BaseTestCase" {
2+
3+
function beforeAll() {
4+
super.beforeAll();
5+
6+
// Clean out tmp directory before all tests
7+
local.tempFolder = expandPath( "../../../models/tmp" );
8+
if ( directoryExists( local.tempFolder ) ) {
9+
directoryDelete( local.tempFolder, true );
10+
}
11+
directoryCreate( local.tempFolder );
12+
13+
// Ensure /resources exists
14+
local.resourcePath = expandPath( "../resources" );
15+
if ( !directoryExists( local.resourcePath ) ) {
16+
directoryCreate( local.resourcePath );
17+
}
18+
}
19+
20+
function run( testResults, testBox ) {
21+
describe( "FileUpload.cfc", function() {
22+
23+
beforeEach( function( currentSpec ) {
24+
setup();
25+
26+
testComponent = getInstance( "wires.TestComponent" );
27+
testComponent
28+
._withEvent( getRequestContext() )
29+
._withPath( "wires.TestComponent" );
30+
31+
prepareMock( testComponent );
32+
33+
fileUpload = getInstance( "FileUpload@cbwire" );
34+
prepareMock( fileUpload );
35+
});
36+
37+
it( "should return an object", function() {
38+
var result = getInstance( "FileUpload@cbwire" );
39+
expect( isObject( result ) ).toBeTrue();
40+
});
41+
42+
it( "should load without error", function() {
43+
var result = loadMockedFileUpload( "test", "text", "plain" );
44+
expect( isObject( result ) ).toBeTrue();
45+
});
46+
47+
it( "should return the meta data", function() {
48+
var result = loadMockedFileUpload( "test", "text", "plain" );
49+
expect( result.getMeta().uuid ).toBe( "test" );
50+
});
51+
52+
it( "should return fileupload: uuid on serializeIt", function() {
53+
var result = loadMockedFileUpload( "test", "text", "plain" );
54+
expect( result.serializeIt() ).toBe( "fileupload:test" );
55+
});
56+
57+
it( "should return expected preview URL", function() {
58+
var result = loadMockedFileUpload( "test", "text", "plain" );
59+
expect( result.getPreviewURL() ).toBe( "/cbwire/preview-file/test" );
60+
});
61+
62+
it( "should determine is image", function() {
63+
var result = loadMockedFileUpload( "test", "image", "png" );
64+
expect( result.isImage() ).toBeTrue();
65+
});
66+
67+
it( "should determine is NOT image", function() {
68+
var result = loadMockedFileUpload( "test", "text", "plain" );
69+
expect( result.isImage() ).toBeFalse();
70+
});
71+
72+
it( "should return the file size", function() {
73+
var result = loadMockedFileUpload( "test", "text", "plain" );
74+
expect( result.getSize() ).toBe( 1234 );
75+
});
76+
77+
it( "should return the MIME type", function() {
78+
var result = loadMockedFileUpload( "test", "text", "plain" );
79+
expect( result.getMIMEType() ).toBe( "text/plain" );
80+
});
81+
82+
it( "should return the temporary storage path", function() {
83+
var result = loadMockedFileUpload( "test", "text", "plain" );
84+
expect( result.getTemporaryStoragePath() ).toBe( expandPath( "../resources/logo.png" ) );
85+
});
86+
87+
it( "should return binary file contents when calling get", function() {
88+
var result = loadMockedFileUpload( "test", "text", "plain" );
89+
expect( isBinary( result.get() ) ).toBeTrue();
90+
});
91+
92+
it ( "should return base 64 encoded string when calling getBase64", function() {
93+
var result = loadMockedFileUpload( "test", "text", "plain" );
94+
expect( isBinary( toBinary( result.getBase64() ) ) ).toBeTrue();
95+
});
96+
97+
it( "should return base 64 src attribute contents when calling getBase64Src", function() {
98+
var result = loadMockedFileUpload( "test", "text", "plain" );
99+
expect( result.getBase64Src() ).toInclude( "data:" );
100+
});
101+
102+
});
103+
}
104+
105+
private function writeTestMetaFile( required path, required struct data ) {
106+
if ( fileExists( arguments.path ) ) {
107+
fileDelete( arguments.path );
108+
}
109+
fileWrite( arguments.path, serializeJSON( arguments.data ) );
110+
}
111+
112+
private function loadMockedFileUpload(
113+
required string uuid,
114+
required string contentType,
115+
required string contentSubType
116+
) {
117+
var metaPath = expandPath( "../resources/fileupload_metadata.json" );
118+
119+
writeTestMetaFile(
120+
path = metaPath,
121+
data = {
122+
"uuid" : arguments.uuid,
123+
"serverDirectory" : expandPath( "../resources" ),
124+
"serverFile" : "logo.png",
125+
"contentType" : arguments.contentType,
126+
"contentSubType" : arguments.contentSubType,
127+
"fileSize" : 1234
128+
}
129+
);
130+
131+
fileUpload.$( "getMetaPath", metaPath );
132+
return fileUpload.load( testComponent, "test", arguments.uuid );
133+
}
134+
}

0 commit comments

Comments
 (0)