microsoft/vscode-react-native
Publicmirrored fromhttps://github.com/microsoft/vscode-react-nativeAvailable
test/extension/ios/plistBuddy.test.ts
106lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. All rights reserved. |
| 2 | // Licensed under the MIT license. See LICENSE file in the project root for details. |
| 3 | |
| 4 | import {PlistBuddy} from "../../../src/extension/ios/plistBuddy"; |
| 5 | |
| 6 | import {IXcodeProjFile} from "../../../src/extension/ios/xcodeproj"; |
| 7 | |
| 8 | import * as assert from "assert"; |
| 9 | import * as path from "path"; |
| 10 | import * as Q from "q"; |
| 11 | import * as sinon from "sinon"; |
| 12 | |
| 13 | suite("plistBuddy", function() { |
| 14 | suite("extensionContext", function() { |
| 15 | test("setPlistProperty should attempt to modify, then add, plist properties", function() { |
| 16 | const plistFileName = "testFile.plist"; |
| 17 | const plistProperty = ":RCTDevMenu:ExecutorClass"; |
| 18 | const plistValue = "RCTWebSocketExecutor"; |
| 19 | |
| 20 | const setCallArgs = `/usr/libexec/PlistBuddy -c 'Set ${plistProperty} ${plistValue}' '${plistFileName}'`; |
| 21 | const addCallArgs = `/usr/libexec/PlistBuddy -c 'Add ${plistProperty} string ${plistValue}' '${plistFileName}'`; |
| 22 | |
| 23 | const mockedExecFunc = sinon.stub(); |
| 24 | mockedExecFunc.withArgs(setCallArgs).returns({ outcome: Q.reject(new Error("Setting does not exist")) }); |
| 25 | mockedExecFunc.withArgs(addCallArgs).returns({ outcome: Q.resolve("stdout") }); |
| 26 | mockedExecFunc.throws(); |
| 27 | |
| 28 | const mockChildProcess: any = { |
| 29 | exec: mockedExecFunc, |
| 30 | }; |
| 31 | const plistBuddy = new PlistBuddy({ nodeChildProcess: mockChildProcess }); |
| 32 | |
| 33 | return plistBuddy.setPlistProperty(plistFileName, plistProperty, plistValue) |
| 34 | .then(() => { |
| 35 | assert(mockedExecFunc.calledWithExactly(setCallArgs), "plistBuddy did not attempt to set first"); |
| 36 | assert(mockedExecFunc.calledWithExactly(addCallArgs), "plistBuddy did not attempt to add after set failed"); |
| 37 | assert.equal(mockedExecFunc.callCount, 2); |
| 38 | }); |
| 39 | }); |
| 40 | |
| 41 | test("setPlistProperty should stop after modifying if the attempt succeeds", function() { |
| 42 | const plistFileName = "testFile.plist"; |
| 43 | const plistProperty = ":RCTDevMenu:ExecutorClass"; |
| 44 | const plistValue = "RCTWebSocketExecutor"; |
| 45 | |
| 46 | const setCallArgs = `/usr/libexec/PlistBuddy -c 'Set ${plistProperty} ${plistValue}' '${plistFileName}'`; |
| 47 | |
| 48 | const mockedExecFunc = sinon.stub(); |
| 49 | mockedExecFunc.withArgs(setCallArgs).returns({ outcome: Q.resolve("stdout") }); |
| 50 | mockedExecFunc.throws(); |
| 51 | |
| 52 | const mockChildProcess: any = { |
| 53 | exec: mockedExecFunc, |
| 54 | }; |
| 55 | const plistBuddy = new PlistBuddy({ nodeChildProcess: mockChildProcess }); |
| 56 | |
| 57 | return plistBuddy.setPlistProperty(plistFileName, plistProperty, plistValue) |
| 58 | .then(() => { |
| 59 | assert(mockedExecFunc.calledWithExactly(setCallArgs), "plistBuddy did not attempt to set first"); |
| 60 | assert.equal(mockedExecFunc.callCount, 1); |
| 61 | }); |
| 62 | }); |
| 63 | |
| 64 | test("getBundleId should return the bundle ID", function() { |
| 65 | const projectRoot = path.join("/", "userHome", "rnProject"); |
| 66 | const appName = "myApp"; |
| 67 | |
| 68 | const infoPlistPath = (simulator: boolean) => |
| 69 | path.join(projectRoot, "build", "Build", "Products", |
| 70 | simulator ? "Debug-iphonesimulator" : "Debug-iphoneos", |
| 71 | `${appName}.app`, "Info.plist"); |
| 72 | |
| 73 | const simulatorBundleId = "com.contoso.simulator"; |
| 74 | const deviceBundleId = "com.contoso.device"; |
| 75 | |
| 76 | const printExecCall = (simulator: boolean) => `/usr/libexec/PlistBuddy -c 'Print:CFBundleIdentifier' '${infoPlistPath(simulator)}'`; |
| 77 | |
| 78 | const mockedExecFunc = sinon.stub(); |
| 79 | mockedExecFunc.withArgs(printExecCall(true)).returns({outcome: Q.resolve(simulatorBundleId)}); |
| 80 | mockedExecFunc.withArgs(printExecCall(false)).returns({outcome: Q.resolve(deviceBundleId)}); |
| 81 | const mockChildProcess: any = { |
| 82 | exec: mockedExecFunc, |
| 83 | }; |
| 84 | |
| 85 | const mockedFindXcodeprojFile = sinon.stub(); |
| 86 | const mockedProjResult: IXcodeProjFile = { |
| 87 | fileName: appName + ".xcodeproj", |
| 88 | fileType: ".xcodeproj", |
| 89 | projectName: appName, |
| 90 | }; |
| 91 | mockedFindXcodeprojFile.withArgs(projectRoot).returns(Q.resolve(mockedProjResult)); |
| 92 | const mockXcodeproj: any = { |
| 93 | findXcodeprojFile: mockedFindXcodeprojFile, |
| 94 | }; |
| 95 | const plistBuddy = new PlistBuddy({ nodeChildProcess: mockChildProcess, xcodeproj: mockXcodeproj }); |
| 96 | |
| 97 | return Q.all([ |
| 98 | plistBuddy.getBundleId(projectRoot, true), |
| 99 | plistBuddy.getBundleId(projectRoot, false), |
| 100 | ]).spread((simulatorId, deviceId) => { |
| 101 | assert.equal(simulatorBundleId, simulatorId); |
| 102 | assert.equal(deviceBundleId, deviceId); |
| 103 | }); |
| 104 | }); |
| 105 | }); |
| 106 | }); |