Search code examples
swiftmacosxctestnsdocument

What is the correct way to open a file from line arguments in an NSDocument application in Swift?


I'm working on a MacOS Document based application that opens a certain file type. What I want to do is write some UI tests for this application, but I want to load some mock data for these UI tests. From what I understand, I should actually use launchArguments or launchEnvironment variables to load this mock data.

So, it sounds to me like the correct thing to do is create some test data files, and open those files at the launch of the application using something like this:

let app = XCUIApplication()  
app.launchArguments.append("-url")  
app.launchArguments.append($PATH)  
app.launch()

Now my question is, where should I add the code for opening a file during launch? Is there a method that NSDocumentDelegate has that I should override? Should I call openDocument(withContentsOf:display:completionHandler:) or just set the fileURL or something else entirely?

Right now my application opens the last opened file or opens a new document. I could try to override makeUntitledDocument(ofType typeName: String) or func restoreWindow(withIdentifier identifier: NSUserInterfaceItemIdentifier, state: NSCoder, completionHandler: @escaping (NSWindow?, Error?) -> Void) but I don't feel like either of those is the correct option.

So I guess I have two questions: 1) what is the correct way to pass mock data for UI testing of an NSDocument based application. 2) what is the correct way to open a file on launch of an application using a line argument.


Solution

  • 1) what is the correct way to pass mock data for UI testing of an NSDocument based application?

    What I do is the following:

    1) To open a new document I call makeUntitledDocument(ofType typeName: String). There is no need to override it at all. You can then set up the document as you wish with the returned value of this API.

    2) To open a previously saved document I call indeed openDocument(withContentsOf:display:completionHandler:)

    Using pseudo-code would be something like this, where you can pass any URL with the mock data:

    func openDocument(itemData:ItemData) {
      let controller = NSDocumentController.shared
       controller.openDocument(withContentsOf: itemData.url, display: true)
       { (_, _, error:Error?) in
            if error != nil {
                 handleError(.unableToOpenDocument(itemData.url))
            }
        }
    }
    

    Once again, there is no need to override openDocument(withContentsOf:display:completionHandler:).

    2) what is the correct way to open a file on launch of an application using a line argument?

    I would use a bash script for that using:

    open -a $APP_PATH $DOCUMENT_PATH
    

    This will mimic what the Finder does, but if you don't like that option, then you can always try what they propose in the answers to this question here.